OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-inspector commits / 1a6d510

Initial hyper-inspector: inspect, audit, and analyze Hypercore/Hyperdrive storage
Commands: - scan: find all corestores under a directory - audit: categorize by active/stale/junk with lock detection - cores: enumerate all cores with public keys, lengths, aliases - drives: discover Hyperdrives by parsing Hyperbee headers - drive: open and traverse a Hyperdrive's file tree - ls: list all files in a Hyperdrive via RocksDB read-only access - du: comprehensive disk usage across all corestores and drives - usage: per-core RocksDB disk consumption analysis - blocks: raw Hyperbee block decoder with file entry parsing - apps: list pear:// app registrations in platform corestores - inspect: low-level RocksDB key/value inspection Works read-only on locked databases. Decodes both JSON (compat) and compact-encoding Hyperdrive entry formats. Identifies apps by file fingerprinting. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1a6d51059042a684708f58ebc631f9389b3779c8
by plankatron <fleeky@gmail.com> · 2026-03-25T13:35:48.000Z

Changed files (1127) +127190 -0

bin/cli.js +668 -0
……@@ -0,0 +1,668 @@
1#!/usr/bin/env node
2
3import { openDB, listApps, getCorestoreStats, formatBytes } from '../lib/rocksdb-inspector.js'
4import { findCorestores, getDirSize, getLastModified, isLocked, getLockHolder } from '../lib/scanner.js'
5import { openDrive, getDriveStats, discoverDrives } from '../lib/drive-inspector.js'
6import { enumerateCores } from '../lib/core-enumerator.js'
7import { analyzeCoreDiskUsage, formatAnalysis } from '../lib/deep-analyzer.js'
8import { walkHyperbeeBlocks, decodeNode, decodeDriveEntry, stripSubEncoder, decodeHeader } from '../lib/block-reader.js'
9import { listDriveFromDB, buildTree, formatTree, formatFlat } from '../lib/drive-ls.js'
10import { corestoreDU, formatDU } from '../lib/du.js'
11import b4a from 'b4a'
12import { existsSync } from 'fs'
13import { join, resolve } from 'path'
14import { homedir } from 'os'
15
16const args = process.argv.slice(2)
17const command = args[0]
18
19const HELP = `
20hyper-inspector - Inspect, audit, and manage Hypercore corestores
21
22Commands:
23 scan [dir] Scan a directory for all corestores (default: ~/)
24 audit [dir] Full audit with sizes, lock status, and staleness
25 du [dir] Full Hyperdrive disk usage across all corestores
26 inspect <db-path> Inspect a corestore's RocksDB (path to db/ dir)
27 apps <db-path> List pear:// apps in a platform corestore
28 cores <storage-path> Enumerate all cores in a corestore (path with CORESTORE file)
29 drives <storage-path> Discover all Hyperdrives in a corestore
30 drive <storage-path> Open and traverse a Hyperdrive, list all files
31 drive <storage-path> --key <hex> Open a specific drive by key
32 ls <db-path> <dataPtr> List all files in a Hyperdrive (by RocksDB dataPointer)
33 usage <db-path> Deep analysis: which cores consume how many bytes on disk
34 blocks <storage-path> --key <hex> Read raw Hyperbee blocks, decode file entries
35
36Options:
37 --readonly Open databases in read-only mode (for locked DBs)
38 --limit <n> Max keys to scan (default: 100000)
39 --key <hex> Specify a Hypercore key
40 --help Show this help
41
42Examples:
43 hyper-inspector scan
44 hyper-inspector audit
45 hyper-inspector cores ~/.config/hypernote/server-data
46 hyper-inspector drive ~/.config/hypernote/server-data
47 hyper-inspector inspect ~/.config/pear/corestores/platform/db --readonly
48 hyper-inspector apps ~/.config/pear/corestores/platform/db --readonly
49`
50
51if (!command || command === '--help' || command === 'help') {
52 console.log(HELP)
53 process.exit(0)
54}
55
56if (command === 'scan') {
57 const dir = args[1] || homedir()
58 console.log(`\nScanning ${dir} for Hypercore storage...\n`)
59
60 const stores = findCorestores(dir)
61 let totalSize = 0
62
63 for (const store of stores) {
64 totalSize += store.size
65 const modified = getLastModified(store.path)
66 const modStr = modified ? modified.toISOString().slice(0, 10) : 'unknown'
67 console.log(` ${formatBytes(store.size).padStart(10)} ${modStr} ${store.path}`)
68 }
69
70 console.log(`\n Total: ${formatBytes(totalSize)} across ${stores.length} locations\n`)
71}
72
73if (command === 'inspect') {
74 const dbPath = resolve(args[1] || '')
75 const readOnly = args.includes('--readonly')
76 const limit = parseInt(args[args.indexOf('--limit') + 1]) || 100000
77
78 if (!dbPath || !existsSync(dbPath)) {
79 console.error('Error: provide a valid path to a db/ directory')
80 process.exit(1)
81 }
82
83 const locked = isLocked(dbPath)
84 if (locked && !readOnly) {
85 const holder = getLockHolder(dbPath)
86 console.error(`Database is locked by ${holder?.command} (PID ${holder?.pid})`)
87 console.error('Use --readonly to open in read-only mode')
88 process.exit(1)
89 }
90
91 console.log(`\nInspecting: ${dbPath}`)
92 console.log(`Mode: ${readOnly ? 'read-only' : 'read-write'}`)
93
94 const db = await openDB(dbPath, { readOnly })
95 const stats = await getCorestoreStats(db)
96
97 console.log(`\nCorestore column family:`)
98 console.log(` Keys scanned: ${stats.totalKeys}`)
99 console.log(` Value bytes: ${formatBytes(stats.totalBytes)}`)
100
101 console.log(`\nKey type breakdown:`)
102 for (const t of stats.typeBreakdown) {
103 console.log(` ${t.type.padEnd(16)} ${t.count.toString().padStart(8)} keys ${t.mb.padStart(10)} MB`)
104 }
105
106 if (stats.readable.length > 0) {
107 console.log(`\nSample readable values (${stats.readable.length}):`)
108 for (const r of stats.readable.slice(0, 30)) {
109 const label = KEY_TYPES_LABEL[r.type] || `0x${r.type.toString(16)}`
110 try {
111 const obj = JSON.parse(r.value)
112 if (obj.slug || obj.name || obj.title || obj.id) {
113 console.log(` [${label}] ${obj.title || obj.name || obj.slug || obj.id}`)
114 continue
115 }
116 } catch {}
117 console.log(` [${label}] ${r.value.slice(0, 100)}`)
118 }
119 }
120
121 const parentPath = dbPath.replace(/\/db\/?$/, '')
122 const diskSize = getDirSize(parentPath)
123 console.log(`\nDisk usage: ${formatBytes(diskSize)}`)
124
125 await db.close()
126}
127
128if (command === 'apps') {
129 const dbPath = resolve(args[1] || '')
130 const readOnly = args.includes('--readonly')
131
132 if (!dbPath || !existsSync(dbPath)) {
133 console.error('Error: provide a valid path to a platform db/ directory')
134 process.exit(1)
135 }
136
137 const db = await openDB(dbPath, { readOnly })
138 const { pearApps, fileSources } = await listApps(db)
139
140 const appRegistrations = pearApps.filter(a => a.prefix === 0x03)
141 const appVersions = pearApps.filter(a => a.prefix === 0x06)
142
143 console.log(`\n=== Pear Apps (${appRegistrations.length} registered) ===\n`)
144 for (const app of appRegistrations) {
145 const versionEntry = appVersions.find(v => v.url === app.url)
146 const hasVersion = versionEntry ? 'active' : 'no-version'
147 const dkeyMatch = app.storage.match(/by-dkey\/([a-f0-9]+)/)
148 const randomMatch = app.storage.match(/by-random\/([a-f0-9]+)/)
149 const storageId = dkeyMatch ? `dkey:${dkeyMatch[1].slice(0, 12)}...` : randomMatch ? `random:${randomMatch[1].slice(0, 12)}...` : ''
150
151 const storagePath = app.storage.match(/\/home\/[^\s|]+/)?.[0]
152 let sizeStr = ''
153 if (storagePath && existsSync(storagePath)) {
154 sizeStr = formatBytes(getDirSize(storagePath))
155 }
156
157 console.log(` ${app.url}`)
158 console.log(` status: ${hasVersion} storage: ${storageId} size: ${sizeStr || 'n/a'}`)
159 }
160
161 console.log(`\n=== Staging Sources (${fileSources.length}) ===\n`)
162 for (const f of fileSources) {
163 console.log(` ${f.path}`)
164 }
165
166 await db.close()
167}
168
169if (command === 'cores') {
170 const storagePath = resolve(args[1] || '')
171 const readOnly = args.includes('--readonly')
172
173 if (!storagePath || !existsSync(storagePath)) {
174 console.error('Error: provide a valid corestore path (directory with CORESTORE file)')
175 process.exit(1)
176 }
177
178 const dbPath = join(storagePath, 'db')
179 const locked = isLocked(dbPath)
180
181 if (locked && !readOnly) {
182 const holder = getLockHolder(dbPath)
183 console.error(`Database is locked by ${holder?.command} (PID ${holder?.pid})`)
184 console.error('Use --readonly to open in read-only mode')
185 process.exit(1)
186 }
187
188 console.log(`\nEnumerating cores in: ${storagePath}`)
189 console.log(`Mode: ${readOnly ? 'read-only' : 'read-write'}\n`)
190
191 const cores = await enumerateCores(dbPath, { readOnly })
192
193 console.log(`Found ${cores.length} cores:\n`)
194 for (const core of cores) {
195 const alias = core.alias
196 ? `${core.alias.name} (ns: ${core.alias.namespace.slice(0, 8)}...)`
197 : '(unnamed)'
198 const key = core.publicKey ? `key: ${core.publicKey.slice(0, 16)}...` : ''
199 const len = core.length != null ? `len: ${core.length}` : ''
200 console.log(` #${String(core.corePointer).padEnd(4)} ${alias.padEnd(30)} ${len.padEnd(12)} ${key}`)
201 console.log(` dkey: ${core.discoveryKey.slice(0, 32)}...`)
202 }
203}
204
205if (command === 'drives') {
206 const storagePath = resolve(args[1] || '')
207 const readOnly = args.includes('--readonly')
208
209 if (!storagePath || !existsSync(storagePath)) {
210 console.error('Error: provide a valid corestore path')
211 process.exit(1)
212 }
213
214 console.log(`\nDiscovering Hyperdrives in: ${storagePath}\n`)
215
216 const drives = await discoverDrives(storagePath, { readOnly })
217
218 if (drives.length === 0) {
219 console.log('No Hyperdrives found (data may be Autobase/Hyperbee, not Hyperdrive)')
220 } else {
221 for (const d of drives) {
222 const alias = d.alias ? d.alias.name : '(unnamed)'
223 const rw = d.writable ? 'writable' : 'read-only'
224 console.log(` Hyperdrive: ${alias}`)
225 console.log(` key: ${d.key}`)
226 console.log(` content: ${d.contentKey || 'n/a'}`)
227 console.log(` version: ${d.version} bytes: ${formatBytes(d.byteLength)} ${rw}`)
228
229 if (d.filePaths.length > 0) {
230 console.log(` files (${d.filePaths.length} found):`)
231 for (const f of d.filePaths.slice(0, 15)) {
232 console.log(` ${f}`)
233 }
234 if (d.filePaths.length > 15) {
235 console.log(` ... and ${d.filePaths.length - 15} more`)
236 }
237 }
238 console.log()
239 }
240 }
241}
242
243if (command === 'drive') {
244 const storagePath = resolve(args[1] || '')
245 const keyIdx = args.indexOf('--key')
246 const key = keyIdx >= 0 ? args[keyIdx + 1] : null
247
248 if (!storagePath || !existsSync(storagePath)) {
249 console.error('Error: provide a valid corestore path')
250 process.exit(1)
251 }
252
253 const dbPath = join(storagePath, 'db')
254 const locked = isLocked(dbPath)
255 if (locked) {
256 const holder = getLockHolder(dbPath)
257 console.error(`Corestore is locked by ${holder?.command} (PID ${holder?.pid})`)
258 console.error('Cannot open a Hyperdrive while another process holds the lock.')
259 console.error('Stop the process first, or use "cores" / "inspect" with --readonly.')
260 process.exit(1)
261 }
262
263 console.log(`\nOpening Hyperdrive from: ${storagePath}`)
264 if (key) console.log(`Key: ${key}`)
265
266 const { store, drive } = await openDrive(storagePath, { key })
267
268 console.log(`\nDrive key: ${drive.key.toString('hex')}`)
269 console.log(`Version: ${drive.version}`)
270 console.log(`Writable: ${drive.writable}`)
271
272 const stats = await getDriveStats(drive)
273
274 console.log(`\nFiles: ${stats.fileCount}`)
275 console.log(`Total content: ${formatBytes(stats.totalBytes)}`)
276 console.log(`Blob blocks: ${stats.blobBlocks}`)
277
278 if (stats.topDirs.length > 0) {
279 console.log(`\n--- By directory ---`)
280 for (const d of stats.topDirs.slice(0, 15)) {
281 console.log(` ${formatBytes(d.bytes).padStart(10)} ${d.count.toString().padStart(5)} files ${d.dir}`)
282 }
283 }
284
285 if (stats.extensions.length > 0) {
286 console.log(`\n--- By extension ---`)
287 for (const e of stats.extensions.slice(0, 15)) {
288 console.log(` ${formatBytes(e.bytes).padStart(10)} ${e.count.toString().padStart(5)} files .${e.ext}`)
289 }
290 }
291
292 // Show first 50 files
293 console.log(`\n--- Files (first 50 of ${stats.files.length}) ---`)
294 for (const f of stats.files.slice(0, 50)) {
295 const size = f.byteLength ? formatBytes(f.byteLength) : '0 B'
296 const link = f.linkname ? ` -> ${f.linkname}` : ''
297 const exec = f.executable ? ' *' : ''
298 console.log(` ${size.padStart(10)} ${f.path}${exec}${link}`)
299 }
300
301 if (stats.files.length > 50) {
302 console.log(` ... and ${stats.files.length - 50} more files`)
303 }
304
305 await drive.close()
306 await store.close()
307}
308
309if (command === 'ls') {
310 const dbPath = resolve(args[1] || '')
311 const dataPtr = parseInt(args[2])
312 const readOnly = args.includes('--readonly')
313 const flat = args.includes('--flat')
314 const filterIdx = args.indexOf('--filter')
315 const filter = filterIdx >= 0 ? args[filterIdx + 1] : null
316 const depthIdx = args.indexOf('--depth')
317 const maxDepth = depthIdx >= 0 ? parseInt(args[depthIdx + 1]) : 3
318 const minIdx = args.indexOf('--min')
319 const minBytes = minIdx >= 0 ? parseSize(args[minIdx + 1]) : 0
320
321 if (!dbPath || isNaN(dataPtr)) {
322 console.error('Usage: hyper-inspector ls <db-path> <dataPointer> [--readonly] [--flat] [--filter <path>] [--depth <n>] [--min <size>]')
323 console.error(' dataPointer: the data pointer number from "cores" output')
324 console.error(' --flat: flat file list sorted by size')
325 console.error(' --filter: only show paths containing this string')
326 console.error(' --depth: max tree depth (default: 3)')
327 console.error(' --min: minimum file size to show (e.g., 1M, 100K)')
328 process.exit(1)
329 }
330
331 console.log(`\nListing Hyperdrive at dataPointer ${dataPtr} in ${dbPath}\n`)
332
333 const { header, files, blocksRead } = await listDriveFromDB(dbPath, dataPtr, { readOnly })
334
335 if (header) {
336 console.log(`Hyperbee: protocol="${header.protocol}"`)
337 if (header.contentFeed) {
338 console.log(`Content core: ${b4a.toString(header.contentFeed, 'hex')}`)
339 }
340 }
341
342 console.log(`Scanned ${blocksRead} blocks, found ${files.length} files`)
343
344 let totalBytes = 0
345 for (const f of files) totalBytes += f.bytes
346 console.log(`Total content: ${formatBytes(totalBytes)}\n`)
347
348 if (files.length === 0) {
349 console.log('No Hyperdrive file entries found.')
350 } else if (flat) {
351 console.log(formatFlat(files, { filter, limit: 200 }))
352 } else {
353 const tree = buildTree(files)
354 console.log(formatTree(tree, { maxDepth, minBytes, showFiles: maxDepth <= 2 }))
355 }
356}
357
358function parseSize (str) {
359 if (!str) return 0
360 const num = parseFloat(str)
361 if (str.endsWith('G') || str.endsWith('g')) return num * 1024 * 1024 * 1024
362 if (str.endsWith('M') || str.endsWith('m')) return num * 1024 * 1024
363 if (str.endsWith('K') || str.endsWith('k')) return num * 1024
364 return num
365}
366
367if (command === 'usage') {
368 const dbPath = resolve(args[1] || '')
369 const readOnly = args.includes('--readonly')
370 const sampleIdx = args.indexOf('--sample')
371 const sampleSize = sampleIdx >= 0 ? parseInt(args[sampleIdx + 1]) : 500000
372
373 if (!dbPath || !existsSync(dbPath)) {
374 console.error('Error: provide a valid path to a db/ directory')
375 process.exit(1)
376 }
377
378 console.log(`\nDeep disk usage analysis: ${dbPath}`)
379 console.log(`Sampling up to ${sampleSize} entries...\n`)
380
381 const analysis = await analyzeCoreDiskUsage(dbPath, { readOnly, sampleSize })
382 console.log(formatAnalysis(analysis))
383}
384
385if (command === 'blocks') {
386 const storagePath = resolve(args[1] || '')
387 const keyIdx = args.indexOf('--key')
388 const keyHex = keyIdx >= 0 ? args[keyIdx + 1] : null
389 const maxIdx = args.indexOf('--max')
390 const maxBlocks = maxIdx >= 0 ? parseInt(args[maxIdx + 1]) : 500
391
392 if (!storagePath || !keyHex) {
393 console.error('Usage: hyper-inspector blocks <storage-path> --key <hex> [--max <n>]')
394 process.exit(1)
395 }
396
397 const dbPath = join(storagePath, 'db')
398 const locked = isLocked(dbPath)
399 if (locked) {
400 const holder = getLockHolder(dbPath)
401 console.error(`Locked by ${holder?.command} (PID ${holder?.pid}). Cannot open core.`)
402 process.exit(1)
403 }
404
405 const Corestore = (await import('corestore')).default
406 const store = new Corestore(storagePath)
407 await store.ready()
408
409 const core = store.get({ key: Buffer.from(keyHex, 'hex') })
410 await core.ready()
411
412 console.log(`\nCore: len=${core.length} bytes=${formatBytes(core.byteLength)} writable=${core.writable}`)
413
414 const { header, entries } = await walkHyperbeeBlocks(core, { maxBlocks })
415
416 if (header) {
417 console.log(`\nHyperbee header: protocol="${header.protocol}"`)
418 if (header.contentFeed) {
419 console.log(`Content feed: ${b4a.toString(header.contentFeed, 'hex')}`)
420 }
421 }
422
423 console.log(`\nDecoded ${entries.length} Hyperbee entries from ${Math.min(core.length, maxBlocks)} blocks\n`)
424
425 // Try to decode as Hyperdrive file entries
426 let driveEntries = 0
427 let totalBlobBytes = 0
428 const filesByExt = new Map()
429 const filesByDir = new Map()
430 const allFiles = []
431
432 for (const entry of entries) {
433 const rawKey = stripSubEncoder(entry.key)
434 let filePath = ''
435 try {
436 filePath = b4a.toString(rawKey, 'utf8')
437 } catch {
438 continue
439 }
440
441 // Skip non-path entries
442 if (!filePath.startsWith('/')) continue
443
444 let driveEntry = null
445 try {
446 driveEntry = decodeDriveEntry(entry.value)
447 } catch {}
448
449 if (driveEntry) {
450 driveEntries++
451 const blob = driveEntry.blob
452 const bytes = blob?.byteLength || 0
453 totalBlobBytes += bytes
454
455 // By extension
456 const ext = filePath.includes('.') ? filePath.split('.').pop() : '(none)'
457 const extInfo = filesByExt.get(ext) || { count: 0, bytes: 0 }
458 extInfo.count++
459 extInfo.bytes += bytes
460 filesByExt.set(ext, extInfo)
461
462 // By top-level directory
463 const parts = filePath.split('/')
464 const topDir = parts.length > 2 ? '/' + parts[1] : '/'
465 const dirInfo = filesByDir.get(topDir) || { count: 0, bytes: 0 }
466 dirInfo.count++
467 dirInfo.bytes += bytes
468 filesByDir.set(topDir, dirInfo)
469
470 allFiles.push({
471 path: filePath,
472 blob,
473 executable: driveEntry.executable,
474 linkname: driveEntry.linkname,
475 bytes
476 })
477 }
478 }
479
480 if (driveEntries > 0) {
481 console.log(`=== Hyperdrive File Analysis ===`)
482 console.log(`Files: ${driveEntries}`)
483 console.log(`Total blob content: ${formatBytes(totalBlobBytes)}\n`)
484
485 // By directory
486 const sortedDirs = [...filesByDir.entries()].sort((a, b) => b[1].bytes - a[1].bytes)
487 console.log('--- By directory ---')
488 for (const [dir, info] of sortedDirs.slice(0, 20)) {
489 console.log(` ${formatBytes(info.bytes).padStart(10)} ${info.count.toString().padStart(5)} files ${dir}`)
490 }
491
492 // By extension
493 const sortedExts = [...filesByExt.entries()].sort((a, b) => b[1].bytes - a[1].bytes)
494 console.log('\n--- By extension ---')
495 for (const [ext, info] of sortedExts.slice(0, 20)) {
496 console.log(` ${formatBytes(info.bytes).padStart(10)} ${info.count.toString().padStart(5)} files .${ext}`)
497 }
498
499 // Largest files
500 allFiles.sort((a, b) => b.bytes - a.bytes)
501 console.log('\n--- Largest files ---')
502 for (const f of allFiles.slice(0, 20)) {
503 const blockInfo = f.blob ? `blocks[${f.blob.blockOffset}..${f.blob.blockOffset + f.blob.blockLength}]` : ''
504 console.log(` ${formatBytes(f.bytes).padStart(10)} ${f.path} ${blockInfo}`)
505 }
506
507 // Show blob block range summary
508 if (allFiles.length > 0 && allFiles[0].blob) {
509 let minBlock = Infinity
510 let maxBlock = 0
511 for (const f of allFiles) {
512 if (f.blob) {
513 minBlock = Math.min(minBlock, f.blob.blockOffset)
514 maxBlock = Math.max(maxBlock, f.blob.blockOffset + f.blob.blockLength)
515 }
516 }
517 console.log(`\nBlob block range: ${minBlock} - ${maxBlock} (${maxBlock - minBlock} blocks in content core)`)
518 }
519 } else {
520 // Not a Hyperdrive - show raw entries
521 console.log('Not a Hyperdrive (no file path entries found).')
522 console.log('Raw Hyperbee entries:')
523 for (const entry of entries.slice(0, 30)) {
524 let keyStr = ''
525 try {
526 keyStr = b4a.toString(entry.key, 'utf8')
527 if (!/^[\x20-\x7e\n\r\t]+$/.test(keyStr)) {
528 keyStr = `[hex: ${b4a.toString(entry.key, 'hex').slice(0, 40)}]`
529 }
530 } catch {
531 keyStr = `[hex: ${b4a.toString(entry.key, 'hex').slice(0, 40)}]`
532 }
533 const valLen = entry.value ? entry.value.length : 0
534 console.log(` seq=${entry.seq} ${keyStr} (val: ${valLen}B)`)
535 }
536 }
537
538 await core.close()
539 await store.close()
540}
541
542if (command === 'du') {
543 const dir = args[1] || homedir()
544 const depthIdx = args.indexOf('--depth')
545 const dirDepth = depthIdx >= 0 ? parseInt(args[depthIdx + 1]) : 2
546 const minIdx = args.indexOf('--min')
547 const minSize = minIdx >= 0 ? parseSize(args[minIdx + 1]) : 1024 * 1024
548
549 console.log(`\n=== Hyperdrive Disk Usage: ${dir} ===\n`)
550
551 const stores = findCorestores(dir)
552
553 for (const store of stores) {
554 const dbPath = join(store.path, 'db')
555 if (!existsSync(dbPath)) {
556 // Try nested corestore/db
557 const nested = join(store.path, 'corestore', 'db')
558 if (!existsSync(nested)) continue
559 }
560
561 const actualDbPath = existsSync(join(store.path, 'db'))
562 ? join(store.path, 'db')
563 : join(store.path, 'corestore', 'db')
564
565 const diskSize = getDirSize(store.path)
566 const locked = isLocked(actualDbPath)
567 const lockInfo = locked ? getLockHolder(actualDbPath) : null
568
569 console.log(`--- ${store.path} (${formatBytes(diskSize)} on disk)${locked ? ` [LOCKED by ${lockInfo?.command}]` : ''} ---\n`)
570
571 try {
572 const result = await corestoreDU(actualDbPath, { readOnly: true, dirDepth })
573 console.log(formatDU(result, { dirDepth, minSize }))
574 } catch (err) {
575 if (err.message.includes('Column families not opened')) {
576 console.log(' (not a corestore RocksDB — legacy or different format)')
577 } else {
578 console.log(` Error: ${err.message.slice(0, 100)}`)
579 }
580 }
581
582 console.log('')
583 }
584}
585
586if (command === 'audit') {
587 const dir = args[1] || homedir()
588 console.log(`\n=== Hypercore Storage Audit: ${dir} ===\n`)
589
590 const stores = findCorestores(dir)
591 let totalSize = 0
592 const categories = { active: [], stale: [], junk: [], unknown: [] }
593
594 for (const store of stores) {
595 totalSize += store.size
596 const modified = getLastModified(store.path)
597 const now = new Date()
598 const ageMs = modified ? now - modified : Infinity
599 const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24))
600
601 const dbPath = join(store.path, 'db')
602 const parentDb = existsSync(dbPath) ? dbPath : join(store.path, 'corestore', 'db')
603 const locked = existsSync(parentDb) ? isLocked(parentDb) : false
604 const holder = locked ? getLockHolder(parentDb) : null
605
606 const entry = {
607 ...store,
608 modified,
609 ageDays,
610 locked,
611 holder,
612 sizeFormatted: formatBytes(store.size)
613 }
614
615 if (locked) {
616 categories.active.push(entry)
617 } else if (ageDays > 180) {
618 categories.stale.push(entry)
619 } else if (store.path.includes('backup') || store.path.includes('broken') || store.path.includes('test') || store.path.includes('Videos')) {
620 categories.junk.push(entry)
621 } else {
622 categories.unknown.push(entry)
623 }
624 }
625
626 const printEntry = (e) => {
627 const lockStr = e.locked ? ` [LOCKED by ${e.holder?.command} PID ${e.holder?.pid}]` : ''
628 const ageStr = e.ageDays < 365 ? `${e.ageDays}d ago` : `${Math.floor(e.ageDays / 365)}y ago`
629 console.log(` ${e.sizeFormatted.padStart(10)} ${ageStr.padStart(8)} ${e.path}${lockStr}`)
630 }
631
632 if (categories.active.length > 0) {
633 console.log('ACTIVE (locked by running processes):')
634 categories.active.forEach(printEntry)
635 console.log()
636 }
637
638 if (categories.unknown.length > 0) {
639 console.log('NEEDS REVIEW (unlocked, relatively recent):')
640 categories.unknown.forEach(printEntry)
641 console.log()
642 }
643
644 if (categories.stale.length > 0) {
645 console.log('STALE (>6 months old, unlocked):')
646 categories.stale.forEach(printEntry)
647 console.log()
648 }
649
650 if (categories.junk.length > 0) {
651 console.log('LIKELY JUNK (backups, test data, broken):')
652 categories.junk.forEach(printEntry)
653 console.log()
654 }
655
656 console.log(`Total: ${formatBytes(totalSize)} across ${stores.length} locations`)
657 const staleSize = categories.stale.reduce((s, e) => s + e.size, 0)
658 const junkSize = categories.junk.reduce((s, e) => s + e.size, 0)
659 console.log(`Potentially reclaimable: ${formatBytes(staleSize + junkSize)} (stale + junk)`)
660}
661
662const KEY_TYPES_LABEL = {
663 0x00: 'seed',
664 0x01: 'core-key',
665 0x02: 'dk',
666 0x03: 'info',
667 0x04: 'data'
668}
index.js +2 -0
……@@ -0,0 +1,2 @@
1export { openDB, listApps, getCorestoreStats, scanColumnFamily, formatBytes } from './lib/rocksdb-inspector.js'
2export { findCorestores, getDirSize, getLastModified, isLocked, getLockHolder, hasRocksDB } from './lib/scanner.js'
lib/block-reader.js +295 -0
……@@ -0,0 +1,295 @@
1// Deep block reader - parse Hyperbee nodes from raw Hypercore blocks
2// and decode Hyperdrive file entries with full blob mapping
3import b4a from 'b4a'
4
5// Protobuf varint decoder
6function pbVarint (buf, offset) {
7 let result = 0
8 let shift = 0
9 let pos = offset
10 while (pos < buf.length) {
11 const byte = buf[pos]
12 result |= (byte & 0x7f) << shift
13 pos++
14 if ((byte & 0x80) === 0) break
15 shift += 7
16 }
17 return { value: result, end: pos }
18}
19
20// Protobuf bytes decoder (length-delimited)
21function pbBytes (buf, offset) {
22 const { value: len, end: lenEnd } = pbVarint(buf, offset)
23 return { value: buf.subarray(lenEnd, lenEnd + len), end: lenEnd + len }
24}
25
26// Decode a Hyperbee Node protobuf { index, key, value }
27export function decodeNode (buf) {
28 let offset = 0
29 const node = { index: null, key: null, value: null }
30
31 while (offset < buf.length) {
32 const { value: prefix, end: tagEnd } = pbVarint(buf, offset)
33 offset = tagEnd
34 const tag = prefix >> 3
35 const wireType = prefix & 7
36
37 if (tag === 1 && wireType === 2) {
38 const { value, end } = pbBytes(buf, offset)
39 node.index = decodeYoloIndex(value)
40 offset = end
41 } else if (tag === 2 && wireType === 2) {
42 const { value, end } = pbBytes(buf, offset)
43 node.key = value
44 offset = end
45 } else if (tag === 3 && wireType === 2) {
46 const { value, end } = pbBytes(buf, offset)
47 node.value = value
48 offset = end
49 } else {
50 // Skip unknown fields
51 if (wireType === 0) { pbVarint(buf, offset); offset = pbVarint(buf, offset).end }
52 else if (wireType === 2) { const { end } = pbBytes(buf, offset); offset = end }
53 else break
54 }
55 }
56
57 return node
58}
59
60// Decode YoloIndex { levels: [{ keys: [seq], children: [seq] }] }
61function decodeYoloIndex (buf) {
62 const levels = []
63 let offset = 0
64
65 while (offset < buf.length) {
66 const { value: prefix, end: tagEnd } = pbVarint(buf, offset)
67 offset = tagEnd
68 const tag = prefix >> 3
69
70 if (tag === 1) {
71 const { value: levelBuf, end } = pbBytes(buf, offset)
72 offset = end
73 levels.push(decodeLevel(levelBuf))
74 } else {
75 break
76 }
77 }
78
79 return { levels }
80}
81
82function decodeLevel (buf) {
83 const keys = []
84 const children = []
85 let offset = 0
86
87 while (offset < buf.length) {
88 const { value: prefix, end: tagEnd } = pbVarint(buf, offset)
89 offset = tagEnd
90 const tag = prefix >> 3
91
92 if (tag === 1) {
93 // packed varints for keys
94 const { value: packedLen, end: lenEnd } = pbVarint(buf, offset)
95 offset = lenEnd
96 const packedEnd = offset + packedLen
97 while (offset < packedEnd) {
98 const { value, end } = pbVarint(buf, offset)
99 keys.push(value)
100 offset = end
101 }
102 } else if (tag === 2) {
103 // packed varints for children
104 const { value: packedLen, end: lenEnd } = pbVarint(buf, offset)
105 offset = lenEnd
106 const packedEnd = offset + packedLen
107 while (offset < packedEnd) {
108 const { value, end } = pbVarint(buf, offset)
109 children.push(value)
110 offset = end
111 }
112 } else {
113 break
114 }
115 }
116
117 return { keys, children }
118}
119
120// Decode Hyperbee Header protobuf { protocol: string, metadata?: { contentFeed? } }
121export function decodeHeader (buf) {
122 let offset = 0
123 const header = { protocol: '', contentFeed: null }
124
125 while (offset < buf.length) {
126 const { value: prefix, end: tagEnd } = pbVarint(buf, offset)
127 offset = tagEnd
128 const tag = prefix >> 3
129
130 if (tag === 1) {
131 // protocol string
132 const { value, end } = pbBytes(buf, offset)
133 header.protocol = b4a.toString(value, 'utf8')
134 offset = end
135 } else if (tag === 2) {
136 // metadata submessage
137 const { value: metaBuf, end } = pbBytes(buf, offset)
138 offset = end
139 // Parse metadata: field 1 = contentFeed (bytes)
140 let mOff = 0
141 while (mOff < metaBuf.length) {
142 const { value: mPrefix, end: mTagEnd } = pbVarint(metaBuf, mOff)
143 mOff = mTagEnd
144 const mTag = mPrefix >> 3
145 if (mTag === 1) {
146 const { value, end } = pbBytes(metaBuf, mOff)
147 header.contentFeed = value
148 mOff = end
149 } else {
150 break
151 }
152 }
153 } else {
154 break
155 }
156 }
157
158 return header
159}
160
161// Decode a Hyperdrive file entry value
162// Supports both JSON (compat/legacy) and compact-encoding formats
163export function decodeDriveEntry (buf) {
164 if (!buf || buf.length === 0) return null
165
166 // JSON format starts with { (0x7b)
167 if (buf[0] === 0x7b) {
168 try {
169 const obj = JSON.parse(b4a.toString(buf, 'utf8'))
170 return {
171 executable: obj.executable || false,
172 linkname: obj.linkname || null,
173 blob: obj.blob || null,
174 metadata: obj.metadata || null
175 }
176 } catch {
177 return null
178 }
179 }
180
181 // Compact-encoding format
182 let pos = 0
183 const flags = buf[pos++]
184
185 const entry = {
186 executable: !!(flags & 1),
187 linkname: null,
188 blob: null,
189 metadata: null
190 }
191
192 if (flags & 2) {
193 const { value: len, end: lenEnd } = readCEVarint(buf, pos)
194 pos = lenEnd
195 entry.linkname = b4a.toString(buf.subarray(pos, pos + len), 'utf8')
196 pos += len
197 }
198
199 if (flags & 4) {
200 const { value: blockOffset, end: e1 } = readCEVarint(buf, pos)
201 pos = e1
202 const { value: blockLength, end: e2 } = readCEVarint(buf, pos)
203 pos = e2
204 const { value: byteOffset, end: e3 } = readCEVarint(buf, pos)
205 pos = e3
206 const { value: byteLength, end: e4 } = readCEVarint(buf, pos)
207 pos = e4
208 entry.blob = { blockOffset, blockLength, byteOffset, byteLength }
209 }
210
211 if (flags & 8) {
212 const { value: len, end: lenEnd } = readCEVarint(buf, pos)
213 pos = lenEnd
214 entry.metadata = buf.subarray(pos, pos + len)
215 pos += len
216 }
217
218 return entry
219}
220
221// Compact-encoding varint (unsigned)
222function readCEVarint (buf, offset) {
223 let result = 0
224 let shift = 0
225 let pos = offset
226 while (pos < buf.length) {
227 const byte = buf[pos]
228 result |= (byte & 0x7f) << shift
229 pos++
230 if ((byte & 0x80) === 0) break
231 shift += 7
232 if (shift > 49) break // safety: max 7 bytes
233 }
234 return { value: result, end: pos }
235}
236
237// Strip SubEncoder prefix from a Hyperbee key
238// SubEncoder 'files' adds: [prefix_byte, 0x00] at start and [0x00] at end
239export function stripSubEncoder (key) {
240 if (!key || key.length < 3) return key
241 // SubEncoder format: prefix + SEP(0x00) + actual_key + SEP(0x00)
242 // The prefix is the sub-encoder name encoded
243 // For 'files': it's the string 'files' length-prefixed, then 0x00 separator
244 // Let's find the first 0x00 after position 0 and strip up to there + the trailing 0x00
245 const firstSep = key.indexOf(0x00)
246 if (firstSep < 0) return key
247
248 const lastByte = key[key.length - 1]
249 const end = lastByte === 0x00 ? key.length - 1 : key.length
250
251 return key.subarray(firstSep + 1, end)
252}
253
254// Walk all Hyperbee blocks in a core and extract key-value entries
255export async function walkHyperbeeBlocks (core, opts = {}) {
256 const { maxBlocks = Infinity, waitForBlocks = false } = opts
257 const entries = []
258 let headerBlock = null
259
260 const limit = Math.min(core.length, maxBlocks)
261
262 for (let i = 0; i < limit; i++) {
263 try {
264 const block = await core.get(i, { wait: waitForBlocks })
265 if (!block) continue
266
267 if (i === 0) {
268 // Block 0 is the Hyperbee header
269 try {
270 headerBlock = decodeHeader(block)
271 } catch {}
272 continue
273 }
274
275 // All other blocks are Node protobuf messages
276 try {
277 const node = decodeNode(block)
278 if (node.key && node.key.length > 0) {
279 entries.push({
280 seq: i,
281 key: node.key,
282 value: node.value,
283 childCount: node.index?.levels?.[0]?.children?.length || 0,
284 keyCount: node.index?.levels?.[0]?.keys?.length || 0
285 })
286 }
287 } catch {}
288 } catch {
289 // Block not available locally
290 continue
291 }
292 }
293
294 return { header: headerBlock, entries }
295}
lib/core-enumerator.js +251 -0
……@@ -0,0 +1,251 @@
1import RocksDB from 'rocksdb-native'
2import b4a from 'b4a'
3
4// Mirrors hypercore-storage key encoding
5// TL_CORE_BY_DKEY = 1, keys are: varint(1) + fixed32(discoveryKey)
6// Values are @corestore/core: { version, corePointer, dataPointer, alias? }
7
8const CORESTORE_CF = 'corestore'
9
10export async function enumerateCores (dbPath, opts = {}) {
11 const { readOnly = false } = opts
12
13 const db = new RocksDB(dbPath, {
14 readOnly,
15 columnFamilies: [CORESTORE_CF]
16 })
17 await db.ready()
18
19 const cs = db.columnFamily(CORESTORE_CF)
20 const cores = []
21
22 // Key prefix 0x01 = TL_CORE_BY_DKEY (varint-encoded 1)
23 // Each entry maps a discovery key to a @corestore/core record
24 const start = Buffer.from([0x01])
25 const end = Buffer.from([0x02])
26
27 const iter = cs.iterator({ gte: start, lt: end, limit: 10000 })
28
29 await new Promise((resolve, reject) => {
30 iter.on('data', ({ key, value }) => {
31 if (!value || key[0] !== 0x01) return
32
33 // Discovery key is the 32 bytes after the varint prefix
34 const discoveryKey = b4a.toString(key.subarray(1, 33), 'hex')
35
36 // Decode @corestore/core value using compact-encoding
37 try {
38 const core = decodeCoreRecord(value)
39 cores.push({
40 discoveryKey,
41 ...core
42 })
43 } catch (err) {
44 cores.push({
45 discoveryKey,
46 corePointer: -1,
47 dataPointer: -1,
48 alias: null,
49 error: err.message
50 })
51 }
52 })
53 iter.on('end', resolve)
54 iter.on('error', reject)
55 })
56
57 // Read auth records to get public keys and head lengths
58 // Auth key format: varint(3) + varint(corePointer) + varint(0)
59 // Auth value: fixed32(key) + fixed32(discoveryKey) + varint(flags) + ...
60 // Head key format: varint(4) + varint(dataPointer) + varint(0)
61 // Head value: { fork, length, rootHash, signature }
62 for (const core of cores) {
63 // Build auth key
64 const authKey = encodeKey(3, core.corePointer, 0)
65 try {
66 const authIter = cs.iterator({ gte: authKey, lt: incrementKey(authKey), limit: 1 })
67 await new Promise((resolve, reject) => {
68 authIter.on('data', ({ value }) => {
69 if (value && value.length >= 64) {
70 core.publicKey = b4a.toString(value.subarray(0, 32), 'hex')
71 }
72 })
73 authIter.on('end', resolve)
74 authIter.on('error', reject)
75 })
76 } catch {}
77
78 // Build head key to get core length
79 const headKey = encodeKey(4, core.dataPointer, 0)
80 try {
81 const headIter = cs.iterator({ gte: headKey, lt: incrementKey(headKey), limit: 1 })
82 await new Promise((resolve, reject) => {
83 headIter.on('data', ({ value }) => {
84 if (value) {
85 const head = decodeHeadRecord(value)
86 core.length = head.length
87 core.fork = head.fork
88 }
89 })
90 headIter.on('end', resolve)
91 headIter.on('error', reject)
92 })
93 } catch {}
94 }
95
96 // Also try to read the corestore head for allocation counts
97 let head = null
98 try {
99 const headKey = Buffer.from([0x00])
100 const headIter = cs.iterator({ gte: headKey, lt: Buffer.from([0x01]), limit: 1 })
101 await new Promise((resolve, reject) => {
102 headIter.on('data', ({ value }) => {
103 if (value) head = decodeHead(value)
104 })
105 headIter.on('end', resolve)
106 headIter.on('error', reject)
107 })
108 } catch {}
109
110 if (head) {
111 cores._head = head
112 }
113
114 await db.close()
115
116 // Sort by corePointer
117 cores.sort((a, b) => a.corePointer - b.corePointer)
118
119 return cores
120}
121
122// Encode a RocksDB key from varint parts
123function encodeKey (...parts) {
124 const bufs = parts.map(encodeVarint)
125 return Buffer.concat(bufs)
126}
127
128function encodeVarint (n) {
129 const bytes = []
130 while (n >= 0x80) {
131 bytes.push((n & 0x7f) | 0x80)
132 n >>>= 7
133 }
134 bytes.push(n & 0x7f)
135 return Buffer.from(bytes)
136}
137
138function incrementKey (key) {
139 const buf = Buffer.from(key)
140 for (let i = buf.length - 1; i >= 0; i--) {
141 if (buf[i] < 0xff) {
142 buf[i]++
143 return buf
144 }
145 buf[i] = 0
146 }
147 return Buffer.concat([Buffer.from([0x01]), buf])
148}
149
150// Decode @core/head { fork, length, rootHash, signature }
151function decodeHeadRecord (buf) {
152 let pos = 0
153 const { value: fork, bytesRead: fb } = readVarint(buf, pos)
154 pos += fb
155 const { value: length, bytesRead: lb } = readVarint(buf, pos)
156 pos += lb
157 return { fork, length }
158}
159
160// Minimal varint decoder
161function readVarint (buf, offset) {
162 let result = 0
163 let shift = 0
164 let pos = offset
165 while (pos < buf.length) {
166 const byte = buf[pos]
167 result |= (byte & 0x7f) << shift
168 pos++
169 if ((byte & 0x80) === 0) break
170 shift += 7
171 }
172 return { value: result, bytesRead: pos - offset }
173}
174
175function readFixed32 (buf, offset) {
176 return {
177 value: b4a.toString(buf.subarray(offset, offset + 32), 'hex'),
178 bytesRead: 32
179 }
180}
181
182function readString (buf, offset) {
183 const { value: len, bytesRead: lenBytes } = readVarint(buf, offset)
184 const str = b4a.toString(buf.subarray(offset + lenBytes, offset + lenBytes + len), 'utf8')
185 return { value: str, bytesRead: lenBytes + len }
186}
187
188// Decode @corestore/core { version, corePointer, dataPointer, alias? }
189function decodeCoreRecord (buf) {
190 let pos = 0
191
192 const { value: version, bytesRead: vb } = readVarint(buf, pos)
193 pos += vb
194
195 const { value: corePointer, bytesRead: cpb } = readVarint(buf, pos)
196 pos += cpb
197
198 const { value: dataPointer, bytesRead: dpb } = readVarint(buf, pos)
199 pos += dpb
200
201 const { value: flags, bytesRead: fb } = readVarint(buf, pos)
202 pos += fb
203
204 let alias = null
205 if (flags & 1) {
206 // @corestore/alias { name, namespace }
207 const { value: name, bytesRead: nb } = readString(buf, pos)
208 pos += nb
209 const { value: namespace, bytesRead: nsb } = readFixed32(buf, pos)
210 pos += nsb
211 alias = { name, namespace }
212 }
213
214 return { version, corePointer, dataPointer, alias }
215}
216
217// Decode @corestore/head { version, flags, allocated?, seed?, defaultDiscoveryKey? }
218function decodeHead (buf) {
219 let pos = 0
220
221 const { value: version, bytesRead: vb } = readVarint(buf, pos)
222 pos += vb
223
224 const { value: flags, bytesRead: fb } = readVarint(buf, pos)
225 pos += fb
226
227 let allocated = null
228 if (flags & 1) {
229 const { value: cores, bytesRead: cb } = readVarint(buf, pos)
230 pos += cb
231 const { value: datas, bytesRead: db } = readVarint(buf, pos)
232 pos += db
233 allocated = { cores, datas }
234 }
235
236 let seed = null
237 if (flags & 2) {
238 const { value, bytesRead } = readFixed32(buf, pos)
239 pos += bytesRead
240 seed = value
241 }
242
243 let defaultDiscoveryKey = null
244 if (flags & 4) {
245 const { value, bytesRead } = readFixed32(buf, pos)
246 pos += bytesRead
247 defaultDiscoveryKey = value
248 }
249
250 return { version, allocated, seed, defaultDiscoveryKey }
251}
lib/deep-analyzer.js +196 -0
……@@ -0,0 +1,196 @@
1// Deep analysis of a corestore - understand WHY it's big
2// Maps cores → apps → files → blobs → disk bytes
3import RocksDB from 'rocksdb-native'
4import b4a from 'b4a'
5
6const CORESTORE_CF = 'corestore'
7
8// Analyze disk usage per core by scanning RocksDB data blocks
9// Key format: varint(4) + varint(dataPointer) + varint(DATA_BLOCK=3) + varint(blockIndex)
10// This is where the actual data bytes live
11export async function analyzeCoreDiskUsage (dbPath, opts = {}) {
12 const { readOnly = false, sampleSize = 500000 } = opts
13
14 const db = new RocksDB(dbPath, {
15 readOnly,
16 columnFamilies: [CORESTORE_CF]
17 })
18 await db.ready()
19
20 const cs = db.columnFamily(CORESTORE_CF)
21
22 // Scan data blocks (key prefix 0x04 = varint-encoded TL_DATA=4)
23 // Within TL_DATA, the next varint is the dataPointer, then the type:
24 // 0 = head, 1 = dependency, 2 = hints, 3 = block, 4 = tree, 5 = bitfield, 6 = userData
25 const dataPtrStats = new Map()
26 let totalScanned = 0
27 let totalBytes = 0
28
29 const iter = cs.iterator({ gte: Buffer.from([0x04]), lt: Buffer.from([0x05]), limit: sampleSize })
30
31 await new Promise((resolve, reject) => {
32 iter.on('data', ({ key, value }) => {
33 totalScanned++
34 const valLen = value ? value.length : 0
35 totalBytes += valLen
36
37 // Decode dataPointer from key: skip first byte (0x04), then read varint
38 let pos = 1
39 let dataPtr = 0
40 let shift = 0
41 while (pos < key.length) {
42 const byte = key[pos]
43 dataPtr |= (byte & 0x7f) << shift
44 pos++
45 if ((byte & 0x80) === 0) break
46 shift += 7
47 }
48
49 // Decode type
50 let type = 0
51 shift = 0
52 while (pos < key.length) {
53 const byte = key[pos]
54 type |= (byte & 0x7f) << shift
55 pos++
56 if ((byte & 0x80) === 0) break
57 shift += 7
58 }
59
60 const stats = dataPtrStats.get(dataPtr) || {
61 dataPointer: dataPtr,
62 blocks: 0,
63 blockBytes: 0,
64 trees: 0,
65 treeBytes: 0,
66 bitfields: 0,
67 bitfieldBytes: 0,
68 userData: 0,
69 userDataBytes: 0,
70 heads: 0,
71 other: 0,
72 otherBytes: 0
73 }
74
75 switch (type) {
76 case 3: // DATA_BLOCK
77 stats.blocks++
78 stats.blockBytes += valLen
79 break
80 case 4: // DATA_TREE
81 stats.trees++
82 stats.treeBytes += valLen
83 break
84 case 5: // DATA_BITFIELD
85 stats.bitfields++
86 stats.bitfieldBytes += valLen
87 break
88 case 6: // DATA_USER_DATA
89 stats.userData++
90 stats.userDataBytes += valLen
91 break
92 case 0: // DATA_HEAD
93 stats.heads++
94 break
95 default:
96 stats.other++
97 stats.otherBytes += valLen
98 }
99
100 dataPtrStats.set(dataPtr, stats)
101 })
102 iter.on('end', resolve)
103 iter.on('error', reject)
104 })
105
106 // Also get core info to map dataPointers to cores
107 const coreMap = new Map() // dataPointer -> core info
108 const coreIter = cs.iterator({ gte: Buffer.from([0x01]), lt: Buffer.from([0x02]), limit: 10000 })
109
110 await new Promise((resolve, reject) => {
111 coreIter.on('data', ({ key, value }) => {
112 if (!value || key[0] !== 0x01) return
113 const discoveryKey = b4a.toString(key.subarray(1, 33), 'hex')
114
115 // Decode @corestore/core { version, corePointer, dataPointer, alias? }
116 try {
117 let pos = 0
118 const readV = (buf, off) => {
119 let r = 0, s = 0, p = off
120 while (p < buf.length) {
121 const b = buf[p]; r |= (b & 0x7f) << s; p++
122 if ((b & 0x80) === 0) break; s += 7
123 }
124 return { value: r, end: p }
125 }
126
127 const { value: version, end: e1 } = readV(value, pos)
128 const { value: corePointer, end: e2 } = readV(value, e1)
129 const { value: dataPointer, end: e3 } = readV(value, e2)
130 const { value: flags, end: e4 } = readV(value, e3)
131
132 let alias = null
133 if (flags & 1) {
134 const { value: nameLen, end: ne } = readV(value, e4)
135 const name = b4a.toString(value.subarray(ne, ne + nameLen), 'utf8')
136 alias = name
137 }
138
139 // Read auth for public key
140 let publicKey = null
141 const authKey = Buffer.from([0x03])
142 // Will be done separately
143
144 coreMap.set(dataPointer, { discoveryKey, corePointer, dataPointer, alias })
145 } catch {}
146 })
147 coreIter.on('end', resolve)
148 coreIter.on('error', reject)
149 })
150
151 await db.close()
152
153 // Combine: annotate dataPtrStats with core info
154 const results = []
155 for (const [ptr, stats] of dataPtrStats) {
156 const core = coreMap.get(ptr)
157 results.push({
158 ...stats,
159 corePointer: core?.corePointer ?? -1,
160 discoveryKey: core?.discoveryKey?.slice(0, 16) ?? 'unknown',
161 alias: core?.alias ?? null,
162 totalBytes: stats.blockBytes + stats.treeBytes + stats.bitfieldBytes + stats.userDataBytes + stats.otherBytes
163 })
164 }
165
166 results.sort((a, b) => b.totalBytes - a.totalBytes)
167
168 return {
169 totalScanned,
170 totalBytes,
171 sampleComplete: totalScanned < sampleSize,
172 coresAnalyzed: results.length,
173 topCores: results
174 }
175}
176
177export function formatAnalysis (analysis) {
178 const lines = []
179 lines.push(`Scanned ${analysis.totalScanned} RocksDB entries (${(analysis.totalBytes / 1024 / 1024).toFixed(1)} MB in sample)`)
180 lines.push(`${analysis.sampleComplete ? 'Complete scan' : 'Partial scan (hit limit)'}`)
181 lines.push(`${analysis.coresAnalyzed} data pointers found\n`)
182
183 lines.push('--- Disk usage by core (top 20) ---\n')
184
185 for (const c of analysis.topCores.slice(0, 20)) {
186 const totalMB = (c.totalBytes / 1024 / 1024).toFixed(2)
187 const blockMB = (c.blockBytes / 1024 / 1024).toFixed(2)
188 const treeMB = (c.treeBytes / 1024 / 1024).toFixed(2)
189 const alias = c.alias ? c.alias : c.corePointer >= 0 ? `core #${c.corePointer}` : `data #${c.dataPointer}`
190
191 lines.push(` ${totalMB.padStart(10)} MB ${alias} (dkey: ${c.discoveryKey}...)`)
192 lines.push(` blocks: ${c.blocks} (${blockMB} MB) tree: ${c.trees} (${treeMB} MB) bitfield: ${c.bitfields} userData: ${c.userData}`)
193 }
194
195 return lines.join('\n')
196}
lib/drive-inspector.js +182 -0
……@@ -0,0 +1,182 @@
1import Corestore from 'corestore'
2import Hyperdrive from 'hyperdrive'
3import b4a from 'b4a'
4import { enumerateCores } from './core-enumerator.js'
5import { join } from 'path'
6
7export async function openDrive (storagePath, opts = {}) {
8 const { key = null } = opts
9 const store = new Corestore(storagePath)
10 await store.ready()
11
12 const drive = key
13 ? new Hyperdrive(store, b4a.isBuffer(key) ? key : b4a.from(key, 'hex'))
14 : new Hyperdrive(store)
15
16 await drive.ready()
17 return { store, drive }
18}
19
20// Discover all Hyperdrives in a corestore by finding cores with Hyperbee headers
21export async function discoverDrives (storagePath, opts = {}) {
22 const dbPath = join(storagePath, 'db')
23 const cores = await enumerateCores(dbPath, opts)
24
25 const store = new Corestore(storagePath)
26 await store.ready()
27
28 const drives = []
29
30 for (const c of cores) {
31 if (!c.publicKey) continue
32
33 const keyBuf = b4a.from(c.publicKey, 'hex')
34 const core = store.get({ key: keyBuf })
35 await core.ready()
36
37 if (core.length > 0) {
38 try {
39 const block0 = await core.get(0, { wait: false })
40 if (block0) {
41 // Check for Hyperbee header signature: starts with protobuf field for "hyperbee"
42 const hexStart = b4a.toString(block0.subarray(0, 12), 'hex')
43 if (hexStart.startsWith('0a0868797065726265')) {
44 // Extract content key from header
45 let contentKey = null
46 if (block0.length > 12) {
47 try {
48 // The content key is at offset 12 (tag 0x12, length 0x22=34, then 0x0a 0x20 + 32 bytes key)
49 const contentKeyStart = block0.indexOf(Buffer.from([0x0a, 0x20]), 10)
50 if (contentKeyStart >= 0 && contentKeyStart + 34 <= block0.length) {
51 contentKey = b4a.toString(block0.subarray(contentKeyStart + 2, contentKeyStart + 34), 'hex')
52 }
53 } catch {}
54 }
55
56 // Scan some blocks for embedded file paths
57 const filePaths = []
58 const scanLimit = Math.min(core.length, 200)
59 for (let i = 0; i < scanLimit; i++) {
60 try {
61 const block = await core.get(i, { wait: false })
62 if (!block) continue
63 const str = b4a.toString(block, 'utf8')
64 const paths = str.match(/\/[a-zA-Z0-9._\-/]+\.[a-zA-Z0-9]+/g)
65 if (paths) {
66 for (const p of paths) {
67 if (!filePaths.includes(p) && filePaths.length < 100) filePaths.push(p)
68 }
69 }
70 } catch { break }
71 }
72
73 drives.push({
74 key: c.publicKey,
75 discoveryKey: c.discoveryKey,
76 corePointer: c.corePointer,
77 alias: c.alias,
78 version: core.length,
79 byteLength: core.byteLength,
80 writable: core.writable,
81 contentKey,
82 filePaths
83 })
84 }
85 }
86 } catch {}
87 }
88
89 await core.close()
90 }
91
92 await store.close()
93 return drives
94}
95
96export async function listDriveFiles (drive, folder = '/', opts = {}) {
97 const { recursive = true } = opts
98 const files = []
99
100 const stream = drive.list(folder, { recursive })
101
102 return new Promise((resolve, reject) => {
103 stream.on('data', (entry) => {
104 const blob = entry.value?.blob
105 files.push({
106 path: entry.key,
107 executable: entry.value?.executable || false,
108 linkname: entry.value?.linkname || null,
109 metadata: entry.value?.metadata || null,
110 blobOffset: blob?.blockOffset,
111 blobLength: blob?.blockLength,
112 byteOffset: blob?.byteOffset,
113 byteLength: blob?.byteLength
114 })
115 })
116 stream.on('end', () => resolve(files))
117 stream.on('error', reject)
118 })
119}
120
121export async function getDriveStats (drive) {
122 const files = await listDriveFiles(drive)
123
124 let totalBytes = 0
125 let blobBlocks = 0
126 const extensions = new Map()
127 const topDirs = new Map()
128
129 for (const f of files) {
130 const bytes = f.byteLength || 0
131 totalBytes += bytes
132 blobBlocks += f.blobLength || 0
133
134 // Count by extension
135 const ext = f.path.includes('.') ? f.path.split('.').pop() : '(none)'
136 const extInfo = extensions.get(ext) || { count: 0, bytes: 0 }
137 extInfo.count++
138 extInfo.bytes += bytes
139 extensions.set(ext, extInfo)
140
141 // Count by top-level directory
142 const parts = f.path.split('/')
143 const topDir = parts.length > 2 ? '/' + parts[1] : '/'
144 const dirInfo = topDirs.get(topDir) || { count: 0, bytes: 0 }
145 dirInfo.count++
146 dirInfo.bytes += bytes
147 topDirs.set(topDir, dirInfo)
148 }
149
150 return {
151 fileCount: files.length,
152 totalBytes,
153 blobBlocks,
154 driveKey: b4a.toString(drive.key, 'hex'),
155 driveVersion: drive.version,
156 writable: drive.writable,
157 extensions: [...extensions.entries()]
158 .map(([ext, info]) => ({ ext, ...info }))
159 .sort((a, b) => b.bytes - a.bytes),
160 topDirs: [...topDirs.entries()]
161 .map(([dir, info]) => ({ dir, ...info }))
162 .sort((a, b) => b.bytes - a.bytes),
163 files
164 }
165}
166
167export async function readDriveFile (drive, path) {
168 return drive.get(path)
169}
170
171export async function driveSummary (drive) {
172 const stats = await getDriveStats(drive)
173 return {
174 key: stats.driveKey,
175 version: stats.driveVersion,
176 writable: stats.writable,
177 files: stats.fileCount,
178 totalBytes: stats.totalBytes,
179 topExtensions: stats.extensions.slice(0, 10),
180 topDirs: stats.topDirs.slice(0, 10)
181 }
182}
lib/drive-ls.js +203 -0
……@@ -0,0 +1,203 @@
1// List all files in a Hyperdrive stored in RocksDB
2// Works read-only on locked databases — reads raw Hyperbee blocks
3import RocksDB from 'rocksdb-native'
4import b4a from 'b4a'
5import { decodeNode, decodeDriveEntry, stripSubEncoder, decodeHeader } from './block-reader.js'
6
7function encodeVarint (n) {
8 const bytes = []
9 while (n >= 0x80) { bytes.push((n & 0x7f) | 0x80); n >>>= 7 }
10 bytes.push(n & 0x7f)
11 return Buffer.from(bytes)
12}
13
14// Extract all Hyperdrive file entries from a specific dataPointer in a corestore RocksDB
15export async function listDriveFromDB (dbPath, dataPointer, opts = {}) {
16 const { readOnly = false, maxBlocks = Infinity } = opts
17
18 const db = new RocksDB(dbPath, { readOnly, columnFamilies: ['corestore'] })
19 await db.ready()
20
21 const cs = db.columnFamily('corestore')
22
23 // Key range for data blocks: varint(4) + varint(dataPointer) + varint(3=DATA_BLOCK)
24 const prefix = Buffer.concat([encodeVarint(4), encodeVarint(dataPointer), encodeVarint(3)])
25 const endPrefix = Buffer.concat([encodeVarint(4), encodeVarint(dataPointer), encodeVarint(4)])
26
27 const files = []
28 let header = null
29 let blocksRead = 0
30
31 const iter = cs.iterator({ gte: prefix, lt: endPrefix, limit: maxBlocks })
32
33 await new Promise((resolve, reject) => {
34 iter.on('data', ({ key, value }) => {
35 blocksRead++
36 if (!value) return
37
38 // Decode block index from key
39 let pos = prefix.length
40 let blockIdx = 0
41 let shift = 0
42 while (pos < key.length) {
43 const byte = key[pos]
44 blockIdx |= (byte & 0x7f) << shift
45 pos++
46 if ((byte & 0x80) === 0) break
47 shift += 7
48 }
49
50 if (blockIdx === 0) {
51 try { header = decodeHeader(value) } catch {}
52 return
53 }
54
55 try {
56 const node = decodeNode(value)
57 if (!node.key || node.key.length === 0) return
58
59 const rawKey = stripSubEncoder(node.key)
60 let filePath = ''
61 try { filePath = b4a.toString(rawKey, 'utf8') } catch { return }
62 if (!filePath.startsWith('/')) return
63
64 let entry = null
65 try { entry = decodeDriveEntry(node.value) } catch {}
66 if (!entry) return
67
68 files.push({
69 path: filePath,
70 blob: entry.blob,
71 executable: entry.executable,
72 linkname: entry.linkname,
73 metadata: entry.metadata,
74 bytes: entry.blob?.byteLength || 0,
75 seq: blockIdx
76 })
77 } catch {}
78 })
79 iter.on('end', resolve)
80 iter.on('error', reject)
81 })
82
83 await db.close()
84
85 return { header, files, blocksRead }
86}
87
88// Build a directory tree from flat file list
89export function buildTree (files) {
90 const root = { name: '/', children: new Map(), files: [], totalBytes: 0, totalFiles: 0 }
91
92 for (const f of files) {
93 const parts = f.path.split('/').filter(Boolean)
94 let node = root
95
96 // Walk/create directory nodes
97 for (let i = 0; i < parts.length - 1; i++) {
98 if (!node.children.has(parts[i])) {
99 node.children.set(parts[i], {
100 name: parts[i],
101 children: new Map(),
102 files: [],
103 totalBytes: 0,
104 totalFiles: 0
105 })
106 }
107 node = node.children.get(parts[i])
108 }
109
110 // Add file to its parent directory
111 const fileName = parts[parts.length - 1]
112 node.files.push({ name: fileName, ...f })
113 node.totalFiles++
114 node.totalBytes += f.bytes
115
116 // Propagate totals up
117 let parent = root
118 for (let i = 0; i < parts.length - 1; i++) {
119 parent.totalFiles++
120 parent.totalBytes += f.bytes
121 parent = parent.children.get(parts[i])
122 }
123 }
124
125 return root
126}
127
128// Format tree as a string (like `ls -lR` or `tree`)
129export function formatTree (root, opts = {}) {
130 const { maxDepth = 3, minBytes = 0, showFiles = true, indent = '' } = opts
131 const lines = []
132
133 function fmt (bytes) {
134 if (bytes >= 1024 * 1024 * 1024) return (bytes / 1024 / 1024 / 1024).toFixed(2) + ' GB'
135 if (bytes >= 1024 * 1024) return (bytes / 1024 / 1024).toFixed(2) + ' MB'
136 if (bytes >= 1024) return (bytes / 1024).toFixed(1) + ' KB'
137 return bytes + ' B'
138 }
139
140 function walk (node, depth, prefix) {
141 if (depth > maxDepth) return
142
143 // Sort children by totalBytes descending
144 const dirs = [...node.children.entries()].sort((a, b) => b[1].totalBytes - a[1].totalBytes)
145
146 for (const [name, child] of dirs) {
147 if (child.totalBytes < minBytes && minBytes > 0) continue
148 const sizeStr = fmt(child.totalBytes).padStart(10)
149 const countStr = `${child.totalFiles} files`.padStart(10)
150 lines.push(`${prefix}${sizeStr} ${countStr} ${name}/`)
151 walk(child, depth + 1, prefix + ' ')
152 }
153
154 // Show files at this level
155 if (showFiles && depth <= maxDepth) {
156 const sortedFiles = [...node.files].sort((a, b) => b.bytes - a.bytes)
157 for (const f of sortedFiles) {
158 if (f.bytes < minBytes && minBytes > 0) continue
159 const sizeStr = fmt(f.bytes).padStart(10)
160 const exec = f.executable ? ' *' : ''
161 const link = f.linkname ? ` -> ${f.linkname}` : ''
162 const blk = f.blob ? ` [blk ${f.blob.blockOffset}..${f.blob.blockOffset + f.blob.blockLength}]` : ''
163 lines.push(`${prefix}${sizeStr} ${f.name}${exec}${link}${blk}`)
164 }
165 }
166 }
167
168 const totalStr = fmt(root.totalBytes).padStart(10)
169 lines.push(`${totalStr} ${root.totalFiles} files /`)
170 walk(root, 1, ' ')
171
172 return lines.join('\n')
173}
174
175// Format as flat ls output (like `ls -lhRS`)
176export function formatFlat (files, opts = {}) {
177 const { sortBy = 'size', limit = Infinity, filter = null } = opts
178 const lines = []
179
180 let sorted = [...files]
181 if (sortBy === 'size') sorted.sort((a, b) => b.bytes - a.bytes)
182 else if (sortBy === 'path') sorted.sort((a, b) => a.path.localeCompare(b.path))
183
184 if (filter) {
185 sorted = sorted.filter(f => f.path.includes(filter))
186 }
187
188 function fmt (bytes) {
189 if (bytes >= 1024 * 1024 * 1024) return (bytes / 1024 / 1024 / 1024).toFixed(2) + ' GB'
190 if (bytes >= 1024 * 1024) return (bytes / 1024 / 1024).toFixed(2) + ' MB'
191 if (bytes >= 1024) return (bytes / 1024).toFixed(1) + ' KB'
192 return bytes + ' B'
193 }
194
195 for (const f of sorted.slice(0, limit)) {
196 const sizeStr = fmt(f.bytes).padStart(10)
197 const exec = f.executable ? ' *' : ''
198 const blk = f.blob ? ` [blk ${f.blob.blockOffset}..${f.blob.blockOffset + f.blob.blockLength}]` : ''
199 lines.push(`${sizeStr} ${f.path}${exec}${blk}`)
200 }
201
202 return lines.join('\n')
203}
lib/du.js +302 -0
……@@ -0,0 +1,302 @@
1// du — comprehensive disk usage analysis for all Hyperdrives in a corestore
2import RocksDB from 'rocksdb-native'
3import b4a from 'b4a'
4import { decodeNode, decodeDriveEntry, stripSubEncoder, decodeHeader } from './block-reader.js'
5
6function encodeVarint (n) {
7 const bytes = []
8 while (n >= 0x80) { bytes.push((n & 0x7f) | 0x80); n >>>= 7 }
9 bytes.push(n & 0x7f)
10 return Buffer.from(bytes)
11}
12
13function fmt (bytes) {
14 if (bytes >= 1024 * 1024 * 1024) return (bytes / 1024 / 1024 / 1024).toFixed(2) + ' GB'
15 if (bytes >= 1024 * 1024) return (bytes / 1024 / 1024).toFixed(2) + ' MB'
16 if (bytes >= 1024) return (bytes / 1024).toFixed(1) + ' KB'
17 return bytes + ' B'
18}
19
20// Full disk usage report for a single corestore RocksDB
21export async function corestoreDU (dbPath, opts = {}) {
22 const { readOnly = true, maxBlocksPerDrive = 50000, dirDepth = 2 } = opts
23
24 const db = new RocksDB(dbPath, { readOnly, columnFamilies: ['corestore'] })
25 await db.ready()
26 const cs = db.columnFamily('corestore')
27
28 // Step 1: Enumerate all cores (key prefix 0x01 = TL_CORE_BY_DKEY)
29 const cores = []
30 const coreIter = cs.iterator({ gte: Buffer.from([0x01]), lt: Buffer.from([0x02]), limit: 10000 })
31 await drain(coreIter, ({ key, value }) => {
32 if (!value || key[0] !== 0x01) return
33 const discoveryKey = b4a.toString(key.subarray(1, 33), 'hex')
34 try {
35 let pos = 0
36 const r = (buf, off) => { let r = 0, s = 0, p = off; while (p < buf.length) { const b = buf[p]; r |= (b & 0x7f) << s; p++; if ((b & 0x80) === 0) break; s += 7 } return { v: r, e: p } }
37 const { v: version, e: e1 } = r(value, pos)
38 const { v: corePointer, e: e2 } = r(value, e1)
39 const { v: dataPointer, e: e3 } = r(value, e2)
40 const { v: flags, e: e4 } = r(value, e3)
41 let alias = null
42 if (flags & 1) {
43 const { v: nameLen, e: ne } = r(value, e4)
44 alias = b4a.toString(value.subarray(ne, ne + nameLen), 'utf8')
45 }
46
47 // Read auth for public key
48 const authKey = Buffer.concat([encodeVarint(3), encodeVarint(corePointer), encodeVarint(0)])
49 cores.push({ discoveryKey, corePointer, dataPointer, alias })
50 } catch {}
51 })
52
53 // Step 2: For each core, check if block 0 is a Hyperbee header
54 const drives = []
55 const nonDriveCores = []
56
57 for (const core of cores) {
58 const blockKey = Buffer.concat([encodeVarint(4), encodeVarint(core.dataPointer), encodeVarint(3), encodeVarint(0)])
59 const blockEnd = Buffer.concat([encodeVarint(4), encodeVarint(core.dataPointer), encodeVarint(3), encodeVarint(1)])
60
61 let block0 = null
62 const b0Iter = cs.iterator({ gte: blockKey, lt: blockEnd, limit: 1 })
63 await drain(b0Iter, ({ value }) => { block0 = value })
64
65 if (!block0) {
66 nonDriveCores.push({ ...core, type: 'empty' })
67 continue
68 }
69
70 const hex = b4a.toString(block0.subarray(0, Math.min(12, block0.length)), 'hex')
71 const isHyperbee = hex.startsWith('0a08687970657262')
72
73 if (!isHyperbee) {
74 nonDriveCores.push({ ...core, type: 'data' })
75 continue
76 }
77
78 // Parse header for contentFeed
79 let header = null
80 try { header = decodeHeader(block0) } catch {}
81
82 const contentKey = header?.contentFeed ? b4a.toString(header.contentFeed, 'hex') : null
83
84 drives.push({ ...core, header, contentKey, type: 'hyperbee' })
85 }
86
87 // Step 3: For each Hyperbee, read all blocks and decode file entries
88 const driveReports = []
89
90 for (const drive of drives) {
91 const prefix = Buffer.concat([encodeVarint(4), encodeVarint(drive.dataPointer), encodeVarint(3)])
92 const endPrefix = Buffer.concat([encodeVarint(4), encodeVarint(drive.dataPointer), encodeVarint(4)])
93
94 const files = []
95 let blocksRead = 0
96
97 const iter = cs.iterator({ gte: prefix, lt: endPrefix, limit: maxBlocksPerDrive })
98 await drain(iter, ({ key, value }) => {
99 blocksRead++
100 if (!value) return
101
102 // Skip block 0 (header)
103 let pos = prefix.length
104 let blockIdx = 0
105 let shift = 0
106 while (pos < key.length) {
107 const byte = key[pos]; blockIdx |= (byte & 0x7f) << shift; pos++
108 if ((byte & 0x80) === 0) break; shift += 7
109 }
110 if (blockIdx === 0) return
111
112 try {
113 const node = decodeNode(value)
114 if (!node.key || node.key.length === 0) return
115
116 const rawKey = stripSubEncoder(node.key)
117 let filePath = ''
118 try { filePath = b4a.toString(rawKey, 'utf8') } catch { return }
119 if (!filePath.startsWith('/')) return
120
121 let entry = null
122 try { entry = decodeDriveEntry(node.value) } catch {}
123 if (!entry) return
124
125 files.push({
126 path: filePath,
127 bytes: entry.blob?.byteLength || 0,
128 blockOffset: entry.blob?.blockOffset,
129 blockLength: entry.blob?.blockLength,
130 executable: entry.executable
131 })
132 } catch {}
133 })
134
135 // Build directory breakdown
136 const dirs = buildDirSummary(files, dirDepth)
137 const totalBytes = files.reduce((s, f) => s + f.bytes, 0)
138
139 // Fingerprint the app by unique files
140 const appName = identifyApp(files)
141
142 driveReports.push({
143 dataPointer: drive.dataPointer,
144 corePointer: drive.corePointer,
145 alias: drive.alias,
146 discoveryKey: drive.discoveryKey,
147 contentKey: drive.contentKey,
148 blocksRead,
149 fileCount: files.length,
150 totalBytes,
151 appName,
152 dirs,
153 files
154 })
155 }
156
157 // Step 4: Compute RocksDB disk usage per data pointer (sample)
158 const diskUsage = new Map()
159 const diskIter = cs.iterator({ gte: Buffer.from([0x04]), lt: Buffer.from([0x05]), limit: 1000000 })
160 await drain(diskIter, ({ key, value }) => {
161 let pos = 1
162 let dataPtr = 0
163 let shift = 0
164 while (pos < key.length) {
165 const byte = key[pos]; dataPtr |= (byte & 0x7f) << shift; pos++
166 if ((byte & 0x80) === 0) break; shift += 7
167 }
168 const cur = diskUsage.get(dataPtr) || 0
169 diskUsage.set(dataPtr, cur + (value ? value.length : 0))
170 })
171
172 await db.close()
173
174 // Map disk usage to drives
175 const driveDataPtrs = new Set(driveReports.map(d => d.dataPointer))
176 let orphanedBytes = 0
177 let totalDiskBytes = 0
178 for (const [ptr, bytes] of diskUsage) {
179 totalDiskBytes += bytes
180 if (!driveDataPtrs.has(ptr)) {
181 // Check if this is a content core referenced by a drive
182 const isContent = driveReports.some(d => {
183 const contentCore = cores.find(c => c.discoveryKey === d.contentKey?.slice(0, 64))
184 return contentCore && contentCore.dataPointer === ptr
185 })
186 if (!isContent) {
187 // Check if it's a known non-drive core (odd-numbered = typically content for compat drives)
188 const isOddPair = driveReports.some(d => d.dataPointer === ptr - 1 || d.dataPointer === ptr + 1)
189 if (!isOddPair) {
190 orphanedBytes += bytes
191 }
192 }
193 }
194 }
195
196 return {
197 driveReports: driveReports.sort((a, b) => b.totalBytes - a.totalBytes),
198 nonDriveCores,
199 totalDiskSampled: totalDiskBytes,
200 orphanedBytes,
201 coreCount: cores.length,
202 driveCount: driveReports.length
203 }
204}
205
206function buildDirSummary (files, maxDepth) {
207 const dirs = new Map()
208
209 for (const f of files) {
210 const parts = f.path.split('/').filter(Boolean)
211
212 for (let depth = 1; depth <= Math.min(parts.length, maxDepth); depth++) {
213 const dirPath = '/' + parts.slice(0, depth).join('/')
214 const info = dirs.get(dirPath) || { path: dirPath, bytes: 0, count: 0, depth }
215 info.bytes += f.bytes
216 info.count++
217 dirs.set(dirPath, info)
218 }
219
220 // Root
221 const rootInfo = dirs.get('/') || { path: '/', bytes: 0, count: 0, depth: 0 }
222 rootInfo.bytes += f.bytes
223 rootInfo.count++
224 dirs.set('/', rootInfo)
225 }
226
227 return [...dirs.values()].sort((a, b) => b.bytes - a.bytes)
228}
229
230function identifyApp (files) {
231 // Heuristics based on unique files
232 for (const f of files) {
233 if (f.path === '/gateway.js') return 'hyperident-gateway'
234 if (f.path.includes('/hyper-wallet.bundle.js')) return 'hyper-wallet'
235 if (f.path === '/ARCHITECTURE.md' && files.some(g => g.path.includes('/by-arch/'))) return 'pear-runtime'
236 if (f.path.includes('/bare-ffmpeg/') || f.path.includes('/pear-electron/')) return 'keet'
237 if (f.path.includes('/socks5-server')) return 'hyperident-gateway'
238 if (f.path.includes('/vendor/pear-docs/')) return 'pear-git'
239 if (f.path === '/public/app.js') return 'wirecore'
240 if (f.path.includes('/keet-tui/') || f.path === '/keet-tui.js') return 'keet-tui'
241 if (f.path.includes('/keet-cli/') || f.path === '/keet-cli.js') return 'keet-cli'
242 if (f.path.includes('/anproto')) return 'anproto-terminal'
243 }
244
245 // Check top-level files for package.json identification
246 for (const f of files) {
247 if (f.path === '/package.json' && f.bytes > 0 && f.bytes < 10000) {
248 // We can't read the content from here, just note it
249 return '(unknown app)'
250 }
251 }
252
253 return files.length > 0 ? '(unknown)' : '(empty)'
254}
255
256export function formatDU (result, opts = {}) {
257 const { dirDepth = 2, minSize = 1024 * 1024 } = opts
258 const lines = []
259
260 lines.push(`${result.coreCount} cores, ${result.driveCount} Hyperdrives found`)
261 lines.push(`RocksDB sampled: ${fmt(result.totalDiskSampled)}`)
262 lines.push('')
263
264 for (const d of result.driveReports) {
265 const name = d.appName || d.alias || `core #${d.corePointer}`
266 lines.push(` ${fmt(d.totalBytes).padStart(10)} ${name} (dptr=${d.dataPointer}, ${d.fileCount} files)`)
267
268 // Show top directories
269 const topDirs = d.dirs
270 .filter(dir => dir.depth > 0 && dir.depth <= dirDepth && dir.bytes >= minSize)
271 .slice(0, 15)
272
273 for (const dir of topDirs) {
274 const indent = ' ' + ' '.repeat(dir.depth - 1)
275 lines.push(`${indent}${fmt(dir.bytes).padStart(10)} ${dir.count.toString().padStart(5)} files ${dir.path}`)
276 }
277
278 lines.push('')
279 }
280
281 if (result.nonDriveCores.length > 0) {
282 const dataCores = result.nonDriveCores.filter(c => c.type === 'data')
283 const emptyCores = result.nonDriveCores.filter(c => c.type === 'empty')
284 if (dataCores.length > 0) {
285 lines.push(` ${dataCores.length} content/blob cores (paired with Hyperdrives above)`)
286 }
287 if (emptyCores.length > 0) {
288 lines.push(` ${emptyCores.length} empty cores (no data blocks)`)
289 }
290 }
291
292 return lines.join('\n')
293}
294
295// Helper: drain a RocksDB iterator stream
296function drain (iter, onData) {
297 return new Promise((resolve, reject) => {
298 iter.on('data', onData)
299 iter.on('end', resolve)
300 iter.on('error', reject)
301 })
302}
lib/rocksdb-inspector.js +129 -0
……@@ -0,0 +1,129 @@
1import RocksDB from 'rocksdb-native'
2import b4a from 'b4a'
3
4const CORESTORE_CF = 'corestore'
5
6// Key type labels based on hypercore-storage schema
7const KEY_TYPES = {
8 0x00: 'seed',
9 0x01: 'core-key',
10 0x02: 'discovery-key',
11 0x03: 'core-info',
12 0x04: 'data-block'
13}
14
15export async function openDB (dbPath, opts = {}) {
16 const { readOnly = false } = opts
17 const db = new RocksDB(dbPath, {
18 readOnly,
19 columnFamilies: [CORESTORE_CF]
20 })
21 await db.ready()
22 return db
23}
24
25export async function scanColumnFamily (session, opts = {}) {
26 const { limit = 100000 } = opts
27
28 const keyTypes = new Map()
29 let totalKeys = 0
30 let totalBytes = 0
31 const readable = []
32
33 const iter = session.iterator({ limit })
34
35 return new Promise((resolve, reject) => {
36 iter.on('data', ({ key, value }) => {
37 totalKeys++
38 const valLen = value ? value.length : 0
39 totalBytes += valLen
40
41 const firstByte = key[0]
42 const info = keyTypes.get(firstByte) || { count: 0, bytes: 0 }
43 info.count++
44 info.bytes += valLen
45 keyTypes.set(firstByte, info)
46
47 // Collect readable strings
48 if (value && valLen > 2 && valLen < 2000) {
49 try {
50 const str = b4a.toString(value, 'utf8')
51 if (/^[\x20-\x7e\n\r\t]+$/.test(str) && readable.length < 100) {
52 readable.push({
53 key: b4a.toString(key, 'hex'),
54 type: firstByte,
55 value: str.slice(0, 300)
56 })
57 }
58 } catch {}
59 }
60 })
61
62 iter.on('end', () => resolve({ totalKeys, totalBytes, keyTypes, readable }))
63 iter.on('error', reject)
64 })
65}
66
67export async function listApps (db) {
68 const defaultIter = db.iterator({ limit: 10000 })
69
70 const pearApps = []
71 const fileSources = []
72
73 return new Promise((resolve, reject) => {
74 defaultIter.on('data', ({ key, value }) => {
75 if (key.length < 2) return
76
77 // Extract readable string from key (skip prefix byte)
78 let keyStr = ''
79 for (let i = 1; i < key.length; i++) {
80 if (key[i] >= 0x20 && key[i] <= 0x7e) {
81 keyStr += String.fromCharCode(key[i])
82 }
83 }
84
85 // Extract readable string from value
86 let valStr = ''
87 if (value && value.length < 500) {
88 for (let i = 0; i < value.length; i++) {
89 if (value[i] >= 0x20 && value[i] <= 0x7e) {
90 valStr += String.fromCharCode(value[i])
91 }
92 }
93 }
94
95 const prefix = key[0]
96 if (keyStr.startsWith('pear://')) {
97 pearApps.push({ prefix, url: keyStr, storage: valStr, valLen: value ? value.length : 0 })
98 } else if (keyStr.startsWith('file://')) {
99 fileSources.push({ prefix, path: keyStr, storage: valStr, valLen: value ? value.length : 0 })
100 }
101 })
102
103 defaultIter.on('end', () => resolve({ pearApps, fileSources }))
104 defaultIter.on('error', reject)
105 })
106}
107
108export async function getCorestoreStats (db) {
109 const cs = db.columnFamily(CORESTORE_CF)
110 const stats = await scanColumnFamily(cs)
111
112 return {
113 ...stats,
114 typeBreakdown: [...stats.keyTypes.entries()].map(([byte, info]) => ({
115 type: KEY_TYPES[byte] || `unknown-0x${byte.toString(16)}`,
116 byte,
117 count: info.count,
118 bytes: info.bytes,
119 mb: (info.bytes / 1024 / 1024).toFixed(2)
120 })).sort((a, b) => b.bytes - a.bytes)
121 }
122}
123
124export function formatBytes (bytes) {
125 if (bytes >= 1024 * 1024 * 1024) return (bytes / 1024 / 1024 / 1024).toFixed(2) + ' GB'
126 if (bytes >= 1024 * 1024) return (bytes / 1024 / 1024).toFixed(2) + ' MB'
127 if (bytes >= 1024) return (bytes / 1024).toFixed(1) + ' KB'
128 return bytes + ' B'
129}
lib/scanner.js +110 -0
……@@ -0,0 +1,110 @@
1import { execSync } from 'child_process'
2import { existsSync, readdirSync, statSync } from 'fs'
3import { join } from 'path'
4
5// Known Hypercore storage locations under a home directory
6const KNOWN_PATHS = [
7 '.config/pear/corestores',
8 '.config/pear/app-storage',
9 '.config/pear/by-dkey',
10 '.config/Holepunch',
11 '.config/hypernote',
12 '.config/keet-cli',
13 '.config/keet-daemon',
14 '.config/godot-keet',
15 '.config/hyper-tps',
16 '.config/agregore-browser/hyper',
17 '.config/Beaker Browser',
18 '.config/manyverse',
19 '.config/holepunch-runtime',
20 '.config/pear-runtime',
21 '.config/hyper-social-web'
22]
23
24export function findCorestores (homeDir) {
25 const results = []
26
27 // Check known paths
28 for (const rel of KNOWN_PATHS) {
29 const full = join(homeDir, rel)
30 if (existsSync(full)) {
31 const size = getDirSize(full)
32 results.push({ path: full, size, type: 'known', rel })
33 }
34 }
35
36 // Find CORESTORE marker files
37 try {
38 const output = execSync(
39 `find ${homeDir} -maxdepth 5 -name "CORESTORE" -type f 2>/dev/null`,
40 { encoding: 'utf8', timeout: 30000 }
41 )
42 for (const line of output.trim().split('\n').filter(Boolean)) {
43 const dir = line.replace(/\/CORESTORE$/, '')
44 // Check if already covered by known paths
45 const isKnown = results.some(r => dir.startsWith(r.path))
46 if (!isKnown) {
47 const size = getDirSize(dir)
48 results.push({ path: dir, size, type: 'discovered', marker: line })
49 }
50 }
51 } catch {}
52
53 // Sort by size descending
54 results.sort((a, b) => b.size - a.size)
55
56 return results
57}
58
59export function getDirSize (dirPath) {
60 try {
61 const output = execSync(`du -sb "${dirPath}" 2>/dev/null`, { encoding: 'utf8', timeout: 30000 })
62 return parseInt(output.split('\t')[0]) || 0
63 } catch {
64 return 0
65 }
66}
67
68export function getLastModified (dirPath) {
69 try {
70 const stat = statSync(dirPath)
71 return stat.mtime
72 } catch {
73 return null
74 }
75}
76
77export function isLocked (dbPath) {
78 try {
79 const lockFile = join(dbPath, 'LOCK')
80 if (!existsSync(lockFile)) return false
81 const output = execSync(`lsof "${lockFile}" 2>/dev/null`, { encoding: 'utf8', timeout: 5000 })
82 return output.trim().length > 0
83 } catch {
84 return false
85 }
86}
87
88export function getLockHolder (dbPath) {
89 try {
90 const lockFile = join(dbPath, 'LOCK')
91 const output = execSync(`lsof "${lockFile}" 2>/dev/null`, { encoding: 'utf8', timeout: 5000 })
92 const lines = output.trim().split('\n')
93 if (lines.length > 1) {
94 const parts = lines[1].split(/\s+/)
95 return { command: parts[0], pid: parts[1] }
96 }
97 } catch {}
98 return null
99}
100
101export function hasRocksDB (dirPath) {
102 const dbPath = join(dirPath, 'db')
103 if (existsSync(dbPath)) {
104 try {
105 const files = readdirSync(dbPath)
106 return files.some(f => f.endsWith('.sst') || f.endsWith('.blob'))
107 } catch {}
108 }
109 return false
110}
node_modules/.package-lock.json +1004 -0
……@@ -0,0 +1,1004 @@
1{
2 "name": "hyper-inspector",
3 "version": "0.1.0",
4 "lockfileVersion": 3,
5 "requires": true,
6 "packages": {
7 "node_modules/@hyperswarm/secret-stream": {
8 "version": "6.9.1",
9 "resolved": "https://registry.npmjs.org/@hyperswarm/secret-stream/-/secret-stream-6.9.1.tgz",
10 "integrity": "sha512-xb0S5y3YJwBakD77JOGBHlBxdp63mHClZoXBYoLv+9wH8e054ESKlmQptWqjJK5dv5VMUIVYOJB4MaOpB0JdGw==",
11 "license": "Apache-2.0",
12 "dependencies": {
13 "b4a": "^1.1.0",
14 "hypercore-crypto": "^3.3.1",
15 "noise-curve-ed": "^2.0.1",
16 "noise-handshake": "^4.0.0",
17 "sodium-secretstream": "^1.1.0",
18 "sodium-universal": "^5.0.0",
19 "streamx": "^2.14.0",
20 "timeout-refresh": "^2.0.0",
21 "unslab": "^1.3.0"
22 }
23 },
24 "node_modules/@hyperswarm/secret-stream/node_modules/sodium-native": {
25 "version": "5.1.0",
26 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-5.1.0.tgz",
27 "integrity": "sha512-3RxgyWyJlhTsABPnJVpCI5CoTDANZTqqFrEPqr+kjfnRaBihpVtMUE3yTF40ukdoB1APXeoBNKF3MzZAIHg39g==",
28 "license": "MIT",
29 "dependencies": {
30 "bare-assert": "^1.2.0",
31 "require-addon": "^1.1.0",
32 "which-runtime": "^1.2.1"
33 },
34 "engines": {
35 "bare": ">=1.16.0"
36 }
37 },
38 "node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal": {
39 "version": "5.0.1",
40 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-5.0.1.tgz",
41 "integrity": "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q==",
42 "license": "MIT",
43 "dependencies": {
44 "sodium-native": "^5.0.1"
45 },
46 "peerDependencies": {
47 "sodium-javascript": "~0.8.0"
48 },
49 "peerDependenciesMeta": {
50 "sodium-javascript": {
51 "optional": true
52 }
53 }
54 },
55 "node_modules/b4a": {
56 "version": "1.8.0",
57 "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz",
58 "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==",
59 "license": "Apache-2.0",
60 "peerDependencies": {
61 "react-native-b4a": "*"
62 },
63 "peerDependenciesMeta": {
64 "react-native-b4a": {
65 "optional": true
66 }
67 }
68 },
69 "node_modules/bare-addon-resolve": {
70 "version": "1.10.0",
71 "resolved": "https://registry.npmjs.org/bare-addon-resolve/-/bare-addon-resolve-1.10.0.tgz",
72 "integrity": "sha512-sSd0jieRJlDaODOzj0oe0RjFVC1QI0ZIjGIdPkbrTXsdVVtENg14c+lHHAhHwmWCZ2nQlMhy8jA3Y5LYPc/isA==",
73 "license": "Apache-2.0",
74 "dependencies": {
75 "bare-module-resolve": "^1.10.0",
76 "bare-semver": "^1.0.0"
77 },
78 "peerDependencies": {
79 "bare-url": "*"
80 },
81 "peerDependenciesMeta": {
82 "bare-url": {
83 "optional": true
84 }
85 }
86 },
87 "node_modules/bare-ansi-escapes": {
88 "version": "2.2.3",
89 "resolved": "https://registry.npmjs.org/bare-ansi-escapes/-/bare-ansi-escapes-2.2.3.tgz",
90 "integrity": "sha512-02ES4/E2RbrtZSnHJ9LntBhYkLA6lPpSEeP8iqS3MccBIVhVBlEmruF1I7HZqx5Q8aiTeYfQVeqmrU9YO2yYoQ==",
91 "license": "Apache-2.0",
92 "dependencies": {
93 "bare-stream": "^2.6.5"
94 },
95 "peerDependencies": {
96 "bare-buffer": "*"
97 },
98 "peerDependenciesMeta": {
99 "bare-buffer": {
100 "optional": true
101 }
102 }
103 },
104 "node_modules/bare-assert": {
105 "version": "1.2.0",
106 "resolved": "https://registry.npmjs.org/bare-assert/-/bare-assert-1.2.0.tgz",
107 "integrity": "sha512-c6uvgvTJBspTDxtVnPgrBKmLgcpW3Fp72NVKDLg6oT4QjQbhGtvrkHMhGYMK1sh4vjBHOBmuUalyt9hSzV37fQ==",
108 "license": "Apache-2.0",
109 "dependencies": {
110 "bare-inspect": "^3.1.2"
111 }
112 },
113 "node_modules/bare-events": {
114 "version": "2.8.2",
115 "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz",
116 "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==",
117 "license": "Apache-2.0",
118 "peerDependencies": {
119 "bare-abort-controller": "*"
120 },
121 "peerDependenciesMeta": {
122 "bare-abort-controller": {
123 "optional": true
124 }
125 }
126 },
127 "node_modules/bare-fs": {
128 "version": "4.5.6",
129 "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.6.tgz",
130 "integrity": "sha512-1QovqDrR80Pmt5HPAsMsXTCFcDYr+NSUKW6nd6WO5v0JBmnItc/irNRzm2KOQ5oZ69P37y+AMujNyNtG+1Rggw==",
131 "license": "Apache-2.0",
132 "dependencies": {
133 "bare-events": "^2.5.4",
134 "bare-path": "^3.0.0",
135 "bare-stream": "^2.6.4",
136 "bare-url": "^2.2.2",
137 "fast-fifo": "^1.3.2"
138 },
139 "engines": {
140 "bare": ">=1.16.0"
141 },
142 "peerDependencies": {
143 "bare-buffer": "*"
144 },
145 "peerDependenciesMeta": {
146 "bare-buffer": {
147 "optional": true
148 }
149 }
150 },
151 "node_modules/bare-inspect": {
152 "version": "3.1.4",
153 "resolved": "https://registry.npmjs.org/bare-inspect/-/bare-inspect-3.1.4.tgz",
154 "integrity": "sha512-jfW5KRA84o3REpI6Vr4nbvMn+hqVAw8GU1mMdRwUsY5yJovQamxYeKGVKGqdzs+8ZbG4jRzGUXP/3Ji/DnqfPg==",
155 "license": "Apache-2.0",
156 "dependencies": {
157 "bare-ansi-escapes": "^2.1.0",
158 "bare-type": "^1.0.0"
159 },
160 "engines": {
161 "bare": ">=1.18.0"
162 }
163 },
164 "node_modules/bare-module-resolve": {
165 "version": "1.12.1",
166 "resolved": "https://registry.npmjs.org/bare-module-resolve/-/bare-module-resolve-1.12.1.tgz",
167 "integrity": "sha512-hbmAPyFpEq8FoZMd5sFO3u6MC5feluWoGE8YKlA8fCrl6mNtx68Wjg4DTiDJcqRJaovTvOYKfYngoBUnbaT7eg==",
168 "license": "Apache-2.0",
169 "dependencies": {
170 "bare-semver": "^1.0.0"
171 },
172 "peerDependencies": {
173 "bare-url": "*"
174 },
175 "peerDependenciesMeta": {
176 "bare-url": {
177 "optional": true
178 }
179 }
180 },
181 "node_modules/bare-os": {
182 "version": "3.8.0",
183 "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.8.0.tgz",
184 "integrity": "sha512-Dc9/SlwfxkXIGYhvMQNUtKaXCaGkZYGcd1vuNUUADVqzu4/vQfvnMkYYOUnt2VwQ2AqKr/8qAVFRtwETljgeFg==",
185 "license": "Apache-2.0",
186 "engines": {
187 "bare": ">=1.14.0"
188 }
189 },
190 "node_modules/bare-path": {
191 "version": "3.0.0",
192 "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz",
193 "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==",
194 "license": "Apache-2.0",
195 "dependencies": {
196 "bare-os": "^3.0.1"
197 }
198 },
199 "node_modules/bare-semver": {
200 "version": "1.0.2",
201 "resolved": "https://registry.npmjs.org/bare-semver/-/bare-semver-1.0.2.tgz",
202 "integrity": "sha512-ESVaN2nzWhcI5tf3Zzcq9aqCZ676VWzqw07eEZ0qxAcEOAFYBa0pWq8sK34OQeHLY3JsfKXZS9mDyzyxGjeLzA==",
203 "license": "Apache-2.0"
204 },
205 "node_modules/bare-stream": {
206 "version": "2.10.0",
207 "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.10.0.tgz",
208 "integrity": "sha512-DOPZF/DDcDruKDA43cOw6e9Quq5daua7ygcAwJE/pKJsRWhgSSemi7qVNGE5kyDIxIeN1533G/zfbvWX7Wcb9w==",
209 "license": "Apache-2.0",
210 "dependencies": {
211 "streamx": "^2.25.0",
212 "teex": "^1.0.1"
213 },
214 "peerDependencies": {
215 "bare-buffer": "*",
216 "bare-events": "*"
217 },
218 "peerDependenciesMeta": {
219 "bare-buffer": {
220 "optional": true
221 },
222 "bare-events": {
223 "optional": true
224 }
225 }
226 },
227 "node_modules/bare-type": {
228 "version": "1.1.0",
229 "resolved": "https://registry.npmjs.org/bare-type/-/bare-type-1.1.0.tgz",
230 "integrity": "sha512-LdtnnEEYldOc87Dr4GpsKnStStZk3zfgoEMXy8yvEZkXrcCv9RtYDrUYWFsBQHtaB0s1EUWmcvS6XmEZYIj3Bw==",
231 "license": "Apache-2.0",
232 "engines": {
233 "bare": ">=1.2.0"
234 }
235 },
236 "node_modules/bare-url": {
237 "version": "2.4.0",
238 "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.0.tgz",
239 "integrity": "sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA==",
240 "license": "Apache-2.0",
241 "dependencies": {
242 "bare-path": "^3.0.0"
243 }
244 },
245 "node_modules/big-sparse-array": {
246 "version": "1.0.3",
247 "resolved": "https://registry.npmjs.org/big-sparse-array/-/big-sparse-array-1.0.3.tgz",
248 "integrity": "sha512-6RjV/3mSZORlMdpUaQ6rUSpG637cZm0//E54YYGtQg1c1O+AbZP8UTdJ/TchsDZcTVLmyWZcseBfp2HBeXUXOQ==",
249 "license": "MIT"
250 },
251 "node_modules/binary-stream-equals": {
252 "version": "1.0.0",
253 "resolved": "https://registry.npmjs.org/binary-stream-equals/-/binary-stream-equals-1.0.0.tgz",
254 "integrity": "sha512-xiUT5LGfD8JiLhbXiG+ByOnbgb9f2ssRLfZDQMl3nZdf89EotQZGZuMkDN8J3n46emabE7RnJ1q0r7Hv3INExw==",
255 "license": "MIT",
256 "dependencies": {
257 "b4a": "^1.3.1"
258 }
259 },
260 "node_modules/codecs": {
261 "version": "3.1.0",
262 "resolved": "https://registry.npmjs.org/codecs/-/codecs-3.1.0.tgz",
263 "integrity": "sha512-Dqx8NwvBvnMeuPQdVKy/XEF71igjR5apxBvCGeV0pP1tXadOiaLvDTXt7xh+/5wI1ASB195mXQGJbw3Ml4YDWQ==",
264 "license": "MIT",
265 "dependencies": {
266 "b4a": "^1.6.3"
267 }
268 },
269 "node_modules/compact-encoding": {
270 "version": "2.19.1",
271 "resolved": "https://registry.npmjs.org/compact-encoding/-/compact-encoding-2.19.1.tgz",
272 "integrity": "sha512-4J4FHc5UugLv2YMss1tL8OBZdgR0vVkV4EuXoAqFS4NbK4gz0Qp+E+VGUnwvDqmMOw2ce/H8duXh3rreC0Qccg==",
273 "license": "Apache-2.0",
274 "dependencies": {
275 "b4a": "^1.3.0"
276 }
277 },
278 "node_modules/corestore": {
279 "version": "6.18.4",
280 "resolved": "https://registry.npmjs.org/corestore/-/corestore-6.18.4.tgz",
281 "integrity": "sha512-KL1cOUyj3DFRNzeVRekGPRiGN4sIfGo7BsncSJQQBT3Rh2y1nQ32MOR9X5DlOMlWIT4txwqBzhzam6+JXtwFVw==",
282 "license": "MIT",
283 "dependencies": {
284 "b4a": "^1.6.4",
285 "hypercore": "^10.37.10",
286 "hypercore-crypto": "^3.4.0",
287 "hypercore-id-encoding": "^1.2.0",
288 "read-write-mutexify": "^2.1.0",
289 "ready-resource": "^1.0.0",
290 "safety-catch": "^1.0.1",
291 "sodium-universal": "^4.0.0",
292 "xache": "^1.1.0"
293 }
294 },
295 "node_modules/crc-native": {
296 "version": "1.1.8",
297 "resolved": "https://registry.npmjs.org/crc-native/-/crc-native-1.1.8.tgz",
298 "integrity": "sha512-R/RYbD8lhG5M1k0iLX49tJdwHM0ipevJPpZw2Wk7b4EShyvx2P0uaq79xyRpcknjiVGiUfjFA8Gyy0mOlhABvw==",
299 "license": "Apache-2.0",
300 "optional": true,
301 "dependencies": {
302 "require-addon": "^1.1.0"
303 }
304 },
305 "node_modules/crc-universal": {
306 "version": "1.0.4",
307 "resolved": "https://registry.npmjs.org/crc-universal/-/crc-universal-1.0.4.tgz",
308 "integrity": "sha512-CE9xWEI6Gd5V0Bdmj5NoWH3d7+EIe4zUpy1sv6uvKYznzsDP1vhiWsTBmL6q9IrH2P6RRshp+8AkhR4CMtY5Hg==",
309 "license": "ISC",
310 "optionalDependencies": {
311 "crc-native": "^1.0.3"
312 }
313 },
314 "node_modules/debounceify": {
315 "version": "1.1.0",
316 "resolved": "https://registry.npmjs.org/debounceify/-/debounceify-1.1.0.tgz",
317 "integrity": "sha512-eKuHDVfJVg+u/0nPy8P+fhnLgbyuTgVxuCRrS/R7EpDSMMkBDgSes41MJtSAY1F1hcqfHz3Zy/qpqHHIp/EhdA==",
318 "license": "MIT"
319 },
320 "node_modules/events-universal": {
321 "version": "1.0.1",
322 "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz",
323 "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==",
324 "license": "Apache-2.0",
325 "dependencies": {
326 "bare-events": "^2.7.0"
327 }
328 },
329 "node_modules/fast-fifo": {
330 "version": "1.3.2",
331 "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
332 "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
333 "license": "MIT"
334 },
335 "node_modules/flat-tree": {
336 "version": "1.13.0",
337 "resolved": "https://registry.npmjs.org/flat-tree/-/flat-tree-1.13.0.tgz",
338 "integrity": "sha512-fT3HIuCPwHhFgJ20QYzDHgUG0zMmFg5cHvFiFo5h+QMSJ28TihsEVY0f8HGliuO+pOzmvjMx1odToeaEWkTnyQ==",
339 "license": "MIT"
340 },
341 "node_modules/fs-native-extensions": {
342 "version": "1.4.5",
343 "resolved": "https://registry.npmjs.org/fs-native-extensions/-/fs-native-extensions-1.4.5.tgz",
344 "integrity": "sha512-ekV0T//iDm4AvhOcuPaHpxub4DI7HvY5ucLJVDvi7T2J+NZkQ9S6MuvgP0yeQvoqNUaAGyLjVYb1905BF9bpmg==",
345 "license": "Apache-2.0",
346 "optional": true,
347 "dependencies": {
348 "require-addon": "^1.1.0",
349 "which-runtime": "^1.2.0"
350 }
351 },
352 "node_modules/hyperbee": {
353 "version": "2.27.3",
354 "resolved": "https://registry.npmjs.org/hyperbee/-/hyperbee-2.27.3.tgz",
355 "integrity": "sha512-PXURH2U4juUZyJRKHTrY5z1zX851pmI1Q0jfv5F/hCIErDt/ND8jOZuxc3hfOLM9f0W3qJEDTMlV5AJBkVPy8w==",
356 "license": "MIT",
357 "dependencies": {
358 "b4a": "^1.6.0",
359 "codecs": "^3.0.0",
360 "debounceify": "^1.0.0",
361 "hypercore-errors": "^1.0.0",
362 "mutexify": "^1.4.0",
363 "protocol-buffers-encodings": "^1.2.0",
364 "rache": "^1.0.0",
365 "ready-resource": "^1.0.0",
366 "resolve-reject-promise": "^1.1.0",
367 "safety-catch": "^1.0.2",
368 "streamx": "^2.12.4",
369 "unslab": "^1.2.0"
370 }
371 },
372 "node_modules/hyperblobs": {
373 "version": "2.9.0",
374 "resolved": "https://registry.npmjs.org/hyperblobs/-/hyperblobs-2.9.0.tgz",
375 "integrity": "sha512-kbJV2+QvXIcFejqOj2UgSjeeHMjWqP1n083vcI+j4E93MhV3oVV2L8/6X+K/id/KQrUmngPTzNTHHXKlkb1CEA==",
376 "license": "Apache-2.0",
377 "dependencies": {
378 "b4a": "^1.6.1",
379 "bare-events": "^2.5.0",
380 "compact-encoding": "^2.18.0",
381 "hypercore-crypto": "^3.6.1",
382 "hypercore-errors": "^1.1.1",
383 "mutexify": "^1.4.0",
384 "speedometer": "^1.1.0",
385 "streamx": "^2.13.2"
386 }
387 },
388 "node_modules/hypercore": {
389 "version": "10.38.2",
390 "resolved": "https://registry.npmjs.org/hypercore/-/hypercore-10.38.2.tgz",
391 "integrity": "sha512-2vx42g2RKdP/o2XzlxKfvgEaZ3+h/B855gCR8iscUDnxUoOZej7vXZ2buex0sweDUEW5aEfMxFR6o5hncio3Nw==",
392 "license": "MIT",
393 "dependencies": {
394 "@hyperswarm/secret-stream": "^6.0.0",
395 "b4a": "^1.1.0",
396 "bare-events": "^2.2.0",
397 "big-sparse-array": "^1.0.3",
398 "compact-encoding": "^2.11.0",
399 "crc-universal": "^1.0.2",
400 "fast-fifo": "^1.3.0",
401 "flat-tree": "^1.9.0",
402 "hypercore-crypto": "^3.2.1",
403 "hypercore-errors": "^1.2.0",
404 "hypercore-id-encoding": "^1.2.0",
405 "is-options": "^1.0.1",
406 "protomux": "^3.5.0",
407 "quickbit-universal": "^2.2.0",
408 "random-access-file": "^4.0.0",
409 "random-array-iterator": "^1.0.0",
410 "safety-catch": "^1.0.1",
411 "sodium-universal": "^4.0.0",
412 "streamx": "^2.12.4",
413 "unslab": "^1.3.0",
414 "xache": "^1.1.0",
415 "z32": "^1.0.0"
416 }
417 },
418 "node_modules/hypercore-crypto": {
419 "version": "3.6.1",
420 "resolved": "https://registry.npmjs.org/hypercore-crypto/-/hypercore-crypto-3.6.1.tgz",
421 "integrity": "sha512-ltIz2uDwy9pO/ZGTvqcjzyBkvt6O4cVm4r/nNxh0GFs/RbQtqP/i4wCvLEdmU7ptgtnw7fI67WYD1aHPuv4OVA==",
422 "license": "MIT",
423 "dependencies": {
424 "b4a": "^1.6.6",
425 "compact-encoding": "^2.15.0",
426 "sodium-universal": "^5.0.0"
427 }
428 },
429 "node_modules/hypercore-crypto/node_modules/sodium-native": {
430 "version": "5.1.0",
431 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-5.1.0.tgz",
432 "integrity": "sha512-3RxgyWyJlhTsABPnJVpCI5CoTDANZTqqFrEPqr+kjfnRaBihpVtMUE3yTF40ukdoB1APXeoBNKF3MzZAIHg39g==",
433 "license": "MIT",
434 "dependencies": {
435 "bare-assert": "^1.2.0",
436 "require-addon": "^1.1.0",
437 "which-runtime": "^1.2.1"
438 },
439 "engines": {
440 "bare": ">=1.16.0"
441 }
442 },
443 "node_modules/hypercore-crypto/node_modules/sodium-universal": {
444 "version": "5.0.1",
445 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-5.0.1.tgz",
446 "integrity": "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q==",
447 "license": "MIT",
448 "dependencies": {
449 "sodium-native": "^5.0.1"
450 },
451 "peerDependencies": {
452 "sodium-javascript": "~0.8.0"
453 },
454 "peerDependenciesMeta": {
455 "sodium-javascript": {
456 "optional": true
457 }
458 }
459 },
460 "node_modules/hypercore-errors": {
461 "version": "1.5.0",
462 "resolved": "https://registry.npmjs.org/hypercore-errors/-/hypercore-errors-1.5.0.tgz",
463 "integrity": "sha512-5KQ/SuDxsvet+7qWA35Ay6zdD9WyAHQoyWHGcPUTbmJBd300gvNIJoi3oma7kp4TTCSzii6qYumNZe/s0j/saQ==",
464 "license": "Apache-2.0",
465 "dependencies": {
466 "hypercore-id-encoding": "^1.3.0"
467 }
468 },
469 "node_modules/hypercore-id-encoding": {
470 "version": "1.3.0",
471 "resolved": "https://registry.npmjs.org/hypercore-id-encoding/-/hypercore-id-encoding-1.3.0.tgz",
472 "integrity": "sha512-W6sHdGo5h7LXEsoWfKf/KfuROZmZRQDlGqJF2EPHW+noCK66Vvr0+zE6cL0vqQi18s0kQPeN7Sq3QyR0Ytc2VQ==",
473 "license": "Apache-2.0",
474 "dependencies": {
475 "b4a": "^1.5.3",
476 "z32": "^1.0.0"
477 }
478 },
479 "node_modules/hyperdrive": {
480 "version": "11.13.4",
481 "resolved": "https://registry.npmjs.org/hyperdrive/-/hyperdrive-11.13.4.tgz",
482 "integrity": "sha512-PN0gClSRx+QBbsLGnGqo2ei9TavJN8d6D3jv2yNMlu7zgXSnqR6QcGo8mgyKnrzgR336oNfvQ2C2Y6cY5klScg==",
483 "license": "Apache-2.0",
484 "dependencies": {
485 "hyperbee": "^2.11.1",
486 "hyperblobs": "^2.3.0",
487 "hypercore": "^10.33.0",
488 "hypercore-errors": "^1.0.0",
489 "is-options": "^1.0.2",
490 "mirror-drive": "^1.2.0",
491 "ready-resource": "^1.0.0",
492 "safety-catch": "^1.0.2",
493 "speedometer": "^1.1.0",
494 "streamx": "^2.12.4",
495 "sub-encoder": "^2.1.1",
496 "unix-path-resolve": "^1.0.2"
497 }
498 },
499 "node_modules/is-options": {
500 "version": "1.0.2",
501 "resolved": "https://registry.npmjs.org/is-options/-/is-options-1.0.2.tgz",
502 "integrity": "sha512-u+Ai74c8Q74aS8BuHwPdI1jptGOT1FQXgCq8/zv0xRuE+wRgSMEJLj8lVO8Zp9BeGb29BXY6AsNPinfqjkr7Fg==",
503 "license": "MIT",
504 "dependencies": {
505 "b4a": "^1.1.1"
506 }
507 },
508 "node_modules/mirror-drive": {
509 "version": "1.13.0",
510 "resolved": "https://registry.npmjs.org/mirror-drive/-/mirror-drive-1.13.0.tgz",
511 "integrity": "sha512-dwf2eIaeFgzv03hfW4aCQ/smNIGuxbsnNRrdGAGIyS70Hp0lbOoHXce2V34hGCoxmzn7jeLA4bHJiWlfKOu2Sg==",
512 "license": "Apache-2.0",
513 "dependencies": {
514 "bare-events": "^2.8.2",
515 "binary-stream-equals": "^1.0.0",
516 "rabin-stream": "^2.0.0",
517 "same-data": "^1.0.0",
518 "speedometer": "^1.1.0",
519 "streamx": "^2.22.1",
520 "unix-path-resolve": "^1.0.2"
521 }
522 },
523 "node_modules/mutexify": {
524 "version": "1.4.0",
525 "resolved": "https://registry.npmjs.org/mutexify/-/mutexify-1.4.0.tgz",
526 "integrity": "sha512-pbYSsOrSB/AKN5h/WzzLRMFgZhClWccf2XIB4RSMC8JbquiB0e0/SH5AIfdQMdyHmYtv4seU7yV/TvAwPLJ1Yg==",
527 "license": "MIT",
528 "dependencies": {
529 "queue-tick": "^1.0.0"
530 }
531 },
532 "node_modules/nanoassert": {
533 "version": "2.0.0",
534 "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-2.0.0.tgz",
535 "integrity": "sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==",
536 "license": "ISC"
537 },
538 "node_modules/noise-curve-ed": {
539 "version": "2.1.0",
540 "resolved": "https://registry.npmjs.org/noise-curve-ed/-/noise-curve-ed-2.1.0.tgz",
541 "integrity": "sha512-zAzJx+VwZM3w6EA1hTmDhJfvAnCeBQn/1FAeZ0LtGxCcCtlAK/uJXQVF/eDVUOaAZ286lHlx77WJ+qj9SmsRRg==",
542 "license": "ISC",
543 "dependencies": {
544 "b4a": "^1.1.0",
545 "nanoassert": "^2.0.0",
546 "sodium-universal": "^5.0.0"
547 }
548 },
549 "node_modules/noise-curve-ed/node_modules/sodium-native": {
550 "version": "5.1.0",
551 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-5.1.0.tgz",
552 "integrity": "sha512-3RxgyWyJlhTsABPnJVpCI5CoTDANZTqqFrEPqr+kjfnRaBihpVtMUE3yTF40ukdoB1APXeoBNKF3MzZAIHg39g==",
553 "license": "MIT",
554 "dependencies": {
555 "bare-assert": "^1.2.0",
556 "require-addon": "^1.1.0",
557 "which-runtime": "^1.2.1"
558 },
559 "engines": {
560 "bare": ">=1.16.0"
561 }
562 },
563 "node_modules/noise-curve-ed/node_modules/sodium-universal": {
564 "version": "5.0.1",
565 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-5.0.1.tgz",
566 "integrity": "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q==",
567 "license": "MIT",
568 "dependencies": {
569 "sodium-native": "^5.0.1"
570 },
571 "peerDependencies": {
572 "sodium-javascript": "~0.8.0"
573 },
574 "peerDependenciesMeta": {
575 "sodium-javascript": {
576 "optional": true
577 }
578 }
579 },
580 "node_modules/noise-handshake": {
581 "version": "4.2.0",
582 "resolved": "https://registry.npmjs.org/noise-handshake/-/noise-handshake-4.2.0.tgz",
583 "integrity": "sha512-9O/VTNX/E2/AToyMTTDU0J/4WhaXMTdqc2DHs9vf+snoZ0cenSBq0dNYTVV1snYYEkmo6QeRrYMxtqtoYnY+LA==",
584 "license": "Apache-2.0",
585 "dependencies": {
586 "b4a": "^1.1.0",
587 "nanoassert": "^2.0.0",
588 "sodium-universal": "^5.0.0"
589 }
590 },
591 "node_modules/noise-handshake/node_modules/sodium-native": {
592 "version": "5.1.0",
593 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-5.1.0.tgz",
594 "integrity": "sha512-3RxgyWyJlhTsABPnJVpCI5CoTDANZTqqFrEPqr+kjfnRaBihpVtMUE3yTF40ukdoB1APXeoBNKF3MzZAIHg39g==",
595 "license": "MIT",
596 "dependencies": {
597 "bare-assert": "^1.2.0",
598 "require-addon": "^1.1.0",
599 "which-runtime": "^1.2.1"
600 },
601 "engines": {
602 "bare": ">=1.16.0"
603 }
604 },
605 "node_modules/noise-handshake/node_modules/sodium-universal": {
606 "version": "5.0.1",
607 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-5.0.1.tgz",
608 "integrity": "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q==",
609 "license": "MIT",
610 "dependencies": {
611 "sodium-native": "^5.0.1"
612 },
613 "peerDependencies": {
614 "sodium-javascript": "~0.8.0"
615 },
616 "peerDependenciesMeta": {
617 "sodium-javascript": {
618 "optional": true
619 }
620 }
621 },
622 "node_modules/paparam": {
623 "version": "1.10.1",
624 "resolved": "https://registry.npmjs.org/paparam/-/paparam-1.10.1.tgz",
625 "integrity": "sha512-viyQI64VIja0Za3njIzhoEP8ZVkgPowhZPuG0E96NwBfYJ6ZIyrrlhWGtFPkdN7eYLl2L8CTWL+wla0evm1KKQ==",
626 "license": "Apache-2.0"
627 },
628 "node_modules/protocol-buffers-encodings": {
629 "version": "1.2.0",
630 "resolved": "https://registry.npmjs.org/protocol-buffers-encodings/-/protocol-buffers-encodings-1.2.0.tgz",
631 "integrity": "sha512-daeNPuKh1NlLD1uDfbLpD+xyUTc07nEtfHwmBZmt/vH0B7VOM+JOCOpDcx9ZRpqHjAiIkGqyTDi+wfGSl17R9w==",
632 "license": "MIT",
633 "dependencies": {
634 "b4a": "^1.6.0",
635 "signed-varint": "^2.0.1",
636 "varint": "5.0.0"
637 }
638 },
639 "node_modules/protomux": {
640 "version": "3.10.1",
641 "resolved": "https://registry.npmjs.org/protomux/-/protomux-3.10.1.tgz",
642 "integrity": "sha512-jgBqx8ZyaBWea/DFG4eOu1scOaeBwcnagiRC1XFVrjeGt7oAb0Pk5udPpBUpJ4DJBRjra50jD6YcZiQQTRqaaA==",
643 "license": "MIT",
644 "dependencies": {
645 "b4a": "^1.3.1",
646 "compact-encoding": "^2.5.1",
647 "queue-tick": "^1.0.0",
648 "safety-catch": "^1.0.1",
649 "unslab": "^1.3.0"
650 }
651 },
652 "node_modules/queue-tick": {
653 "version": "1.0.1",
654 "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
655 "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==",
656 "license": "MIT"
657 },
658 "node_modules/quickbit-native": {
659 "version": "2.4.8",
660 "resolved": "https://registry.npmjs.org/quickbit-native/-/quickbit-native-2.4.8.tgz",
661 "integrity": "sha512-FcCcqI+nIAWGknqhtrYT5TSD7t/N+Xd8ctM+2PrIIBuwOi5hx0SxAvuPtzLIEMfT/2h9+fhBakUe2uALOHX6yw==",
662 "license": "Apache-2.0",
663 "optional": true,
664 "dependencies": {
665 "require-addon": "^1.1.0"
666 }
667 },
668 "node_modules/quickbit-universal": {
669 "version": "2.2.0",
670 "resolved": "https://registry.npmjs.org/quickbit-universal/-/quickbit-universal-2.2.0.tgz",
671 "integrity": "sha512-w02i1R8n7+6pEKTud8DfF8zbFY9o7RtPlUc3jWbtCkDKvhbx/AvV7oNnz4/TcmsPGpSJS+fq5Ud6RH6+YPvSGg==",
672 "license": "ISC",
673 "dependencies": {
674 "b4a": "^1.6.0",
675 "simdle-universal": "^1.1.0"
676 },
677 "optionalDependencies": {
678 "quickbit-native": "^2.2.0"
679 }
680 },
681 "node_modules/rabin-native": {
682 "version": "2.0.0",
683 "resolved": "https://registry.npmjs.org/rabin-native/-/rabin-native-2.0.0.tgz",
684 "integrity": "sha512-x1BlYdIWh+nk9G0scvxyscrYiDPJ7vQZepqqPlVUSInIko1Zxooi8cm6lzBghEGI9aN3DXiunC8FXLgy6kke3Q==",
685 "license": "Apache-2.0",
686 "dependencies": {
687 "require-addon": "^1.1.0"
688 }
689 },
690 "node_modules/rabin-stream": {
691 "version": "2.0.0",
692 "resolved": "https://registry.npmjs.org/rabin-stream/-/rabin-stream-2.0.0.tgz",
693 "integrity": "sha512-EzS2Ig/qsMBSk1PahC0O0IPdRZe3bspHHLWChhqW1feKz+J46tlVL3g4wWr4lrQdXGzABIMsOhvdT6bjXYMuUw==",
694 "license": "Apache-2.0",
695 "dependencies": {
696 "rabin-native": "^2.0.0",
697 "streamx": "^2.23.0"
698 }
699 },
700 "node_modules/rache": {
701 "version": "1.0.0",
702 "resolved": "https://registry.npmjs.org/rache/-/rache-1.0.0.tgz",
703 "integrity": "sha512-e0k0g0w/8jOCB+7YqCIlOa+OJ38k0wrYS4x18pMSmqOvLKoyhmMhmQyCcvfY6VaP8D75cqkEnlakXs+RYYLqNg==",
704 "license": "Apache-2.0"
705 },
706 "node_modules/random-access-file": {
707 "version": "4.1.2",
708 "resolved": "https://registry.npmjs.org/random-access-file/-/random-access-file-4.1.2.tgz",
709 "integrity": "sha512-GQM6R78DceZDcQod8KxlDFwXIiUvlvuy1EOzxTDsjuDjW5NlnlZi0MOk6iI4itAj/2vcvdqcEExYbVpC/dJcEw==",
710 "license": "MIT",
711 "dependencies": {
712 "bare-fs": "^4.0.1",
713 "bare-path": "^3.0.0",
714 "random-access-storage": "^3.0.0"
715 },
716 "optionalDependencies": {
717 "fs-native-extensions": "^1.3.1"
718 }
719 },
720 "node_modules/random-access-storage": {
721 "version": "3.0.2",
722 "resolved": "https://registry.npmjs.org/random-access-storage/-/random-access-storage-3.0.2.tgz",
723 "integrity": "sha512-Es9maUyWdJXWKckKy9s1+vT+DEgAt+PBb9lxPaake/0EDUsHehloKGv9v1zimS2V3gpFAcQXubvc1Rgci2sDPQ==",
724 "license": "MIT",
725 "dependencies": {
726 "bare-events": "^2.2.0",
727 "queue-tick": "^1.0.0"
728 }
729 },
730 "node_modules/random-array-iterator": {
731 "version": "1.0.0",
732 "resolved": "https://registry.npmjs.org/random-array-iterator/-/random-array-iterator-1.0.0.tgz",
733 "integrity": "sha512-u7xCM93XqKEvPTP6xZp2ehttcAemKnh73oKNf1FvzuVCfpt6dILDt1Kxl1LeBjm2iNIeR49VGFhy4Iz3yOun+Q==",
734 "license": "MIT"
735 },
736 "node_modules/read-write-mutexify": {
737 "version": "2.1.0",
738 "resolved": "https://registry.npmjs.org/read-write-mutexify/-/read-write-mutexify-2.1.0.tgz",
739 "integrity": "sha512-fDw/p5/acI1ytVY1UbxEDma/ej1yJH/n9NcjS9YNzcE6sPBPWdlru3ydRa/UBowUg4zqOvNMD5SOGYJrlQ6MzQ==",
740 "license": "MIT"
741 },
742 "node_modules/ready-resource": {
743 "version": "1.2.0",
744 "resolved": "https://registry.npmjs.org/ready-resource/-/ready-resource-1.2.0.tgz",
745 "integrity": "sha512-nfcco/8iAFV0M+2PYnmIc+/xY0iRb35d42HFHQ7AfjulbGEAFa+XWpByfwSyeVeiBoMLLFVMv1HixxNCqzSQ1g==",
746 "license": "MIT",
747 "dependencies": {
748 "bare-events": "^2.2.0"
749 }
750 },
751 "node_modules/refcounter": {
752 "version": "1.0.0",
753 "resolved": "https://registry.npmjs.org/refcounter/-/refcounter-1.0.0.tgz",
754 "integrity": "sha512-1WosVzUy0kPUaPMEtlNDwm99UsteALIhXXR8rerELoa63WkYIXAl0hxgwPFrIYBRWZPGUyekQ04FRtPJ7dHk9w==",
755 "license": "Apache-2.0"
756 },
757 "node_modules/require-addon": {
758 "version": "1.2.0",
759 "resolved": "https://registry.npmjs.org/require-addon/-/require-addon-1.2.0.tgz",
760 "integrity": "sha512-VNPDZlYgIYQwWp9jMTzljx+k0ZtatKlcvOhktZ/anNPI3dQ9NXk7cq2U4iJ1wd9IrytRnYhyEocFWbkdPb+MYA==",
761 "license": "Apache-2.0",
762 "dependencies": {
763 "bare-addon-resolve": "^1.3.0"
764 },
765 "engines": {
766 "bare": ">=1.10.0"
767 }
768 },
769 "node_modules/resolve-reject-promise": {
770 "version": "1.1.0",
771 "resolved": "https://registry.npmjs.org/resolve-reject-promise/-/resolve-reject-promise-1.1.0.tgz",
772 "integrity": "sha512-LWsTOA91AqzBTjSGgX79Tc130pwcBK6xjpJEO+qRT5IKZ6bGnHKcc8QL3upUBcWuU8OTIDzKK2VNSwmmlqvAVg==",
773 "license": "MIT"
774 },
775 "node_modules/rocksdb-native": {
776 "version": "3.15.0",
777 "resolved": "https://registry.npmjs.org/rocksdb-native/-/rocksdb-native-3.15.0.tgz",
778 "integrity": "sha512-czYx0hOzKAy+HYmJROZm7thvJ1tHFWHNkGI3nomumXWzrJghJdrWo4MIhehGX4OTff0lnOCoB2zu6ekzIKY0rQ==",
779 "license": "Apache-2.0",
780 "dependencies": {
781 "compact-encoding": "^2.15.0",
782 "ready-resource": "^1.0.0",
783 "refcounter": "^1.0.0",
784 "require-addon": "^1.0.2",
785 "resolve-reject-promise": "^1.1.0",
786 "signal-promise": "^1.0.3",
787 "streamx": "^2.16.1"
788 },
789 "engines": {
790 "bare": ">=1.16.0"
791 }
792 },
793 "node_modules/safety-catch": {
794 "version": "1.0.3",
795 "resolved": "https://registry.npmjs.org/safety-catch/-/safety-catch-1.0.3.tgz",
796 "integrity": "sha512-Zq+J1TefpoEq/HTUabo0YXX5MNvttjWYODGohgPBO2jfko8Wqx3JYMgE823szDFVamdH5PlpByvfiWScTdSYDA==",
797 "license": "MIT"
798 },
799 "node_modules/same-data": {
800 "version": "1.0.0",
801 "resolved": "https://registry.npmjs.org/same-data/-/same-data-1.0.0.tgz",
802 "integrity": "sha512-Eqn7N2yV+aKMlUHTRqUwYG1Iv0cJqjlvLKj/GoP5PozJn361QaOYX14+v87r7NqQUZC22noP/LfLrSQiPwAygw==",
803 "license": "MIT"
804 },
805 "node_modules/signal-promise": {
806 "version": "1.0.3",
807 "resolved": "https://registry.npmjs.org/signal-promise/-/signal-promise-1.0.3.tgz",
808 "integrity": "sha512-WBgv0UnIq2C+Aeh0/n+IRpP6967eIx9WpynTUoiW3isPpfe1zu2LJzyfXdo9Tgef8yR/sGjcMvoUXD7EYdiz+g==",
809 "license": "MIT"
810 },
811 "node_modules/signed-varint": {
812 "version": "2.0.1",
813 "resolved": "https://registry.npmjs.org/signed-varint/-/signed-varint-2.0.1.tgz",
814 "integrity": "sha512-abgDPg1106vuZZOvw7cFwdCABddfJRz5akcCcchzTbhyhYnsG31y4AlZEgp315T7W3nQq5P4xeOm186ZiPVFzw==",
815 "license": "MIT",
816 "dependencies": {
817 "varint": "~5.0.0"
818 }
819 },
820 "node_modules/simdle-native": {
821 "version": "1.3.9",
822 "resolved": "https://registry.npmjs.org/simdle-native/-/simdle-native-1.3.9.tgz",
823 "integrity": "sha512-Isc8sP4OiiIU0mpslD4GHEnR0VQWvR/54WN7YtwEDkNdTJVWtpmvsSvsgRlw5BNGxdYXlVRegdnrSu10H/PhvA==",
824 "license": "Apache-2.0",
825 "optional": true,
826 "dependencies": {
827 "b4a": "^1.6.0",
828 "require-addon": "^1.1.0"
829 }
830 },
831 "node_modules/simdle-universal": {
832 "version": "1.1.2",
833 "resolved": "https://registry.npmjs.org/simdle-universal/-/simdle-universal-1.1.2.tgz",
834 "integrity": "sha512-3n3w1bs+uwgHKQjt6arez83EywNlhZzYvNOhvAASTl/8KqNIcqr6aHyGt3JRlfuUC7iB0tomJRPlJ2cRGIpBzA==",
835 "license": "ISC",
836 "dependencies": {
837 "b4a": "^1.6.0"
838 },
839 "optionalDependencies": {
840 "simdle-native": "^1.1.1"
841 }
842 },
843 "node_modules/sodium-native": {
844 "version": "4.3.3",
845 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.3.tgz",
846 "integrity": "sha512-OnxSlN3uyY8D0EsLHpmm2HOFmKddQVvEMmsakCrXUzSd8kjjbzL413t4ZNF3n0UxSwNgwTyUvkmZHTfuCeiYSw==",
847 "license": "MIT",
848 "dependencies": {
849 "require-addon": "^1.1.0"
850 }
851 },
852 "node_modules/sodium-secretstream": {
853 "version": "1.2.0",
854 "resolved": "https://registry.npmjs.org/sodium-secretstream/-/sodium-secretstream-1.2.0.tgz",
855 "integrity": "sha512-q/DbraNFXm1KfCiiZvapmz5UC3OlpirYFIvBK2MhGaOFSb3gRyk8OXTi17UI9SGfshQNCpsVvlopogbzZNyW6Q==",
856 "license": "MIT",
857 "dependencies": {
858 "b4a": "^1.1.1",
859 "sodium-universal": "^5.0.0"
860 }
861 },
862 "node_modules/sodium-secretstream/node_modules/sodium-native": {
863 "version": "5.1.0",
864 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-5.1.0.tgz",
865 "integrity": "sha512-3RxgyWyJlhTsABPnJVpCI5CoTDANZTqqFrEPqr+kjfnRaBihpVtMUE3yTF40ukdoB1APXeoBNKF3MzZAIHg39g==",
866 "license": "MIT",
867 "dependencies": {
868 "bare-assert": "^1.2.0",
869 "require-addon": "^1.1.0",
870 "which-runtime": "^1.2.1"
871 },
872 "engines": {
873 "bare": ">=1.16.0"
874 }
875 },
876 "node_modules/sodium-secretstream/node_modules/sodium-universal": {
877 "version": "5.0.1",
878 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-5.0.1.tgz",
879 "integrity": "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q==",
880 "license": "MIT",
881 "dependencies": {
882 "sodium-native": "^5.0.1"
883 },
884 "peerDependencies": {
885 "sodium-javascript": "~0.8.0"
886 },
887 "peerDependenciesMeta": {
888 "sodium-javascript": {
889 "optional": true
890 }
891 }
892 },
893 "node_modules/sodium-universal": {
894 "version": "4.0.1",
895 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-4.0.1.tgz",
896 "integrity": "sha512-sNp13PrxYLaUFHTGoDKkSDFvoEu51bfzE12RwGlqU1fcrkpAOK0NvizaJzOWV0Omtk9me2+Pnbjcf/l0efxuGQ==",
897 "license": "MIT",
898 "dependencies": {
899 "sodium-native": "^4.0.0"
900 },
901 "peerDependencies": {
902 "sodium-javascript": "~0.8.0"
903 },
904 "peerDependenciesMeta": {
905 "sodium-javascript": {
906 "optional": true
907 }
908 }
909 },
910 "node_modules/speedometer": {
911 "version": "1.1.0",
912 "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-1.1.0.tgz",
913 "integrity": "sha512-z/wAiTESw2XVPssY2XRcme4niTc4S5FkkJ4gknudtVoc33Zil8TdTxHy5torRcgqMqksJV2Yz8HQcvtbsnw0mQ==",
914 "license": "MIT"
915 },
916 "node_modules/streamx": {
917 "version": "2.25.0",
918 "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz",
919 "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==",
920 "license": "MIT",
921 "dependencies": {
922 "events-universal": "^1.0.0",
923 "fast-fifo": "^1.3.2",
924 "text-decoder": "^1.1.0"
925 }
926 },
927 "node_modules/sub-encoder": {
928 "version": "2.1.3",
929 "resolved": "https://registry.npmjs.org/sub-encoder/-/sub-encoder-2.1.3.tgz",
930 "integrity": "sha512-Xxx04ygZo/1J3yHvaSA6VhDmiSaBQkw/PmO3YnnYFXle+tfOGToC6FcDpIfMztWZXJzuKG14b/57HMkiL58C6A==",
931 "license": "Apache-2.0",
932 "dependencies": {
933 "b4a": "^1.6.0",
934 "codecs": "^3.1.0"
935 }
936 },
937 "node_modules/teex": {
938 "version": "1.0.1",
939 "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz",
940 "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==",
941 "license": "MIT",
942 "dependencies": {
943 "streamx": "^2.12.5"
944 }
945 },
946 "node_modules/text-decoder": {
947 "version": "1.2.7",
948 "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz",
949 "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==",
950 "license": "Apache-2.0",
951 "dependencies": {
952 "b4a": "^1.6.4"
953 }
954 },
955 "node_modules/timeout-refresh": {
956 "version": "2.0.1",
957 "resolved": "https://registry.npmjs.org/timeout-refresh/-/timeout-refresh-2.0.1.tgz",
958 "integrity": "sha512-SVqEcMZBsZF9mA78rjzCrYrUs37LMJk3ShZ851ygZYW1cMeIjs9mL57KO6Iv5mmjSQnOe/29/VAfGXo+oRCiVw==",
959 "license": "MIT"
960 },
961 "node_modules/unix-path-resolve": {
962 "version": "1.0.2",
963 "resolved": "https://registry.npmjs.org/unix-path-resolve/-/unix-path-resolve-1.0.2.tgz",
964 "integrity": "sha512-kG4g5nobBBaMnH2XbrS4sLUXEpx4nY2J3C6KAlAUcnahG2HChxSPVKWYrqEq76iTo+cyMkLUjqxGaQR2tz097Q==",
965 "license": "MIT"
966 },
967 "node_modules/unslab": {
968 "version": "1.3.0",
969 "resolved": "https://registry.npmjs.org/unslab/-/unslab-1.3.0.tgz",
970 "integrity": "sha512-YATkfKAFj47kTzmiQrWXMyRvaVrHsW6MEALa4bm+FhiA2YG4oira+Z3DXN6LrYOYn2Y8eO94Lwl9DOHjs1FpoQ==",
971 "license": "Apache-2.0",
972 "dependencies": {
973 "b4a": "^1.6.6"
974 }
975 },
976 "node_modules/varint": {
977 "version": "5.0.0",
978 "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.0.tgz",
979 "integrity": "sha512-gC13b/bWrqQoKY2EmROCZ+AR0jitc6DnDGaQ6Ls9QpKmuSgJB1eQ7H3KETtQm7qSdMWMKCmsshyCmUwMLh3OAA==",
980 "license": "MIT"
981 },
982 "node_modules/which-runtime": {
983 "version": "1.3.2",
984 "resolved": "https://registry.npmjs.org/which-runtime/-/which-runtime-1.3.2.tgz",
985 "integrity": "sha512-5kwCfWml7+b2NO7KrLMhYihjRx0teKkd3yGp1Xk5Vaf2JGdSh+rgVhEALAD9c/59dP+YwJHXoEO7e8QPy7gOkw==",
986 "license": "Apache-2.0"
987 },
988 "node_modules/xache": {
989 "version": "1.2.1",
990 "resolved": "https://registry.npmjs.org/xache/-/xache-1.2.1.tgz",
991 "integrity": "sha512-igRS6jPreJ54ABdzhh4mCDXcz+XMaWO2q1ABRV2yWYuk29jlp8VT7UBdCqNkX7rpYBbXsebVVKkwIuYZjyZNqA==",
992 "license": "MIT"
993 },
994 "node_modules/z32": {
995 "version": "1.1.0",
996 "resolved": "https://registry.npmjs.org/z32/-/z32-1.1.0.tgz",
997 "integrity": "sha512-1WUHy+VS6d0HPNspDxvLssBbeQjXMjSnpv0vH82vRAUfg847NmX3OXozp/hRP5jPhxBbrVzrgvAt+UsGNzRFQQ==",
998 "license": "MIT",
999 "dependencies": {
1000 "b4a": "^1.5.3"
1001 }
1002 }
1003 }
1004}
node_modules/@hyperswarm/secret-stream/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/@hyperswarm/secret-stream/README.md +160 -0
……@@ -0,0 +1,160 @@
1# @hyperswarm/secret-stream
2
3### [See the full API docs at docs.holepunch.to](https://docs.holepunch.to/building-blocks/hyperswarm#secretstream)
4
5Secret stream backed by Noise and libsodium's secretstream
6
7```
8npm install @hyperswarm/secret-stream
9```
10
11## Usage
12
13You can either make a secret stream from an existing transport stream.
14
15```js
16const SecretStream = require('@hyperswarm/secret-stream')
17
18const a = new SecretStream(true, tcpClientStream)
19const b = new SecretStream(false, tcpServerStream)
20
21// pipe the underlying rawstreams together
22
23a.write(Buffer.from('hello encrypted!'))
24
25b.on('data', function (data) {
26 console.log(data) // <Buffer hello encrypted!>
27})
28```
29
30Or by making your own pipeline
31
32```js
33const a = new SecretStream(true)
34const b = new SecretStream(false)
35
36// pipe the underlying rawstreams together
37a.rawStream.pipe(b.rawStream).pipe(a.rawStream)
38
39a.write(Buffer.from('hello encrypted!'))
40
41b.on('data', function (data) {
42 console.log(data) // <Buffer hello encrypted!>
43})
44```
45
46## API
47
48#### `const s = new SecretStream(isInitiator, [rawStream], [options])`
49
50Make a new stream. `isInitiator` is a boolean indication whether you are the client or the server.
51`rawStream` can be set to an underlying transport stream you want to run the noise stream over.
52
53Options include:
54
55```js
56{
57 pattern: 'XX', // which noise pattern to use
58 remotePublicKey, // set if your handshake requires it
59 keyPair: { publicKey, secretKey },
60 handshake: { // if you want to use an handshake performed elsewhere pass it here
61 tx,
62 rx,
63 hash,
64 publicKey,
65 remotePublicKey
66 },
67 enableSend: true // (advanced) set false to disable the send API
68}
69```
70
71The SecretStream returned is a Duplex stream that you use as as normal stream, to write/read data from,
72except it's payloads are encrypted using the libsodium secretstream.
73
74Note that this uses ed25519 for the handshakes per default.
75
76If need to load the key pair asynchronously, then secret-stream also supports passing in a promise
77instead of the keypair that later resolves to `{ publicKey, secretKey }`. The stream lifecycle will wait
78for the resolution and auto destroy the stream if the promise errors.
79
80#### `s.start(rawStream, [options])`
81
82Start a SecretStream from a rawStream asynchrously.
83
84```js
85const s = new SecretStream({
86 autoStart: false // call start manually
87})
88
89// ... do async stuff or destroy the stream
90
91s.start(rawStream, {
92 ... options from above
93})
94```
95
96#### `s.setTimeout(ms)`
97
98Set the stream timeout. If no data is received within a `ms` window,
99the stream is auto destroyed.
100
101#### `s.setKeepAlive(ms)`
102
103Send a heartbeat (empty message) every time the socket is idle for `ms` milliseconds. **Note:** If one side calls `s.setKeepAlive()` and the other does not, then the empty messages will be passed through to the piped stream.
104
105#### `s.publicKey`
106
107Get the local public key.
108
109#### `s.remotePublicKey`
110
111Get the remote's public key.
112Populated after `open` is emitted.
113
114#### `s.handshakeHash`
115
116Get the unique hash of this handshake.
117Populated after `open` is emitted.
118
119#### `s.keepAlive`
120
121Get the interval (in milliseconds) at which keep-alive messages are sent (0 means none are sent).
122
123#### `s.sendKeepAlive()`
124
125A convenience method that sends an empty message.
126
127#### `s.rawBytesWritten`
128
129The number of bytes (measured after encryption) written.
130
131#### `s.rawBytesRead`
132
133The number of bytes (measured before decryption) received.
134
135#### `s.on('connect', onconnect)`
136
137Emitted when the handshake is fully done.
138It is safe to write to the stream immediately though, as data is buffered
139internally before the handshake has been completed.
140
141#### `await s.send(buffer)`
142
143Sends an encrypted unordered message, see [udx-native](https://github.com/holepunchto/udx-native/tree/main?tab=readme-ov-file#await-streamsendbuffer) for details.
144This method with silently fail if called before handshake is complete or if the underlying rawStream is not an UDX-stream (not capable of UDP).
145
146#### `s.trySend(buffer)`
147
148Same as `send(buffer)` but does not return a promise.
149
150#### `s.on('message', onmessage)`
151
152Emmitted when an unordered message is received
153
154#### `keyPair = SecretStream.keyPair([seed])`
155
156Generate a ed25519 key pair.
157
158## License
159
160Apache-2.0
node_modules/@hyperswarm/secret-stream/index.js +645 -0
……@@ -0,0 +1,645 @@
1const { Pull, Push, HEADERBYTES, KEYBYTES, ABYTES } = require('sodium-secretstream')
2const sodium = require('sodium-universal')
3const crypto = require('hypercore-crypto')
4const { Duplex, Writable, getStreamError } = require('streamx')
5const b4a = require('b4a')
6const Timeout = require('timeout-refresh')
7const unslab = require('unslab')
8const Bridge = require('./lib/bridge')
9const Handshake = require('./lib/handshake')
10
11const IDHEADERBYTES = HEADERBYTES + 32
12const [NS_INITIATOR, NS_RESPONDER, NS_SEND] = crypto.namespace('hyperswarm/secret-stream', 3)
13const MAX_ATOMIC_WRITE = 256 * 256 * 256 - 1
14
15module.exports = class NoiseSecretStream extends Duplex {
16 constructor(isInitiator, rawStream, opts = {}) {
17 super({ mapWritable: toBuffer })
18
19 if (typeof isInitiator !== 'boolean') {
20 throw new Error('isInitiator should be a boolean')
21 }
22
23 this.noiseStream = this
24 this.isInitiator = isInitiator
25 this.rawStream = null
26
27 this.publicKey = opts.publicKey || null
28 this.remotePublicKey = opts.remotePublicKey || null
29 this.handshakeHash = null
30 this.connected = false
31 this.keepAlive = opts.keepAlive || 0
32 this.timeout = 0
33 this.enableSend = opts.enableSend !== false
34
35 // pointer for upstream to set data here if they want
36 this.userData = null
37
38 let openedDone = null
39 this.opened = new Promise((resolve) => {
40 openedDone = resolve
41 })
42
43 this.rawBytesWritten = 0
44 this.rawBytesRead = 0
45
46 // metadata used by 'hyperdht'
47 this.relay = null
48 this.puncher = null
49
50 // unwrapped raw stream
51 this._rawStream = null
52
53 // handshake state
54 this._handshake = null
55 this._handshakePattern = opts.pattern || null
56 this._handshakeDone = null
57
58 // message parsing state
59 this._state = 0
60 this._len = 0
61 this._tmp = 1
62 this._message = null
63
64 this._openedDone = openedDone
65 this._startDone = null
66 this._drainDone = null
67 this._outgoingPlain = null
68 this._outgoingWrapped = null
69 this._utp = null
70 this._setup = true
71 this._ended = 2
72 this._encrypt = null
73 this._decrypt = null
74 this._timeoutTimer = null
75 this._keepAliveTimer = null
76 this._sendState = null
77
78 if (opts.autoStart !== false) this.start(rawStream, opts)
79
80 // wiggle it to trigger open immediately (TODO add streamx option for this)
81 this.resume()
82 this.pause()
83 }
84
85 static keyPair(seed) {
86 return Handshake.keyPair(seed)
87 }
88
89 static id(handshakeHash, isInitiator, id) {
90 return streamId(handshakeHash, isInitiator, id)
91 }
92
93 setTimeout(ms) {
94 if (!ms) ms = 0
95
96 this._clearTimeout()
97 this.timeout = ms
98
99 if (!ms || this.rawStream === null) return
100
101 this._timeoutTimer = Timeout.once(ms, destroyTimeout, this)
102 this._timeoutTimer.unref()
103 }
104
105 setKeepAlive(ms) {
106 if (!ms) ms = 0
107
108 this._clearKeepAlive()
109
110 this.keepAlive = ms
111
112 if (!ms || this.rawStream === null) return
113
114 this._keepAliveTimer = Timeout.on(ms, sendKeepAlive, this)
115 this._keepAliveTimer.unref()
116 }
117
118 sendKeepAlive() {
119 const empty = this.alloc(0)
120 this.write(empty)
121 }
122
123 start(rawStream, opts = {}) {
124 if (rawStream) {
125 this.rawStream = rawStream
126 this._rawStream = rawStream
127 if (typeof this.rawStream.setContentSize === 'function') {
128 this._utp = rawStream
129 }
130 } else {
131 this.rawStream = new Bridge(this)
132 this._rawStream = this.rawStream.reverse
133 }
134
135 this.rawStream.on('error', this._onrawerror.bind(this))
136 this.rawStream.on('close', this._onrawclose.bind(this))
137
138 this._startHandshake(opts.handshake, opts.keyPair || null)
139 this._continueOpen(null)
140
141 if (this.destroying) return
142
143 if (opts.data) this._onrawdata(opts.data)
144 if (opts.ended) this._onrawend()
145
146 if (this.keepAlive > 0 && this._keepAliveTimer === null) {
147 this.setKeepAlive(this.keepAlive)
148 }
149
150 if (this.timeout > 0 && this._timeoutTimer === null) {
151 this.setTimeout(this.timeout)
152 }
153 }
154
155 async flush() {
156 if ((await this.opened) === false) return false
157 if ((await Writable.drained(this)) === false) return false
158 if (this.destroying) return false
159
160 if (this.rawStream !== null && this.rawStream.flush) {
161 return await this.rawStream.flush()
162 }
163
164 return true
165 }
166
167 _continueOpen(err) {
168 if (err) this.destroy(err)
169 if (this._startDone === null) return
170 const done = this._startDone
171 this._startDone = null
172 this._open(done)
173 }
174
175 _onkeypairpromise(p) {
176 const self = this
177 const cont = this._continueOpen.bind(this)
178
179 p.then(onkeypair, cont)
180
181 function onkeypair(kp) {
182 self._onkeypair(kp)
183 cont(null)
184 }
185 }
186
187 _onkeypair(keyPair) {
188 const pattern = this._handshakePattern || 'XX'
189 const remotePublicKey = this.remotePublicKey
190
191 this._handshake = new Handshake(this.isInitiator, keyPair, remotePublicKey, pattern)
192 this.publicKey = this._handshake.keyPair.publicKey
193 }
194
195 _startHandshake(handshake, keyPair) {
196 if (handshake) {
197 const { tx, rx, hash, publicKey, remotePublicKey } = handshake
198 this._setupSecretStream(tx, rx, hash, publicKey, remotePublicKey)
199 return
200 }
201
202 if (!keyPair) keyPair = Handshake.keyPair()
203
204 if (typeof keyPair.then === 'function') {
205 this._onkeypairpromise(keyPair)
206 } else {
207 this._onkeypair(keyPair)
208 }
209 }
210
211 _onrawerror(err) {
212 this.destroy(err)
213 }
214
215 _onrawclose() {
216 if (this._ended !== 0) this.destroy()
217 }
218
219 _onrawdata(data) {
220 let offset = 0
221
222 if (this._timeoutTimer !== null) {
223 this._timeoutTimer.refresh()
224 }
225
226 do {
227 switch (this._state) {
228 case 0: {
229 while (this._tmp !== 0x1000000 && offset < data.byteLength) {
230 const v = data[offset++]
231 this._len += this._tmp * v
232 this._tmp *= 256
233 }
234
235 if (this._tmp === 0x1000000) {
236 this._tmp = 0
237 this._state = 1
238 const unprocessed = data.byteLength - offset
239 if (unprocessed < this._len && this._utp !== null)
240 this._utp.setContentSize(this._len - unprocessed)
241 }
242
243 break
244 }
245
246 case 1: {
247 const missing = this._len - this._tmp
248 const end = missing + offset
249
250 if (this._message === null && end <= data.byteLength) {
251 this._message = data.subarray(offset, end)
252 offset += missing
253 this._incoming()
254 break
255 }
256
257 const unprocessed = data.byteLength - offset
258
259 if (this._message === null) {
260 this._message = b4a.allocUnsafe(this._len)
261 }
262
263 b4a.copy(data, this._message, this._tmp, offset)
264 this._tmp += unprocessed
265
266 if (end <= data.byteLength) {
267 offset += missing
268 this._incoming()
269 } else {
270 offset += unprocessed
271 }
272
273 break
274 }
275 }
276 } while (offset < data.byteLength && !this.destroying)
277 }
278
279 _onrawend() {
280 this._ended--
281 this.push(null)
282 }
283
284 _onrawdrain() {
285 const drain = this._drainDone
286 if (drain === null) return
287 this._drainDone = null
288 drain()
289 }
290
291 _read(cb) {
292 this.rawStream.resume()
293 cb(null)
294 }
295
296 _incoming() {
297 const message = this._message
298
299 this._state = 0
300 this._len = 0
301 this._tmp = 1
302 this._message = null
303
304 if (this._setup === true) {
305 if (this._handshake) {
306 this._onhandshakert(this._handshake.recv(message))
307 } else {
308 if (message.byteLength !== IDHEADERBYTES) {
309 this.destroy(new Error('Invalid header message received'))
310 return
311 }
312
313 const remoteId = message.subarray(0, 32)
314 const expectedId = streamId(this.handshakeHash, !this.isInitiator)
315 const header = message.subarray(32)
316
317 if (!b4a.equals(expectedId, remoteId)) {
318 this.destroy(new Error('Invalid header received'))
319 return
320 }
321
322 this._decrypt.init(header)
323 this._setup = false // setup is now done
324 }
325 return
326 }
327
328 if (message.byteLength < ABYTES) {
329 this.destroy(new Error('Invalid message received'))
330 return
331 }
332
333 this.rawBytesRead += message.byteLength
334
335 const plain = message.subarray(1, message.byteLength - ABYTES + 1)
336
337 try {
338 this._decrypt.next(message, plain)
339 } catch (err) {
340 this.destroy(err)
341 return
342 }
343
344 // If keep alive is selective, eat the empty buffers (ie assume the other side has it enabled also)
345 if (plain.byteLength === 0 && this.keepAlive !== 0) return
346
347 if (this.push(plain) === false) {
348 this.rawStream.pause()
349 }
350 }
351
352 _onhandshakert(h) {
353 if (this._handshakeDone === null) return
354
355 if (h !== null) {
356 if (h.data) this._rawStream.write(h.data)
357 if (!h.tx) return
358 }
359
360 const done = this._handshakeDone
361 const publicKey = this._handshake.keyPair.publicKey
362
363 this._handshakeDone = null
364 this._handshake = null
365
366 if (h === null) return done(new Error('Noise handshake failed'))
367
368 this._setupSecretStream(h.tx, h.rx, h.hash, publicKey, h.remotePublicKey)
369 this._resolveOpened(true)
370 done(null)
371 }
372
373 _setupSecretStream(tx, rx, handshakeHash, publicKey, remotePublicKey) {
374 const buf = b4a.allocUnsafeSlow(3 + IDHEADERBYTES)
375 writeUint24le(IDHEADERBYTES, buf)
376
377 this._encrypt = new Push(unslab(tx.subarray(0, KEYBYTES)), undefined, buf.subarray(3 + 32))
378 this._decrypt = new Pull(unslab(rx.subarray(0, KEYBYTES)))
379
380 this.publicKey = publicKey
381 this.remotePublicKey = remotePublicKey
382 this.handshakeHash = handshakeHash
383
384 const id = buf.subarray(3, 3 + 32)
385 streamId(handshakeHash, this.isInitiator, id)
386
387 // initialize secretbox state for unordered messages
388 this._setupSecretSend(handshakeHash)
389
390 this.emit('handshake')
391 // if rawStream is a bridge, also emit it there
392 if (this.rawStream !== this._rawStream) this.rawStream.emit('handshake')
393
394 if (this.destroying) return
395
396 this._rawStream.write(buf)
397 }
398
399 _setupSecretSend(handshakeHash) {
400 this._sendState = b4a.allocUnsafeSlow(32 + 32 + 8 + 8)
401 const encrypt = this._sendState.subarray(0, 32) // secrets
402 const decrypt = this._sendState.subarray(32, 64)
403 const counter = this._sendState.subarray(64, 72) // nonce
404 const initial = this._sendState.subarray(72)
405
406 const inputs = this.isInitiator
407 ? [
408 [NS_INITIATOR, NS_SEND],
409 [NS_RESPONDER, NS_SEND]
410 ]
411 : [
412 [NS_RESPONDER, NS_SEND],
413 [NS_INITIATOR, NS_SEND]
414 ]
415
416 sodium.crypto_generichash_batch(encrypt, inputs[0], handshakeHash)
417 sodium.crypto_generichash_batch(decrypt, inputs[1], handshakeHash)
418
419 sodium.randombytes_buf(initial)
420 counter.set(initial)
421 }
422
423 _open(cb) {
424 // no autostart or no handshake yet
425 if (this._rawStream === null || (this._handshake === null && this._encrypt === null)) {
426 this._startDone = cb
427 return
428 }
429
430 this._rawStream.on('data', this._onrawdata.bind(this))
431 this._rawStream.on('end', this._onrawend.bind(this))
432 this._rawStream.on('drain', this._onrawdrain.bind(this))
433
434 if (this.enableSend) this._rawStream.on('message', this._onmessage.bind(this))
435
436 if (this._encrypt !== null) {
437 this._resolveOpened(true)
438 return cb(null)
439 }
440
441 this._handshakeDone = cb
442
443 if (this.isInitiator) this._onhandshakert(this._handshake.send())
444 }
445
446 _predestroy() {
447 if (this.rawStream) {
448 const error = getStreamError(this)
449 this.rawStream.destroy(error)
450 }
451
452 if (this._startDone !== null) {
453 const done = this._startDone
454 this._startDone = null
455 done(new Error('Stream destroyed'))
456 }
457
458 if (this._handshakeDone !== null) {
459 const done = this._handshakeDone
460 this._handshakeDone = null
461 done(new Error('Stream destroyed'))
462 }
463
464 if (this._drainDone !== null) {
465 const done = this._drainDone
466 this._drainDone = null
467 done(new Error('Stream destroyed'))
468 }
469 }
470
471 _write(data, cb) {
472 let wrapped = this._outgoingWrapped
473
474 if (data !== this._outgoingPlain) {
475 wrapped = b4a.allocUnsafe(data.byteLength + 3 + ABYTES)
476 wrapped.set(data, 4)
477 } else {
478 this._outgoingWrapped = this._outgoingPlain = null
479 }
480
481 if (wrapped.byteLength - 3 > MAX_ATOMIC_WRITE) {
482 return cb(
483 new Error(
484 'Message is too large for an atomic write. Max size is ' + MAX_ATOMIC_WRITE + ' bytes.'
485 )
486 )
487 }
488 this.rawBytesWritten += wrapped.byteLength
489
490 writeUint24le(wrapped.byteLength - 3, wrapped)
491 // offset 4 so we can do it in-place
492 this._encrypt.next(wrapped.subarray(4, 4 + data.byteLength), wrapped.subarray(3))
493
494 if (this._keepAliveTimer !== null) this._keepAliveTimer.refresh()
495
496 if (this._rawStream.write(wrapped) === false) {
497 this._drainDone = cb
498 } else {
499 cb(null)
500 }
501 }
502
503 _final(cb) {
504 this._clearKeepAlive()
505 this._ended--
506 this._rawStream.end()
507 cb(null)
508 }
509
510 _resolveOpened(val) {
511 if (this._openedDone === null) return
512 const opened = this._openedDone
513 this._openedDone = null
514 opened(val)
515 if (!val) return
516 this.connected = true
517 this.emit('connect')
518 }
519
520 _clearTimeout() {
521 if (this._timeoutTimer === null) return
522 this._timeoutTimer.destroy()
523 this._timeoutTimer = null
524 this.timeout = 0
525 }
526
527 _clearKeepAlive() {
528 if (this._keepAliveTimer === null) return
529 this._keepAliveTimer.destroy()
530 this._keepAliveTimer = null
531 this.keepAlive = 0
532 }
533
534 _destroy(cb) {
535 this._clearKeepAlive()
536 this._clearTimeout()
537 this._resolveOpened(false)
538 cb(null)
539 }
540
541 _boxMessage(buffer) {
542 const MB = sodium.crypto_secretbox_MACBYTES // 16
543 const NB = sodium.crypto_secretbox_NONCEBYTES // 24
544
545 const counter = this._sendState.subarray(64, 72)
546 sodium.sodium_increment(counter)
547 if (b4a.equals(counter, this._sendState.subarray(72))) {
548 this.destroy(new Error('udp send nonce exchausted'))
549 return
550 }
551
552 const secret = this._sendState.subarray(0, 32)
553 const envelope = b4a.allocUnsafe(8 + MB + buffer.byteLength)
554 const nonce = envelope.subarray(0, NB)
555 const ciphertext = envelope.subarray(8)
556
557 b4a.fill(nonce, 0) // pad suffix
558 nonce.set(counter)
559
560 sodium.crypto_secretbox_easy(ciphertext, buffer, nonce, secret)
561 return envelope
562 }
563
564 send(buffer) {
565 if (!this._sendState) return
566 if (!this.rawStream?.send) return // udx-stream expected
567
568 const message = this._boxMessage(buffer)
569 return this.rawStream.send(message)
570 }
571
572 trySend(buffer) {
573 if (!this._sendState) return
574 if (!this.rawStream?.trySend) return // udx-stream expected
575
576 const message = this._boxMessage(buffer)
577 this.rawStream.trySend(message)
578 }
579
580 _onmessage(buffer) {
581 if (!this._sendState) return // messages before handshake are dropped
582
583 const MB = sodium.crypto_secretbox_MACBYTES // 16
584 const NB = sodium.crypto_secretbox_NONCEBYTES // 24
585
586 if (buffer.byteLength < NB) return // Invalid message
587
588 const nonce = b4a.allocUnsafe(NB)
589 b4a.fill(nonce, 0)
590 nonce.set(buffer.subarray(0, 8))
591
592 const secret = this._sendState.subarray(32, 64)
593 const ciphertext = buffer.subarray(8)
594 const plain = buffer.subarray(8, buffer.byteLength - MB)
595
596 if (ciphertext.byteLength < MB) return // invalid message
597
598 const success = sodium.crypto_secretbox_open_easy(plain, ciphertext, nonce, secret)
599
600 if (success) this.emit('message', plain)
601 }
602
603 alloc(len) {
604 const buf = b4a.allocUnsafe(len + 3 + ABYTES)
605 this._outgoingWrapped = buf
606 this._outgoingPlain = buf.subarray(4, buf.byteLength - ABYTES + 1)
607 return this._outgoingPlain
608 }
609
610 toJSON() {
611 return {
612 isInitiator: this.isInitiator,
613 publicKey: this.publicKey && b4a.toString(this.publicKey, 'hex'),
614 remotePublicKey: this.remotePublicKey && b4a.toString(this.remotePublicKey, 'hex'),
615 connected: this.connected,
616 destroying: this.destroying,
617 destroyed: this.destroyed,
618 rawStream: this.rawStream && this.rawStream.toJSON ? this.rawStream.toJSON() : null
619 }
620 }
621}
622
623function writeUint24le(n, buf) {
624 buf[0] = n & 255
625 buf[1] = (n >>> 8) & 255
626 buf[2] = (n >>> 16) & 255
627}
628
629function streamId(handshakeHash, isInitiator, out = b4a.allocUnsafe(32)) {
630 sodium.crypto_generichash(out, isInitiator ? NS_INITIATOR : NS_RESPONDER, handshakeHash)
631 return out
632}
633
634function toBuffer(data) {
635 return typeof data === 'string' ? b4a.from(data) : data
636}
637
638function destroyTimeout() {
639 this.destroy(new Error('Stream timed out'))
640}
641
642function sendKeepAlive() {
643 const empty = this.alloc(0)
644 this.write(empty)
645}
node_modules/@hyperswarm/secret-stream/lib/bridge.js +76 -0
……@@ -0,0 +1,76 @@
1const { Duplex, Writable } = require('streamx')
2
3class ReversePassThrough extends Duplex {
4 constructor(s) {
5 super()
6 this._stream = s
7 this._ondrain = null
8 }
9
10 _write(data, cb) {
11 if (this._stream.push(data) === false) {
12 this._stream._ondrain = cb
13 } else {
14 cb(null)
15 }
16 }
17
18 _final(cb) {
19 this._stream.push(null)
20 cb(null)
21 }
22
23 _read(cb) {
24 const ondrain = this._ondrain
25 this._ondrain = null
26 if (ondrain) ondrain()
27 cb(null)
28 }
29}
30
31module.exports = class Bridge extends Duplex {
32 constructor(noiseStream) {
33 super()
34
35 this.noiseStream = noiseStream
36
37 this._ondrain = null
38 this.reverse = new ReversePassThrough(this)
39 }
40
41 get publicKey() {
42 return this.noiseStream.publicKey
43 }
44
45 get remotePublicKey() {
46 return this.noiseStream.remotePublicKey
47 }
48
49 get handshakeHash() {
50 return this.noiseStream.handshakeHash
51 }
52
53 flush() {
54 return Writable.drained(this)
55 }
56
57 _read(cb) {
58 const ondrain = this._ondrain
59 this._ondrain = null
60 if (ondrain) ondrain()
61 cb(null)
62 }
63
64 _write(data, cb) {
65 if (this.reverse.push(data) === false) {
66 this.reverse._ondrain = cb
67 } else {
68 cb(null)
69 }
70 }
71
72 _final(cb) {
73 this.reverse.push(null)
74 cb(null)
75 }
76}
node_modules/@hyperswarm/secret-stream/lib/handshake.js +78 -0
……@@ -0,0 +1,78 @@
1const sodium = require('sodium-universal')
2const curve = require('noise-curve-ed')
3const Noise = require('noise-handshake')
4const b4a = require('b4a')
5
6const EMPTY = b4a.alloc(0)
7
8module.exports = class Handshake {
9 constructor(isInitiator, keyPair, remotePublicKey, pattern) {
10 this.isInitiator = isInitiator
11 this.keyPair = keyPair
12 this.noise = new Noise(pattern, isInitiator, keyPair, { curve })
13 this.noise.initialise(EMPTY, remotePublicKey)
14 this.destroyed = false
15 }
16
17 static keyPair(seed) {
18 const publicKey = b4a.alloc(32)
19 const secretKey = b4a.alloc(64)
20 if (seed) sodium.crypto_sign_seed_keypair(publicKey, secretKey, seed)
21 else sodium.crypto_sign_keypair(publicKey, secretKey)
22 return { publicKey, secretKey }
23 }
24
25 recv(data) {
26 try {
27 this.noise.recv(data)
28 if (this.noise.complete) return this._return(null)
29 return this.send()
30 } catch {
31 this.destroy()
32 return null
33 }
34 }
35
36 // note that the data returned here is framed so we don't have to do an extra copy
37 // when sending it...
38 send() {
39 try {
40 const data = this.noise.send()
41 const wrap = b4a.allocUnsafe(data.byteLength + 3)
42
43 writeUint24le(data.byteLength, wrap)
44 wrap.set(data, 3)
45
46 return this._return(wrap)
47 } catch {
48 this.destroy()
49 return null
50 }
51 }
52
53 destroy() {
54 if (this.destroyed) return
55 this.destroyed = true
56 }
57
58 _return(data) {
59 const tx = this.noise.complete ? b4a.toBuffer(this.noise.tx) : null
60 const rx = this.noise.complete ? b4a.toBuffer(this.noise.rx) : null
61 const hash = this.noise.complete ? b4a.toBuffer(this.noise.hash) : null
62 const remotePublicKey = this.noise.complete ? b4a.toBuffer(this.noise.rs) : null
63
64 return {
65 data,
66 remotePublicKey,
67 hash,
68 tx,
69 rx
70 }
71 }
72}
73
74function writeUint24le(n, buf) {
75 buf[0] = n & 255
76 buf[1] = (n >>> 8) & 255
77 buf[2] = (n >>> 16) & 255
78}
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/CMakeLists.txt +279 -0
……@@ -0,0 +1,279 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6find_package(cmake-npm REQUIRED PATHS node_modules/cmake-npm)
7
8set(CMAKE_POSITION_INDEPENDENT_CODE ON)
9
10project(sodium_native C ASM CXX)
11
12fetch_package("github:jedisct1/libsodium#e18eee6" SOURCE_DIR sodium)
13
14fetch_package("github:holepunchto/libjstl#098664c")
15
16bare_target(target)
17
18if(target MATCHES "win32")
19 add_compile_options(/MT$<$<CONFIG:Debug>:d>)
20endif()
21
22file(COPY_FILE "${sodium}/builds/msvc/version.h" "${sodium}/src/libsodium/include/sodium/version.h")
23
24file(GLOB_RECURSE sodium_headers CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.h")
25file(GLOB_RECURSE sodium_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.c")
26file(GLOB_RECURSE sodium_asm_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.S")
27
28add_library(sodium OBJECT)
29
30target_sources(
31 sodium
32 INTERFACE
33 ${sodium_headers}
34 PRIVATE
35 ${sodium_sources}
36)
37
38target_include_directories(
39 sodium
40 INTERFACE
41 "${sodium}/src/libsodium/include"
42 PRIVATE
43 "${sodium}/src/libsodium/include/sodium"
44)
45
46if(NOT target MATCHES "win32")
47 target_compile_options(
48 sodium
49 PRIVATE
50 -fvisibility=hidden
51 -fno-strict-aliasing
52 -fwrapv
53 -flax-vector-conversions
54 )
55endif()
56
57target_compile_definitions(
58 sodium
59 PUBLIC
60 SODIUM_STATIC=1
61 PRIVATE
62 _GNU_SOURCE=1
63 CONFIGURED=1
64 DEV_MODE=1
65 HAVE_ATOMIC_OPS=1
66 HAVE_C11_MEMORY_FENCES=1
67 HAVE_CET_H=1
68 HAVE_GCC_MEMORY_FENCES=1
69 HAVE_INLINE_ASM=1
70 HAVE_INTTYPES_H=1
71 HAVE_STDINT_H=1
72 HAVE_TI_MODE=1
73)
74
75if(target MATCHES "darwin|ios")
76 target_compile_definitions(
77 sodium
78 PRIVATE
79 ASM_HIDE_SYMBOL=.private_extern
80 TLS=_Thread_local
81 HAVE_ARC4RANDOM=1
82 HAVE_ARC4RANDOM_BUF=1
83 HAVE_CATCHABLE_ABRT=1
84 HAVE_CATCHABLE_SEGV=1
85 HAVE_CLOCK_GETTIME=1
86 HAVE_GETPID=1
87 HAVE_MADVISE=1
88 HAVE_MEMSET_S=1
89 HAVE_MLOCK=1
90 HAVE_MMAP=1
91 HAVE_MPROTECT=1
92 HAVE_NANOSLEEP=1
93 HAVE_POSIX_MEMALIGN=1
94 HAVE_PTHREAD=1
95 HAVE_PTHREAD_PRIO_INHERIT=1
96 HAVE_RAISE=1
97 HAVE_SYSCONF=1
98 HAVE_SYS_MMAN_H=1
99 HAVE_SYS_PARAM_H=1
100 HAVE_WEAK_SYMBOLS=1
101 )
102
103 if(NOT target MATCHES "ios")
104 target_compile_definitions(
105 sodium
106 PRIVATE
107 HAVE_GETENTROPY=1
108 HAVE_SYS_RANDOM_H=1
109 )
110 endif()
111endif()
112
113if(target MATCHES "linux")
114 target_compile_definitions(
115 sodium
116 PRIVATE
117 ASM_HIDE_SYMBOL=.hidden
118 TLS=_Thread_local
119 HAVE_CATCHABLE_ABRT=1
120 HAVE_CATCHABLE_SEGV=1
121 HAVE_CLOCK_GETTIME=1
122 HAVE_GETPID=1
123 HAVE_MADVISE=1
124 HAVE_MLOCK=1
125 HAVE_MMAP=1
126 HAVE_MPROTECT=1
127 HAVE_NANOSLEEP=1
128 HAVE_POSIX_MEMALIGN=1
129 HAVE_PTHREAD_PRIO_INHERIT=1
130 HAVE_PTHREAD=1
131 HAVE_RAISE=1
132 HAVE_SYSCONF=1
133 HAVE_SYS_AUXV_H=1
134 HAVE_SYS_MMAN_H=1
135 HAVE_SYS_PARAM_H=1
136 HAVE_SYS_RANDOM_H=1
137 HAVE_WEAK_SYMBOLS=1
138 )
139endif()
140
141if(target MATCHES "win32")
142 target_compile_definitions(
143 sodium
144 PRIVATE
145 _CRT_SECURE_NO_WARNINGS=1
146 HAVE_RAISE=1
147 )
148endif()
149
150if(target MATCHES "x64")
151 target_compile_definitions(
152 sodium
153 PRIVATE
154 HAVE_CPUID=1
155 HAVE_RDRAND=1
156 HAVE_EMMINTRIN_H=1 # SSE2
157 HAVE_PMMINTRIN_H=1 # SSE3
158 HAVE_TMMINTRIN_H=1 # SSSE3
159 HAVE_SMMINTRIN_H=1 # SSE4.1
160 HAVE_WMMINTRIN_H=1 # AES
161 HAVE_AVXINTRIN_H=1 # AVX
162 HAVE_AVX2INTRIN_H=1 # AVX2
163 HAVE_AVX512FINTRIN_H # AVX512F
164 )
165
166 if(NOT target MATCHES "win32")
167 target_compile_definitions(
168 sodium
169 PRIVATE
170 HAVE_AMD64_ASM=1
171 HAVE_AVX_ASM=1
172 )
173
174 target_sources(
175 sodium
176 PRIVATE
177 ${sodium_asm_sources}
178 )
179 endif()
180endif()
181
182if(target MATCHES "arm64")
183 target_compile_definitions(
184 sodium
185 PRIVATE
186 HAVE_ARMCRYPTO=1
187 )
188endif()
189
190if(CMAKE_C_BYTE_ORDER MATCHES "BIG_ENDIAN")
191 target_compile_definitions(
192 sodium
193 PRIVATE
194 NATIVE_BIG_ENDIAN=1
195 )
196else()
197 target_compile_definitions(
198 sodium
199 PRIVATE
200 NATIVE_LITTLE_ENDIAN=1
201 )
202endif()
203
204if(target MATCHES "linux|android")
205 target_link_options(
206 sodium
207 PUBLIC
208 -Wl,-z,noexecstack
209 )
210endif()
211
212add_library(sodium_extensions OBJECT)
213
214target_sources(
215 sodium_extensions
216 PRIVATE
217 extensions/tweak/tweak.c
218 extensions/tweak/tweak.h
219 extensions/pbkdf2/pbkdf2.c
220 extensions/pbkdf2/pbkdf2.h
221)
222
223target_link_libraries(
224 sodium_extensions
225 PUBLIC
226 sodium
227)
228
229add_bare_module(sodium_native_bare)
230
231target_sources(
232 ${sodium_native_bare}
233 PRIVATE
234 binding.cc
235)
236
237target_link_libraries(
238 ${sodium_native_bare}
239 PRIVATE
240 $<TARGET_OBJECTS:sodium>
241 $<TARGET_OBJECTS:sodium_extensions>
242 jstl
243 PUBLIC
244 sodium
245 sodium_extensions
246)
247
248add_napi_module(sodium_native_node)
249
250target_sources(
251 ${sodium_native_node}
252 PRIVATE
253 binding.cc
254)
255
256target_compile_definitions(
257 ${sodium_native_node}
258 PRIVATE
259 NAPI_VERSION=9
260)
261
262target_link_libraries(
263 ${sodium_native_node}
264 PRIVATE
265 $<TARGET_OBJECTS:sodium>
266 $<TARGET_OBJECTS:sodium_extensions>
267 jstl
268 PUBLIC
269 sodium
270 sodium_extensions
271)
272
273resolve_node_module(bare-compat-napi compat)
274
275target_include_directories(
276 ${sodium_native_node}
277 PRIVATE
278 "${compat}/include"
279)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2016 Mathias Buus and Emil Bay
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/README.md +51 -0
……@@ -0,0 +1,51 @@
1# sodium-native
2
3Low level bindings for [libsodium](https://github.com/jedisct1/libsodium).
4
5```
6npm install sodium-native
7```
8
9The goal of this project is to be thin, stable, unopionated wrapper around libsodium.
10
11All methods exposed are more or less a direct translation of the libsodium c-api.
12This means that most data types are buffers and you have to manage allocating return values and passing them in as arguments instead of receiving them as return values.
13
14This makes this API harder to use than other libsodium wrappers out there, but also means that you'll be able to get a lot of perf / memory improvements as you can do stuff like inline encryption / decryption, reuse buffers etc.
15
16This also makes this library useful as a foundation for more high level crypto abstractions that you want to make.
17
18## Usage
19
20```js
21var sodium = require('sodium-native')
22
23var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
24var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) // secure buffer
25var message = Buffer.from('Hello, World!')
26var ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
27
28sodium.randombytes_buf(nonce) // insert random data into nonce
29sodium.randombytes_buf(key) // insert random data into key
30
31// encrypted message is stored in ciphertext.
32sodium.crypto_secretbox_easy(ciphertext, message, nonce, key)
33
34console.log('Encrypted message:', ciphertext)
35
36var plainText = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES)
37
38if (!sodium.crypto_secretbox_open_easy(plainText, ciphertext, nonce, key)) {
39 console.log('Decryption failed!')
40} else {
41 console.log('Decrypted message:', plainText, '(' + plainText.toString() + ')')
42}
43```
44
45## Documentation
46
47Complete documentation may be found on the [sodium-friends website](https://sodium-friends.github.io/docs/docs/getstarted)
48
49## License
50
51MIT
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/binding.cc +4094 -0
……@@ -0,0 +1,4094 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4#include <jstl.h>
5#include <sodium.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <string.h>
9#include <uv.h>
10
11#include "extensions/pbkdf2/pbkdf2.h"
12#include "extensions/tweak/tweak.h"
13
14#define assert_bounds(arraybuffer) \
15 assert(arraybuffer##_offset + arraybuffer##_len <= arraybuffer.size())
16
17static inline void
18sn_sodium_memzero(
19 js_env_t *,
20 js_receiver_t,
21 js_typedarray_span_t<> buf
22) {
23 sodium_memzero(buf.data(), buf.size_bytes());
24}
25
26static inline int
27sn_sodium_mlock(
28 js_env_t *,
29 js_receiver_t,
30 js_typedarray_span_t<> buf
31) {
32 return sodium_mlock(buf.data(), buf.size_bytes());
33}
34
35static inline int
36sn_sodium_munlock(
37 js_env_t *,
38 js_receiver_t,
39 js_typedarray_span_t<> buf
40) {
41 return sodium_munlock(buf.data(), buf.size_bytes());
42}
43
44static void
45sn_external_arraybuffer_finalize(js_env_t *env, uint8_t *ptr) {
46 sodium_free(ptr);
47}
48
49static js_arraybuffer_t
50sn_sodium_malloc(js_env_t *env, js_receiver_t, uint32_t len) {
51 int err;
52
53 auto ptr = reinterpret_cast<uint8_t *>(sodium_malloc(len));
54
55 js_arraybuffer_t buffer;
56
57 err = js_create_external_arraybuffer<sn_external_arraybuffer_finalize>(env, ptr, len, buffer);
58 assert(err == 0);
59
60 return buffer;
61}
62
63static void
64sn_sodium_free(js_env_t *env, js_receiver_t, js_arraybuffer_t buf) {
65 int err;
66
67 std::span<uint8_t> view;
68 err = js_get_arraybuffer_info(env, buf, view);
69 assert(err == 0);
70
71 if (view.empty()) return;
72
73 err = js_detach_arraybuffer(env, buf);
74 assert(err == 0);
75}
76
77static inline int
78sn_sodium_mprotect_noaccess(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
79 return sodium_mprotect_noaccess(buf.data());
80}
81
82static inline int
83sn_sodium_mprotect_readonly(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
84 return sodium_mprotect_readonly(buf.data());
85}
86
87static inline int
88sn_sodium_mprotect_readwrite(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
89 return sodium_mprotect_readwrite(buf.data());
90}
91
92static inline uint32_t // TODO: test envless
93sn_randombytes_random(js_env_t *env, js_receiver_t) {
94 return randombytes_random();
95}
96
97static inline uint32_t // TODO: test envless
98sn_randombytes_uniform(js_env_t *env, js_receiver_t, uint32_t upper_bound) {
99 return randombytes_uniform(upper_bound);
100}
101
102static inline void
103sn_randombytes_buf(
104 js_env_t *env,
105 js_receiver_t,
106 js_arraybuffer_span_t buf,
107 uint32_t buf_offset,
108 uint32_t buf_len
109) {
110 assert_bounds(buf);
111
112 randombytes_buf(&buf[buf_offset], buf_len);
113}
114
115static inline void
116sn_randombytes_buf_deterministic(
117 js_env_t *env,
118 js_receiver_t,
119
120 js_arraybuffer_span_t buf,
121 uint32_t buf_offset,
122 uint32_t buf_len,
123
124 js_arraybuffer_span_t seed,
125 uint32_t seed_offset,
126 uint32_t seed_len
127) {
128 assert_bounds(buf);
129 assert_bounds(seed);
130
131 assert(seed_len == randombytes_SEEDBYTES);
132
133 randombytes_buf_deterministic(&buf[buf_offset], buf_len, &seed[seed_offset]);
134}
135
136static inline bool
137sn_sodium_memcmp(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
138 if (a.size_bytes() != b.size_bytes()) return false;
139
140 return sodium_memcmp(a.data(), b.data(), a.size_bytes()) == 0;
141}
142
143static inline void
144sn_sodium_increment(js_env_t *, js_receiver_t, js_typedarray_span_t<> n) {
145 sodium_increment(n.data(), n.size_bytes());
146}
147
148static inline void
149sn_sodium_add(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
150 sodium_add(a.data(), b.data(), a.size_bytes());
151}
152
153static inline void
154sn_sodium_sub(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
155 sodium_sub(a.data(), b.data(), a.size_bytes());
156}
157
158static inline int32_t
159sn_sodium_compare(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
160 return sodium_compare(a.data(), b.data(), a.size_bytes());
161}
162
163static inline bool
164sn_sodium_is_zero(js_env_t *, js_receiver_t, js_typedarray_span_t<> buffer, uint32_t len) {
165 assert(len <= buffer.size_bytes());
166
167 return sodium_is_zero(buffer.data(), len) != 0;
168}
169
170static inline uint32_t
171sn_sodium_pad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t unpadded_buflen, uint32_t blocksize) {
172 size_t padded_buflen;
173
174 sodium_pad(&padded_buflen, buf.data(), unpadded_buflen, blocksize, buf.size_bytes());
175
176 return padded_buflen;
177}
178
179static inline uint32_t
180sn_sodium_unpad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t padded_buflen, uint32_t blocksize) {
181 size_t unpadded_buflen;
182
183 sodium_unpad(&unpadded_buflen, buf.data(), padded_buflen, blocksize);
184
185 return unpadded_buflen;
186}
187
188static inline int
189sn_crypto_sign_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
190 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
191 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
192
193 return crypto_sign_keypair(pk.data(), sk.data());
194}
195
196static inline int
197sn_crypto_sign_seed_keypair(
198 js_env_t *,
199 js_receiver_t,
200 js_typedarray_span_t<> pk,
201 js_typedarray_span_t<> sk,
202 js_typedarray_span_t<> seed
203) {
204 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
205 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
206 assert(seed.size_bytes() == crypto_sign_SEEDBYTES);
207
208 return crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data());
209}
210
211static inline int
212sn_crypto_sign(
213 js_env_t *,
214 js_receiver_t,
215 js_typedarray_span_t<> sm,
216 js_typedarray_span_t<> m,
217 js_typedarray_span_t<> sk
218) {
219 assert(sm.size_bytes() == crypto_sign_BYTES + m.size_bytes());
220 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
221
222 return crypto_sign(sm.data(), NULL, m.data(), m.size_bytes(), sk.data());
223}
224
225static inline bool
226sn_crypto_sign_open(
227 js_env_t *,
228 js_receiver_t,
229 js_typedarray_span_t<> m,
230 js_typedarray_span_t<> sm,
231 js_typedarray_span_t<> pk
232) {
233 assert(m.size_bytes() == sm.size_bytes() - crypto_sign_BYTES);
234 assert(sm.size_bytes() >= crypto_sign_BYTES);
235 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
236
237 return crypto_sign_open(m.data(), NULL, sm.data(), sm.size_bytes(), pk.data()) == 0;
238}
239
240static inline int
241sn_crypto_sign_detached(
242 js_env_t *env,
243 js_receiver_t,
244 js_typedarray_span_t<> sig,
245 js_typedarray_span_t<> m,
246 js_typedarray_span_t<> sk
247) {
248 assert(sig.size_bytes() == crypto_sign_BYTES);
249 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
250
251 return crypto_sign_detached(sig.data(), NULL, m.data(), m.size_bytes(), sk.data());
252}
253
254static inline bool
255sn_crypto_sign_verify_detached(
256 js_env_t *env,
257 js_receiver_t,
258
259 js_arraybuffer_span_t sig,
260 uint32_t sig_offset,
261 uint32_t sig_len,
262
263 js_arraybuffer_span_t m,
264 uint32_t m_offset,
265 uint32_t m_len,
266
267 js_arraybuffer_span_t pk,
268 uint32_t pk_offset,
269 uint32_t pk_len
270) {
271 assert_bounds(sig);
272 assert_bounds(m);
273 assert_bounds(pk);
274
275 assert(sig_len >= crypto_sign_BYTES);
276 assert(pk_len == crypto_sign_PUBLICKEYBYTES);
277
278 return crypto_sign_verify_detached(&sig[sig_offset], &m[m_offset], m_len, &pk[pk_offset]) == 0;
279}
280
281static inline int
282sn_crypto_sign_ed25519_sk_to_pk(
283 js_env_t *,
284 js_receiver_t,
285 js_typedarray_span_t<> pk,
286 js_typedarray_span_t<> sk
287) {
288 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
289 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
290
291 return crypto_sign_ed25519_sk_to_pk(pk.data(), sk.data());
292}
293
294static inline int
295sn_crypto_sign_ed25519_pk_to_curve25519(
296 js_env_t *,
297 js_receiver_t,
298 js_typedarray_span_t<> x25519_pk,
299 js_typedarray_span_t<> ed25519_pk
300) {
301 assert(x25519_pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
302 assert(ed25519_pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
303
304 return crypto_sign_ed25519_pk_to_curve25519(x25519_pk.data(), ed25519_pk.data());
305}
306
307static inline int
308sn_crypto_sign_ed25519_sk_to_curve25519(
309 js_env_t *,
310 js_receiver_t,
311 js_typedarray_span_t<> x25519_sk,
312 js_typedarray_span_t<> ed25519_sk
313) {
314 assert(x25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES);
315 assert(
316 ed25519_sk.size_bytes() == crypto_sign_SECRETKEYBYTES ||
317 ed25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES
318 );
319
320 return crypto_sign_ed25519_sk_to_curve25519(x25519_sk.data(), ed25519_sk.data());
321}
322
323static inline int
324sn_crypto_generichash(
325 js_env_t *env,
326 js_receiver_t,
327
328 js_arraybuffer_span_t out,
329 uint32_t out_offset,
330 uint32_t out_len,
331
332 js_arraybuffer_span_t in,
333 uint32_t in_offset,
334 uint32_t in_len,
335
336 js_arraybuffer_span_t key,
337 uint32_t key_offset,
338 uint32_t key_len
339) {
340 assert_bounds(out);
341 assert(
342 out_len >= crypto_generichash_BYTES_MIN &&
343 out_len <= crypto_generichash_BYTES_MAX
344 );
345
346 assert_bounds(in);
347
348 uint8_t *key_data = NULL;
349 if (key_len) {
350 assert_bounds(key);
351 assert(
352 key_len >= crypto_generichash_KEYBYTES_MIN &&
353 key_len <= crypto_generichash_KEYBYTES_MAX
354 );
355 key_data = &key[key_offset];
356 }
357
358 return crypto_generichash(&out[out_offset], out_len, &in[in_offset], in_len, key_data, key_len);
359}
360
361static inline int
362sn_crypto_generichash_batch(
363 js_env_t *env,
364 js_receiver_t,
365 js_typedarray_t<uint8_t> out,
366 std::vector<js_typedarray_span_t<>> batch,
367 bool use_key,
368 js_typedarray_t<uint8_t> key
369) {
370 int err;
371
372 uint8_t *out_data;
373 size_t out_len;
374 err = js_get_typedarray_info(env, out, out_data, out_len);
375 assert(err == 0);
376 assert(
377 out_len >= crypto_generichash_BYTES_MIN &&
378 out_len <= crypto_generichash_BYTES_MAX
379 );
380
381 uint8_t *key_data = NULL;
382 size_t key_len = 0;
383 if (use_key) {
384 err = js_get_typedarray_info(env, key, key_data, key_len);
385 assert(err == 0);
386 assert(
387 key_len >= crypto_generichash_KEYBYTES_MIN &&
388 key_len <= crypto_generichash_KEYBYTES_MAX
389 );
390 }
391
392 crypto_generichash_state state;
393 err = crypto_generichash_init(&state, key_data, key_len, out_len);
394 if (err != 0) return err;
395
396 for (auto &buf : batch) {
397 err = crypto_generichash_update(&state, buf.data(), buf.size());
398 if (err != 0) return err;
399 }
400
401 return crypto_generichash_final(&state, out_data, out_len);
402}
403
404static inline void
405sn_crypto_generichash_keygen(
406 js_env_t *env,
407 js_receiver_t,
408
409 js_arraybuffer_span_t key,
410 uint32_t key_offset,
411 uint32_t key_len
412) {
413 assert_bounds(key);
414 assert(key_len == crypto_generichash_KEYBYTES);
415
416 crypto_generichash_keygen(&key[key_offset]);
417}
418
419static inline int
420sn_crypto_generichash_init(
421 js_env_t *env,
422 js_receiver_t,
423
424 js_arraybuffer_span_t state,
425 uint32_t state_offset,
426 uint32_t state_len,
427
428 js_arraybuffer_span_t key,
429 uint32_t key_offset,
430 uint32_t key_len,
431
432 uint32_t out_len
433) {
434 assert_bounds(state);
435
436 assert(state_len == sizeof(crypto_generichash_state));
437
438 uint8_t *key_data = NULL;
439 if (key_len) {
440 assert_bounds(key);
441 assert(
442 key_len >= crypto_generichash_KEYBYTES_MIN &&
443 key_len <= crypto_generichash_KEYBYTES_MAX
444 );
445 key_data = &key[key_offset];
446 }
447
448 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
449
450 return crypto_generichash_init(state_data, key_data, key_len, out_len);
451}
452
453static inline int
454sn_crypto_generichash_update(
455 js_env_t *env,
456 js_receiver_t,
457
458 js_arraybuffer_span_t state,
459 uint32_t state_offset,
460 uint32_t state_len,
461
462 js_arraybuffer_span_t in,
463 uint32_t in_offset,
464 uint32_t in_len
465) {
466 assert_bounds(state);
467 assert_bounds(in);
468
469 assert(state_len == sizeof(crypto_generichash_state));
470
471 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
472
473 return crypto_generichash_update(state_data, &in[in_offset], in_len);
474}
475
476static inline int
477sn_crypto_generichash_final(
478 js_env_t *env,
479 js_receiver_t,
480
481 js_arraybuffer_span_t state,
482 uint32_t state_offset,
483 uint32_t state_len,
484
485 js_arraybuffer_span_t out,
486 uint32_t out_offset,
487 uint32_t out_len
488) {
489 assert_bounds(state);
490 assert_bounds(out);
491
492 assert(state_len == sizeof(crypto_generichash_state));
493
494 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
495
496 return crypto_generichash_final(state_data, &out[out_offset], out_len);
497}
498
499static inline int
500sn_crypto_box_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
501 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
502 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
503
504 return crypto_box_keypair(pk.data(), sk.data());
505}
506
507static inline int
508sn_crypto_box_seed_keypair(
509 js_env_t *,
510 js_receiver_t,
511 js_typedarray_span_t<> pk,
512 js_typedarray_span_t<> sk,
513 js_typedarray_span_t<> seed
514) {
515 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
516 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
517 assert(seed.size_bytes() == crypto_box_SEEDBYTES);
518
519 return crypto_box_seed_keypair(pk.data(), sk.data(), seed.data());
520}
521
522static inline int
523sn_crypto_box_easy(
524 js_env_t *,
525 js_receiver_t,
526 js_typedarray_span_t<> c,
527 js_typedarray_span_t<> m,
528 js_typedarray_span_t<> n,
529 js_typedarray_span_t<> pk,
530 js_typedarray_span_t<> sk
531) {
532 assert(c.size_bytes() == m.size_bytes() + crypto_box_MACBYTES);
533 assert(n.size_bytes() == crypto_box_NONCEBYTES);
534 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
535 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
536
537 return crypto_box_easy(c.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
538}
539
540static inline bool
541sn_crypto_box_open_easy(
542 js_env_t *,
543 js_receiver_t,
544 js_typedarray_span_t<> m,
545 js_typedarray_span_t<> c,
546 js_typedarray_span_t<> n,
547 js_typedarray_span_t<> pk,
548 js_typedarray_span_t<> sk
549) {
550 assert(c.size_bytes() >= crypto_box_MACBYTES);
551 assert(m.size_bytes() == c.size_bytes() - crypto_box_MACBYTES);
552 assert(n.size_bytes() == crypto_box_NONCEBYTES);
553 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
554 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
555
556 return crypto_box_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
557}
558
559static inline int
560sn_crypto_box_detached(
561 js_env_t *,
562 js_receiver_t,
563 js_typedarray_span_t<> c,
564 js_typedarray_span_t<> mac,
565 js_typedarray_span_t<> m,
566 js_typedarray_span_t<> n,
567 js_typedarray_span_t<> pk,
568 js_typedarray_span_t<> sk
569) {
570 assert(c.size_bytes() == m.size_bytes());
571 assert(mac.size_bytes() == crypto_box_MACBYTES);
572 assert(n.size_bytes() == crypto_box_NONCEBYTES);
573 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
574 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
575
576 return crypto_box_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
577}
578
579static inline bool
580sn_crypto_box_open_detached(
581 js_env_t *,
582 js_receiver_t,
583 js_typedarray_span_t<> m,
584 js_typedarray_span_t<> c,
585 js_typedarray_span_t<> mac,
586 js_typedarray_span_t<> n,
587 js_typedarray_span_t<> pk,
588 js_typedarray_span_t<> sk
589) {
590 assert(m.size_bytes() == c.size_bytes());
591 assert(mac.size_bytes() == crypto_box_MACBYTES);
592 assert(n.size_bytes() == crypto_box_NONCEBYTES);
593 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
594 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
595
596 return crypto_box_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
597}
598
599static inline int
600sn_crypto_box_seal(
601 js_env_t *,
602 js_receiver_t,
603 js_typedarray_span_t<> c,
604 js_typedarray_span_t<> m,
605 js_typedarray_span_t<> pk
606) {
607 assert(c.size_bytes() == m.size_bytes() + crypto_box_SEALBYTES);
608 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
609
610 return crypto_box_seal(c.data(), m.data(), m.size_bytes(), pk.data());
611}
612
613static inline bool
614sn_crypto_box_seal_open(
615 js_env_t *env,
616 js_receiver_t,
617
618 js_arraybuffer_span_t m,
619 uint32_t m_offset,
620 uint32_t m_len,
621
622 js_arraybuffer_span_t c,
623 uint32_t c_offset,
624 uint32_t c_len,
625
626 js_arraybuffer_span_t pk,
627 uint32_t pk_offset,
628 uint32_t pk_len,
629
630 js_arraybuffer_span_t sk,
631 uint32_t sk_offset,
632 uint32_t sk_len
633) {
634 assert_bounds(m);
635 assert_bounds(c);
636 assert_bounds(pk);
637 assert_bounds(sk);
638
639 assert(m_len == c_len - crypto_box_SEALBYTES);
640 assert(c_len >= crypto_box_SEALBYTES);
641 assert(sk_len == crypto_box_SECRETKEYBYTES);
642 assert(pk_len == crypto_box_PUBLICKEYBYTES);
643
644 return crypto_box_seal_open(&m[m_offset], &c[c_offset], c_len, &pk[pk_offset], &sk[sk_offset]) == 0;
645}
646
647static inline int
648sn_crypto_secretbox_easy(
649 js_env_t *,
650 js_receiver_t,
651 js_typedarray_span_t<> c,
652 js_typedarray_span_t<> m,
653 js_typedarray_span_t<> n,
654 js_typedarray_span_t<> k
655) {
656 assert(c.size_bytes() == m.size_bytes() + crypto_secretbox_MACBYTES);
657 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
658 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
659
660 return crypto_secretbox_easy(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
661}
662
663static inline bool
664sn_crypto_secretbox_open_easy(
665 js_env_t *,
666 js_receiver_t,
667 js_typedarray_span_t<> m,
668 js_typedarray_span_t<> c,
669 js_typedarray_span_t<> n,
670 js_typedarray_span_t<> k
671) {
672 assert(m.size_bytes() == c.size_bytes() - crypto_secretbox_MACBYTES);
673 assert(c.size_bytes() >= crypto_secretbox_MACBYTES);
674 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
675 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
676
677 return crypto_secretbox_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), k.data()) == 0;
678}
679
680static inline int
681sn_crypto_secretbox_detached(
682 js_env_t *,
683 js_receiver_t,
684 js_typedarray_span_t<> c,
685 js_typedarray_span_t<> mac,
686 js_typedarray_span_t<> m,
687 js_typedarray_span_t<> n,
688 js_typedarray_span_t<> k
689) {
690 assert(c.size_bytes() == m.size_bytes());
691 assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
692 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
693 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
694
695 return crypto_secretbox_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), k.data());
696}
697
698static inline bool
699sn_crypto_secretbox_open_detached(
700 js_env_t *,
701 js_receiver_t,
702 js_typedarray_span_t<> m,
703 js_typedarray_span_t<> c,
704 js_typedarray_span_t<> mac,
705 js_typedarray_span_t<> n,
706 js_typedarray_span_t<> k
707) {
708 assert(m.size_bytes() == c.size_bytes());
709 assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
710 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
711 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
712
713 return crypto_secretbox_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), k.data()) == 0;
714}
715
716static inline int
717sn_crypto_stream(
718 js_env_t *,
719 js_receiver_t,
720 js_typedarray_span_t<> c,
721 js_typedarray_span_t<> n,
722 js_typedarray_span_t<> k
723) {
724 assert(n.size_bytes() == crypto_stream_NONCEBYTES);
725 assert(k.size_bytes() == crypto_stream_KEYBYTES);
726
727 return crypto_stream(c.data(), c.size_bytes(), n.data(), k.data());
728}
729
730static inline int
731sn_crypto_stream_xor(
732 js_env_t *env,
733 js_receiver_t,
734
735 js_arraybuffer_span_t c,
736 uint32_t c_offset,
737 uint32_t c_len,
738
739 js_arraybuffer_span_t m,
740 uint32_t m_offset,
741 uint32_t m_len,
742
743 js_arraybuffer_span_t n,
744 uint32_t n_offset,
745 uint32_t n_len,
746
747 js_arraybuffer_span_t k,
748 uint32_t k_offset,
749 uint32_t k_len
750) {
751 assert_bounds(c);
752 assert_bounds(m);
753 assert_bounds(n);
754 assert_bounds(k);
755
756 assert(c_len == m_len);
757 assert(n_len == crypto_stream_NONCEBYTES);
758 assert(k_len == crypto_stream_KEYBYTES);
759
760 return crypto_stream_xor(&c[c_offset], &m[m_offset], m_len, &n[n_offset], &k[k_offset]);
761}
762
763static inline int
764sn_crypto_stream_chacha20(
765 js_env_t *,
766 js_receiver_t,
767 js_typedarray_span_t<> c,
768 js_typedarray_span_t<> n,
769 js_typedarray_span_t<> k
770) {
771 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
772 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
773
774 return crypto_stream_chacha20(c.data(), c.size_bytes(), n.data(), k.data());
775}
776
777static inline int
778sn_crypto_stream_chacha20_xor(
779 js_env_t *,
780 js_receiver_t,
781 js_typedarray_span_t<> c,
782 js_typedarray_span_t<> m,
783 js_typedarray_span_t<> n,
784 js_typedarray_span_t<> k
785) {
786 assert(c.size_bytes() == m.size_bytes());
787 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
788 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
789
790 return crypto_stream_chacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
791}
792
793static inline int
794sn_crypto_stream_chacha20_xor_ic(
795 js_env_t *,
796 js_receiver_t,
797 js_typedarray_span_t<> c,
798 js_typedarray_span_t<> m,
799 js_typedarray_span_t<> n,
800 uint32_t ic,
801 js_typedarray_span_t<> k
802) {
803 assert(c.size_bytes() == m.size_bytes());
804 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
805 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
806
807 return crypto_stream_chacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
808}
809
810static inline int
811sn_crypto_stream_chacha20_ietf(
812 js_env_t *,
813 js_receiver_t,
814 js_typedarray_span_t<> c,
815 js_typedarray_span_t<> n,
816 js_typedarray_span_t<> k
817) {
818 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
819 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
820
821 return crypto_stream_chacha20_ietf(c.data(), c.size_bytes(), n.data(), k.data());
822}
823
824static inline int
825sn_crypto_stream_chacha20_ietf_xor(
826 js_env_t *,
827 js_receiver_t,
828 js_typedarray_span_t<> c,
829 js_typedarray_span_t<> m,
830 js_typedarray_span_t<> n,
831 js_typedarray_span_t<> k
832) {
833 assert(c.size_bytes() == m.size_bytes());
834 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
835 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
836
837 return crypto_stream_chacha20_ietf_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
838}
839
840static inline int
841sn_crypto_stream_chacha20_ietf_xor_ic(
842 js_env_t *,
843 js_receiver_t,
844 js_typedarray_span_t<> c,
845 js_typedarray_span_t<> m,
846 js_typedarray_span_t<> n,
847 uint32_t ic,
848 js_typedarray_span_t<> k
849) {
850 assert(c.size_bytes() == m.size_bytes());
851 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
852 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
853
854 return crypto_stream_chacha20_ietf_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
855}
856
857static inline int
858sn_crypto_stream_xchacha20(
859 js_env_t *,
860 js_receiver_t,
861 js_typedarray_span_t<> c,
862 js_typedarray_span_t<> n,
863 js_typedarray_span_t<> k
864) {
865 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
866 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
867
868 return crypto_stream_xchacha20(c.data(), c.size_bytes(), n.data(), k.data());
869}
870
871static inline int
872sn_crypto_stream_xchacha20_xor(
873 js_env_t *,
874 js_receiver_t,
875 js_typedarray_span_t<> c,
876 js_typedarray_span_t<> m,
877 js_typedarray_span_t<> n,
878 js_typedarray_span_t<> k
879) {
880 assert(c.size_bytes() == m.size_bytes());
881 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
882 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
883
884 return crypto_stream_xchacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
885}
886
887static inline int
888sn_crypto_stream_xchacha20_xor_ic(
889 js_env_t *,
890 js_receiver_t,
891 js_typedarray_span_t<> c,
892 js_typedarray_span_t<> m,
893 js_typedarray_span_t<> n,
894 uint32_t ic,
895 js_typedarray_span_t<> k
896) {
897 assert(c.size_bytes() == m.size_bytes());
898 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
899 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
900
901 return crypto_stream_xchacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
902}
903
904static inline int
905sn_crypto_stream_salsa20(
906 js_env_t *,
907 js_receiver_t,
908 js_typedarray_span_t<> c,
909 js_typedarray_span_t<> n,
910 js_typedarray_span_t<> k
911) {
912 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
913 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
914
915 return crypto_stream_salsa20(c.data(), c.size_bytes(), n.data(), k.data());
916}
917
918static inline int
919sn_crypto_stream_salsa20_xor(
920 js_env_t *,
921 js_receiver_t,
922 js_typedarray_span_t<> c,
923 js_typedarray_span_t<> m,
924 js_typedarray_span_t<> n,
925 js_typedarray_span_t<> k
926) {
927 assert(c.size_bytes() == m.size_bytes());
928 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
929 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
930
931 return crypto_stream_salsa20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
932}
933
934static inline int
935sn_crypto_stream_salsa20_xor_ic(
936 js_env_t *,
937 js_receiver_t,
938 js_typedarray_span_t<> c,
939 js_typedarray_span_t<> m,
940 js_typedarray_span_t<> n,
941 uint32_t ic,
942 js_typedarray_span_t<> k
943) {
944 assert(c.size_bytes() == m.size_bytes());
945 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
946 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
947
948 return crypto_stream_salsa20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
949}
950
951static inline int
952sn_crypto_auth(
953 js_env_t *,
954 js_receiver_t,
955 js_typedarray_span_t<> out,
956 js_typedarray_span_t<> in,
957 js_typedarray_span_t<> k
958) {
959 assert(out.size_bytes() == crypto_auth_BYTES);
960 assert(k.size_bytes() == crypto_auth_KEYBYTES);
961
962 return crypto_auth(out.data(), in.data(), in.size_bytes(), k.data());
963}
964
965static inline bool
966sn_crypto_auth_verify(
967 js_env_t *,
968 js_receiver_t,
969 js_typedarray_span_t<> h,
970 js_typedarray_span_t<> in,
971 js_typedarray_span_t<> k
972) {
973 assert(h.size_bytes() == crypto_auth_BYTES);
974 assert(k.size_bytes() == crypto_auth_KEYBYTES);
975
976 return crypto_auth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
977}
978
979static inline int
980sn_crypto_onetimeauth(
981 js_env_t *,
982 js_receiver_t,
983 js_typedarray_span_t<> out,
984 js_typedarray_span_t<> in,
985 js_typedarray_span_t<> k
986) {
987 assert(out.size_bytes() == crypto_onetimeauth_BYTES);
988 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
989
990 return crypto_onetimeauth(out.data(), in.data(), in.size_bytes(), k.data());
991}
992
993static inline int
994sn_crypto_onetimeauth_init(
995 js_env_t *,
996 js_receiver_t,
997 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
998 js_typedarray_span_t<> k
999) {
1000 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
1001
1002 return crypto_onetimeauth_init(&*state, k.data());
1003}
1004
1005static inline int
1006sn_crypto_onetimeauth_update(
1007 js_env_t *,
1008 js_receiver_t,
1009 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
1010 js_typedarray_span_t<> in
1011) {
1012 return crypto_onetimeauth_update(&*state, in.data(), in.size_bytes());
1013}
1014
1015static inline int
1016sn_crypto_onetimeauth_final(
1017 js_env_t *,
1018 js_receiver_t,
1019 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
1020 js_typedarray_span_t<> out
1021) {
1022 assert(out.size_bytes() == crypto_onetimeauth_BYTES);
1023
1024 return crypto_onetimeauth_final(&*state, out.data());
1025}
1026
1027static inline bool
1028sn_crypto_onetimeauth_verify(
1029 js_env_t *,
1030 js_receiver_t,
1031 js_typedarray_span_t<> h,
1032 js_typedarray_span_t<> in,
1033 js_typedarray_span_t<> k
1034) {
1035 assert(h.size_bytes() == crypto_onetimeauth_BYTES);
1036 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
1037
1038 return crypto_onetimeauth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
1039}
1040
1041// CHECK: memlimit can be >32bit
1042static inline int
1043sn_crypto_pwhash(
1044 js_env_t *,
1045 js_receiver_t,
1046 js_typedarray_span_t<> out,
1047 js_typedarray_span_of_t<char> passwd,
1048 js_typedarray_span_t<> salt,
1049 uint64_t opslimit,
1050 uint64_t memlimit,
1051 int32_t alg
1052) {
1053 assert(out.size_bytes() >= crypto_pwhash_BYTES_MIN);
1054 assert(out.size_bytes() <= crypto_pwhash_BYTES_MAX);
1055 assert(salt.size_bytes() == crypto_pwhash_SALTBYTES);
1056 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1057 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1058 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1059 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1060 assert(alg == 1 || alg == 2); // Argon2i or Argon2id
1061
1062 return crypto_pwhash(
1063 out.data(),
1064 out.size_bytes(),
1065 passwd.data(),
1066 passwd.size_bytes(),
1067 salt.data(),
1068 opslimit,
1069 memlimit,
1070 alg
1071 );
1072}
1073
1074static inline int
1075sn_crypto_pwhash_str(
1076 js_env_t *,
1077 js_receiver_t,
1078 js_typedarray_span_of_t<char> out,
1079 js_typedarray_span_of_t<char> passwd,
1080 uint64_t opslimit,
1081 uint64_t memlimit
1082) {
1083 assert(out.size_bytes() == crypto_pwhash_STRBYTES);
1084 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1085 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1086 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1087 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1088
1089 return crypto_pwhash_str(
1090 out.data(),
1091 passwd.data(),
1092 passwd.size_bytes(),
1093 opslimit,
1094 memlimit
1095 );
1096}
1097
1098static inline bool
1099sn_crypto_pwhash_str_verify(
1100 js_env_t *,
1101 js_receiver_t,
1102 js_typedarray_span_of_t<char> str,
1103 js_typedarray_span_of_t<char> passwd
1104) {
1105 assert(str.size_bytes() == crypto_pwhash_STRBYTES);
1106
1107 return crypto_pwhash_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
1108}
1109
1110// CHECK: returns 1, 0, -1
1111static inline bool
1112sn_crypto_pwhash_str_needs_rehash(
1113 js_env_t *,
1114 js_receiver_t,
1115 js_typedarray_span_of_t<char> str,
1116 uint64_t opslimit,
1117 uint64_t memlimit
1118) {
1119 assert(str.size_bytes() == crypto_pwhash_STRBYTES);
1120 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1121 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1122 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1123 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1124
1125 return crypto_pwhash_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
1126}
1127
1128// CHECK: memlimit can be >32bit
1129static inline int
1130sn_crypto_pwhash_scryptsalsa208sha256(
1131 js_env_t *,
1132 js_receiver_t,
1133 js_typedarray_span_t<> out,
1134 js_typedarray_span_of_t<char> passwd,
1135 js_typedarray_span_t<> salt,
1136 uint64_t opslimit,
1137 uint64_t memlimit
1138) {
1139 assert(out.size_bytes() >= crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
1140 assert(out.size_bytes() <= crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
1141 assert(salt.size_bytes() == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
1142 assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
1143 assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
1144 assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
1145 assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
1146
1147 return crypto_pwhash_scryptsalsa208sha256(
1148 out.data(),
1149 out.size_bytes(),
1150 passwd.data(),
1151 passwd.size_bytes(),
1152 salt.data(),
1153 opslimit,
1154 memlimit
1155 );
1156}
1157
1158static inline int
1159sn_crypto_pwhash_scryptsalsa208sha256_str(
1160 js_env_t *,
1161 js_receiver_t,
1162 js_typedarray_span_of_t<char> out,
1163 js_typedarray_span_of_t<char> passwd,
1164 uint64_t opslimit,
1165 uint64_t memlimit
1166) {
1167 assert(out.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1168 assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
1169 assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
1170 assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
1171 assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
1172
1173 return crypto_pwhash_scryptsalsa208sha256_str(
1174 out.data(),
1175 passwd.data(),
1176 passwd.size_bytes(),
1177 opslimit,
1178 memlimit
1179 );
1180}
1181
1182static inline bool
1183sn_crypto_pwhash_scryptsalsa208sha256_str_verify(
1184 js_env_t *,
1185 js_receiver_t,
1186 js_typedarray_span_of_t<char> str,
1187 js_typedarray_span_of_t<char> passwd
1188) {
1189 assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1190
1191 return crypto_pwhash_scryptsalsa208sha256_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
1192}
1193
1194static inline bool
1195sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
1196 js_env_t *,
1197 js_receiver_t,
1198 js_typedarray_span_of_t<char> str,
1199 uint64_t opslimit,
1200 uint64_t memlimit
1201) {
1202 assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1203 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1204 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1205 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1206 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1207
1208 return crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
1209}
1210
1211static inline int
1212sn_crypto_kx_keypair(
1213 js_env_t *,
1214 js_receiver_t,
1215 js_typedarray_span_t<> pk,
1216 js_typedarray_span_t<> sk
1217) {
1218 assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1219 assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1220
1221 return crypto_kx_keypair(pk.data(), sk.data());
1222}
1223
1224static inline int
1225sn_crypto_kx_seed_keypair(
1226 js_env_t *,
1227 js_receiver_t,
1228 js_typedarray_span_t<> pk,
1229 js_typedarray_span_t<> sk,
1230 js_typedarray_span_t<> seed
1231) {
1232 assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1233 assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1234 assert(seed.size_bytes() == crypto_kx_SEEDBYTES);
1235
1236 return crypto_kx_seed_keypair(pk.data(), sk.data(), seed.data());
1237}
1238
1239static inline int
1240sn_crypto_kx_client_session_keys(
1241 js_env_t *,
1242 js_receiver_t,
1243 std::optional<js_typedarray_span_t<>> rx,
1244 std::optional<js_typedarray_span_t<>> tx,
1245 js_typedarray_span_t<> client_pk,
1246 js_typedarray_span_t<> client_sk,
1247 js_typedarray_span_t<> server_pk
1248) {
1249 assert(rx.has_value() || tx.has_value());
1250
1251 if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1252 if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1253
1254 assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1255 assert(client_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1256 assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1257
1258 return crypto_kx_client_session_keys(
1259 rx ? rx->data() : nullptr,
1260 tx ? tx->data() : nullptr,
1261 client_pk.data(),
1262 client_sk.data(),
1263 server_pk.data()
1264 );
1265}
1266
1267static inline int
1268sn_crypto_kx_server_session_keys(
1269 js_env_t *,
1270 js_receiver_t,
1271 std::optional<js_typedarray_span_t<>> rx,
1272 std::optional<js_typedarray_span_t<>> tx,
1273 js_typedarray_span_t<> server_pk,
1274 js_typedarray_span_t<> server_sk,
1275 js_typedarray_span_t<> client_pk
1276) {
1277 assert(rx.has_value() || tx.has_value());
1278
1279 if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1280 if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1281
1282 assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1283 assert(server_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1284 assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1285
1286 return crypto_kx_server_session_keys(
1287 rx ? rx->data() : nullptr,
1288 tx ? tx->data() : nullptr,
1289 server_pk.data(),
1290 server_sk.data(),
1291 client_pk.data()
1292 );
1293}
1294
1295static inline int
1296sn_crypto_scalarmult_base(
1297 js_env_t *,
1298 js_receiver_t,
1299 js_typedarray_span_t<> q,
1300 js_typedarray_span_t<> n
1301) {
1302 assert(q.size_bytes() == crypto_scalarmult_BYTES);
1303 assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
1304
1305 return crypto_scalarmult_base(q.data(), n.data());
1306}
1307
1308static inline int
1309sn_crypto_scalarmult(
1310 js_env_t *,
1311 js_receiver_t,
1312 js_typedarray_span_t<> q,
1313 js_typedarray_span_t<> n,
1314 js_typedarray_span_t<> p
1315) {
1316 assert(q.size_bytes() == crypto_scalarmult_BYTES);
1317 assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
1318 assert(p.size_bytes() == crypto_scalarmult_BYTES);
1319
1320 return crypto_scalarmult(q.data(), n.data(), p.data());
1321}
1322
1323static inline int
1324sn_crypto_scalarmult_ed25519_base(
1325 js_env_t *,
1326 js_receiver_t,
1327 js_typedarray_span_t<> q,
1328 js_typedarray_span_t<> n
1329) {
1330 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1331 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1332
1333 return crypto_scalarmult_ed25519_base(q.data(), n.data());
1334}
1335
1336static inline int
1337sn_crypto_scalarmult_ed25519(
1338 js_env_t *,
1339 js_receiver_t,
1340 js_typedarray_span_t<> q,
1341 js_typedarray_span_t<> n,
1342 js_typedarray_span_t<> p
1343) {
1344 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1345 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1346 assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1347
1348 return crypto_scalarmult_ed25519(q.data(), n.data(), p.data());
1349}
1350
1351static inline bool
1352sn_crypto_core_ed25519_is_valid_point(
1353 js_env_t *,
1354 js_receiver_t,
1355 js_typedarray_span_t<> p
1356) {
1357 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1358
1359 return crypto_core_ed25519_is_valid_point(p.data()) != 0;
1360}
1361
1362static inline int
1363sn_crypto_core_ed25519_from_uniform(
1364 js_env_t *,
1365 js_receiver_t,
1366 js_typedarray_span_t<> p,
1367 js_typedarray_span_t<> r
1368) {
1369 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1370 assert(r.size_bytes() == crypto_core_ed25519_UNIFORMBYTES);
1371
1372 return crypto_core_ed25519_from_uniform(p.data(), r.data());
1373}
1374
1375static inline int
1376sn_crypto_scalarmult_ed25519_base_noclamp(
1377 js_env_t *,
1378 js_receiver_t,
1379 js_typedarray_span_t<> q,
1380 js_typedarray_span_t<> n
1381) {
1382 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1383 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1384
1385 return crypto_scalarmult_ed25519_base_noclamp(q.data(), n.data());
1386}
1387
1388static inline int
1389sn_crypto_scalarmult_ed25519_noclamp(
1390 js_env_t *,
1391 js_receiver_t,
1392 js_typedarray_span_t<> q,
1393 js_typedarray_span_t<> n,
1394 js_typedarray_span_t<> p
1395) {
1396 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1397 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1398 assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1399
1400 return crypto_scalarmult_ed25519_noclamp(q.data(), n.data(), p.data());
1401}
1402
1403static inline int
1404sn_crypto_core_ed25519_add(
1405 js_env_t *,
1406 js_receiver_t,
1407 js_typedarray_span_t<> r,
1408 js_typedarray_span_t<> p,
1409 js_typedarray_span_t<> q
1410) {
1411 assert(r.size_bytes() == crypto_core_ed25519_BYTES);
1412 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1413 assert(q.size_bytes() == crypto_core_ed25519_BYTES);
1414
1415 return crypto_core_ed25519_add(r.data(), p.data(), q.data());
1416}
1417
1418static inline int
1419sn_crypto_core_ed25519_sub(
1420 js_env_t *,
1421 js_receiver_t,
1422 js_typedarray_span_t<> r,
1423 js_typedarray_span_t<> p,
1424 js_typedarray_span_t<> q
1425) {
1426 assert(r.size_bytes() == crypto_core_ed25519_BYTES);
1427 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1428 assert(q.size_bytes() == crypto_core_ed25519_BYTES);
1429
1430 return crypto_core_ed25519_sub(r.data(), p.data(), q.data());
1431}
1432
1433static inline void
1434sn_crypto_core_ed25519_scalar_random(
1435 js_env_t *,
1436 js_receiver_t,
1437 js_typedarray_span_t<> r
1438) {
1439 assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1440
1441 crypto_core_ed25519_scalar_random(r.data());
1442}
1443
1444static inline void
1445sn_crypto_core_ed25519_scalar_reduce(
1446 js_env_t *,
1447 js_receiver_t,
1448 js_typedarray_span_t<> r,
1449 js_typedarray_span_t<> s
1450) {
1451 assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1452 assert(s.size_bytes() == crypto_core_ed25519_NONREDUCEDSCALARBYTES);
1453
1454 crypto_core_ed25519_scalar_reduce(r.data(), s.data());
1455}
1456
1457static inline void
1458sn_crypto_core_ed25519_scalar_invert(
1459 js_env_t *,
1460 js_receiver_t,
1461 js_typedarray_span_t<> recip,
1462 js_typedarray_span_t<> s
1463) {
1464 assert(recip.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1465 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1466
1467 crypto_core_ed25519_scalar_invert(recip.data(), s.data());
1468}
1469
1470static inline void
1471sn_crypto_core_ed25519_scalar_negate(
1472 js_env_t *,
1473 js_receiver_t,
1474 js_typedarray_span_t<> neg,
1475 js_typedarray_span_t<> s
1476) {
1477 assert(neg.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1478 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1479
1480 crypto_core_ed25519_scalar_negate(neg.data(), s.data());
1481}
1482
1483static inline void
1484sn_crypto_core_ed25519_scalar_complement(
1485 js_env_t *,
1486 js_receiver_t,
1487 js_typedarray_span_t<> comp,
1488 js_typedarray_span_t<> s
1489) {
1490 assert(comp.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1491 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1492
1493 crypto_core_ed25519_scalar_complement(comp.data(), s.data());
1494}
1495
1496static inline void
1497sn_crypto_core_ed25519_scalar_add(
1498 js_env_t *,
1499 js_receiver_t,
1500 js_typedarray_span_t<> z,
1501 js_typedarray_span_t<> x,
1502 js_typedarray_span_t<> y
1503) {
1504 assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1505 assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1506 assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1507
1508 crypto_core_ed25519_scalar_add(z.data(), x.data(), y.data());
1509}
1510
1511static inline void
1512sn_crypto_core_ed25519_scalar_sub(
1513 js_env_t *,
1514 js_receiver_t,
1515 js_typedarray_span_t<> z,
1516 js_typedarray_span_t<> x,
1517 js_typedarray_span_t<> y
1518) {
1519 assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1520 assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1521 assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1522
1523 crypto_core_ed25519_scalar_sub(z.data(), x.data(), y.data());
1524}
1525
1526static inline int
1527sn_crypto_shorthash(
1528 js_env_t *,
1529 js_receiver_t,
1530 js_typedarray_span_t<> out,
1531 js_typedarray_span_t<> in,
1532 js_typedarray_span_t<> k
1533) {
1534 assert(out.size_bytes() == crypto_shorthash_BYTES);
1535 assert(k.size_bytes() == crypto_shorthash_KEYBYTES);
1536
1537 return crypto_shorthash(out.data(), in.data(), in.size_bytes(), k.data());
1538}
1539
1540static inline void
1541sn_crypto_kdf_keygen(
1542 js_env_t *,
1543 js_receiver_t,
1544 js_typedarray_span_t<> key
1545) {
1546 assert(key.size_bytes() == crypto_kdf_KEYBYTES);
1547
1548 crypto_kdf_keygen(key.data());
1549}
1550
1551static inline int
1552sn_crypto_kdf_derive_from_key(
1553 js_env_t *,
1554 js_receiver_t,
1555 js_typedarray_span_t<> subkey,
1556 uint64_t subkey_id,
1557 js_typedarray_span_of_t<char> ctx,
1558 js_typedarray_span_t<> key
1559) {
1560 assert(subkey.size_bytes() >= crypto_kdf_BYTES_MIN);
1561 assert(subkey.size_bytes() <= crypto_kdf_BYTES_MAX);
1562 assert(ctx.size_bytes() == crypto_kdf_CONTEXTBYTES);
1563 assert(key.size_bytes() == crypto_kdf_KEYBYTES);
1564
1565 return crypto_kdf_derive_from_key(
1566 subkey.data(),
1567 subkey.size_bytes(),
1568 subkey_id,
1569 ctx.data(),
1570 key.data()
1571 );
1572}
1573
1574static inline int
1575sn_crypto_hash(
1576 js_env_t *,
1577 js_receiver_t,
1578 js_typedarray_span_t<> out,
1579 js_typedarray_span_t<> in
1580) {
1581 assert(out.size_bytes() == crypto_hash_BYTES);
1582
1583 return crypto_hash(out.data(), in.data(), in.size_bytes());
1584}
1585
1586static inline int
1587sn_crypto_hash_sha256(
1588 js_env_t *,
1589 js_receiver_t,
1590 js_typedarray_span_t<> out,
1591 js_typedarray_span_t<> in
1592) {
1593 assert(out.size_bytes() == crypto_hash_sha256_BYTES);
1594
1595 return crypto_hash_sha256(out.data(), in.data(), in.size_bytes());
1596}
1597
1598static inline int
1599sn_crypto_hash_sha256_init(
1600 js_env_t *,
1601 js_receiver_t,
1602 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state
1603) {
1604 return crypto_hash_sha256_init(&*state);
1605}
1606
1607static inline int
1608sn_crypto_hash_sha256_update(
1609 js_env_t *,
1610 js_receiver_t,
1611 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
1612 js_typedarray_span_t<> in
1613) {
1614 return crypto_hash_sha256_update(&*state, in.data(), in.size_bytes());
1615}
1616
1617static inline int
1618sn_crypto_hash_sha256_final(
1619 js_env_t *,
1620 js_receiver_t,
1621 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
1622 js_typedarray_span_t<> out
1623) {
1624 assert(out.size_bytes() == crypto_hash_sha256_BYTES);
1625
1626 return crypto_hash_sha256_final(&*state, out.data());
1627}
1628
1629static inline int
1630sn_crypto_hash_sha512(
1631 js_env_t *,
1632 js_receiver_t,
1633 js_typedarray_span_t<> out,
1634 js_typedarray_span_t<> in
1635) {
1636 assert(out.size_bytes() == crypto_hash_sha512_BYTES);
1637
1638 return crypto_hash_sha512(out.data(), in.data(), in.size_bytes());
1639}
1640
1641static inline int
1642sn_crypto_hash_sha512_init(
1643 js_env_t *,
1644 js_receiver_t,
1645 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state
1646) {
1647 return crypto_hash_sha512_init(&*state);
1648}
1649
1650static inline int
1651sn_crypto_hash_sha512_update(
1652 js_env_t *,
1653 js_receiver_t,
1654 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
1655 js_typedarray_span_t<> in
1656) {
1657 return crypto_hash_sha512_update(&*state, in.data(), in.size_bytes());
1658}
1659
1660static inline int
1661sn_crypto_hash_sha512_final(
1662 js_env_t *,
1663 js_receiver_t,
1664 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
1665 js_typedarray_span_t<> out
1666) {
1667 assert(out.size_bytes() == crypto_hash_sha512_BYTES);
1668
1669 return crypto_hash_sha512_final(&*state, out.data());
1670}
1671
1672static inline void
1673sn_crypto_aead_xchacha20poly1305_ietf_keygen(
1674 js_env_t *,
1675 js_receiver_t,
1676 js_typedarray_span_t<> k
1677) {
1678 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1679
1680 crypto_aead_xchacha20poly1305_ietf_keygen(k.data());
1681}
1682
1683static inline uint64_t
1684sn_crypto_aead_xchacha20poly1305_ietf_encrypt(
1685 js_env_t *,
1686 js_receiver_t,
1687 js_typedarray_span_t<> c,
1688 js_typedarray_span_t<> m,
1689 std::optional<js_typedarray_span_t<>> ad,
1690 js_typedarray_span_t<> npub,
1691 js_typedarray_span_t<> k
1692) {
1693 assert(c.size_bytes() == m.size_bytes() + crypto_aead_xchacha20poly1305_ietf_ABYTES);
1694 assert(c.size_bytes() <= 0xffffffff);
1695 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1696 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1697
1698 uint8_t *ad_data = nullptr;
1699 size_t ad_size = 0;
1700 if (ad) {
1701 ad_data = ad->data();
1702 ad_size = ad->size_bytes();
1703 }
1704
1705 unsigned long long clen = 0;
1706 int status = crypto_aead_xchacha20poly1305_ietf_encrypt(
1707 c.data(),
1708 &clen,
1709 m.data(),
1710 m.size_bytes(),
1711 ad_data,
1712 ad_size,
1713 nullptr,
1714 npub.data(),
1715 k.data()
1716 );
1717
1718 if (status < 0) return status;
1719
1720 return clen;
1721}
1722
1723static inline uint64_t
1724sn_crypto_aead_xchacha20poly1305_ietf_decrypt(
1725 js_env_t *,
1726 js_receiver_t,
1727 js_typedarray_span_t<> m,
1728 js_typedarray_span_t<> c,
1729 std::optional<js_typedarray_span_t<>> ad,
1730 js_typedarray_span_t<> npub,
1731 js_typedarray_span_t<> k
1732) {
1733 assert(m.size_bytes() == c.size_bytes() - crypto_aead_xchacha20poly1305_ietf_ABYTES);
1734 assert(m.size_bytes() <= 0xffffffff);
1735 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1736 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1737
1738 uint8_t *ad_data = nullptr;
1739 size_t ad_size = 0;
1740 if (ad) {
1741 ad_data = ad->data();
1742 ad_size = ad->size_bytes();
1743 }
1744
1745 unsigned long long mlen = 0;
1746 int status = crypto_aead_xchacha20poly1305_ietf_decrypt(
1747 m.data(),
1748 &mlen,
1749 nullptr,
1750 c.data(),
1751 c.size_bytes(),
1752 ad_data,
1753 ad_size,
1754 npub.data(),
1755 k.data()
1756 );
1757
1758 if (status < 0) return status;
1759
1760 return mlen;
1761}
1762
1763static inline uint64_t
1764sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
1765 js_env_t *,
1766 js_receiver_t,
1767 js_typedarray_span_t<> c,
1768 js_typedarray_span_t<> mac,
1769 js_typedarray_span_t<> m,
1770 std::optional<js_typedarray_span_t<>> ad,
1771 js_typedarray_span_t<> npub,
1772 js_typedarray_span_t<> k
1773) {
1774 assert(c.size_bytes() == m.size_bytes());
1775 assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
1776 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1777 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1778
1779 uint8_t *ad_data = nullptr;
1780 size_t ad_size = 0;
1781 if (ad) {
1782 ad_data = ad->data();
1783 ad_size = ad->size_bytes();
1784 }
1785
1786 unsigned long long maclen = 0;
1787 int status = crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
1788 c.data(),
1789 mac.data(),
1790 &maclen,
1791 m.data(),
1792 m.size_bytes(),
1793 ad_data,
1794 ad_size,
1795 nullptr,
1796 npub.data(),
1797 k.data()
1798 );
1799
1800 if (status < 0) return status;
1801
1802 return maclen;
1803}
1804
1805static inline int
1806sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
1807 js_env_t *,
1808 js_receiver_t,
1809 js_typedarray_span_t<> m,
1810 js_typedarray_span_t<> c,
1811 js_typedarray_span_t<> mac,
1812 std::optional<js_typedarray_span_t<>> ad,
1813 js_typedarray_span_t<> npub,
1814 js_typedarray_span_t<> k
1815) {
1816 assert(m.size_bytes() == c.size_bytes());
1817 assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
1818 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1819 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1820
1821 uint8_t *ad_data = nullptr;
1822 size_t ad_size = 0;
1823 if (ad) {
1824 ad_data = ad->data();
1825 ad_size = ad->size_bytes();
1826 }
1827
1828 return crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
1829 m.data(),
1830 nullptr,
1831 c.data(),
1832 c.size_bytes(),
1833 mac.data(),
1834 ad_data,
1835 ad_size,
1836 npub.data(),
1837 k.data()
1838 );
1839}
1840
1841static inline void
1842sn_crypto_aead_chacha20poly1305_ietf_keygen(
1843 js_env_t *,
1844 js_receiver_t,
1845 js_typedarray_span_t<> k
1846) {
1847 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1848
1849 crypto_aead_chacha20poly1305_ietf_keygen(k.data());
1850}
1851
1852static inline uint64_t
1853sn_crypto_aead_chacha20poly1305_ietf_encrypt(
1854 js_env_t *,
1855 js_receiver_t,
1856 js_typedarray_span_t<> c,
1857 js_typedarray_span_t<> m,
1858 std::optional<js_typedarray_span_t<>> ad,
1859 js_typedarray_span_t<> npub,
1860 js_typedarray_span_t<> k
1861) {
1862 assert(c.size_bytes() == m.size_bytes() + crypto_aead_chacha20poly1305_ietf_ABYTES);
1863 assert(c.size_bytes() <= 0xffffffff);
1864 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1865 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1866
1867 uint8_t *ad_data = nullptr;
1868 size_t ad_size = 0;
1869 if (ad) {
1870 ad_data = ad->data();
1871 ad_size = ad->size_bytes();
1872 }
1873
1874 unsigned long long clen = 0;
1875 int status = crypto_aead_chacha20poly1305_ietf_encrypt(
1876 c.data(),
1877 &clen,
1878 m.data(),
1879 m.size_bytes(),
1880 ad_data,
1881 ad_size,
1882 nullptr,
1883 npub.data(),
1884 k.data()
1885 );
1886
1887 if (status < 0) return status;
1888
1889 return clen;
1890}
1891
1892static inline uint64_t
1893sn_crypto_aead_chacha20poly1305_ietf_decrypt(
1894 js_env_t *,
1895 js_receiver_t,
1896 js_typedarray_span_t<> m,
1897 js_typedarray_span_t<> c,
1898 std::optional<js_typedarray_span_t<>> ad,
1899 js_typedarray_span_t<> npub,
1900 js_typedarray_span_t<> k
1901) {
1902 assert(m.size_bytes() == c.size_bytes() - crypto_aead_chacha20poly1305_ietf_ABYTES);
1903 assert(m.size_bytes() <= 0xffffffff);
1904 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1905 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1906
1907 uint8_t *ad_data = nullptr;
1908 size_t ad_size = 0;
1909 if (ad) {
1910 ad_data = ad->data();
1911 ad_size = ad->size_bytes();
1912 }
1913
1914 unsigned long long mlen = 0;
1915 int status = crypto_aead_chacha20poly1305_ietf_decrypt(
1916 m.data(),
1917 &mlen,
1918 nullptr,
1919 c.data(),
1920 c.size_bytes(),
1921 ad_data,
1922 ad_size,
1923 npub.data(),
1924 k.data()
1925 );
1926
1927 if (status < 0) return status;
1928
1929 return mlen;
1930}
1931
1932static inline uint64_t
1933sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached(
1934 js_env_t *,
1935 js_receiver_t,
1936 js_typedarray_span_t<> c,
1937 js_typedarray_span_t<> mac,
1938 js_typedarray_span_t<> m,
1939 std::optional<js_typedarray_span_t<>> ad,
1940 js_typedarray_span_t<> npub,
1941 js_typedarray_span_t<> k
1942) {
1943 assert(c.size_bytes() == m.size_bytes());
1944 assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
1945 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1946 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1947
1948 uint8_t *ad_data = nullptr;
1949 size_t ad_size = 0;
1950 if (ad) {
1951 ad_data = ad->data();
1952 ad_size = ad->size_bytes();
1953 }
1954
1955 unsigned long long maclen = 0;
1956 int status = crypto_aead_chacha20poly1305_ietf_encrypt_detached(
1957 c.data(),
1958 mac.data(),
1959 &maclen,
1960 m.data(),
1961 m.size_bytes(),
1962 ad_data,
1963 ad_size,
1964 nullptr,
1965 npub.data(),
1966 k.data()
1967 );
1968
1969 if (status < 0) return status;
1970
1971 return maclen;
1972}
1973
1974static inline int
1975sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached(
1976 js_env_t *,
1977 js_receiver_t,
1978 js_typedarray_span_t<> m,
1979 js_typedarray_span_t<> c,
1980 js_typedarray_span_t<> mac,
1981 std::optional<js_typedarray_span_t<>> ad,
1982 js_typedarray_span_t<> npub,
1983 js_typedarray_span_t<> k
1984) {
1985 assert(m.size_bytes() == c.size_bytes());
1986 assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
1987 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1988 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1989
1990 uint8_t *ad_data = nullptr;
1991 size_t ad_size = 0;
1992 if (ad) {
1993 ad_data = ad->data();
1994 ad_size = ad->size_bytes();
1995 }
1996
1997 return crypto_aead_chacha20poly1305_ietf_decrypt_detached(
1998 m.data(),
1999 nullptr,
2000 c.data(),
2001 c.size_bytes(),
2002 mac.data(),
2003 ad_data,
2004 ad_size,
2005 npub.data(),
2006 k.data()
2007 );
2008}
2009
2010static inline void
2011sn_crypto_secretstream_xchacha20poly1305_keygen(
2012 js_env_t *env,
2013 js_receiver_t,
2014
2015 js_arraybuffer_span_t k,
2016 uint32_t k_offset,
2017 uint32_t k_len
2018) {
2019 assert_bounds(k);
2020 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2021
2022 crypto_secretstream_xchacha20poly1305_keygen(&k[k_offset]);
2023}
2024
2025static inline int
2026sn_crypto_secretstream_xchacha20poly1305_init_push(
2027 js_env_t *env,
2028 js_receiver_t,
2029
2030 js_arraybuffer_span_t state,
2031 uint32_t state_offset,
2032 uint32_t state_len,
2033
2034 js_arraybuffer_span_t header,
2035 uint32_t header_offset,
2036 uint32_t header_len,
2037
2038 js_arraybuffer_span_t k,
2039 uint32_t k_offset,
2040 uint32_t k_len
2041) {
2042 assert_bounds(state);
2043 assert_bounds(header);
2044 assert_bounds(k);
2045
2046 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2047 assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
2048 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2049
2050 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2051
2052 return crypto_secretstream_xchacha20poly1305_init_push(state_data, &header[header_offset], &k[k_offset]);
2053}
2054
2055static inline uint64_t
2056sn_crypto_secretstream_xchacha20poly1305_push(
2057 js_env_t *env,
2058 js_receiver_t,
2059
2060 js_arraybuffer_span_t state,
2061 uint32_t state_offset,
2062 uint32_t state_len,
2063
2064 js_arraybuffer_span_t c,
2065 uint32_t c_offset,
2066 uint32_t c_len,
2067
2068 js_arraybuffer_span_t m,
2069 uint32_t m_offset,
2070 uint32_t m_len,
2071
2072 js_arraybuffer_span_t ad,
2073 uint32_t ad_offset,
2074 uint32_t ad_len,
2075
2076 uint32_t tag
2077) {
2078 assert_bounds(state);
2079 assert_bounds(c);
2080 assert_bounds(m);
2081
2082 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2083 assert(c_len == m_len + crypto_secretstream_xchacha20poly1305_ABYTES);
2084 assert(c_len <= 0xffffffff && "32bit integer");
2085
2086 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2087
2088 uint8_t *ad_data = NULL;
2089 if (ad_len) {
2090 assert_bounds(ad);
2091 ad_data = &ad[ad_offset];
2092 }
2093
2094 unsigned long long clen = 0;
2095 int status = crypto_secretstream_xchacha20poly1305_push(
2096 state_data,
2097 &c[c_offset],
2098 &clen,
2099 &m[m_offset],
2100 m_len,
2101 ad_data,
2102 ad_len,
2103 tag
2104 );
2105
2106 if (status < 0) return status;
2107
2108 return clen;
2109}
2110
2111static inline int
2112sn_crypto_secretstream_xchacha20poly1305_init_pull(
2113 js_env_t *,
2114 js_receiver_t,
2115
2116 js_arraybuffer_span_t state,
2117 uint32_t state_offset,
2118 uint32_t state_len,
2119
2120 js_arraybuffer_span_t header,
2121 uint32_t header_offset,
2122 uint32_t header_len,
2123
2124 js_arraybuffer_span_t k,
2125 uint32_t k_offset,
2126 uint32_t k_len
2127) {
2128 assert_bounds(state);
2129 assert_bounds(header);
2130 assert_bounds(k);
2131
2132 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2133 assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
2134 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2135
2136 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2137
2138 return crypto_secretstream_xchacha20poly1305_init_pull(state_data, &header[header_offset], &k[k_offset]);
2139}
2140
2141static inline uint64_t
2142sn_crypto_secretstream_xchacha20poly1305_pull(
2143 js_env_t *env,
2144 js_receiver_t,
2145
2146 js_arraybuffer_span_t state,
2147 uint32_t state_offset,
2148 uint32_t state_len,
2149
2150 js_arraybuffer_span_t m,
2151 uint32_t m_offset,
2152 uint32_t m_len,
2153
2154 js_arraybuffer_span_t tag,
2155 uint32_t tag_offset,
2156 uint32_t tag_len,
2157
2158 js_arraybuffer_span_t c,
2159 uint32_t c_offset,
2160 uint32_t c_len,
2161
2162 js_arraybuffer_span_t ad,
2163 uint32_t ad_offset,
2164 uint32_t ad_len
2165) {
2166 assert_bounds(state);
2167 assert_bounds(m);
2168 assert_bounds(tag);
2169 assert_bounds(c);
2170
2171 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2172 assert(c_len >= crypto_secretstream_xchacha20poly1305_ABYTES);
2173 assert(tag_len == 1);
2174 assert(m_len == c_len - crypto_secretstream_xchacha20poly1305_ABYTES);
2175 assert(m_len <= 0xffffffff);
2176
2177 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2178
2179 uint8_t *ad_data = NULL;
2180 if (ad_len) {
2181 assert_bounds(ad);
2182 ad_data = &ad[ad_offset];
2183 }
2184
2185 unsigned long long mlen = 0;
2186 int status = crypto_secretstream_xchacha20poly1305_pull(
2187 state_data,
2188 &m[m_offset],
2189 &mlen,
2190 &tag[tag_offset],
2191 &c[c_offset],
2192 c_len,
2193 ad_data,
2194 ad_len
2195 );
2196
2197 if (status < 0) return status;
2198
2199 return mlen;
2200}
2201
2202static inline void
2203sn_crypto_secretstream_xchacha20poly1305_rekey(
2204 js_env_t *,
2205 js_receiver_t,
2206
2207 js_arraybuffer_span_t state,
2208 uint32_t state_offset,
2209 uint32_t state_len
2210) {
2211 assert_bounds(state);
2212
2213 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2214
2215 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2216
2217 crypto_secretstream_xchacha20poly1305_rekey(state_data);
2218}
2219
2220struct sn_async_task {
2221 uv_work_t task;
2222 js_env_t *env;
2223 js_persistent_t<js_function_t<void, int>> cb;
2224 js_deferred_teardown_t *teardown;
2225 int code = 0;
2226 bool exiting = false;
2227
2228 sn_async_task(js_env_t *env) : env(env) {
2229 int err;
2230 err = js_add_teardown_callback<on_teardown, sn_async_task>(env, this, teardown);
2231 assert(err == 0);
2232 }
2233
2234 ~sn_async_task() {
2235 int err;
2236 err = js_finish_teardown_callback(teardown);
2237 assert(err == 0);
2238 }
2239
2240private:
2241 static void
2242 on_teardown(js_deferred_teardown_t *teardown, sn_async_task *req) {
2243 req->exiting = true;
2244 }
2245};
2246
2247struct sn_async_pwhash_request : sn_async_task {
2248 js_persistent_t<js_arraybuffer_t> out_ref;
2249 std::span<uint8_t> out;
2250
2251 js_persistent_t<js_arraybuffer_t> pwd_ref;
2252 std::span<char> pwd;
2253
2254 js_persistent_t<js_arraybuffer_t> salt_ref;
2255 std::span<uint8_t> salt;
2256
2257 uint64_t opslimit;
2258 size_t memlimit;
2259 int alg;
2260
2261 sn_async_pwhash_request(js_env_t *env) : sn_async_task(env) {}
2262};
2263
2264static void
2265async_pwhash_execute(uv_work_t *uv_req) {
2266 auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
2267
2268 req->code = crypto_pwhash(
2269 req->out.data(),
2270 req->out.size(),
2271 req->pwd.data(),
2272 req->pwd.size(),
2273 req->salt.data(),
2274 req->opslimit,
2275 req->memlimit,
2276 req->alg
2277 );
2278}
2279
2280static void
2281async_pwhash_complete(uv_work_t *uv_req, int status) {
2282 int err;
2283
2284 auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
2285
2286 if (req->exiting) return delete req;
2287
2288 js_handle_scope_t *scope;
2289 err = js_open_handle_scope(req->env, &scope);
2290 assert(err == 0);
2291
2292 js_function_t<void, int> callback;
2293 err = js_get_reference_value(req->env, req->cb, callback);
2294 assert(err == 0);
2295
2296 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2297 assert(err != js_pending_exception);
2298
2299 err = js_close_handle_scope(req->env, scope);
2300 assert(err == 0);
2301
2302 delete req;
2303}
2304
2305static inline void
2306sn_crypto_pwhash_async(
2307 js_env_t *env,
2308 js_receiver_t,
2309
2310 js_arraybuffer_t out,
2311 uint32_t out_offset,
2312 uint32_t out_len,
2313
2314 js_arraybuffer_t pwd,
2315 uint32_t pwd_offset,
2316 uint32_t pwd_len,
2317
2318 js_arraybuffer_t salt,
2319 uint32_t salt_offset,
2320 uint32_t salt_len,
2321
2322 uint64_t opslimit,
2323 uint64_t memlimit,
2324 uint32_t alg,
2325
2326 js_function_t<void, int> callback
2327) {
2328 int err;
2329
2330 auto *req = new sn_async_pwhash_request(env);
2331
2332 std::span<uint8_t> out_view;
2333 err = js_get_arraybuffer_info(env, out, out_view);
2334 assert(err == 0);
2335 assert(out_offset + out_len <= out_view.size());
2336
2337 req->out = {&out_view[out_offset], out_len};
2338
2339 std::span<char> pwd_view;
2340 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2341 assert(err == 0);
2342 assert(pwd_offset + pwd_len <= pwd_view.size());
2343
2344 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2345
2346 std::span<uint8_t> salt_view;
2347 err = js_get_arraybuffer_info(env, salt, salt_view);
2348 assert(err == 0);
2349 assert(salt_offset + salt_len <= salt_view.size());
2350
2351 req->salt = {&salt_view[salt_offset], salt_len};
2352
2353 req->opslimit = opslimit;
2354 req->memlimit = memlimit;
2355 req->alg = alg;
2356
2357 err = js_create_reference(env, out, req->out_ref);
2358 assert(err == 0);
2359
2360 err = js_create_reference(env, pwd, req->pwd_ref);
2361 assert(err == 0);
2362
2363 err = js_create_reference(env, salt, req->salt_ref);
2364 assert(err == 0);
2365
2366 err = js_create_reference(env, callback, req->cb);
2367 assert(err == 0);
2368
2369 uv_loop_t *loop;
2370 err = js_get_env_loop(env, &loop);
2371 assert(err == 0);
2372
2373 err = uv_queue_work(loop, &req->task, async_pwhash_execute, async_pwhash_complete);
2374 assert(err == 0);
2375}
2376
2377struct sn_async_pwhash_str_request : sn_async_task {
2378 js_persistent_t<js_arraybuffer_t> out_ref;
2379 std::span<char> out;
2380
2381 js_persistent_t<js_arraybuffer_t> pwd_ref;
2382 std::span<char> pwd;
2383
2384 uint64_t opslimit;
2385 size_t memlimit;
2386
2387 sn_async_pwhash_str_request(js_env_t *env) : sn_async_task(env) {}
2388};
2389
2390static void
2391async_pwhash_str_execute(uv_work_t *uv_req) {
2392 auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
2393
2394 req->code = crypto_pwhash_str(
2395 req->out.data(),
2396 req->pwd.data(),
2397 req->pwd.size(),
2398 req->opslimit,
2399 req->memlimit
2400 );
2401}
2402
2403static void
2404async_pwhash_str_complete(uv_work_t *uv_req, int status) {
2405 int err;
2406
2407 auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
2408
2409 if (req->exiting) return delete req;
2410
2411 js_handle_scope_t *scope;
2412 err = js_open_handle_scope(req->env, &scope);
2413 assert(err == 0);
2414
2415 js_function_t<void, int> callback;
2416 err = js_get_reference_value(req->env, req->cb, callback);
2417 assert(err == 0);
2418
2419 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2420 assert(err != js_pending_exception);
2421
2422 err = js_close_handle_scope(req->env, scope);
2423 assert(err == 0);
2424
2425 delete req;
2426}
2427
2428static inline void
2429sn_crypto_pwhash_str_async(
2430 js_env_t *env,
2431 js_receiver_t,
2432
2433 js_arraybuffer_t out,
2434 uint32_t out_offset,
2435 uint32_t out_len,
2436
2437 js_arraybuffer_t pwd,
2438 uint32_t pwd_offset,
2439 uint32_t pwd_len,
2440
2441 uint64_t opslimit,
2442 uint64_t memlimit,
2443 js_function_t<void, int> callback
2444) {
2445 int err;
2446
2447 auto *req = new sn_async_pwhash_str_request(env);
2448
2449 std::span<char> out_view;
2450 err = js_get_arraybuffer_info(env, out, out_view);
2451 assert(err == 0);
2452 assert(out_offset + out_len <= out_view.size());
2453
2454 req->out = {&out_view[out_offset], out_len};
2455
2456 std::span<char> pwd_view;
2457 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2458 assert(err == 0);
2459 assert(pwd_offset + pwd_len <= pwd_view.size());
2460
2461 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2462
2463 req->opslimit = opslimit;
2464 req->memlimit = memlimit;
2465
2466 err = js_create_reference(env, out, req->out_ref);
2467 assert(err == 0);
2468
2469 err = js_create_reference(env, pwd, req->pwd_ref);
2470 assert(err == 0);
2471
2472 err = js_create_reference(env, callback, req->cb);
2473 assert(err == 0);
2474
2475 uv_loop_t *loop;
2476 err = js_get_env_loop(env, &loop);
2477 assert(err == 0);
2478
2479 err = uv_queue_work(loop, &req->task, async_pwhash_str_execute, async_pwhash_str_complete);
2480 assert(err == 0);
2481}
2482
2483struct sn_async_pwhash_str_verify_request : sn_async_task {
2484 js_persistent_t<js_arraybuffer_t> str_ref;
2485 std::span<char> str;
2486
2487 js_persistent_t<js_arraybuffer_t> pwd_ref;
2488 std::span<char> pwd;
2489
2490 sn_async_pwhash_str_verify_request(js_env_t *env) : sn_async_task(env) {}
2491};
2492
2493static void
2494async_pwhash_str_verify_execute(uv_work_t *uv_req) {
2495 auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
2496
2497 req->code = crypto_pwhash_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
2498}
2499
2500static void
2501async_pwhash_str_verify_complete(uv_work_t *uv_req, int status) {
2502 int err;
2503
2504 auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
2505
2506 if (req->exiting) return delete req;
2507
2508 js_handle_scope_t *scope;
2509 err = js_open_handle_scope(req->env, &scope);
2510 assert(err == 0);
2511
2512 js_function_t<void, int> callback;
2513 err = js_get_reference_value(req->env, req->cb, callback);
2514 assert(err == 0);
2515
2516 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2517 assert(err != js_pending_exception);
2518
2519 err = js_close_handle_scope(req->env, scope);
2520 assert(err == 0);
2521
2522 delete req;
2523}
2524
2525static inline void
2526sn_crypto_pwhash_str_verify_async(
2527 js_env_t *env,
2528 js_receiver_t,
2529
2530 js_arraybuffer_t str,
2531 uint32_t str_offset,
2532 uint32_t str_len,
2533
2534 js_arraybuffer_t pwd,
2535 uint32_t pwd_offset,
2536 uint32_t pwd_len,
2537
2538 js_function_t<void, int> callback
2539) {
2540 int err;
2541
2542 auto *req = new sn_async_pwhash_str_verify_request(env);
2543
2544 std::span<char> str_view;
2545 err = js_get_arraybuffer_info(env, str, str_view);
2546 assert(err == 0);
2547 assert(str_offset + str_len <= str_view.size());
2548
2549 req->str = {&str_view[str_offset], str_len};
2550
2551 std::span<char> pwd_view;
2552 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2553 assert(err == 0);
2554 assert(pwd_offset + pwd_len <= pwd_view.size());
2555
2556 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2557
2558 err = js_create_reference(env, str, req->str_ref);
2559 assert(err == 0);
2560
2561 err = js_create_reference(env, pwd, req->pwd_ref);
2562 assert(err == 0);
2563
2564 err = js_create_reference(env, callback, req->cb);
2565 assert(err == 0);
2566
2567 uv_loop_t *loop;
2568 err = js_get_env_loop(env, &loop);
2569 assert(err == 0);
2570
2571 err = uv_queue_work(loop, &req->task, async_pwhash_str_verify_execute, async_pwhash_str_verify_complete);
2572 assert(err == 0);
2573}
2574
2575struct sn_async_pwhash_scryptsalsa208sha256_request : sn_async_task {
2576 js_persistent_t<js_arraybuffer_t> out_ref;
2577 std::span<uint8_t> out;
2578
2579 js_persistent_t<js_arraybuffer_t> pwd_ref;
2580 std::span<char> pwd;
2581
2582 js_persistent_t<js_arraybuffer_t> salt_ref;
2583 std::span<uint8_t> salt;
2584
2585 uint64_t opslimit;
2586 size_t memlimit;
2587
2588 sn_async_pwhash_scryptsalsa208sha256_request(js_env_t *env) : sn_async_task(env) {}
2589};
2590
2591static void
2592async_pwhash_scryptsalsa208sha256_execute(uv_work_t *uv_req) {
2593 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
2594
2595 req->code = crypto_pwhash_scryptsalsa208sha256(
2596 req->out.data(),
2597 req->out.size(),
2598 req->pwd.data(),
2599 req->pwd.size(),
2600 req->salt.data(),
2601 req->opslimit,
2602 req->memlimit
2603 );
2604}
2605
2606static void
2607async_pwhash_scryptsalsa208sha256_complete(uv_work_t *uv_req, int status) {
2608 int err;
2609
2610 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
2611
2612 if (req->exiting) return delete req;
2613
2614 js_handle_scope_t *scope;
2615 err = js_open_handle_scope(req->env, &scope);
2616 assert(err == 0);
2617
2618 js_function_t<void, int> callback;
2619 err = js_get_reference_value(req->env, req->cb, callback);
2620 assert(err == 0);
2621
2622 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2623 assert(err != js_pending_exception);
2624
2625 err = js_close_handle_scope(req->env, scope);
2626 assert(err == 0);
2627
2628 delete req;
2629}
2630
2631static inline void
2632sn_crypto_pwhash_scryptsalsa208sha256_async(
2633 js_env_t *env,
2634 js_receiver_t,
2635
2636 js_arraybuffer_t out,
2637 uint32_t out_offset,
2638 uint32_t out_len,
2639
2640 js_arraybuffer_t pwd,
2641 uint32_t pwd_offset,
2642 uint32_t pwd_len,
2643
2644 js_arraybuffer_t salt,
2645 uint32_t salt_offset,
2646 uint32_t salt_len,
2647
2648 uint64_t opslimit,
2649 uint64_t memlimit,
2650
2651 js_function_t<void, int> callback
2652) {
2653 int err;
2654
2655 auto *req = new sn_async_pwhash_scryptsalsa208sha256_request(env);
2656
2657 std::span<uint8_t> out_view;
2658 err = js_get_arraybuffer_info(env, out, out_view);
2659 assert(err == 0);
2660 assert(out_offset + out_len <= out_view.size());
2661
2662 req->out = {&out_view[out_offset], out_len};
2663
2664 std::span<char> pwd_view;
2665 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2666 assert(err == 0);
2667 assert(pwd_offset + pwd_len <= pwd_view.size());
2668
2669 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2670
2671 std::span<uint8_t> salt_view;
2672 err = js_get_arraybuffer_info(env, salt, salt_view);
2673 assert(err == 0);
2674 assert(salt_offset + salt_len <= salt_view.size());
2675 assert(salt_len == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
2676
2677 req->salt = {&salt_view[salt_offset], salt_len};
2678
2679 req->opslimit = opslimit;
2680 req->memlimit = memlimit;
2681
2682 err = js_create_reference(env, out, req->out_ref);
2683 assert(err == 0);
2684
2685 err = js_create_reference(env, pwd, req->pwd_ref);
2686 assert(err == 0);
2687
2688 err = js_create_reference(env, salt, req->salt_ref);
2689 assert(err == 0);
2690
2691 err = js_create_reference(env, callback, req->cb);
2692 assert(err == 0);
2693
2694 uv_loop_t *loop;
2695 err = js_get_env_loop(env, &loop);
2696 assert(err == 0);
2697
2698 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_execute, async_pwhash_scryptsalsa208sha256_complete);
2699 assert(err == 0);
2700}
2701
2702struct sn_async_pwhash_scryptsalsa208sha256_str_request : sn_async_task {
2703 js_persistent_t<js_arraybuffer_t> out_ref;
2704 std::span<char> out;
2705
2706 js_persistent_t<js_arraybuffer_t> pwd_ref;
2707 std::span<char> pwd;
2708
2709 uint64_t opslimit;
2710 size_t memlimit;
2711
2712 sn_async_pwhash_scryptsalsa208sha256_str_request(js_env_t *env) : sn_async_task(env) {}
2713};
2714
2715static void
2716async_pwhash_scryptsalsa208sha256_str_execute(uv_work_t *uv_req) {
2717 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
2718
2719 req->code = crypto_pwhash_scryptsalsa208sha256_str(
2720 req->out.data(),
2721 req->pwd.data(),
2722 req->pwd.size(),
2723 req->opslimit,
2724 req->memlimit
2725 );
2726}
2727
2728static void
2729async_pwhash_scryptsalsa208sha256_str_complete(uv_work_t *uv_req, int status) {
2730 int err;
2731
2732 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
2733
2734 if (req->exiting) return delete req;
2735
2736 js_handle_scope_t *scope;
2737 err = js_open_handle_scope(req->env, &scope);
2738 assert(err == 0);
2739
2740 js_function_t<void, int> callback;
2741 err = js_get_reference_value(req->env, req->cb, callback);
2742 assert(err == 0);
2743
2744 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2745 assert(err != js_pending_exception);
2746
2747 err = js_close_handle_scope(req->env, scope);
2748 assert(err == 0);
2749
2750 delete req;
2751}
2752
2753static inline void
2754sn_crypto_pwhash_scryptsalsa208sha256_str_async(
2755 js_env_t *env,
2756 js_receiver_t,
2757
2758 js_arraybuffer_t out,
2759 uint32_t out_offset,
2760 uint32_t out_len,
2761
2762 js_arraybuffer_t pwd,
2763 uint32_t pwd_offset,
2764 uint32_t pwd_len,
2765
2766 uint64_t opslimit,
2767 uint64_t memlimit,
2768
2769 js_function_t<void, int> callback
2770) {
2771 int err;
2772
2773 auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_request(env);
2774
2775 std::span<char> out_view;
2776 err = js_get_arraybuffer_info(env, out, out_view);
2777 assert(err == 0);
2778 assert(out_offset + out_len <= out_view.size());
2779
2780 req->out = {&out_view[out_offset], out_len};
2781
2782 std::span<char> pwd_view;
2783 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2784 assert(err == 0);
2785 assert(pwd_offset + pwd_len <= pwd_view.size());
2786
2787 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2788
2789 req->opslimit = opslimit;
2790 req->memlimit = memlimit;
2791
2792 err = js_create_reference(env, out, req->out_ref);
2793 assert(err == 0);
2794
2795 err = js_create_reference(env, pwd, req->pwd_ref);
2796 assert(err == 0);
2797
2798 err = js_create_reference(env, callback, req->cb);
2799 assert(err == 0);
2800
2801 uv_loop_t *loop;
2802 err = js_get_env_loop(env, &loop);
2803 assert(err == 0);
2804
2805 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_execute, async_pwhash_scryptsalsa208sha256_str_complete);
2806 assert(err == 0);
2807}
2808
2809struct sn_async_pwhash_scryptsalsa208sha256_str_verify_request : sn_async_task {
2810 js_persistent_t<js_arraybuffer_t> str_ref;
2811 std::span<char> str;
2812
2813 js_persistent_t<js_arraybuffer_t> pwd_ref;
2814 std::span<char> pwd;
2815
2816 sn_async_pwhash_scryptsalsa208sha256_str_verify_request(js_env_t *env) : sn_async_task(env) {}
2817};
2818
2819static void
2820async_pwhash_scryptsalsa208sha256_str_verify_execute(uv_work_t *uv_req) {
2821 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
2822
2823 req->code = crypto_pwhash_scryptsalsa208sha256_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
2824}
2825
2826static void
2827async_pwhash_scryptsalsa208sha256_str_verify_complete(uv_work_t *uv_req, int status) {
2828 int err;
2829
2830 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
2831
2832 if (req->exiting) return delete req;
2833
2834 js_handle_scope_t *scope;
2835 err = js_open_handle_scope(req->env, &scope);
2836 assert(err == 0);
2837
2838 js_function_t<void, int> callback;
2839 err = js_get_reference_value(req->env, req->cb, callback);
2840 assert(err == 0);
2841
2842 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2843 assert(err != js_pending_exception);
2844
2845 err = js_close_handle_scope(req->env, scope);
2846 assert(err == 0);
2847
2848 delete req;
2849}
2850
2851static inline void
2852sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async(
2853 js_env_t *env,
2854 js_receiver_t,
2855
2856 js_arraybuffer_t str,
2857 uint32_t str_offset,
2858 uint32_t str_len,
2859
2860 js_arraybuffer_t pwd,
2861 uint32_t pwd_offset,
2862 uint32_t pwd_len,
2863
2864 js_function_t<void, int> callback
2865) {
2866 int err;
2867
2868 auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_verify_request(env);
2869
2870 std::span<char> str_view;
2871 err = js_get_arraybuffer_info(env, str, str_view);
2872 assert(err == 0);
2873 assert(str_offset + str_len <= str_view.size());
2874
2875 req->str = {&str_view[str_offset], str_len};
2876
2877 std::span<char> pwd_view;
2878 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2879 assert(err == 0);
2880 assert(pwd_offset + pwd_len <= pwd_view.size());
2881
2882 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2883
2884 err = js_create_reference(env, str, req->str_ref);
2885 assert(err == 0);
2886
2887 err = js_create_reference(env, pwd, req->pwd_ref);
2888 assert(err == 0);
2889
2890 err = js_create_reference(env, callback, req->cb);
2891 assert(err == 0);
2892
2893 uv_loop_t *loop;
2894 err = js_get_env_loop(env, &loop);
2895 assert(err == 0);
2896
2897 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_verify_execute, async_pwhash_scryptsalsa208sha256_str_verify_complete);
2898 assert(err == 0);
2899}
2900
2901struct sn_crypto_stream_xor_state {
2902 unsigned char n[crypto_stream_NONCEBYTES];
2903 unsigned char k[crypto_stream_KEYBYTES];
2904 unsigned char next_block[64];
2905 int remainder;
2906 uint64_t block_counter;
2907};
2908
2909static inline void
2910sn_crypto_stream_xor_wrap_init(
2911 js_env_t *,
2912 js_receiver_t,
2913 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
2914 js_typedarray_span_t<> n,
2915 js_typedarray_span_t<> k
2916) {
2917 assert(n.size_bytes() == crypto_stream_NONCEBYTES);
2918 assert(k.size_bytes() == crypto_stream_KEYBYTES);
2919
2920 state->remainder = 0;
2921 state->block_counter = 0;
2922 memcpy(state->n, n.data(), crypto_stream_NONCEBYTES);
2923 memcpy(state->k, k.data(), crypto_stream_KEYBYTES);
2924}
2925
2926static inline void
2927sn_crypto_stream_xor_wrap_update(
2928 js_env_t *,
2929 js_receiver_t,
2930 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
2931 js_typedarray_span_t<> c,
2932 js_typedarray_span_t<> m
2933) {
2934 assert(c.size_bytes() == m.size_bytes());
2935
2936 auto next_block = state->next_block;
2937
2938 size_t m_size = m.size_bytes();
2939 auto *c_ptr = c.data();
2940 auto *m_ptr = m.data();
2941
2942 if (state->remainder) {
2943 uint64_t offset = 0;
2944 int rem = state->remainder;
2945
2946 while (rem < 64 && offset < m_size) {
2947 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
2948 ++offset;
2949 ++rem;
2950 }
2951
2952 c_ptr += offset;
2953 m_ptr += offset;
2954 m_size -= offset;
2955 state->remainder = (rem == 64) ? 0 : rem;
2956
2957 if (m_size == 0) return;
2958 }
2959
2960 state->remainder = m_size & 63;
2961 size_t main_len = m_size - state->remainder;
2962
2963 crypto_stream_xsalsa20_xor_ic(c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k);
2964 state->block_counter += main_len / 64;
2965
2966 if (state->remainder) {
2967 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
2968 memcpy(next_block, m_ptr + main_len, state->remainder);
2969
2970 crypto_stream_xsalsa20_xor_ic(
2971 next_block, next_block, 64, state->n, state->block_counter, state->k
2972 );
2973 memcpy(c_ptr + main_len, next_block, state->remainder);
2974
2975 state->block_counter++;
2976 }
2977}
2978
2979static inline void
2980sn_crypto_stream_xor_wrap_final(
2981 js_env_t *,
2982 js_receiver_t,
2983 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state
2984) {
2985 sodium_memzero(state->n, sizeof(state->n));
2986 sodium_memzero(state->k, sizeof(state->k));
2987 sodium_memzero(state->next_block, sizeof(state->next_block));
2988 state->remainder = 0;
2989}
2990
2991struct sn_crypto_stream_chacha20_xor_state {
2992 unsigned char n[crypto_stream_chacha20_NONCEBYTES];
2993 unsigned char k[crypto_stream_chacha20_KEYBYTES];
2994 unsigned char next_block[64];
2995 int remainder;
2996 uint64_t block_counter;
2997};
2998
2999static inline void
3000sn_crypto_stream_chacha20_xor_wrap_init(
3001 js_env_t *,
3002 js_receiver_t,
3003 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
3004 js_typedarray_span_t<> n,
3005 js_typedarray_span_t<> k
3006) {
3007 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
3008 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
3009
3010 state->remainder = 0;
3011 state->block_counter = 0;
3012 memcpy(state->n, n.data(), crypto_stream_chacha20_NONCEBYTES);
3013 memcpy(state->k, k.data(), crypto_stream_chacha20_KEYBYTES);
3014}
3015
3016static inline void
3017sn_crypto_stream_chacha20_xor_wrap_update(
3018 js_env_t *,
3019 js_receiver_t,
3020 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
3021 js_typedarray_span_t<> c,
3022 js_typedarray_span_t<> m
3023) {
3024 assert(c.size_bytes() == m.size_bytes());
3025
3026 auto *next_block = state->next_block;
3027
3028 size_t m_size = m.size_bytes();
3029 auto *c_ptr = c.data();
3030 auto *m_ptr = m.data();
3031
3032 if (state->remainder) {
3033 uint64_t offset = 0;
3034 int rem = state->remainder;
3035
3036 while (rem < 64 && offset < m_size) {
3037 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3038 offset++;
3039 rem++;
3040 }
3041
3042 c_ptr += offset;
3043 m_ptr += offset;
3044 m_size -= offset;
3045 state->remainder = (rem == 64) ? 0 : rem;
3046
3047 if (m_size == 0) return;
3048 }
3049
3050 state->remainder = m_size & 63;
3051 size_t main_len = m_size - state->remainder;
3052
3053 crypto_stream_chacha20_xor_ic(
3054 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3055 );
3056
3057 state->block_counter += main_len / 64;
3058
3059 if (state->remainder) {
3060 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3061 memcpy(next_block, m_ptr + main_len, state->remainder);
3062
3063 crypto_stream_chacha20_xor_ic(
3064 next_block, next_block, 64, state->n, state->block_counter, state->k
3065 );
3066 memcpy(c_ptr + main_len, next_block, state->remainder);
3067
3068 state->block_counter++;
3069 }
3070}
3071
3072static inline void
3073sn_crypto_stream_chacha20_xor_wrap_final(
3074 js_env_t *,
3075 js_receiver_t,
3076 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state
3077) {
3078 sodium_memzero(state->n, sizeof(state->n));
3079 sodium_memzero(state->k, sizeof(state->k));
3080 sodium_memzero(state->next_block, sizeof(state->next_block));
3081 state->remainder = 0;
3082}
3083
3084struct sn_crypto_stream_chacha20_ietf_xor_state {
3085 unsigned char n[crypto_stream_chacha20_ietf_NONCEBYTES];
3086 unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES];
3087 unsigned char next_block[64];
3088 int remainder;
3089 uint64_t block_counter;
3090};
3091
3092static inline void
3093sn_crypto_stream_chacha20_ietf_xor_wrap_init(
3094 js_env_t *,
3095 js_receiver_t,
3096 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
3097 js_typedarray_span_t<> n,
3098 js_typedarray_span_t<> k
3099) {
3100 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
3101 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
3102
3103 state->remainder = 0;
3104 state->block_counter = 0;
3105 memcpy(state->n, n.data(), crypto_stream_chacha20_ietf_NONCEBYTES);
3106 memcpy(state->k, k.data(), crypto_stream_chacha20_ietf_KEYBYTES);
3107}
3108
3109static inline void
3110sn_crypto_stream_chacha20_ietf_xor_wrap_update(
3111 js_env_t *,
3112 js_receiver_t,
3113 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
3114 js_typedarray_span_t<> c,
3115 js_typedarray_span_t<> m
3116) {
3117 assert(c.size_bytes() == m.size_bytes());
3118
3119 auto *next_block = state->next_block;
3120
3121 size_t m_size = m.size_bytes();
3122 auto *c_ptr = c.data();
3123 auto *m_ptr = m.data();
3124
3125 if (state->remainder) {
3126 uint64_t offset = 0;
3127 int rem = state->remainder;
3128
3129 while (rem < 64 && offset < m_size) {
3130 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3131 offset++;
3132 rem++;
3133 }
3134
3135 c_ptr += offset;
3136 m_ptr += offset;
3137 m_size -= offset;
3138 state->remainder = (rem == 64) ? 0 : rem;
3139
3140 if (m_size == 0) return;
3141 }
3142
3143 state->remainder = m_size & 63;
3144 size_t main_len = m_size - state->remainder;
3145
3146 crypto_stream_chacha20_ietf_xor_ic(
3147 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3148 );
3149
3150 state->block_counter += main_len / 64;
3151
3152 if (state->remainder) {
3153 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3154 memcpy(next_block, m_ptr + main_len, state->remainder);
3155
3156 crypto_stream_chacha20_ietf_xor_ic(
3157 next_block, next_block, 64, state->n, state->block_counter, state->k
3158 );
3159 memcpy(c_ptr + main_len, next_block, state->remainder);
3160
3161 state->block_counter++;
3162 }
3163}
3164
3165static inline void
3166sn_crypto_stream_chacha20_ietf_xor_wrap_final(
3167 js_env_t *,
3168 js_receiver_t,
3169 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state
3170) {
3171 sodium_memzero(state->n, sizeof(state->n));
3172 sodium_memzero(state->k, sizeof(state->k));
3173 sodium_memzero(state->next_block, sizeof(state->next_block));
3174 state->remainder = 0;
3175}
3176
3177struct sn_crypto_stream_xchacha20_xor_state {
3178 unsigned char n[crypto_stream_xchacha20_NONCEBYTES];
3179 unsigned char k[crypto_stream_xchacha20_KEYBYTES];
3180 unsigned char next_block[64];
3181 int remainder;
3182 uint64_t block_counter;
3183};
3184
3185static inline void
3186sn_crypto_stream_xchacha20_xor_wrap_init(
3187 js_env_t *,
3188 js_receiver_t,
3189 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
3190 js_typedarray_span_t<> n,
3191 js_typedarray_span_t<> k
3192) {
3193 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
3194 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
3195
3196 state->remainder = 0;
3197 state->block_counter = 0;
3198 memcpy(state->n, n.data(), crypto_stream_xchacha20_NONCEBYTES);
3199 memcpy(state->k, k.data(), crypto_stream_xchacha20_KEYBYTES);
3200}
3201
3202static inline void
3203sn_crypto_stream_xchacha20_xor_wrap_update(
3204 js_env_t *,
3205 js_receiver_t,
3206 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
3207 js_typedarray_span_t<> c,
3208 js_typedarray_span_t<> m
3209) {
3210 assert(c.size_bytes() == m.size_bytes());
3211
3212 auto *next_block = state->next_block;
3213
3214 size_t m_size = m.size_bytes();
3215 auto *c_ptr = c.data();
3216 auto *m_ptr = m.data();
3217
3218 if (state->remainder) {
3219 uint64_t offset = 0;
3220 int rem = state->remainder;
3221
3222 while (rem < 64 && offset < m_size) {
3223 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3224 ++offset;
3225 ++rem;
3226 }
3227
3228 c_ptr += offset;
3229 m_ptr += offset;
3230 m_size -= offset;
3231 state->remainder = (rem == 64) ? 0 : rem;
3232
3233 if (m_size == 0) return;
3234 }
3235
3236 state->remainder = m_size & 63;
3237 size_t main_len = m_size - state->remainder;
3238
3239 crypto_stream_xchacha20_xor_ic(
3240 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3241 );
3242
3243 state->block_counter += main_len / 64;
3244
3245 if (state->remainder) {
3246 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3247 memcpy(next_block, m_ptr + main_len, state->remainder);
3248
3249 crypto_stream_xchacha20_xor_ic(
3250 next_block, next_block, 64, state->n, state->block_counter, state->k
3251 );
3252 memcpy(c_ptr + main_len, next_block, state->remainder);
3253
3254 state->block_counter++;
3255 }
3256}
3257
3258static inline void
3259sn_crypto_stream_xchacha20_xor_wrap_final(
3260 js_env_t *,
3261 js_receiver_t,
3262 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state
3263) {
3264 sodium_memzero(state->n, sizeof(state->n));
3265 sodium_memzero(state->k, sizeof(state->k));
3266 sodium_memzero(state->next_block, sizeof(state->next_block));
3267 state->remainder = 0;
3268}
3269
3270struct sn_crypto_stream_salsa20_xor_state {
3271 unsigned char n[crypto_stream_salsa20_NONCEBYTES];
3272 unsigned char k[crypto_stream_salsa20_KEYBYTES];
3273 unsigned char next_block[64];
3274 int remainder;
3275 uint64_t block_counter;
3276};
3277
3278static inline void
3279sn_crypto_stream_salsa20_xor_wrap_init(
3280 js_env_t *,
3281 js_receiver_t,
3282 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
3283 js_typedarray_span_t<> n,
3284 js_typedarray_span_t<> k
3285) {
3286 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
3287 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
3288
3289 state->remainder = 0;
3290 state->block_counter = 0;
3291 memcpy(state->n, n.data(), crypto_stream_salsa20_NONCEBYTES);
3292 memcpy(state->k, k.data(), crypto_stream_salsa20_KEYBYTES);
3293}
3294
3295static inline void
3296sn_crypto_stream_salsa20_xor_wrap_update(
3297 js_env_t *,
3298 js_receiver_t,
3299 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
3300 js_typedarray_span_t<> c,
3301 js_typedarray_span_t<> m
3302) {
3303 assert(c.size_bytes() == m.size_bytes());
3304
3305 auto *next_block = state->next_block;
3306
3307 size_t m_size = m.size_bytes();
3308 auto *c_ptr = c.data();
3309 auto *m_ptr = m.data();
3310
3311 if (state->remainder) {
3312 uint64_t offset = 0;
3313 int rem = state->remainder;
3314
3315 while (rem < 64 && offset < m_size) {
3316 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3317 ++offset;
3318 ++rem;
3319 }
3320
3321 c_ptr += offset;
3322 m_ptr += offset;
3323 m_size -= offset;
3324 state->remainder = (rem == 64) ? 0 : rem;
3325
3326 if (m_size == 0) return;
3327 }
3328
3329 state->remainder = m_size & 63;
3330 size_t main_len = m_size - state->remainder;
3331
3332 crypto_stream_salsa20_xor_ic(
3333 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3334 );
3335
3336 state->block_counter += main_len / 64;
3337
3338 if (state->remainder) {
3339 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3340 memcpy(next_block, m_ptr + main_len, state->remainder);
3341
3342 crypto_stream_salsa20_xor_ic(
3343 next_block, next_block, 64, state->n, state->block_counter, state->k
3344 );
3345 memcpy(c_ptr + main_len, next_block, state->remainder);
3346
3347 state->block_counter++;
3348 }
3349}
3350
3351static inline void
3352sn_crypto_stream_salsa20_xor_wrap_final(
3353 js_env_t *,
3354 js_receiver_t,
3355 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state
3356) {
3357 sodium_memzero(state->n, sizeof(state->n));
3358 sodium_memzero(state->k, sizeof(state->k));
3359 sodium_memzero(state->next_block, sizeof(state->next_block));
3360 state->remainder = 0;
3361}
3362
3363// Experimental API
3364
3365static inline void
3366sn_extension_tweak_ed25519_base(
3367 js_env_t *,
3368 js_receiver_t,
3369 js_typedarray_span_t<> n,
3370 js_typedarray_span_t<> p,
3371 js_typedarray_span_t<> ns
3372) {
3373 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3374 assert(p.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3375
3376 sn__extension_tweak_ed25519_base(p.data(), n.data(), ns.data(), ns.size_bytes());
3377}
3378
3379static inline int
3380sn_extension_tweak_ed25519_sign_detached(
3381 js_env_t *,
3382 js_receiver_t,
3383 js_typedarray_span_t<> sig,
3384 js_typedarray_span_t<> m,
3385 js_typedarray_span_t<> scalar,
3386 std::optional<js_typedarray_span_t<>> pk
3387) {
3388 assert(sig.size_bytes() == crypto_sign_BYTES);
3389 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3390
3391 uint8_t *pk_data = nullptr;
3392 if (pk) {
3393 assert(pk->size_bytes() == crypto_sign_PUBLICKEYBYTES);
3394 pk_data = pk->data();
3395 }
3396
3397 return sn__extension_tweak_ed25519_sign_detached(
3398 sig.data(),
3399 nullptr,
3400 m.data(),
3401 m.size_bytes(),
3402 scalar.data(),
3403 pk_data
3404 );
3405}
3406
3407static inline void
3408sn_extension_tweak_ed25519_sk_to_scalar(
3409 js_env_t *,
3410 js_receiver_t,
3411 js_typedarray_span_t<> n,
3412 js_typedarray_span_t<> sk
3413) {
3414 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3415 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
3416
3417 sn__extension_tweak_ed25519_sk_to_scalar(n.data(), sk.data());
3418}
3419
3420static inline void
3421sn_extension_tweak_ed25519_scalar(
3422 js_env_t *,
3423 js_receiver_t,
3424 js_typedarray_span_t<> scalar_out,
3425 js_typedarray_span_t<> scalar,
3426 js_typedarray_span_t<> ns
3427) {
3428 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3429 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3430
3431 sn__extension_tweak_ed25519_scalar(scalar_out.data(), scalar.data(), ns.data(), ns.size_bytes());
3432}
3433
3434static inline int
3435sn_extension_tweak_ed25519_pk(
3436 js_env_t *,
3437 js_receiver_t,
3438 js_typedarray_span_t<> tpk,
3439 js_typedarray_span_t<> pk,
3440 js_typedarray_span_t<> ns
3441) {
3442 assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3443 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3444
3445 return sn__extension_tweak_ed25519_pk(tpk.data(), pk.data(), ns.data(), ns.size_bytes());
3446}
3447
3448static inline void
3449sn_extension_tweak_ed25519_keypair(
3450 js_env_t *,
3451 js_receiver_t,
3452 js_typedarray_span_t<> pk,
3453 js_typedarray_span_t<> scalar_out,
3454 js_typedarray_span_t<> scalar_in,
3455 js_typedarray_span_t<> ns
3456) {
3457 assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3458 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3459 assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3460
3461 sn__extension_tweak_ed25519_keypair(
3462 pk.data(),
3463 scalar_out.data(),
3464 scalar_in.data(),
3465 ns.data(),
3466 ns.size_bytes()
3467 );
3468}
3469
3470static inline void
3471sn_extension_tweak_ed25519_scalar_add(
3472 js_env_t *,
3473 js_receiver_t,
3474 js_typedarray_span_t<> scalar_out,
3475 js_typedarray_span_t<> scalar,
3476 js_typedarray_span_t<> n
3477) {
3478 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3479 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3480 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3481
3482 sn__extension_tweak_ed25519_scalar_add(scalar_out.data(), scalar.data(), n.data());
3483}
3484
3485static inline int
3486sn_extension_tweak_ed25519_pk_add(
3487 js_env_t *,
3488 js_receiver_t,
3489 js_typedarray_span_t<> tpk,
3490 js_typedarray_span_t<> pk,
3491 js_typedarray_span_t<> p
3492) {
3493 assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3494 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3495 assert(p.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3496
3497 return sn__extension_tweak_ed25519_pk_add(tpk.data(), pk.data(), p.data());
3498}
3499
3500static inline int
3501sn_extension_tweak_ed25519_keypair_add(
3502 js_env_t *,
3503 js_receiver_t,
3504 js_typedarray_span_t<> pk,
3505 js_typedarray_span_t<> scalar_out,
3506 js_typedarray_span_t<> scalar_in,
3507 js_typedarray_span_t<> tweak
3508) {
3509 assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3510 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3511 assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3512 assert(tweak.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3513
3514 return sn__extension_tweak_ed25519_keypair_add(
3515 pk.data(),
3516 scalar_out.data(),
3517 scalar_in.data(),
3518 tweak.data()
3519 );
3520}
3521
3522static inline int
3523sn_extension_pbkdf2_sha512(
3524 js_env_t *,
3525 js_receiver_t,
3526 js_typedarray_span_t<> out,
3527 js_typedarray_span_t<> passwd,
3528 js_typedarray_span_t<> salt,
3529 uint64_t iter,
3530 uint64_t outlen
3531) {
3532
3533 assert(iter >= sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
3534 assert(outlen <= sn__extension_pbkdf2_sha512_BYTES_MAX);
3535 assert(out.size_bytes() >= static_cast<size_t>(outlen));
3536
3537 return sn__extension_pbkdf2_sha512(
3538 passwd.data(),
3539 passwd.size_bytes(),
3540 salt.data(),
3541 salt.size_bytes(),
3542 iter,
3543 out.data(),
3544 outlen
3545 );
3546}
3547
3548struct sn_async_pbkdf2_sha512_request : sn_async_task {
3549 js_persistent_t<js_arraybuffer_t> out_ref;
3550 std::span<uint8_t> out;
3551
3552 size_t outlen;
3553
3554 js_persistent_t<js_arraybuffer_t> pwd_ref;
3555 std::span<uint8_t> pwd;
3556
3557 js_persistent_t<js_arraybuffer_t> salt_ref;
3558 std::span<uint8_t> salt;
3559
3560 uint64_t iter;
3561
3562 sn_async_pbkdf2_sha512_request(js_env_t *env) : sn_async_task(env) {}
3563};
3564
3565static void
3566async_pbkdf2_sha512_execute(uv_work_t *uv_req) {
3567 auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
3568
3569 req->code = sn__extension_pbkdf2_sha512(
3570 req->pwd.data(),
3571 req->pwd.size(),
3572 req->salt.data(),
3573 req->salt.size(),
3574 req->iter,
3575 req->out.data(),
3576 req->outlen
3577 );
3578}
3579
3580static void
3581async_pbkdf2_sha512_complete(uv_work_t *uv_req, int status) {
3582 int err;
3583
3584 auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
3585
3586 if (req->exiting) return delete req;
3587
3588 js_handle_scope_t *scope;
3589 err = js_open_handle_scope(req->env, &scope);
3590 assert(err == 0);
3591
3592 js_function_t<void, int> callback;
3593 err = js_get_reference_value(req->env, req->cb, callback);
3594 assert(err == 0);
3595
3596 err = js_call_function_with_checkpoint(req->env, callback, req->code);
3597 assert(err != js_pending_exception);
3598
3599 err = js_close_handle_scope(req->env, scope);
3600 assert(err == 0);
3601
3602 delete req;
3603}
3604
3605static inline void
3606sn_extension_pbkdf2_sha512_async(
3607 js_env_t *env,
3608 js_receiver_t,
3609
3610 js_arraybuffer_t out,
3611 uint32_t out_offset,
3612 uint32_t out_len,
3613
3614 js_arraybuffer_t pwd,
3615 uint32_t pwd_offset,
3616 uint32_t pwd_len,
3617
3618 js_arraybuffer_t salt,
3619 uint32_t salt_offset,
3620 uint32_t salt_len,
3621
3622 uint64_t iter,
3623 uint64_t outlen,
3624
3625 js_function_t<void, int> callback
3626) {
3627 int err;
3628
3629 auto *req = new sn_async_pbkdf2_sha512_request(env);
3630
3631 std::span<uint8_t> out_view;
3632 err = js_get_arraybuffer_info(env, out, out_view);
3633 assert(err == 0);
3634 assert(out_offset + out_len <= out_view.size());
3635
3636 req->out = {&out_view[out_offset], out_len};
3637
3638 std::span<uint8_t> pwd_view;
3639 err = js_get_arraybuffer_info(env, pwd, pwd_view);
3640 assert(err == 0);
3641 assert(pwd_offset + pwd_len <= pwd_view.size());
3642
3643 req->pwd = {&pwd_view[pwd_offset], pwd_len};
3644
3645 std::span<uint8_t> salt_view;
3646 err = js_get_arraybuffer_info(env, salt, salt_view);
3647 assert(err == 0);
3648 assert(salt_offset + salt_len <= salt_view.size());
3649
3650 req->salt = {&salt_view[salt_offset], salt_len};
3651
3652 req->iter = iter;
3653 req->outlen = outlen;
3654
3655 err = js_create_reference(env, out, req->out_ref);
3656 assert(err == 0);
3657
3658 err = js_create_reference(env, pwd, req->pwd_ref);
3659 assert(err == 0);
3660
3661 err = js_create_reference(env, salt, req->salt_ref);
3662 assert(err == 0);
3663
3664 err = js_create_reference(env, callback, req->cb);
3665 assert(err == 0);
3666
3667 uv_loop_t *loop;
3668 err = js_get_env_loop(env, &loop);
3669 assert(err == 0);
3670
3671 err = uv_queue_work(loop, &req->task, async_pbkdf2_sha512_execute, async_pbkdf2_sha512_complete);
3672 assert(err == 0);
3673}
3674
3675static js_value_t *
3676sodium_native_exports(js_env_t *env, js_value_t *exports) {
3677 int err;
3678
3679 err = sodium_init();
3680 assert(err >= 0);
3681
3682#define V_FUNCTION(name, fn) \
3683 err = js_set_property<fn>(env, exports, name); \
3684 assert(err == 0);
3685
3686#define V_FUNCTION_NOSCOPE(name, fn) \
3687 err = js_set_property<fn, js_function_options_t{.scoped = false}>(env, exports, name); \
3688 assert(err == 0);
3689
3690#define V_UINT32(name, constant) \
3691 err = js_set_property(env, exports, name, static_cast<uint32_t>(constant)); \
3692 assert(err == 0);
3693
3694#define V_UINT64(name, constant) \
3695 err = js_set_property(env, exports, name, static_cast<int64_t>(std::min<uint64_t>(constant, js_max_safe_integer))); \
3696 assert(err == 0);
3697
3698#define V_STRING(name, str) \
3699 err = js_set_property(env, exports, name, str); \
3700 assert(err == 0);
3701
3702 // memory
3703
3704 V_FUNCTION("sodium_memzero", sn_sodium_memzero);
3705 V_FUNCTION("sodium_mlock", sn_sodium_mlock);
3706 V_FUNCTION("sodium_munlock", sn_sodium_munlock);
3707 V_FUNCTION("sodium_malloc", sn_sodium_malloc);
3708 V_FUNCTION("sodium_free", sn_sodium_free);
3709 V_FUNCTION("sodium_mprotect_noaccess", sn_sodium_mprotect_noaccess);
3710 V_FUNCTION("sodium_mprotect_readonly", sn_sodium_mprotect_readonly);
3711 V_FUNCTION("sodium_mprotect_readwrite", sn_sodium_mprotect_readwrite);
3712
3713 // randombytes
3714
3715 V_FUNCTION_NOSCOPE("randombytes_buf", sn_randombytes_buf);
3716 V_FUNCTION_NOSCOPE("randombytes_buf_deterministic", sn_randombytes_buf_deterministic);
3717 V_FUNCTION_NOSCOPE("randombytes_random", sn_randombytes_random);
3718 V_FUNCTION_NOSCOPE("randombytes_uniform", sn_randombytes_uniform);
3719
3720 V_UINT32("randombytes_SEEDBYTES", randombytes_SEEDBYTES);
3721
3722 // sodium helpers
3723
3724 V_FUNCTION("sodium_memcmp", sn_sodium_memcmp);
3725 V_FUNCTION("sodium_increment", sn_sodium_increment);
3726 V_FUNCTION("sodium_add", sn_sodium_add);
3727 V_FUNCTION("sodium_sub", sn_sodium_sub);
3728 V_FUNCTION("sodium_compare", sn_sodium_compare);
3729 V_FUNCTION("sodium_is_zero", sn_sodium_is_zero);
3730 V_FUNCTION("sodium_pad", sn_sodium_pad);
3731 V_FUNCTION("sodium_unpad", sn_sodium_unpad);
3732
3733 // crypto_aead
3734
3735 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_keygen", sn_crypto_aead_xchacha20poly1305_ietf_keygen);
3736 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt", sn_crypto_aead_xchacha20poly1305_ietf_encrypt);
3737 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt", sn_crypto_aead_xchacha20poly1305_ietf_decrypt);
3738 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached);
3739 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached);
3740 V_UINT32("crypto_aead_xchacha20poly1305_ietf_ABYTES", crypto_aead_xchacha20poly1305_ietf_ABYTES);
3741 V_UINT32("crypto_aead_xchacha20poly1305_ietf_KEYBYTES", crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
3742 V_UINT32("crypto_aead_xchacha20poly1305_ietf_NPUBBYTES", crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
3743 V_UINT32("crypto_aead_xchacha20poly1305_ietf_NSECBYTES", crypto_aead_xchacha20poly1305_ietf_NSECBYTES);
3744 V_UINT64("crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX);
3745
3746 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_keygen", sn_crypto_aead_chacha20poly1305_ietf_keygen);
3747 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt", sn_crypto_aead_chacha20poly1305_ietf_encrypt);
3748 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt", sn_crypto_aead_chacha20poly1305_ietf_decrypt);
3749 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached);
3750 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached);
3751 V_UINT32("crypto_aead_chacha20poly1305_ietf_ABYTES", crypto_aead_chacha20poly1305_ietf_ABYTES);
3752 V_UINT32("crypto_aead_chacha20poly1305_ietf_KEYBYTES", crypto_aead_chacha20poly1305_ietf_KEYBYTES);
3753 V_UINT32("crypto_aead_chacha20poly1305_ietf_NPUBBYTES", crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
3754 V_UINT32("crypto_aead_chacha20poly1305_ietf_NSECBYTES", crypto_aead_chacha20poly1305_ietf_NSECBYTES);
3755 V_UINT64("crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
3756
3757 // crypto_auth
3758
3759 V_FUNCTION("crypto_auth", sn_crypto_auth);
3760 V_FUNCTION("crypto_auth_verify", sn_crypto_auth_verify);
3761 V_UINT32("crypto_auth_BYTES", crypto_auth_BYTES);
3762 V_UINT32("crypto_auth_KEYBYTES", crypto_auth_KEYBYTES);
3763 V_STRING("crypto_auth_PRIMITIVE", crypto_auth_PRIMITIVE);
3764
3765 // crypto_box
3766
3767 V_FUNCTION("crypto_box_keypair", sn_crypto_box_keypair);
3768 V_FUNCTION("crypto_box_seed_keypair", sn_crypto_box_seed_keypair);
3769 V_FUNCTION("crypto_box_easy", sn_crypto_box_easy);
3770 V_FUNCTION("crypto_box_open_easy", sn_crypto_box_open_easy);
3771 V_FUNCTION("crypto_box_detached", sn_crypto_box_detached);
3772 V_FUNCTION("crypto_box_open_detached", sn_crypto_box_open_detached);
3773 V_FUNCTION("crypto_box_seal", sn_crypto_box_seal);
3774 V_FUNCTION_NOSCOPE("crypto_box_seal_open", sn_crypto_box_seal_open);
3775
3776 V_UINT32("crypto_box_SEEDBYTES", crypto_box_SEEDBYTES);
3777 V_UINT32("crypto_box_PUBLICKEYBYTES", crypto_box_PUBLICKEYBYTES);
3778 V_UINT32("crypto_box_SECRETKEYBYTES", crypto_box_SECRETKEYBYTES);
3779 V_UINT32("crypto_box_NONCEBYTES", crypto_box_NONCEBYTES);
3780 V_UINT32("crypto_box_MACBYTES", crypto_box_MACBYTES);
3781 V_UINT32("crypto_box_SEALBYTES", crypto_box_SEALBYTES);
3782 V_STRING("crypto_box_PRIMITIVE", crypto_box_PRIMITIVE);
3783
3784 // crypto_core
3785
3786 V_FUNCTION("crypto_core_ed25519_is_valid_point", sn_crypto_core_ed25519_is_valid_point);
3787 V_FUNCTION("crypto_core_ed25519_from_uniform", sn_crypto_core_ed25519_from_uniform);
3788 V_FUNCTION("crypto_core_ed25519_add", sn_crypto_core_ed25519_add);
3789 V_FUNCTION("crypto_core_ed25519_sub", sn_crypto_core_ed25519_sub);
3790 V_FUNCTION("crypto_core_ed25519_scalar_random", sn_crypto_core_ed25519_scalar_random);
3791 V_FUNCTION("crypto_core_ed25519_scalar_reduce", sn_crypto_core_ed25519_scalar_reduce);
3792 V_FUNCTION("crypto_core_ed25519_scalar_invert", sn_crypto_core_ed25519_scalar_invert);
3793 V_FUNCTION("crypto_core_ed25519_scalar_negate", sn_crypto_core_ed25519_scalar_negate);
3794 V_FUNCTION("crypto_core_ed25519_scalar_complement", sn_crypto_core_ed25519_scalar_complement);
3795 V_FUNCTION("crypto_core_ed25519_scalar_add", sn_crypto_core_ed25519_scalar_add);
3796 V_FUNCTION("crypto_core_ed25519_scalar_sub", sn_crypto_core_ed25519_scalar_sub);
3797 V_UINT32("crypto_core_ed25519_BYTES", crypto_core_ed25519_BYTES);
3798 V_UINT32("crypto_core_ed25519_UNIFORMBYTES", crypto_core_ed25519_UNIFORMBYTES);
3799 V_UINT32("crypto_core_ed25519_SCALARBYTES", crypto_core_ed25519_SCALARBYTES);
3800 V_UINT32("crypto_core_ed25519_NONREDUCEDSCALARBYTES", crypto_core_ed25519_NONREDUCEDSCALARBYTES);
3801
3802 // crypto_kdf
3803
3804 V_FUNCTION("crypto_kdf_keygen", sn_crypto_kdf_keygen);
3805 V_FUNCTION("crypto_kdf_derive_from_key", sn_crypto_kdf_derive_from_key);
3806 V_UINT32("crypto_kdf_BYTES_MIN", crypto_kdf_BYTES_MIN);
3807 V_UINT32("crypto_kdf_BYTES_MAX", crypto_kdf_BYTES_MAX);
3808 V_UINT32("crypto_kdf_CONTEXTBYTES", crypto_kdf_CONTEXTBYTES);
3809 V_UINT32("crypto_kdf_KEYBYTES", crypto_kdf_KEYBYTES);
3810 V_STRING("crypto_kdf_PRIMITIVE", crypto_kdf_PRIMITIVE);
3811
3812 // crypto_kx
3813
3814 V_FUNCTION("crypto_kx_keypair", sn_crypto_kx_keypair);
3815 V_FUNCTION("crypto_kx_seed_keypair", sn_crypto_kx_seed_keypair);
3816 V_FUNCTION("crypto_kx_client_session_keys", sn_crypto_kx_client_session_keys);
3817 V_FUNCTION("crypto_kx_server_session_keys", sn_crypto_kx_server_session_keys);
3818 V_UINT32("crypto_kx_PUBLICKEYBYTES", crypto_kx_PUBLICKEYBYTES);
3819 V_UINT32("crypto_kx_SECRETKEYBYTES", crypto_kx_SECRETKEYBYTES);
3820 V_UINT32("crypto_kx_SEEDBYTES", crypto_kx_SEEDBYTES);
3821 V_UINT32("crypto_kx_SESSIONKEYBYTES", crypto_kx_SESSIONKEYBYTES);
3822 V_STRING("crypto_kx_PRIMITIVE", crypto_kx_PRIMITIVE);
3823
3824 // crypto_generichash
3825
3826 V_FUNCTION_NOSCOPE("crypto_generichash", sn_crypto_generichash);
3827 V_FUNCTION("crypto_generichash_batch", sn_crypto_generichash_batch);
3828 V_FUNCTION_NOSCOPE("crypto_generichash_keygen", sn_crypto_generichash_keygen);
3829 V_FUNCTION_NOSCOPE("crypto_generichash_init", sn_crypto_generichash_init);
3830 V_FUNCTION_NOSCOPE("crypto_generichash_update", sn_crypto_generichash_update);
3831 V_FUNCTION_NOSCOPE("crypto_generichash_final", sn_crypto_generichash_final);
3832
3833 V_UINT32("crypto_generichash_STATEBYTES", sizeof(crypto_generichash_state));
3834 V_STRING("crypto_generichash_PRIMITIVE", crypto_generichash_PRIMITIVE);
3835 V_UINT32("crypto_generichash_BYTES_MIN", crypto_generichash_BYTES_MIN);
3836 V_UINT32("crypto_generichash_BYTES_MAX", crypto_generichash_BYTES_MAX);
3837 V_UINT32("crypto_generichash_BYTES", crypto_generichash_BYTES);
3838 V_UINT32("crypto_generichash_KEYBYTES_MIN", crypto_generichash_KEYBYTES_MIN);
3839 V_UINT32("crypto_generichash_KEYBYTES_MAX", crypto_generichash_KEYBYTES_MAX);
3840 V_UINT32("crypto_generichash_KEYBYTES", crypto_generichash_KEYBYTES);
3841
3842 // crypto_hash
3843
3844 V_FUNCTION("crypto_hash", sn_crypto_hash);
3845 V_UINT32("crypto_hash_BYTES", crypto_hash_BYTES);
3846 V_STRING("crypto_hash_PRIMITIVE", crypto_hash_PRIMITIVE);
3847
3848 V_FUNCTION("crypto_hash_sha256", sn_crypto_hash_sha256);
3849 V_FUNCTION("crypto_hash_sha256_init", sn_crypto_hash_sha256_init);
3850 V_FUNCTION("crypto_hash_sha256_update", sn_crypto_hash_sha256_update);
3851 V_FUNCTION("crypto_hash_sha256_final", sn_crypto_hash_sha256_final);
3852 V_UINT32("crypto_hash_sha256_STATEBYTES", sizeof(crypto_hash_sha256_state));
3853 V_UINT32("crypto_hash_sha256_BYTES", crypto_hash_sha256_BYTES);
3854
3855 V_FUNCTION("crypto_hash_sha512", sn_crypto_hash_sha512);
3856 V_FUNCTION("crypto_hash_sha512_init", sn_crypto_hash_sha512_init);
3857 V_FUNCTION("crypto_hash_sha512_update", sn_crypto_hash_sha512_update);
3858 V_FUNCTION("crypto_hash_sha512_final", sn_crypto_hash_sha512_final);
3859 V_UINT32("crypto_hash_sha512_STATEBYTES", sizeof(crypto_hash_sha512_state));
3860 V_UINT32("crypto_hash_sha512_BYTES", crypto_hash_sha512_BYTES);
3861
3862 // crypto_onetimeauth
3863
3864 V_FUNCTION("crypto_onetimeauth", sn_crypto_onetimeauth);
3865 V_FUNCTION("crypto_onetimeauth_verify", sn_crypto_onetimeauth_verify);
3866 V_FUNCTION("crypto_onetimeauth_init", sn_crypto_onetimeauth_init);
3867 V_FUNCTION("crypto_onetimeauth_update", sn_crypto_onetimeauth_update);
3868 V_FUNCTION("crypto_onetimeauth_final", sn_crypto_onetimeauth_final);
3869 V_UINT32("crypto_onetimeauth_STATEBYTES", sizeof(crypto_onetimeauth_state));
3870 V_UINT32("crypto_onetimeauth_BYTES", crypto_onetimeauth_BYTES);
3871 V_UINT32("crypto_onetimeauth_KEYBYTES", crypto_onetimeauth_KEYBYTES);
3872 V_STRING("crypto_onetimeauth_PRIMITIVE", crypto_onetimeauth_PRIMITIVE);
3873
3874 // crypto_pwhash
3875
3876 V_FUNCTION("crypto_pwhash", sn_crypto_pwhash);
3877 V_FUNCTION("crypto_pwhash_str", sn_crypto_pwhash_str);
3878 V_FUNCTION("crypto_pwhash_str_verify", sn_crypto_pwhash_str_verify);
3879 V_FUNCTION("crypto_pwhash_str_needs_rehash", sn_crypto_pwhash_str_needs_rehash);
3880 V_FUNCTION("crypto_pwhash_async", sn_crypto_pwhash_async);
3881 V_FUNCTION("crypto_pwhash_str_async", sn_crypto_pwhash_str_async);
3882 V_FUNCTION("crypto_pwhash_str_verify_async", sn_crypto_pwhash_str_verify_async);
3883 V_UINT32("crypto_pwhash_ALG_ARGON2I13", crypto_pwhash_ALG_ARGON2I13);
3884 V_UINT32("crypto_pwhash_ALG_ARGON2ID13", crypto_pwhash_ALG_ARGON2ID13);
3885 V_UINT32("crypto_pwhash_ALG_DEFAULT", crypto_pwhash_ALG_DEFAULT);
3886 V_UINT32("crypto_pwhash_BYTES_MIN", crypto_pwhash_BYTES_MIN);
3887 V_UINT32("crypto_pwhash_BYTES_MAX", crypto_pwhash_BYTES_MAX);
3888 V_UINT32("crypto_pwhash_PASSWD_MIN", crypto_pwhash_PASSWD_MIN);
3889 V_UINT32("crypto_pwhash_PASSWD_MAX", crypto_pwhash_PASSWD_MAX);
3890 V_UINT32("crypto_pwhash_SALTBYTES", crypto_pwhash_SALTBYTES);
3891 V_UINT32("crypto_pwhash_STRBYTES", crypto_pwhash_STRBYTES);
3892 V_STRING("crypto_pwhash_STRPREFIX", crypto_pwhash_STRPREFIX);
3893 V_UINT32("crypto_pwhash_OPSLIMIT_MIN", crypto_pwhash_OPSLIMIT_MIN);
3894 V_UINT32("crypto_pwhash_OPSLIMIT_MAX", crypto_pwhash_OPSLIMIT_MAX);
3895 V_UINT64("crypto_pwhash_MEMLIMIT_MIN", crypto_pwhash_MEMLIMIT_MIN);
3896 V_UINT64("crypto_pwhash_MEMLIMIT_MAX", crypto_pwhash_MEMLIMIT_MAX);
3897 V_UINT32("crypto_pwhash_OPSLIMIT_INTERACTIVE", crypto_pwhash_OPSLIMIT_INTERACTIVE);
3898 V_UINT64("crypto_pwhash_MEMLIMIT_INTERACTIVE", crypto_pwhash_MEMLIMIT_INTERACTIVE);
3899 V_UINT32("crypto_pwhash_OPSLIMIT_MODERATE", crypto_pwhash_OPSLIMIT_MODERATE);
3900 V_UINT64("crypto_pwhash_MEMLIMIT_MODERATE", crypto_pwhash_MEMLIMIT_MODERATE);
3901 V_UINT32("crypto_pwhash_OPSLIMIT_SENSITIVE", crypto_pwhash_OPSLIMIT_SENSITIVE);
3902 V_UINT64("crypto_pwhash_MEMLIMIT_SENSITIVE", crypto_pwhash_MEMLIMIT_SENSITIVE);
3903 V_STRING("crypto_pwhash_PRIMITIVE", crypto_pwhash_PRIMITIVE);
3904
3905 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256", sn_crypto_pwhash_scryptsalsa208sha256);
3906 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str", sn_crypto_pwhash_scryptsalsa208sha256_str);
3907 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify", sn_crypto_pwhash_scryptsalsa208sha256_str_verify);
3908 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_needs_rehash", sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash);
3909 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_async", sn_crypto_pwhash_scryptsalsa208sha256_async);
3910 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_async", sn_crypto_pwhash_scryptsalsa208sha256_str_async)
3911 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify_async", sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async);
3912 V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MIN", crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
3913 V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MAX", crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
3914 V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN", crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN);
3915 V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX", crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX);
3916 V_UINT64("crypto_pwhash_scryptsalsa208sha256_SALTBYTES", crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
3917 V_UINT64("crypto_pwhash_scryptsalsa208sha256_STRBYTES", crypto_pwhash_scryptsalsa208sha256_STRBYTES);
3918 V_STRING("crypto_pwhash_scryptsalsa208sha256_STRPREFIX", crypto_pwhash_scryptsalsa208sha256_STRPREFIX);
3919 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
3920 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
3921 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
3922 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
3923 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
3924 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
3925 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE);
3926 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE);
3927
3928 // crypto_scalarmult
3929
3930 V_FUNCTION("crypto_scalarmult_base", sn_crypto_scalarmult_base);
3931 V_FUNCTION("crypto_scalarmult", sn_crypto_scalarmult);
3932 V_STRING("crypto_scalarmult_PRIMITIVE", crypto_scalarmult_PRIMITIVE);
3933 V_UINT32("crypto_scalarmult_BYTES", crypto_scalarmult_BYTES);
3934 V_UINT32("crypto_scalarmult_SCALARBYTES", crypto_scalarmult_SCALARBYTES);
3935
3936 V_FUNCTION("crypto_scalarmult_ed25519_base", sn_crypto_scalarmult_ed25519_base);
3937 V_FUNCTION("crypto_scalarmult_ed25519", sn_crypto_scalarmult_ed25519);
3938 V_FUNCTION("crypto_scalarmult_ed25519_base_noclamp", sn_crypto_scalarmult_ed25519_base_noclamp);
3939 V_FUNCTION("crypto_scalarmult_ed25519_noclamp", sn_crypto_scalarmult_ed25519_noclamp);
3940 V_UINT32("crypto_scalarmult_ed25519_BYTES", crypto_scalarmult_ed25519_BYTES);
3941 V_UINT32("crypto_scalarmult_ed25519_SCALARBYTES", crypto_scalarmult_ed25519_SCALARBYTES);
3942
3943 // crypto_secretbox
3944
3945 V_FUNCTION("crypto_secretbox_easy", sn_crypto_secretbox_easy);
3946 V_FUNCTION("crypto_secretbox_open_easy", sn_crypto_secretbox_open_easy);
3947 V_FUNCTION("crypto_secretbox_detached", sn_crypto_secretbox_detached);
3948 V_FUNCTION("crypto_secretbox_open_detached", sn_crypto_secretbox_open_detached);
3949 V_UINT32("crypto_secretbox_KEYBYTES", crypto_secretbox_KEYBYTES);
3950 V_UINT32("crypto_secretbox_NONCEBYTES", crypto_secretbox_NONCEBYTES);
3951 V_UINT32("crypto_secretbox_MACBYTES", crypto_secretbox_MACBYTES);
3952 V_STRING("crypto_secretbox_PRIMITIVE", crypto_secretbox_PRIMITIVE);
3953
3954 // crypto_secretstream
3955
3956 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_keygen", sn_crypto_secretstream_xchacha20poly1305_keygen);
3957 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_push", sn_crypto_secretstream_xchacha20poly1305_init_push);
3958 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_pull", sn_crypto_secretstream_xchacha20poly1305_init_pull);
3959 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_push", sn_crypto_secretstream_xchacha20poly1305_push);
3960 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_pull", sn_crypto_secretstream_xchacha20poly1305_pull);
3961 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_rekey", sn_crypto_secretstream_xchacha20poly1305_rekey);
3962
3963 V_UINT32("crypto_secretstream_xchacha20poly1305_STATEBYTES", sizeof(crypto_secretstream_xchacha20poly1305_state));
3964 V_UINT32("crypto_secretstream_xchacha20poly1305_ABYTES", crypto_secretstream_xchacha20poly1305_ABYTES);
3965 V_UINT32("crypto_secretstream_xchacha20poly1305_HEADERBYTES", crypto_secretstream_xchacha20poly1305_HEADERBYTES);
3966 V_UINT32("crypto_secretstream_xchacha20poly1305_KEYBYTES", crypto_secretstream_xchacha20poly1305_KEYBYTES);
3967 V_UINT32("crypto_secretstream_xchacha20poly1305_TAGBYTES", 1);
3968 V_UINT64("crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX", crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX);
3969 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_MESSAGE", crypto_secretstream_xchacha20poly1305_TAG_MESSAGE);
3970 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_PUSH", crypto_secretstream_xchacha20poly1305_TAG_PUSH);
3971 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_REKEY", crypto_secretstream_xchacha20poly1305_TAG_REKEY);
3972 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_FINAL", crypto_secretstream_xchacha20poly1305_TAG_FINAL);
3973
3974 // crypto_shorthash
3975
3976 V_FUNCTION("crypto_shorthash", sn_crypto_shorthash);
3977 V_UINT32("crypto_shorthash_BYTES", crypto_shorthash_BYTES);
3978 V_UINT32("crypto_shorthash_KEYBYTES", crypto_shorthash_KEYBYTES);
3979 V_STRING("crypto_shorthash_PRIMITIVE", crypto_shorthash_PRIMITIVE);
3980
3981 // crypto_sign
3982
3983 V_FUNCTION("crypto_sign_keypair", sn_crypto_sign_keypair);
3984 V_FUNCTION("crypto_sign_seed_keypair", sn_crypto_sign_seed_keypair);
3985 V_FUNCTION("crypto_sign", sn_crypto_sign);
3986 V_FUNCTION("crypto_sign_open", sn_crypto_sign_open);
3987 V_FUNCTION("crypto_sign_detached", sn_crypto_sign_detached);
3988 V_FUNCTION_NOSCOPE("crypto_sign_verify_detached", sn_crypto_sign_verify_detached);
3989 V_FUNCTION("crypto_sign_ed25519_sk_to_pk", sn_crypto_sign_ed25519_sk_to_pk);
3990 V_FUNCTION("crypto_sign_ed25519_pk_to_curve25519", sn_crypto_sign_ed25519_pk_to_curve25519);
3991 V_FUNCTION("crypto_sign_ed25519_sk_to_curve25519", sn_crypto_sign_ed25519_sk_to_curve25519);
3992
3993 V_UINT32("crypto_sign_SEEDBYTES", crypto_sign_SEEDBYTES);
3994 V_UINT32("crypto_sign_PUBLICKEYBYTES", crypto_sign_PUBLICKEYBYTES);
3995 V_UINT32("crypto_sign_SECRETKEYBYTES", crypto_sign_SECRETKEYBYTES);
3996 V_UINT32("crypto_sign_BYTES", crypto_sign_BYTES);
3997
3998 // crypto_stream
3999
4000 V_FUNCTION("crypto_stream", sn_crypto_stream);
4001 V_UINT32("crypto_stream_KEYBYTES", crypto_stream_KEYBYTES);
4002 V_UINT32("crypto_stream_NONCEBYTES", crypto_stream_NONCEBYTES);
4003 V_STRING("crypto_stream_PRIMITIVE", crypto_stream_PRIMITIVE);
4004
4005 V_FUNCTION_NOSCOPE("crypto_stream_xor", sn_crypto_stream_xor);
4006 V_FUNCTION("crypto_stream_xor_init", sn_crypto_stream_xor_wrap_init);
4007 V_FUNCTION("crypto_stream_xor_update", sn_crypto_stream_xor_wrap_update);
4008 V_FUNCTION("crypto_stream_xor_final", sn_crypto_stream_xor_wrap_final);
4009 V_UINT32("crypto_stream_xor_STATEBYTES", sizeof(sn_crypto_stream_xor_state));
4010
4011 V_FUNCTION("crypto_stream_chacha20", sn_crypto_stream_chacha20);
4012 V_UINT32("crypto_stream_chacha20_KEYBYTES", crypto_stream_chacha20_KEYBYTES);
4013 V_UINT32("crypto_stream_chacha20_NONCEBYTES", crypto_stream_chacha20_NONCEBYTES);
4014 V_UINT64("crypto_stream_chacha20_MESSAGEBYTES_MAX", crypto_stream_chacha20_MESSAGEBYTES_MAX);
4015
4016 V_FUNCTION("crypto_stream_chacha20_xor", sn_crypto_stream_chacha20_xor);
4017 V_FUNCTION("crypto_stream_chacha20_xor_ic", sn_crypto_stream_chacha20_xor_ic);
4018 V_FUNCTION("crypto_stream_chacha20_xor_init", sn_crypto_stream_chacha20_xor_wrap_init);
4019 V_FUNCTION("crypto_stream_chacha20_xor_update", sn_crypto_stream_chacha20_xor_wrap_update);
4020 V_FUNCTION("crypto_stream_chacha20_xor_final", sn_crypto_stream_chacha20_xor_wrap_final);
4021 V_UINT32("crypto_stream_chacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_xor_state));
4022
4023 V_FUNCTION("crypto_stream_chacha20_ietf", sn_crypto_stream_chacha20_ietf);
4024 V_UINT32("crypto_stream_chacha20_ietf_KEYBYTES", crypto_stream_chacha20_ietf_KEYBYTES);
4025 V_UINT32("crypto_stream_chacha20_ietf_NONCEBYTES", crypto_stream_chacha20_ietf_NONCEBYTES);
4026 V_UINT64("crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX", crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX);
4027 V_UINT32("crypto_stream_chacha20_ietf_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_ietf_xor_state));
4028
4029 V_FUNCTION("crypto_stream_chacha20_ietf_xor", sn_crypto_stream_chacha20_ietf_xor);
4030 V_FUNCTION("crypto_stream_chacha20_ietf_xor_ic", sn_crypto_stream_chacha20_ietf_xor_ic);
4031 V_FUNCTION("crypto_stream_chacha20_ietf_xor_init", sn_crypto_stream_chacha20_ietf_xor_wrap_init);
4032 V_FUNCTION("crypto_stream_chacha20_ietf_xor_update", sn_crypto_stream_chacha20_ietf_xor_wrap_update);
4033 V_FUNCTION("crypto_stream_chacha20_ietf_xor_final", sn_crypto_stream_chacha20_ietf_xor_wrap_final);
4034
4035 V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
4036 V_UINT32("crypto_stream_xchacha20_KEYBYTES", crypto_stream_xchacha20_KEYBYTES);
4037 V_UINT32("crypto_stream_xchacha20_NONCEBYTES", crypto_stream_xchacha20_NONCEBYTES);
4038 V_UINT64("crypto_stream_xchacha20_MESSAGEBYTES_MAX", crypto_stream_xchacha20_MESSAGEBYTES_MAX);
4039
4040 V_FUNCTION("crypto_stream_xchacha20_xor", sn_crypto_stream_xchacha20_xor);
4041 V_FUNCTION("crypto_stream_xchacha20_xor_ic", sn_crypto_stream_xchacha20_xor_ic);
4042 V_FUNCTION("crypto_stream_xchacha20_xor_init", sn_crypto_stream_xchacha20_xor_wrap_init);
4043 V_FUNCTION("crypto_stream_xchacha20_xor_update", sn_crypto_stream_xchacha20_xor_wrap_update);
4044 V_FUNCTION("crypto_stream_xchacha20_xor_final", sn_crypto_stream_xchacha20_xor_wrap_final);
4045 V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
4046 V_UINT32("crypto_stream_xchacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_xchacha20_xor_state));
4047
4048 V_FUNCTION("crypto_stream_salsa20", sn_crypto_stream_salsa20);
4049 V_UINT32("crypto_stream_salsa20_KEYBYTES", crypto_stream_salsa20_KEYBYTES);
4050 V_UINT32("crypto_stream_salsa20_NONCEBYTES", crypto_stream_salsa20_NONCEBYTES);
4051 V_UINT64("crypto_stream_salsa20_MESSAGEBYTES_MAX", crypto_stream_salsa20_MESSAGEBYTES_MAX);
4052
4053 V_FUNCTION("crypto_stream_salsa20_xor", sn_crypto_stream_salsa20_xor);
4054 V_FUNCTION("crypto_stream_salsa20_xor_ic", sn_crypto_stream_salsa20_xor_ic);
4055 V_FUNCTION("crypto_stream_salsa20_xor_init", sn_crypto_stream_salsa20_xor_wrap_init);
4056 V_FUNCTION("crypto_stream_salsa20_xor_update", sn_crypto_stream_salsa20_xor_wrap_update);
4057 V_FUNCTION("crypto_stream_salsa20_xor_final", sn_crypto_stream_salsa20_xor_wrap_final);
4058 V_UINT32("crypto_stream_salsa20_xor_STATEBYTES", sizeof(sn_crypto_stream_salsa20_xor_state));
4059
4060 // extensions
4061
4062 // tweak
4063
4064 V_FUNCTION("extension_tweak_ed25519_base", sn_extension_tweak_ed25519_base);
4065 V_FUNCTION("extension_tweak_ed25519_sign_detached", sn_extension_tweak_ed25519_sign_detached);
4066 V_FUNCTION("extension_tweak_ed25519_sk_to_scalar", sn_extension_tweak_ed25519_sk_to_scalar);
4067 V_FUNCTION("extension_tweak_ed25519_scalar", sn_extension_tweak_ed25519_scalar);
4068 V_FUNCTION("extension_tweak_ed25519_pk", sn_extension_tweak_ed25519_pk);
4069 V_FUNCTION("extension_tweak_ed25519_keypair", sn_extension_tweak_ed25519_keypair);
4070 V_FUNCTION("extension_tweak_ed25519_scalar_add", sn_extension_tweak_ed25519_scalar_add);
4071 V_FUNCTION("extension_tweak_ed25519_pk_add", sn_extension_tweak_ed25519_pk_add);
4072 V_FUNCTION("extension_tweak_ed25519_keypair_add", sn_extension_tweak_ed25519_keypair_add);
4073 V_UINT32("extension_tweak_ed25519_BYTES", sn__extension_tweak_ed25519_BYTES);
4074 V_UINT32("extension_tweak_ed25519_SCALARBYTES", sn__extension_tweak_ed25519_SCALARBYTES);
4075
4076 // pbkdf2
4077
4078 V_FUNCTION("extension_pbkdf2_sha512", sn_extension_pbkdf2_sha512);
4079 V_FUNCTION("extension_pbkdf2_sha512_async", sn_extension_pbkdf2_sha512_async);
4080 V_UINT32("extension_pbkdf2_sha512_SALTBYTES", sn__extension_pbkdf2_sha512_SALTBYTES);
4081 V_UINT32("extension_pbkdf2_sha512_HASHBYTES", sn__extension_pbkdf2_sha512_HASHBYTES);
4082 V_UINT32("extension_pbkdf2_sha512_ITERATIONS_MIN", sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
4083 V_UINT64("extension_pbkdf2_sha512_BYTES_MAX", sn__extension_pbkdf2_sha512_BYTES_MAX);
4084
4085#undef V_FUNCTION
4086#undef V_FUNCTION_NOSCOPE
4087#undef V_UINT32
4088#undef V_UINT64
4089#undef V_STRING
4090
4091 return exports;
4092}
4093
4094BARE_MODULE(sodium_native, sodium_native_exports)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/binding.js +2 -0
……@@ -0,0 +1,2 @@
1require.addon = require('require-addon')
2module.exports = require.addon('.', __filename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/extensions/pbkdf2/pbkdf2.c +90 -0
……@@ -0,0 +1,90 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
29 */
30
31#include <string.h>
32#include <sodium.h>
33
34#include "pbkdf2.h"
35
36/**
37 * pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
38 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
39 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
40 */
41int
42sn__extension_pbkdf2_sha512(const unsigned char *passwd, size_t passwdlen,
43 const unsigned char *salt, size_t saltlen, uint64_t c,
44 unsigned char *buf, size_t dkLen)
45{
46 crypto_auth_hmacsha512_state PShctx, hctx;
47 size_t i;
48 unsigned char ivec[4];
49 unsigned char U[64];
50 unsigned char T[64];
51 uint64_t j;
52 unsigned int k;
53 size_t clen;
54
55 if (dkLen > sn__extension_pbkdf2_sha512_BYTES_MAX) {
56 return -1;
57 }
58
59 crypto_auth_hmacsha512_init(&PShctx, passwd, passwdlen);
60 crypto_auth_hmacsha512_update(&PShctx, salt, saltlen);
61
62 for (i = 0; i * crypto_auth_hmacsha512_BYTES < dkLen; i++) {
63 SN_PBKDF2_STORE32_BE(ivec, (uint32_t)(i + 1));
64 memcpy(&hctx, &PShctx, sizeof(crypto_auth_hmacsha512_state));
65 crypto_auth_hmacsha512_update(&hctx, ivec, 4);
66 crypto_auth_hmacsha512_final(&hctx, U);
67
68 memcpy(T, U, crypto_auth_hmacsha512_BYTES);
69 /* LCOV_EXCL_START */
70 for (j = 2; j <= c; j++) {
71 crypto_auth_hmacsha512_init(&hctx, passwd, passwdlen);
72 crypto_auth_hmacsha512_update(&hctx, U, crypto_auth_hmacsha512_BYTES);
73 crypto_auth_hmacsha512_final(&hctx, U);
74
75 for (k = 0; k < crypto_auth_hmacsha512_BYTES; k++) {
76 T[k] ^= U[k];
77 }
78 }
79 /* LCOV_EXCL_STOP */
80
81 clen = dkLen - i * crypto_auth_hmacsha512_BYTES;
82 if (clen > crypto_auth_hmacsha512_BYTES) {
83 clen = crypto_auth_hmacsha512_BYTES;
84 }
85 memcpy(&buf[i * crypto_auth_hmacsha512_BYTES], T, clen);
86 }
87 sodium_memzero((void *) &PShctx, sizeof PShctx);
88
89 return 0;
90}
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/extensions/pbkdf2/pbkdf2.h +60 -0
……@@ -0,0 +1,60 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28/*
29 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
30 */
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35#include <sodium.h>
36
37#define SN_PBKDF2_STORE32_BE(buf, n32) \
38 buf[0] = n32 >> 24 & 0xff; \
39 buf[1] = n32 >> 16 & 0xff; \
40 buf[2] = n32 >> 8 & 0xff; \
41 buf[3] = n32 >> 0 & 0xff;
42
43#define sn__extension_pbkdf2_sha512_SALTBYTES 16U
44
45#define sn__extension_pbkdf2_sha512_HASHBYTES crypto_hash_sha512_BYTES
46
47#define sn__extension_pbkdf2_sha512_ITERATIONS_MIN 1U
48
49#define sn__extension_pbkdf2_sha512_BYTES_MAX 0x3fffffffc0ULL
50
51/**
52 * extension_pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
53 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
54 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
55 */
56int sn__extension_pbkdf2_sha512(const unsigned char *, size_t, const unsigned char *, size_t,
57 uint64_t, unsigned char *, size_t);
58#ifdef __cplusplus
59};
60#endif
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/extensions/tweak/tweak.c +206 -0
……@@ -0,0 +1,206 @@
1#include "tweak.h"
2
3/*
4 *EXPERIMENTAL API*
5
6 This module is an experimental implementation of a key tweaking protocol
7 over ed25519 keys. The signature algorithm has been reimplemented from
8 libsodium, but the nonce generation algorithm is *non-standard*.
9
10 Use at your own risk
11*/
12
13static void _extension_tweak_nonce (unsigned char *nonce, const unsigned char *n,
14 const unsigned char *m, unsigned long long mlen)
15{
16 // dom2(x, y) with x = 0 (not prehashed) and y = "crypto_tweak_ed25519"
17 static const unsigned char TWEAK_PREFIX[32 + 2 + 20] = {
18 'S', 'i', 'g', 'E', 'd', '2', '5', '5', '1', '9', ' ',
19 'n', 'o', ' ', 'E', 'd', '2', '5', '5', '1', '9', ' ',
20 'c', 'o', 'l', 'l', 'i', 's', 'i', 'o', 'n', 's', 0,
21 20, 'c', 'r', 'y', 'p', 't', 'o', '_', 't', 'w', 'e',
22 'a', 'k', '_', 'e', 'd', '2', '5', '5', '1', '9'
23 };
24
25 crypto_hash_sha512_state hs;
26
27 crypto_hash_sha512_init(&hs);
28 crypto_hash_sha512_update(&hs, TWEAK_PREFIX, sizeof TWEAK_PREFIX);
29 crypto_hash_sha512_update(&hs, n, 32);
30 crypto_hash_sha512_update(&hs, m, mlen);
31 crypto_hash_sha512_final(&hs, nonce);
32}
33
34static inline void
35_crypto_sign_ed25519_clamp(unsigned char k[32])
36{
37 k[0] &= 248;
38 k[31] &= 127;
39 k[31] |= 64;
40}
41
42static void _extension_tweak_ed25519(unsigned char *q, unsigned char *n,
43 const unsigned char *ns, unsigned long long nslen)
44{
45 sodium_memzero(q, sizeof q);
46
47 crypto_hash(n, ns, nslen);
48 n[31] &= 127; // clear highest bit
49
50 crypto_scalarmult_ed25519_base_noclamp(q, n);
51
52 // hash tweak until we get a valid tweaked q
53 while (crypto_core_ed25519_is_valid_point(q) != 1) {
54 crypto_hash(n, n, 32);
55 n[31] &= 127; // clear highest bit
56
57 crypto_scalarmult_ed25519_base_noclamp(q, n);
58 }
59}
60
61void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
62 const unsigned char *ns, unsigned long long nslen)
63{
64 unsigned char n64[64];
65
66 _extension_tweak_ed25519(pk, n64, ns, nslen);
67
68 SN_TWEAK_COPY_32(scalar, n64)
69}
70
71int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
72 const unsigned char *m, unsigned long long mlen,
73 const unsigned char *n, unsigned char *pk)
74{
75 crypto_hash_sha512_state hs;
76
77 unsigned char nonce[64];
78 unsigned char R[32];
79 unsigned char hram[64];
80 unsigned char _pk[32];
81
82 // check if pk was passed
83 if (pk == NULL) {
84 pk = _pk;
85
86 // derive pk from scalar
87 if (crypto_scalarmult_ed25519_base_noclamp(pk, n) != 0) {
88 return -1;
89 }
90 }
91
92 _extension_tweak_nonce(nonce, n, m, mlen);
93 crypto_core_ed25519_scalar_reduce(nonce, nonce);
94
95 // R = G ^ nonce : curve point from nonce
96 if (crypto_scalarmult_ed25519_base_noclamp(R, nonce) != 0) {
97 return -1;
98 }
99
100 // generate challenge as h(ram) = hash(R, pk, message)
101 crypto_hash_sha512_init(&hs);
102 crypto_hash_sha512_update(&hs, R, 32);
103 crypto_hash_sha512_update(&hs, pk, 32);
104 crypto_hash_sha512_update(&hs, m, mlen);
105
106 crypto_hash_sha512_final(&hs, hram);
107
108 crypto_core_ed25519_scalar_reduce(hram, hram);
109
110 // sig = nonce + n * h(ram)
111 crypto_core_ed25519_scalar_mul(sig, hram, n);
112 crypto_core_ed25519_scalar_add(sig + 32, nonce, sig);
113
114 SN_TWEAK_COPY_32(sig, R)
115
116 if (siglen_p != NULL) {
117 *siglen_p = 64U;
118 }
119
120 return 0;
121}
122
123// tweak a secret key
124void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *n, const unsigned char *sk)
125{
126 unsigned char n64[64];
127
128 // get sk scalar from seed, cf. crypto_sign_keypair_seed
129 crypto_hash(n64, sk, 32);
130 _crypto_sign_ed25519_clamp(n64);
131
132 SN_TWEAK_COPY_32(n, n64)
133}
134
135// tweak a secret key
136void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
137 const unsigned char *scalar,
138 const unsigned char *ns,
139 unsigned long long nslen)
140{
141 unsigned char n[64];
142 unsigned char q[32];
143
144 _extension_tweak_ed25519(q, n, ns, nslen);
145 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
146}
147
148// tweak a public key
149int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
150 const unsigned char *pk,
151 const unsigned char *ns,
152 unsigned long long nslen)
153{
154 unsigned char n[64];
155 unsigned char q[32];
156
157 _extension_tweak_ed25519(q, n, ns, nslen);
158 return crypto_core_ed25519_add(tpk, q, pk);
159}
160
161
162void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
163 unsigned char *scalar, const unsigned char *ns,
164 unsigned long long nslen)
165{
166 unsigned char n64[64];
167
168 crypto_hash(n64, ns, nslen);
169 n64[31] &= 127; // clear highest bit
170
171 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
172 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
173
174 // hash tweak until we get a valid tweaked point
175 while (crypto_core_ed25519_is_valid_point(pk) != 1) {
176 crypto_hash(n64, n64, 32);
177 n64[31] &= 127; // clear highest bit
178
179 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
180 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
181 }
182}
183
184// add tweak to scalar
185void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
186 const unsigned char *scalar,
187 const unsigned char *n)
188{
189 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
190}
191
192// add tweak point to public key
193int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
194 const unsigned char *pk,
195 const unsigned char *q)
196{
197 return crypto_core_ed25519_add(tpk, pk, q);
198}
199
200
201int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
202 unsigned char *scalar, const unsigned char *tweak)
203{
204 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, tweak);
205 return crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
206}
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/extensions/tweak/tweak.h +62 -0
……@@ -0,0 +1,62 @@
1#ifdef __cplusplus
2extern "C" {
3#endif
4
5#include <sodium.h>
6
7// copy 32 bytes using int64_t pointers
8#define SN_TWEAK_COPY_32(a, b) \
9 { \
10 long long *dst = (long long *) a; \
11 long long *src = (long long *) b; \
12 dst[0] = src[0]; \
13 dst[1] = src[1]; \
14 dst[2] = src[2]; \
15 dst[3] = src[3]; \
16 }
17
18#define sn__extension_tweak_ed25519_BYTES crypto_sign_ed25519_PUBLICKEYBYTES
19
20#define sn__extension_tweak_ed25519_SCALARBYTES crypto_scalarmult_ed25519_SCALARBYTES
21
22int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
23 const unsigned char *m, unsigned long long mlen,
24 const unsigned char *n, unsigned char *pk);
25
26void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
27 const unsigned char *ns, unsigned long long nslen);
28
29void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *scalar, const unsigned char *sk);
30
31// tweak a secret key
32void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
33 const unsigned char *scalar,
34 const unsigned char *ns,
35 unsigned long long nslen);
36
37// tweak a public key
38int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
39 const unsigned char *pk,
40 const unsigned char *ns,
41 unsigned long long nslen);
42
43void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
44 unsigned char *scalar, const unsigned char *ns,
45 unsigned long long nslen);
46
47// add tweak scalar to private key
48void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
49 const unsigned char *scalar,
50 const unsigned char *n);
51
52// add tweak point to public key
53int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
54 const unsigned char *pk,
55 const unsigned char *q);
56
57int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
58 unsigned char *scalar, const unsigned char *tweak);
59
60#ifdef __cplusplus
61};
62#endif
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/index.js +3231 -0
……@@ -0,0 +1,3231 @@
1const assert = require('assert')
2const binding = require('./binding')
3const { isNode } = require('which-runtime')
4
5const OPTIONAL = Buffer.from(new ArrayBuffer(0))
6
7module.exports = exports = { ...binding }
8
9// memory
10
11exports.sodium_memzero = function (buf) {
12 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
13
14 binding.sodium_memzero(buf)
15}
16
17exports.sodium_mlock = function (buf) {
18 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
19
20 const res = binding.sodium_mlock(buf)
21
22 if (res !== 0) throw new Error('memory lock failed')
23}
24
25exports.sodium_munlock = function (buf) {
26 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
27
28 const res = binding.sodium_munlock(buf)
29
30 if (res !== 0) throw new Error('memory unlock failed')
31}
32
33exports.sodium_malloc = function (size) {
34 assert(size >= 0, 'invalid size')
35
36 const buf = Buffer.from(binding.sodium_malloc(size))
37 buf.secure = true
38 return buf
39}
40
41exports.sodium_free = function (buf) {
42 if (!buf || !buf.secure) return
43
44 binding.sodium_free(buf.buffer)
45}
46
47exports.sodium_mprotect_noaccess = function (buf) {
48 const res = binding.sodium_mprotect_noaccess(buf.buffer)
49
50 if (res !== 0) throw new Error('failed to lock buffer')
51}
52
53exports.sodium_mprotect_readonly = function (buf) {
54 const res = binding.sodium_mprotect_readonly(buf.buffer)
55
56 if (res !== 0) throw new Error('failed to unlock buffer')
57}
58
59exports.sodium_mprotect_readwrite = function (buf) {
60 const res = binding.sodium_mprotect_readwrite(buf.buffer)
61
62 if (res !== 0) throw new Error('failed to unlock buffer')
63}
64
65// crypto_randombytes
66
67exports.randombytes_buf = function (buffer) {
68 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
69
70 binding.randombytes_buf(buffer.buffer, buffer.byteOffset, buffer.byteLength)
71}
72
73exports.randombytes_buf_deterministic = function (buffer, seed) {
74 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
75 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
76 assert(
77 seed.byteLength === binding.randombytes_SEEDBYTES,
78 "seed must be 'randombytes_SEEDBYTES' bytes"
79 )
80
81 binding.randombytes_buf_deterministic(
82 buffer.buffer,
83 buffer.byteOffset,
84 buffer.byteLength,
85
86 seed.buffer,
87 seed.byteOffset,
88 seed.byteLength
89 )
90}
91
92// sodium_helpers
93
94exports.sodium_memcmp = function (a, b) {
95 assert(ArrayBuffer.isView(a), 'a must be a typed array')
96 assert(ArrayBuffer.isView(b), 'b must be a typed array')
97 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
98
99 return binding.sodium_memcmp(a, b)
100}
101
102exports.sodium_add = function (a, b) {
103 assert(ArrayBuffer.isView(a), 'a must be a typed array')
104 assert(ArrayBuffer.isView(b), 'b must be a typed array')
105 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
106
107 binding.sodium_add(a, b)
108}
109
110exports.sodium_sub = function (a, b) {
111 assert(ArrayBuffer.isView(a), 'a must be a typed array')
112 assert(ArrayBuffer.isView(b), 'b must be a typed array')
113 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
114
115 binding.sodium_sub(a, b)
116}
117
118exports.sodium_compare = function (a, b) {
119 assert(ArrayBuffer.isView(a), 'a must be a typed array')
120 assert(ArrayBuffer.isView(b), 'b must be a typed array')
121 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
122
123 return binding.sodium_compare(a, b)
124}
125
126exports.sodium_is_zero = function (buffer, length) {
127 if (length === undefined) length = buffer.byteLength
128
129 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
130 assert(length >= 0 && length <= buffer.byteLength, 'invalid length')
131
132 return binding.sodium_is_zero(buffer, length)
133}
134
135exports.sodium_pad = function (buffer, unpaddedBuflen, blockSize) {
136 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
137 assert(unpaddedBuflen <= buffer.byteLength, 'unpadded length cannot exceed buffer length')
138 assert(blockSize <= buffer.byteLength, 'block size cannot exceed buffer length')
139 assert(blockSize >= 1, 'block size must be at least 1 byte')
140 assert(
141 buffer.byteLength >= unpaddedBuflen + (blockSize - (unpaddedBuflen % blockSize)),
142 'buf not long enough'
143 )
144
145 return binding.sodium_pad(buffer, unpaddedBuflen, blockSize)
146}
147
148exports.sodium_unpad = function (buffer, paddedBuflen, blockSize) {
149 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
150 assert(paddedBuflen <= buffer.byteLength, 'unpadded length cannot exceed buffer length')
151 assert(blockSize <= buffer.byteLength, 'block size cannot exceed buffer length')
152 assert(blockSize >= 1, 'block size must be at least 1 byte')
153
154 return binding.sodium_unpad(buffer, paddedBuflen, blockSize)
155}
156
157// crypto_sign
158
159exports.crypto_sign_keypair = function (pk, sk) {
160 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
161 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
162 assert(
163 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
164 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
165 )
166 assert(
167 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
168 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
169 )
170
171 const res = binding.crypto_sign_keypair(pk, sk)
172
173 if (res !== 0) throw new Error('status: ' + res)
174}
175
176exports.crypto_sign_seed_keypair = function (pk, sk, seed) {
177 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
178 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
179 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
180 assert(
181 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
182 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
183 )
184 assert(
185 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
186 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
187 )
188 assert(
189 seed.byteLength === binding.crypto_sign_SEEDBYTES,
190 "seed must be 'crypto_sign_SEEDBYTES' bytes"
191 )
192
193 const res = binding.crypto_sign_seed_keypair(pk, sk, seed)
194
195 if (res !== 0) throw new Error('status: ' + res)
196}
197
198exports.crypto_sign = function (sm, m, sk) {
199 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
200 assert(ArrayBuffer.isView(m), 'm must be a typed array')
201 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
202 assert(
203 sm.byteLength === binding.crypto_sign_BYTES + m.byteLength,
204 "sm must be 'm.byteLength + crypto_sign_BYTES' bytes"
205 )
206 assert(
207 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
208 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
209 )
210
211 const res = binding.crypto_sign(sm, m, sk)
212
213 if (res !== 0) throw new Error('status: ' + res)
214}
215
216exports.crypto_sign_open = function (m, sm, pk) {
217 assert(ArrayBuffer.isView(m), 'm must be a typed array')
218 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
219 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
220 assert(
221 sm.byteLength >= binding.crypto_sign_BYTES,
222 "sm must be at least 'crypto_sign_BYTES' bytes"
223 )
224 assert(
225 m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
226 "m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
227 )
228 assert(
229 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
230 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
231 )
232
233 const res = binding.crypto_sign_open(m, sm, pk)
234
235 if (res !== 0) throw new Error('status: ' + res)
236}
237
238exports.crypto_sign_open = function (m, sm, pk) {
239 assert(ArrayBuffer.isView(m), 'm must be a typed array')
240 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
241 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
242 assert(
243 sm.byteLength >= binding.crypto_sign_BYTES,
244 "sm must be at least 'crypto_sign_BYTES' bytes"
245 )
246 assert(
247 m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
248 "m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
249 )
250 assert(
251 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
252 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
253 )
254
255 return binding.crypto_sign_open(m, sm, pk)
256}
257
258exports.crypto_sign_detached = function (sig, m, sk) {
259 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
260 assert(ArrayBuffer.isView(m), 'm must be a typed array')
261 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
262 assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes")
263 assert(
264 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
265 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
266 )
267
268 const res = binding.crypto_sign_detached(sig, m, sk)
269
270 if (res !== 0) throw new Error('status: ' + res)
271}
272
273exports.crypto_sign_verify_detached = function (sig, m, pk) {
274 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
275 assert(ArrayBuffer.isView(m), 'm must be a typed array')
276 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
277 assert(
278 sig.byteLength >= binding.crypto_sign_BYTES,
279 "sig must be at least 'crypto_sign_BYTES' bytes"
280 )
281 assert(
282 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
283 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
284 )
285
286 return binding.crypto_sign_verify_detached(
287 sig.buffer,
288 sig.byteOffset,
289 sig.byteLength,
290
291 m.buffer,
292 m.byteOffset,
293 m.byteLength,
294
295 pk.buffer,
296 pk.byteOffset,
297 pk.byteLength
298 )
299}
300
301exports.crypto_sign_ed25519_sk_to_pk = function (pk, sk) {
302 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
303 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
304 assert(
305 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
306 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
307 )
308 assert(
309 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
310 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
311 )
312
313 const res = binding.crypto_sign_ed25519_sk_to_pk(pk, sk)
314
315 if (res !== 0) throw new Error('status: ' + res)
316}
317
318exports.crypto_sign_ed25519_pk_to_curve25519 = function (x25519pk, ed25519pk) {
319 assert(ArrayBuffer.isView(x25519pk), 'x25519pk must be a typed array')
320 assert(ArrayBuffer.isView(ed25519pk), 'ed25519pk must be a typed array')
321 assert(
322 x25519pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
323 "x25519pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
324 )
325 assert(
326 ed25519pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
327 "ed25519pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
328 )
329
330 const res = binding.crypto_sign_ed25519_pk_to_curve25519(x25519pk, ed25519pk)
331
332 if (res !== 0) throw new Error('status: ' + res)
333}
334
335exports.crypto_sign_ed25519_sk_to_curve25519 = function (x25519sk, ed25519sk) {
336 assert(ArrayBuffer.isView(x25519sk), 'x25519sk must be a typed array')
337 assert(ArrayBuffer.isView(ed25519sk), 'ed25519sk must be a typed array')
338 assert(
339 x25519sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
340 "x25519sk must be 'crypto_box_SECRETKEYBYTES' bytes"
341 )
342
343 const edLen = ed25519sk.byteLength
344
345 assert(
346 edLen === binding.crypto_sign_SECRETKEYBYTES || edLen === binding.crypto_box_SECRETKEYBYTES,
347 "ed25519sk must be 'crypto_sign_SECRETKEYBYTES' or 'crypto_sign_SECRETKEYBYTES - crypto_sign_PUBLICKEYBYTES' bytes"
348 )
349
350 const res = binding.crypto_sign_ed25519_sk_to_curve25519(x25519sk, ed25519sk)
351
352 if (res !== 0) throw new Error('status: ' + res)
353}
354
355// crypto_box
356
357exports.crypto_box_keypair = function (pk, sk) {
358 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
359 assert(
360 pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
361 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
362 )
363 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
364 assert(
365 sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
366 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
367 )
368
369 const res = binding.crypto_box_keypair(pk, sk)
370
371 if (res !== 0) throw new Error('status: ' + res)
372}
373
374exports.crypto_box_seed_keypair = function (pk, sk, seed) {
375 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
376 assert(
377 pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
378 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
379 )
380 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
381 assert(
382 sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
383 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
384 )
385 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
386 assert(
387 seed.byteLength === binding.crypto_box_SEEDBYTES,
388 "seed must be 'crypto_box_SEEDBYTES' bytes"
389 )
390
391 const res = binding.crypto_box_seed_keypair(pk, sk, seed)
392
393 if (res !== 0) throw new Error('status: ' + res)
394}
395
396exports.crypto_box_easy = function (c, m, n, pk, sk) {
397 assert(ArrayBuffer.isView(c), 'c must be a typed array')
398 assert(ArrayBuffer.isView(m), 'm must be a typed array')
399 assert(ArrayBuffer.isView(n), 'n must be a typed array')
400 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
401 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
402 assert(
403 c.byteLength === m.byteLength + exports.crypto_box_MACBYTES,
404 "c must be 'm.byteLength + crypto_box_MACBYTES' bytes"
405 )
406 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
407 assert(
408 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
409 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
410 )
411 assert(
412 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
413 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
414 )
415
416 const res = binding.crypto_box_easy(c, m, n, pk, sk)
417
418 if (res !== 0) throw new Error('status: ' + res)
419}
420
421exports.crypto_box_detached = function (c, mac, m, n, pk, sk) {
422 assert(ArrayBuffer.isView(c), 'c must be a typed array')
423 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
424 assert(ArrayBuffer.isView(m), 'm must be a typed array')
425 assert(ArrayBuffer.isView(n), 'n must be a typed array')
426 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
427 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
428 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
429 assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes")
430 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
431 assert(
432 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
433 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
434 )
435 assert(
436 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
437 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
438 )
439
440 const res = binding.crypto_box_detached(c, mac, m, n, pk, sk)
441
442 if (res !== 0) throw new Error('status: ' + res)
443}
444
445exports.crypto_box_open_easy = function (m, c, n, pk, sk) {
446 assert(ArrayBuffer.isView(m), 'm must be a typed array')
447 assert(ArrayBuffer.isView(c), 'c must be a typed array')
448 assert(ArrayBuffer.isView(n), 'n must be a typed array')
449 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
450 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
451 assert(
452 c.byteLength >= exports.crypto_box_MACBYTES,
453 "c must be at least 'crypto_box_MACBYTES' bytes"
454 )
455 assert(
456 m.byteLength === c.byteLength - exports.crypto_box_MACBYTES,
457 "m must be 'c.byteLength - crypto_box_MACBYTES' bytes"
458 )
459 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
460 assert(
461 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
462 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
463 )
464 assert(
465 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
466 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
467 )
468
469 return binding.crypto_box_open_easy(m, c, n, pk, sk)
470}
471
472exports.crypto_box_open_detached = function (m, c, mac, n, pk, sk) {
473 assert(ArrayBuffer.isView(m), 'm must be a typed array')
474 assert(ArrayBuffer.isView(c), 'c must be a typed array')
475 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
476 assert(ArrayBuffer.isView(n), 'n must be a typed array')
477 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
478 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
479 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
480 assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes")
481 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
482 assert(
483 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
484 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
485 )
486 assert(
487 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
488 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
489 )
490
491 return binding.crypto_box_open_detached(m, c, mac, n, pk, sk)
492}
493
494exports.crypto_box_seal = function (c, m, pk) {
495 assert(ArrayBuffer.isView(c), 'c must be a typed array')
496 assert(ArrayBuffer.isView(m), 'm must be a typed array')
497 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
498 assert(
499 c.byteLength === m.byteLength + exports.crypto_box_SEALBYTES,
500 "c must be 'm.byteLength + crypto_box_SEALBYTES' bytes"
501 )
502 assert(
503 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
504 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
505 )
506
507 const res = binding.crypto_box_seal(c, m, pk)
508
509 if (res !== 0) throw new Error('status: ' + res)
510}
511
512exports.crypto_box_seal_open = function (m, c, pk, sk) {
513 assert(ArrayBuffer.isView(m), 'm must be a typed array')
514 assert(ArrayBuffer.isView(c), 'c must be a typed array')
515 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
516 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
517 assert(
518 c.byteLength >= exports.crypto_box_SEALBYTES,
519 "c must be at least 'crypto_box_SEALBYTES' bytes"
520 )
521 assert(
522 m.byteLength === c.byteLength - exports.crypto_box_SEALBYTES,
523 "m must be 'c.byteLength - crypto_box_SEALBYTES' bytes"
524 )
525 assert(
526 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
527 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
528 )
529 assert(
530 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
531 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
532 )
533
534 return binding.crypto_box_seal_open(
535 m.buffer,
536 m.byteOffset,
537 m.byteLength,
538
539 c.buffer,
540 c.byteOffset,
541 c.byteLength,
542
543 pk.buffer,
544 pk.byteOffset,
545 pk.byteLength,
546
547 sk.buffer,
548 sk.byteOffset,
549 sk.byteLength
550 )
551}
552
553// crypto_secretbox
554
555exports.crypto_secretbox_easy = function (c, m, n, k) {
556 assert(ArrayBuffer.isView(c), 'c must be a typed array')
557 assert(ArrayBuffer.isView(m), 'm must be a typed array')
558 assert(ArrayBuffer.isView(n), 'n must be a typed array')
559 assert(ArrayBuffer.isView(k), 'k must be a typed array')
560 assert(
561 c.byteLength === m.byteLength + binding.crypto_secretbox_MACBYTES,
562 "c must be 'm.byteLength + crypto_secretbox_MACBYTES' bytes"
563 )
564 assert(
565 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
566 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
567 )
568 assert(
569 k.byteLength === binding.crypto_secretbox_KEYBYTES,
570 "k must be 'crypto_secretbox_KEYBYTES' bytes"
571 )
572
573 const res = binding.crypto_secretbox_easy(c, m, n, k)
574
575 if (res !== 0) throw new Error('status: ' + res)
576}
577
578exports.crypto_secretbox_open_easy = function (m, c, n, k) {
579 assert(ArrayBuffer.isView(m), 'm must be a typed array')
580 assert(ArrayBuffer.isView(c), 'c must be a typed array')
581 assert(ArrayBuffer.isView(n), 'n must be a typed array')
582 assert(ArrayBuffer.isView(k), 'k must be a typed array')
583 assert(
584 c.byteLength >= binding.crypto_secretbox_MACBYTES,
585 "c must be at least 'crypto_secretbox_MACBYTES' bytes"
586 )
587 assert(
588 m.byteLength === c.byteLength - binding.crypto_secretbox_MACBYTES,
589 "m must be 'c.byteLength - crypto_secretbox_MACBYTES' bytes"
590 )
591 assert(
592 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
593 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
594 )
595 assert(
596 k.byteLength === binding.crypto_secretbox_KEYBYTES,
597 "k must be 'crypto_secretbox_KEYBYTES' bytes"
598 )
599
600 return binding.crypto_secretbox_open_easy(m, c, n, k)
601}
602
603exports.crypto_secretbox_detached = function (c, mac, m, n, k) {
604 assert(ArrayBuffer.isView(c), 'c must be a typed array')
605 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
606 assert(ArrayBuffer.isView(m), 'm must be a typed array')
607 assert(ArrayBuffer.isView(n), 'n must be a typed array')
608 assert(ArrayBuffer.isView(k), 'k must be a typed array')
609 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
610 assert(
611 mac.byteLength === binding.crypto_secretbox_MACBYTES,
612 "mac must be 'crypto_secretbox_MACBYTES' bytes"
613 )
614 assert(
615 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
616 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
617 )
618 assert(
619 k.byteLength === binding.crypto_secretbox_KEYBYTES,
620 "k must be 'crypto_secretbox_KEYBYTES' bytes"
621 )
622
623 const res = binding.crypto_secretbox_detached(c, mac, m, n, k)
624
625 if (res !== 0) throw new Error('status: ' + res)
626}
627
628exports.crypto_secretbox_open_detached = function (m, c, mac, n, k) {
629 assert(ArrayBuffer.isView(m), 'm must be a typed array')
630 assert(ArrayBuffer.isView(c), 'c must be a typed array')
631 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
632 assert(ArrayBuffer.isView(n), 'n must be a typed array')
633 assert(ArrayBuffer.isView(k), 'k must be a typed array')
634 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
635 assert(
636 mac.byteLength === binding.crypto_secretbox_MACBYTES,
637 "mac must be 'crypto_secretbox_MACBYTES' bytes"
638 )
639 assert(
640 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
641 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
642 )
643 assert(
644 k.byteLength === binding.crypto_secretbox_KEYBYTES,
645 "k must be 'crypto_secretbox_KEYBYTES' bytes"
646 )
647
648 return binding.crypto_secretbox_open_detached(m, c, mac, n, k)
649}
650
651// crypto_generichash
652
653exports.crypto_generichash = function (output, input, key) {
654 if (!key) key = OPTIONAL
655
656 assert(ArrayBuffer.isView(output), 'output must be a typed array')
657 assert(ArrayBuffer.isView(input), 'input must be a typed array')
658 assert(
659 output.byteLength >= binding.crypto_generichash_BYTES_MIN &&
660 output.byteLength <= binding.crypto_generichash_BYTES_MAX,
661 'output must be between crypto_generichash_BYTES_MIN and crypto_generichash_BYTES_MAX bytes'
662 )
663
664 if (key !== OPTIONAL) {
665 assert(ArrayBuffer.isView(key), 'key must be a typed array')
666 assert(
667 key.byteLength >= binding.crypto_generichash_KEYBYTES_MIN &&
668 key.byteLength <= binding.crypto_generichash_KEYBYTES_MAX,
669 'key must be between crypto_generichash_KEYBYTES_MIN and crypto_generichash_KEYBYTES_MAX bytes'
670 )
671 }
672
673 const res = binding.crypto_generichash(
674 output.buffer,
675 output.byteOffset,
676 output.byteLength,
677
678 input.buffer,
679 input.byteOffset,
680 input.byteLength,
681
682 key.buffer,
683 key.byteOffset,
684 key.byteLength
685 )
686
687 if (res !== 0) throw new Error('status: ' + res)
688}
689
690exports.crypto_generichash_batch = function (output, batch, key) {
691 assert(ArrayBuffer.isView(output), 'output must be a typed array')
692
693 if (isNode || batch.length < 4) {
694 const res = binding.crypto_generichash_batch(output, batch, !!key, key || OPTIONAL)
695 if (res !== 0) throw new Error('status: ' + res)
696 } else {
697 const state = Buffer.alloc(binding.crypto_generichash_STATEBYTES)
698
699 exports.crypto_generichash_init(state, key, output.byteLength)
700
701 for (const buf of batch) {
702 exports.crypto_generichash_update(state, buf)
703 }
704
705 exports.crypto_generichash_final(state, output)
706 }
707}
708
709exports.crypto_generichash_keygen = function (key) {
710 assert(ArrayBuffer.isView(key), 'key must be a typed array')
711 assert(
712 key.byteLength === binding.crypto_generichash_KEYBYTES,
713 "key must be 'crypto_generichash_KEYBYTES' bytes"
714 )
715
716 const res = binding.crypto_generichash_keygen(key.buffer, key.byteOffset, key.byteLength)
717
718 if (res !== 0) throw new Error('status: ' + res)
719}
720
721exports.crypto_generichash_init = function (state, key, outputLength) {
722 if (!key) key = OPTIONAL
723
724 assert(ArrayBuffer.isView(state), 'state must be a typed array')
725 assert(
726 state.byteLength === binding.crypto_generichash_STATEBYTES,
727 "state must be 'crypto_generichash_STATEBYTES' bytes"
728 )
729
730 const res = binding.crypto_generichash_init(
731 state.buffer,
732 state.byteOffset,
733 state.byteLength,
734
735 key.buffer,
736 key.byteOffset,
737 key.byteLength,
738
739 outputLength
740 )
741
742 if (res !== 0) throw new Error('status: ' + res)
743}
744
745exports.crypto_generichash_update = function (state, input) {
746 assert(ArrayBuffer.isView(state), 'state must be a typed array')
747 assert(ArrayBuffer.isView(input), 'input must be a typed array')
748 assert(
749 state.byteLength === binding.crypto_generichash_STATEBYTES,
750 "state must be 'crypto_generichash_STATEBYTES' bytes"
751 )
752
753 const res = binding.crypto_generichash_update(
754 state.buffer,
755 state.byteOffset,
756 state.byteLength,
757
758 input.buffer,
759 input.byteOffset,
760 input.byteLength
761 )
762
763 if (res !== 0) throw new Error('status: ' + res)
764}
765
766exports.crypto_generichash_final = function (state, output) {
767 assert(ArrayBuffer.isView(state), 'state must be a typed array')
768 assert(ArrayBuffer.isView(output), 'output must be a typed array')
769 assert(
770 state.byteLength === binding.crypto_generichash_STATEBYTES,
771 "state must be 'crypto_generichash_STATEBYTES' bytes"
772 )
773
774 const res = binding.crypto_generichash_final(
775 state.buffer,
776 state.byteOffset,
777 state.byteLength,
778
779 output.buffer,
780 output.byteOffset,
781 output.byteLength
782 )
783
784 if (res !== 0) throw new Error('status: ' + res)
785}
786
787// secretstream
788
789exports.crypto_secretstream_xchacha20poly1305_keygen = function (k) {
790 assert(ArrayBuffer.isView(k), 'k must be a typed array')
791 assert(
792 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
793 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
794 )
795
796 binding.crypto_secretstream_xchacha20poly1305_keygen(k.buffer, k.byteOffset, k.byteLength)
797}
798
799exports.crypto_secretstream_xchacha20poly1305_init_push = function (state, header, k) {
800 assert(ArrayBuffer.isView(state), 'state must be a typed array')
801 assert(ArrayBuffer.isView(header), 'header must be a typed array')
802 assert(ArrayBuffer.isView(k), 'k must be a typed array')
803 assert(
804 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
805 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
806 )
807 assert(
808 header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
809 "header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
810 )
811 assert(
812 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
813 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
814 )
815
816 const res = binding.crypto_secretstream_xchacha20poly1305_init_push(
817 state.buffer,
818 state.byteOffset,
819 state.byteLength,
820
821 header.buffer,
822 header.byteOffset,
823 header.byteLength,
824
825 k.buffer,
826 k.byteOffset,
827 k.byteLength
828 )
829
830 if (res !== 0) throw new Error('status: ' + res)
831}
832
833exports.crypto_secretstream_xchacha20poly1305_init_pull = function (state, header, k) {
834 assert(ArrayBuffer.isView(state), 'state must be a typed array')
835 assert(ArrayBuffer.isView(header), 'header must be a typed array')
836 assert(ArrayBuffer.isView(k), 'k must be a typed array')
837 assert(
838 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
839 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
840 )
841 assert(
842 header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
843 "header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
844 )
845 assert(
846 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
847 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
848 )
849
850 const res = binding.crypto_secretstream_xchacha20poly1305_init_pull(
851 state.buffer,
852 state.byteOffset,
853 state.byteLength,
854
855 header.buffer,
856 header.byteOffset,
857 header.byteLength,
858
859 k.buffer,
860 k.byteOffset,
861 k.byteLength
862 )
863
864 if (res !== 0) throw new Error('status: ' + res)
865}
866
867exports.crypto_secretstream_xchacha20poly1305_push = function (state, c, m, ad, tag) {
868 if (!ad) ad = OPTIONAL
869
870 assert(ArrayBuffer.isView(state), 'state must be a typed array')
871 assert(ArrayBuffer.isView(c), 'c must be a typed array')
872 assert(ArrayBuffer.isView(m), 'm must be a typed array')
873 assert(
874 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
875 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
876 )
877 assert(
878 c.byteLength === m.byteLength + binding.crypto_secretstream_xchacha20poly1305_ABYTES,
879 "c must be 'm.byteLength + crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
880 )
881
882 const res = binding.crypto_secretstream_xchacha20poly1305_push(
883 state.buffer,
884 state.byteOffset,
885 state.byteLength,
886
887 c.buffer,
888 c.byteOffset,
889 c.byteLength,
890
891 m.buffer,
892 m.byteOffset,
893 m.byteLength,
894
895 ad.buffer,
896 ad.byteOffset,
897 ad.byteLength,
898
899 tag
900 )
901
902 if (res < 0) throw new Error('push failed')
903
904 return res
905}
906
907exports.crypto_secretstream_xchacha20poly1305_pull = function (state, m, tag, c, ad) {
908 if (!ad) ad = OPTIONAL
909
910 assert(ArrayBuffer.isView(state), 'state must be a typed array')
911 assert(
912 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
913 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
914 )
915 assert(ArrayBuffer.isView(tag), 'tag must be a typed array')
916 assert(tag.byteLength === 1, 'tag must be 1 byte')
917
918 assert(ArrayBuffer.isView(c), 'c must be a typed array')
919 assert(
920 c.byteLength >= binding.crypto_secretstream_xchacha20poly1305_ABYTES,
921 "c must be at least 'crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
922 )
923 assert(ArrayBuffer.isView(m), 'm must be a typed array')
924 assert(
925 m.byteLength === c.byteLength - binding.crypto_secretstream_xchacha20poly1305_ABYTES,
926 "m must be 'c.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
927 )
928
929 const res = binding.crypto_secretstream_xchacha20poly1305_pull(
930 state.buffer,
931 state.byteOffset,
932 state.byteLength,
933
934 m.buffer,
935 m.byteOffset,
936 m.byteLength,
937
938 tag.buffer,
939 tag.byteOffset,
940 tag.byteLength,
941
942 c.buffer,
943 c.byteOffset,
944 c.byteLength,
945
946 ad.buffer,
947 ad.byteOffset,
948 ad.byteLength
949 )
950
951 if (res < 0) throw new Error('pull failed')
952
953 return res
954}
955
956exports.crypto_secretstream_xchacha20poly1305_rekey = function (state) {
957 assert(ArrayBuffer.isView(state), 'state must be a typed array')
958 assert(
959 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
960 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
961 )
962
963 binding.crypto_secretstream_xchacha20poly1305_rekey(
964 state.buffer,
965 state.byteOffset,
966 state.byteLength
967 )
968}
969
970// crypto_stream
971
972exports.crypto_stream = function (c, n, k) {
973 assert(ArrayBuffer.isView(c), 'c must be a typed array')
974 assert(ArrayBuffer.isView(n), 'n must be a typed array')
975 assert(ArrayBuffer.isView(k), 'k must be a typed array')
976 assert(
977 n.byteLength === binding.crypto_stream_NONCEBYTES,
978 "n must be 'crypto_stream_NONCEBYTES' bytes"
979 )
980 assert(
981 k.byteLength === binding.crypto_stream_KEYBYTES,
982 "k must be 'crypto_stream_KEYBYTES' bytes"
983 )
984
985 const res = binding.crypto_stream(c, n, k)
986
987 if (res !== 0) throw new Error('status: ' + res)
988}
989
990exports.crypto_stream_xor = function (c, m, n, k) {
991 assert(ArrayBuffer.isView(c), 'c must be a typed array')
992 assert(ArrayBuffer.isView(m), 'm must be a typed array')
993 assert(ArrayBuffer.isView(n), 'n must be a typed array')
994 assert(ArrayBuffer.isView(k), 'k must be a typed array')
995 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
996 assert(
997 n.byteLength === binding.crypto_stream_NONCEBYTES,
998 "n must be 'crypto_stream_NONCEBYTES' bytes"
999 )
1000 assert(
1001 k.byteLength === binding.crypto_stream_KEYBYTES,
1002 "k must be 'crypto_stream_KEYBYTES' bytes"
1003 )
1004
1005 const res = binding.crypto_stream_xor(
1006 c.buffer,
1007 c.byteOffset,
1008 c.byteLength,
1009
1010 m.buffer,
1011 m.byteOffset,
1012 m.byteLength,
1013
1014 n.buffer,
1015 n.byteOffset,
1016 n.byteLength,
1017
1018 k.buffer,
1019 k.byteOffset,
1020 k.byteLength
1021 )
1022
1023 if (res !== 0) throw new Error('status: ' + res)
1024}
1025
1026exports.crypto_stream_chacha20 = function (c, n, k) {
1027 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1028 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1029 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1030 assert(
1031 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1032 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1033 )
1034 assert(
1035 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1036 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1037 )
1038
1039 const res = binding.crypto_stream_chacha20(c, n, k)
1040
1041 if (res !== 0) throw new Error('status: ' + res)
1042}
1043
1044exports.crypto_stream_chacha20_xor = function (c, m, n, k) {
1045 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1046 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1047 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1048 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1049 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1050 assert(
1051 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1052 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1053 )
1054 assert(
1055 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1056 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1057 )
1058
1059 const res = binding.crypto_stream_chacha20_xor(c, m, n, k)
1060
1061 if (res !== 0) throw new Error('status: ' + res)
1062}
1063
1064exports.crypto_stream_chacha20_xor_ic = function (c, m, n, ic, k) {
1065 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1066 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1067 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1068 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1069 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1070 assert(
1071 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1072 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1073 )
1074 assert(
1075 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1076 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1077 )
1078
1079 const res = binding.crypto_stream_chacha20_xor_ic(c, m, n, ic, k)
1080
1081 if (res !== 0) throw new Error('status: ' + res)
1082}
1083
1084exports.crypto_stream_chacha20_ietf = function (c, n, k) {
1085 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1086 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1087 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1088 assert(
1089 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1090 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1091 )
1092 assert(
1093 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1094 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1095 )
1096
1097 const res = binding.crypto_stream_chacha20_ietf(c, n, k)
1098
1099 if (res !== 0) throw new Error('status: ' + res)
1100}
1101
1102exports.crypto_stream_chacha20_ietf_xor = function (c, m, n, k) {
1103 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1104 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1105 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1106 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1107 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1108 assert(
1109 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1110 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1111 )
1112 assert(
1113 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1114 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1115 )
1116
1117 const res = binding.crypto_stream_chacha20_ietf_xor(c, m, n, k)
1118
1119 if (res !== 0) throw new Error('status: ' + res)
1120}
1121
1122exports.crypto_stream_chacha20_ietf_xor_ic = function (c, m, n, ic, k) {
1123 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1124 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1125 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1126 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1127 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1128 assert(
1129 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1130 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1131 )
1132 assert(
1133 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1134 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1135 )
1136
1137 const res = binding.crypto_stream_chacha20_ietf_xor_ic(c, m, n, ic, k)
1138
1139 if (res !== 0) throw new Error('status: ' + res)
1140}
1141
1142exports.crypto_stream_xchacha20 = function (c, n, k) {
1143 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1144 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1145 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1146 assert(
1147 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1148 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1149 )
1150 assert(
1151 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1152 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1153 )
1154
1155 const res = binding.crypto_stream_xchacha20(c, n, k)
1156
1157 if (res !== 0) throw new Error('status: ' + res)
1158}
1159
1160exports.crypto_stream_xchacha20_xor = function (c, m, n, k) {
1161 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1162 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1163 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1164 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1165 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1166 assert(
1167 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1168 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1169 )
1170 assert(
1171 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1172 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1173 )
1174
1175 const res = binding.crypto_stream_xchacha20_xor(c, m, n, k)
1176
1177 if (res !== 0) throw new Error('status: ' + res)
1178}
1179
1180exports.crypto_stream_xchacha20_xor_ic = function (c, m, n, ic, k) {
1181 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1182 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1183 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1184 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1185 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1186 assert(
1187 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1188 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1189 )
1190 assert(
1191 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1192 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1193 )
1194
1195 const res = binding.crypto_stream_xchacha20_xor_ic(c, m, n, ic, k)
1196
1197 if (res !== 0) throw new Error('status: ' + res)
1198}
1199
1200exports.crypto_stream_salsa20 = function (c, n, k) {
1201 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1202 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1203 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1204 assert(
1205 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1206 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1207 )
1208 assert(
1209 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1210 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1211 )
1212
1213 const res = binding.crypto_stream_salsa20(c, n, k)
1214
1215 if (res !== 0) throw new Error('status: ' + res)
1216}
1217
1218exports.crypto_stream_salsa20_xor = function (c, m, n, k) {
1219 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1220 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1221 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1222 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1223 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1224 assert(
1225 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1226 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1227 )
1228 assert(
1229 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1230 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1231 )
1232
1233 const res = binding.crypto_stream_salsa20_xor(c, m, n, k)
1234
1235 if (res !== 0) throw new Error('status: ' + res)
1236}
1237
1238exports.crypto_stream_salsa20_xor_ic = function (c, m, n, ic, k) {
1239 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1240 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1241 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1242 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1243 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1244 assert(
1245 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1246 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1247 )
1248 assert(
1249 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1250 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1251 )
1252
1253 const res = binding.crypto_stream_salsa20_xor_ic(c, m, n, ic, k)
1254
1255 if (res !== 0) throw new Error('status: ' + res)
1256}
1257
1258// crypto_auth
1259
1260exports.crypto_auth = function (out, input, k) {
1261 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1262 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1263 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1264 assert(out.byteLength === binding.crypto_auth_BYTES, "out must be 'crypto_auth_BYTES' bytes")
1265 assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes")
1266
1267 const res = binding.crypto_auth(out, input, k)
1268
1269 if (res !== 0) throw new Error('status: ' + res)
1270}
1271
1272exports.crypto_auth_verify = function (h, input, k) {
1273 assert(ArrayBuffer.isView(h), 'h must be a typed array')
1274 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1275 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1276 assert(h.byteLength === binding.crypto_auth_BYTES, "h must be 'crypto_auth_BYTES' bytes")
1277 assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes")
1278
1279 return binding.crypto_auth_verify(h, input, k)
1280}
1281
1282// crypto_onetimeauth
1283
1284exports.crypto_onetimeauth = function (out, input, k) {
1285 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1286 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1287 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1288 assert(
1289 out.byteLength === binding.crypto_onetimeauth_BYTES,
1290 "out must be 'crypto_onetimeauth_BYTES' bytes"
1291 )
1292 assert(
1293 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1294 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1295 )
1296
1297 const res = binding.crypto_onetimeauth(out, input, k)
1298
1299 if (res !== 0) throw new Error('status: ' + res)
1300}
1301
1302exports.crypto_onetimeauth_init = function (state, k) {
1303 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1304 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1305 assert(
1306 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1307 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1308 )
1309 assert(
1310 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1311 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1312 )
1313
1314 const res = binding.crypto_onetimeauth_init(state, k)
1315
1316 if (res !== 0) throw new Error('status: ' + res)
1317}
1318
1319exports.crypto_onetimeauth_update = function (state, input) {
1320 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1321 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1322 assert(
1323 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1324 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1325 )
1326
1327 const res = binding.crypto_onetimeauth_update(state, input)
1328
1329 if (res !== 0) throw new Error('status: ' + res)
1330}
1331
1332exports.crypto_onetimeauth_final = function (state, out) {
1333 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1334 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1335 assert(
1336 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1337 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1338 )
1339 assert(
1340 out.byteLength === binding.crypto_onetimeauth_BYTES,
1341 "out must be 'crypto_onetimeauth_BYTES' bytes"
1342 )
1343
1344 const res = binding.crypto_onetimeauth_final(state, out)
1345
1346 if (res !== 0) throw new Error('status: ' + res)
1347}
1348
1349exports.crypto_onetimeauth_verify = function (h, input, k) {
1350 assert(ArrayBuffer.isView(h), 'h must be a typed array')
1351 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1352 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1353 assert(
1354 h.byteLength === binding.crypto_onetimeauth_BYTES,
1355 "h must be 'crypto_onetimeauth_BYTES' bytes"
1356 )
1357 assert(
1358 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1359 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1360 )
1361
1362 return binding.crypto_onetimeauth_verify(h, input, k)
1363}
1364
1365// crypto_pwhash
1366
1367exports.crypto_pwhash = function (out, passwd, salt, opslimit, memlimit, alg) {
1368 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1369 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1370 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1371 assert(
1372 out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
1373 "out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
1374 )
1375 assert(
1376 out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
1377 "out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
1378 )
1379 assert(
1380 salt.byteLength === binding.crypto_pwhash_SALTBYTES,
1381 "salt must be 'crypto_pwhash_SALTBYTES' bytes"
1382 )
1383 assert(
1384 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1385 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1386 )
1387 assert(
1388 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1389 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1390 )
1391 assert(
1392 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1393 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1394 )
1395 assert(
1396 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1397 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1398 )
1399 assert(alg >= 1 && alg <= 2, 'alg must be either Argon2i 1.3 or Argon2id 1.3')
1400
1401 const res = binding.crypto_pwhash(out, passwd, salt, opslimit, memlimit, alg)
1402
1403 if (res !== 0) throw new Error('status: ' + res)
1404}
1405
1406exports.crypto_pwhash_async = function (
1407 out,
1408 passwd,
1409 salt,
1410 opslimit,
1411 memlimit,
1412 alg,
1413 callback = undefined
1414) {
1415 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1416 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1417 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1418 assert(
1419 out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
1420 "out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
1421 )
1422 assert(
1423 out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
1424 "out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
1425 )
1426 assert(
1427 salt.byteLength === binding.crypto_pwhash_SALTBYTES,
1428 "salt must be 'crypto_pwhash_SALTBYTES' bytes"
1429 )
1430 assert(
1431 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1432 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1433 )
1434 assert(
1435 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1436 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1437 )
1438 assert(
1439 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1440 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1441 )
1442 assert(
1443 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1444 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1445 )
1446 assert(alg >= 1 && alg <= 2, 'alg must be either Argon2i 1.3 or Argon2id 1.3')
1447
1448 const [done, promise] = checkStatus(callback)
1449
1450 binding.crypto_pwhash_async(
1451 out.buffer,
1452 out.byteOffset,
1453 out.byteLength,
1454
1455 passwd.buffer,
1456 passwd.byteOffset,
1457 passwd.byteLength,
1458
1459 salt.buffer,
1460 salt.byteOffset,
1461 salt.byteLength,
1462
1463 opslimit,
1464 memlimit,
1465 alg,
1466
1467 done
1468 )
1469
1470 return promise
1471}
1472
1473exports.crypto_pwhash_str = function (out, passwd, opslimit, memlimit) {
1474 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1475 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1476 assert(
1477 out.byteLength === binding.crypto_pwhash_STRBYTES,
1478 "out must be 'crypto_pwhash_STRBYTES' bytes"
1479 )
1480 assert(typeof opslimit === 'number', 'opslimit must be a number')
1481 assert(
1482 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1483 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1484 )
1485 assert(
1486 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1487 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1488 )
1489 assert(typeof memlimit === 'number', 'memlimit must be a number')
1490 assert(
1491 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1492 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1493 )
1494 assert(
1495 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1496 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1497 )
1498
1499 const res = binding.crypto_pwhash_str(out, passwd, opslimit, memlimit)
1500
1501 if (res !== 0) throw new Error('status: ' + res)
1502}
1503
1504exports.crypto_pwhash_str_async = function (out, passwd, opslimit, memlimit, callback = undefined) {
1505 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1506 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1507 assert(
1508 out.byteLength === binding.crypto_pwhash_STRBYTES,
1509 "out must be 'crypto_pwhash_STRBYTES' bytes"
1510 )
1511 assert(passwd.byteLength > 0, 'passwd must not be empty')
1512 assert(typeof opslimit === 'number', 'opslimit must be a number')
1513 assert(
1514 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1515 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1516 )
1517 assert(
1518 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1519 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1520 )
1521 assert(typeof memlimit === 'number', 'memlimit must be a number')
1522 assert(
1523 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1524 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1525 )
1526 assert(
1527 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1528 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1529 )
1530
1531 const [done, promise] = checkStatus(callback)
1532
1533 binding.crypto_pwhash_str_async(
1534 out.buffer,
1535 out.byteOffset,
1536 out.byteLength,
1537
1538 passwd.buffer,
1539 passwd.byteOffset,
1540 passwd.byteLength,
1541
1542 opslimit,
1543 memlimit,
1544
1545 done
1546 )
1547
1548 return promise
1549}
1550
1551exports.crypto_pwhash_str_verify = function (str, passwd) {
1552 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1553 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1554 assert(
1555 str.byteLength === binding.crypto_pwhash_STRBYTES,
1556 "str must be 'crypto_pwhash_STRBYTES' bytes"
1557 )
1558
1559 return binding.crypto_pwhash_str_verify(str, passwd)
1560}
1561
1562exports.crypto_pwhash_str_verify_async = function (str, passwd, callback = undefined) {
1563 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1564 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1565 assert(
1566 str.byteLength === binding.crypto_pwhash_STRBYTES,
1567 "str must be 'crypto_pwhash_STRBYTES' bytes"
1568 )
1569 assert(passwd.byteLength > 0, 'passwd must not be empty')
1570
1571 const [done, promise] = checkStatus(callback, true)
1572
1573 binding.crypto_pwhash_str_verify_async(
1574 str.buffer,
1575 str.byteOffset,
1576 str.byteLength,
1577
1578 passwd.buffer,
1579 passwd.byteOffset,
1580 passwd.byteLength,
1581
1582 done
1583 )
1584
1585 return promise
1586}
1587
1588exports.crypto_pwhash_str_needs_rehash = function (str, opslimit, memlimit) {
1589 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1590 assert(
1591 str.byteLength === binding.crypto_pwhash_STRBYTES,
1592 "str must be 'crypto_pwhash_STRBYTES' bytes"
1593 )
1594 assert(
1595 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1596 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1597 )
1598 assert(
1599 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1600 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1601 )
1602 assert(
1603 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1604 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1605 )
1606 assert(
1607 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1608 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1609 )
1610
1611 return binding.crypto_pwhash_str_needs_rehash(str, opslimit, memlimit)
1612}
1613
1614exports.crypto_pwhash_scryptsalsa208sha256 = function (out, passwd, salt, opslimit, memlimit) {
1615 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1616 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1617 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1618 assert(
1619 out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
1620 "out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
1621 )
1622 assert(
1623 out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
1624 "out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
1625 )
1626 assert(
1627 salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
1628 "salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
1629 )
1630 assert(
1631 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1632 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1633 )
1634 assert(
1635 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1636 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1637 )
1638 assert(
1639 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1640 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1641 )
1642 assert(
1643 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1644 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1645 )
1646
1647 const res = binding.crypto_pwhash_scryptsalsa208sha256(out, passwd, salt, opslimit, memlimit)
1648
1649 if (res !== 0) throw new Error('status: ' + res)
1650}
1651
1652exports.crypto_pwhash_scryptsalsa208sha256_async = function (
1653 out,
1654 passwd,
1655 salt,
1656 opslimit,
1657 memlimit,
1658 callback = undefined
1659) {
1660 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1661 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1662 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1663 assert(
1664 out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
1665 "out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
1666 )
1667 assert(
1668 out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
1669 "out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
1670 )
1671 assert(passwd.byteLength > 0, 'passwd must not be empty')
1672 assert(
1673 salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
1674 "salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
1675 )
1676 assert(
1677 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1678 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1679 )
1680 assert(
1681 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1682 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1683 )
1684 assert(
1685 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1686 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1687 )
1688 assert(
1689 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1690 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1691 )
1692
1693 const [done, promise] = checkStatus(callback)
1694
1695 binding.crypto_pwhash_scryptsalsa208sha256_async(
1696 out.buffer,
1697 out.byteOffset,
1698 out.byteLength,
1699
1700 passwd.buffer,
1701 passwd.byteOffset,
1702 passwd.byteLength,
1703
1704 salt.buffer,
1705 salt.byteOffset,
1706 salt.byteLength,
1707
1708 opslimit,
1709 memlimit,
1710
1711 done
1712 )
1713
1714 return promise
1715}
1716
1717exports.crypto_pwhash_scryptsalsa208sha256_str_async = function (
1718 out,
1719 passwd,
1720 opslimit,
1721 memlimit,
1722 callback = undefined
1723) {
1724 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1725 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1726 assert(
1727 out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1728 "out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1729 )
1730 assert(passwd.byteLength > 0, 'passwd must not be empty')
1731 assert(
1732 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1733 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1734 )
1735 assert(
1736 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1737 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1738 )
1739 assert(
1740 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1741 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1742 )
1743 assert(
1744 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1745 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1746 )
1747
1748 const [done, promise] = checkStatus(callback)
1749
1750 binding.crypto_pwhash_scryptsalsa208sha256_str_async(
1751 out.buffer,
1752 out.byteOffset,
1753 out.byteLength,
1754
1755 passwd.buffer,
1756 passwd.byteOffset,
1757 passwd.byteLength,
1758
1759 opslimit,
1760 memlimit,
1761
1762 done
1763 )
1764
1765 return promise
1766}
1767
1768exports.crypto_pwhash_scryptsalsa208sha256_str = function (out, passwd, opslimit, memlimit) {
1769 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1770 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1771 assert(
1772 out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1773 "out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1774 )
1775 assert(passwd.byteLength > 0, 'passwd must not be empty')
1776 assert(
1777 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1778 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1779 )
1780 assert(
1781 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1782 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1783 )
1784 assert(
1785 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1786 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1787 )
1788 assert(
1789 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1790 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1791 )
1792
1793 const res = binding.crypto_pwhash_scryptsalsa208sha256_str(out, passwd, opslimit, memlimit)
1794
1795 if (res !== 0) throw new Error('status: ' + res)
1796}
1797
1798exports.crypto_pwhash_scryptsalsa208sha256_str_verify_async = function (
1799 str,
1800 passwd,
1801 callback = undefined
1802) {
1803 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1804 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1805 assert(
1806 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1807 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1808 )
1809 assert(passwd.byteLength > 0, 'passwd must not be empty')
1810
1811 const [done, promise] = checkStatus(callback, true)
1812
1813 binding.crypto_pwhash_scryptsalsa208sha256_str_verify_async(
1814 str.buffer,
1815 str.byteOffset,
1816 str.byteLength,
1817
1818 passwd.buffer,
1819 passwd.byteOffset,
1820 passwd.byteLength,
1821
1822 done
1823 )
1824
1825 return promise
1826}
1827
1828exports.crypto_pwhash_scryptsalsa208sha256_str_verify = function (str, passwd) {
1829 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1830 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1831 assert(
1832 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1833 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1834 )
1835 assert(passwd.byteLength > 0, 'passwd must not be empty')
1836
1837 return binding.crypto_pwhash_scryptsalsa208sha256_str_verify(str, passwd)
1838}
1839
1840exports.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash = function (str, opslimit, memlimit) {
1841 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1842 assert(
1843 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1844 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1845 )
1846 assert(
1847 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1848 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1849 )
1850 assert(
1851 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1852 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1853 )
1854 assert(
1855 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1856 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1857 )
1858 assert(
1859 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1860 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1861 )
1862
1863 return binding.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str, opslimit, memlimit)
1864}
1865
1866// crypto_kx
1867
1868exports.crypto_kx_keypair = function (pk, sk) {
1869 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
1870 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
1871 assert(
1872 pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1873 "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1874 )
1875 assert(
1876 sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1877 "sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1878 )
1879
1880 const res = binding.crypto_kx_keypair(pk, sk)
1881
1882 if (res !== 0) throw new Error('status: ' + res)
1883}
1884
1885exports.crypto_kx_seed_keypair = function (pk, sk, seed) {
1886 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
1887 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
1888 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
1889 assert(
1890 pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1891 "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1892 )
1893 assert(
1894 sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1895 "sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1896 )
1897 assert(
1898 seed.byteLength === binding.crypto_kx_SEEDBYTES,
1899 "seed must be 'crypto_kx_SEEDBYTES' bytes"
1900 )
1901
1902 const res = binding.crypto_kx_seed_keypair(pk, sk, seed)
1903
1904 if (res !== 0) throw new Error('status: ' + res)
1905}
1906
1907exports.crypto_kx_client_session_keys = function (rx, tx, clientPk, clientSk, serverPk) {
1908 if (!rx) rx = undefined
1909 if (!tx) tx = undefined
1910
1911 assert(rx || tx, 'at least one session key must be specified')
1912
1913 if (rx) {
1914 assert(ArrayBuffer.isView(rx), 'rx must be a typed array')
1915 assert(
1916 rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1917 "rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1918 )
1919 }
1920
1921 if (tx) {
1922 assert(ArrayBuffer.isView(tx), 'tx must be a typed array')
1923 assert(
1924 tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1925 "tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1926 )
1927 }
1928
1929 assert(ArrayBuffer.isView(clientPk), 'clientPk must be a typed array')
1930 assert(ArrayBuffer.isView(clientSk), 'clientSk must be a typed array')
1931 assert(ArrayBuffer.isView(serverPk), 'serverPk must be a typed array')
1932 assert(
1933 clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1934 "clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1935 )
1936 assert(
1937 clientSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1938 "clientSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1939 )
1940 assert(
1941 serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1942 "serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1943 )
1944
1945 const res = binding.crypto_kx_client_session_keys(rx, tx, clientPk, clientSk, serverPk)
1946
1947 if (res !== 0) throw new Error('status: ' + res)
1948}
1949
1950exports.crypto_kx_server_session_keys = function (rx, tx, serverPk, serverSk, clientPk) {
1951 if (!rx) rx = undefined
1952 if (!tx) tx = undefined
1953
1954 assert(rx || tx, 'at least one session key must be specified')
1955
1956 if (rx) {
1957 assert(ArrayBuffer.isView(rx), 'rx must be a typed array')
1958 assert(
1959 rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1960 "rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1961 )
1962 }
1963
1964 if (tx) {
1965 assert(ArrayBuffer.isView(tx), 'tx must be a typed array')
1966 assert(
1967 tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1968 "tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1969 )
1970 }
1971
1972 assert(ArrayBuffer.isView(serverPk), 'serverPk must be a typed array')
1973 assert(ArrayBuffer.isView(serverSk), 'serverSk must be a typed array')
1974 assert(ArrayBuffer.isView(clientPk), 'clientPk must be a typed array')
1975 assert(
1976 serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1977 "serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1978 )
1979 assert(
1980 serverSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1981 "serverSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1982 )
1983 assert(
1984 clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1985 "clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1986 )
1987
1988 const res = binding.crypto_kx_server_session_keys(rx, tx, serverPk, serverSk, clientPk)
1989
1990 if (res !== 0) throw new Error('status: ' + res)
1991}
1992
1993// crypto_scalarmult
1994
1995exports.crypto_scalarmult_base = function (q, n) {
1996 assert(ArrayBuffer.isView(q), 'q must be a typed array')
1997 assert(
1998 q.byteLength === binding.crypto_scalarmult_BYTES,
1999 "q must be 'crypto_scalarmult_BYTES' bytes"
2000 )
2001 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2002 assert(
2003 n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
2004 "n must be 'crypto_scalarmult_SCALARBYTES' bytes"
2005 )
2006
2007 const res = binding.crypto_scalarmult_base(q, n)
2008
2009 if (res !== 0) throw new Error('status: ' + res)
2010}
2011
2012exports.crypto_scalarmult = function (q, n, p) {
2013 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2014 assert(
2015 q.byteLength === binding.crypto_scalarmult_BYTES,
2016 "q must be 'crypto_scalarmult_BYTES' bytes"
2017 )
2018 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2019 assert(
2020 n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
2021 "n must be 'crypto_scalarmult_SCALARBYTES' bytes"
2022 )
2023 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2024 assert(
2025 p.byteLength === binding.crypto_scalarmult_BYTES,
2026 "p must be 'crypto_scalarmult_BYTES' bytes"
2027 )
2028
2029 const res = binding.crypto_scalarmult(q, n, p)
2030
2031 if (res !== 0) throw new Error('status: ' + res)
2032}
2033
2034exports.crypto_scalarmult_ed25519_base = function (q, n) {
2035 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2036 assert(
2037 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2038 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2039 )
2040 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2041 assert(
2042 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2043 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2044 )
2045
2046 const res = binding.crypto_scalarmult_ed25519_base(q, n)
2047
2048 if (res !== 0) throw new Error('status: ' + res)
2049}
2050
2051exports.crypto_scalarmult_ed25519 = function (q, n, p) {
2052 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2053 assert(
2054 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2055 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2056 )
2057 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2058 assert(
2059 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2060 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2061 )
2062 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2063 assert(
2064 p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2065 "p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2066 )
2067
2068 const res = binding.crypto_scalarmult_ed25519(q, n, p)
2069
2070 if (res !== 0) throw new Error('status: ' + res)
2071}
2072
2073exports.crypto_core_ed25519_is_valid_point = function (p) {
2074 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2075 assert(
2076 p.byteLength === binding.crypto_core_ed25519_BYTES,
2077 "p must be 'crypto_core_ed25519_BYTES' bytes"
2078 )
2079
2080 return binding.crypto_core_ed25519_is_valid_point(p)
2081}
2082
2083exports.crypto_core_ed25519_from_uniform = function (p, r) {
2084 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2085 assert(
2086 p.byteLength === binding.crypto_core_ed25519_BYTES,
2087 "p must be 'crypto_core_ed25519_BYTES' bytes"
2088 )
2089 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2090 assert(
2091 r.byteLength === binding.crypto_core_ed25519_UNIFORMBYTES,
2092 "r must be 'crypto_core_ed25519_UNIFORMBYTES' bytes"
2093 )
2094
2095 const res = binding.crypto_core_ed25519_from_uniform(p, r)
2096
2097 if (res !== 0) throw new Error('status: ' + res)
2098}
2099
2100exports.crypto_scalarmult_ed25519_base_noclamp = function (q, n) {
2101 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2102 assert(
2103 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2104 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2105 )
2106 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2107 assert(
2108 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2109 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2110 )
2111
2112 const res = binding.crypto_scalarmult_ed25519_base_noclamp(q, n)
2113
2114 if (res !== 0) throw new Error('status: ' + res)
2115}
2116
2117exports.crypto_scalarmult_ed25519_noclamp = function (q, n, p) {
2118 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2119 assert(
2120 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2121 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2122 )
2123 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2124 assert(
2125 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2126 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2127 )
2128 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2129 assert(
2130 p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2131 "p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2132 )
2133
2134 const res = binding.crypto_scalarmult_ed25519_noclamp(q, n, p)
2135
2136 if (res !== 0) throw new Error('status: ' + res)
2137}
2138
2139// crypto_core
2140
2141exports.crypto_core_ed25519_add = function (r, p, q) {
2142 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2143 assert(
2144 r.byteLength === binding.crypto_core_ed25519_BYTES,
2145 "r must be 'crypto_core_ed25519_BYTES' bytes"
2146 )
2147 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2148 assert(
2149 p.byteLength === binding.crypto_core_ed25519_BYTES,
2150 "p must be 'crypto_core_ed25519_BYTES' bytes"
2151 )
2152 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2153 assert(
2154 q.byteLength === binding.crypto_core_ed25519_BYTES,
2155 "q must be 'crypto_core_ed25519_BYTES' bytes"
2156 )
2157
2158 const res = binding.crypto_core_ed25519_add(r, p, q)
2159
2160 if (res !== 0) throw new Error('status: ' + res)
2161}
2162
2163exports.crypto_core_ed25519_sub = function (r, p, q) {
2164 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2165 assert(
2166 r.byteLength === binding.crypto_core_ed25519_BYTES,
2167 "r must be 'crypto_core_ed25519_BYTES' bytes"
2168 )
2169 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2170 assert(
2171 p.byteLength === binding.crypto_core_ed25519_BYTES,
2172 "p must be 'crypto_core_ed25519_BYTES' bytes"
2173 )
2174 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2175 assert(
2176 q.byteLength === binding.crypto_core_ed25519_BYTES,
2177 "q must be 'crypto_core_ed25519_BYTES' bytes"
2178 )
2179
2180 const res = binding.crypto_core_ed25519_sub(r, p, q)
2181
2182 if (res !== 0) throw new Error('status: ' + res)
2183}
2184
2185exports.crypto_core_ed25519_scalar_random = function (r) {
2186 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2187 assert(
2188 r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2189 "r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2190 )
2191
2192 binding.crypto_core_ed25519_scalar_random(r)
2193}
2194
2195exports.crypto_core_ed25519_scalar_reduce = function (r, s) {
2196 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2197 assert(
2198 r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2199 "r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2200 )
2201 assert(ArrayBuffer.isView(s), 's must be a typed array')
2202 assert(
2203 s.byteLength === binding.crypto_core_ed25519_NONREDUCEDSCALARBYTES,
2204 "s must be 'crypto_core_ed25519_NONREDUCEDSCALARBYTES' bytes"
2205 )
2206
2207 binding.crypto_core_ed25519_scalar_reduce(r, s)
2208}
2209
2210exports.crypto_core_ed25519_scalar_invert = function (recip, s) {
2211 assert(ArrayBuffer.isView(recip), 'recip must be a typed array')
2212 assert(
2213 recip.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2214 "recip must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2215 )
2216 assert(ArrayBuffer.isView(s), 's must be a typed array')
2217 assert(
2218 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2219 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2220 )
2221
2222 binding.crypto_core_ed25519_scalar_invert(recip, s)
2223}
2224
2225exports.crypto_core_ed25519_scalar_negate = function (neg, s) {
2226 assert(ArrayBuffer.isView(neg), 'neg must be a typed array')
2227 assert(
2228 neg.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2229 "neg must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2230 )
2231 assert(ArrayBuffer.isView(s), 's must be a typed array')
2232 assert(
2233 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2234 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2235 )
2236
2237 binding.crypto_core_ed25519_scalar_negate(neg, s)
2238}
2239
2240exports.crypto_core_ed25519_scalar_complement = function (comp, s) {
2241 assert(ArrayBuffer.isView(comp), 'comp must be a typed array')
2242 assert(
2243 comp.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2244 "comp must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2245 )
2246 assert(ArrayBuffer.isView(s), 's must be a typed array')
2247 assert(
2248 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2249 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2250 )
2251
2252 binding.crypto_core_ed25519_scalar_complement(comp, s)
2253}
2254
2255exports.crypto_core_ed25519_scalar_add = function (z, x, y) {
2256 assert(ArrayBuffer.isView(z), 'z must be a typed array')
2257 assert(
2258 z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2259 "z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2260 )
2261 assert(ArrayBuffer.isView(x), 'x must be a typed array')
2262 assert(
2263 x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2264 "x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2265 )
2266 assert(ArrayBuffer.isView(y), 'y must be a typed array')
2267 assert(
2268 y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2269 "y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2270 )
2271
2272 binding.crypto_core_ed25519_scalar_add(z, x, y)
2273}
2274
2275exports.crypto_core_ed25519_scalar_sub = function (z, x, y) {
2276 assert(ArrayBuffer.isView(z), 'z must be a typed array')
2277 assert(
2278 z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2279 "z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2280 )
2281 assert(ArrayBuffer.isView(x), 'x must be a typed array')
2282 assert(
2283 x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2284 "x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2285 )
2286 assert(ArrayBuffer.isView(y), 'y must be a typed array')
2287 assert(
2288 y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2289 "y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2290 )
2291
2292 binding.crypto_core_ed25519_scalar_sub(z, x, y)
2293}
2294
2295// crypto_shorthash
2296
2297exports.crypto_shorthash = function (out, input, k) {
2298 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2299 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2300 assert(
2301 out.byteLength === binding.crypto_shorthash_BYTES,
2302 "out must be 'crypto_shorthash_BYTES' bytes"
2303 )
2304 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2305 assert(
2306 k.byteLength === binding.crypto_shorthash_KEYBYTES,
2307 "k must be 'crypto_shorthash_KEYBYTES' bytes"
2308 )
2309
2310 const res = binding.crypto_shorthash(out, input, k)
2311
2312 if (res !== 0) throw new Error('status: ' + res)
2313}
2314
2315// crypto_kdf
2316
2317exports.crypto_kdf_keygen = function (key) {
2318 assert(ArrayBuffer.isView(key), 'key must be a typed array')
2319 assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes")
2320
2321 binding.crypto_kdf_keygen(key)
2322}
2323
2324exports.crypto_kdf_derive_from_key = function (subkey, subkeyId, ctx, key) {
2325 assert(ArrayBuffer.isView(subkey), 'subkey must be a typed array')
2326 assert(
2327 subkey.byteLength >= binding.crypto_kdf_BYTES_MIN,
2328 "subkey must be at least 'crypto_kdf_BYTES_MIN' bytes"
2329 )
2330 assert(
2331 subkey.byteLength <= binding.crypto_kdf_BYTES_MAX,
2332 "subkey must be at most 'crypto_kdf_BYTES_MAX' bytes"
2333 )
2334 assert(ArrayBuffer.isView(ctx), 'ctx must be a typed array')
2335 assert(
2336 ctx.byteLength === binding.crypto_kdf_CONTEXTBYTES,
2337 "ctx must be 'crypto_kdf_CONTEXTBYTES' bytes"
2338 )
2339 assert(ArrayBuffer.isView(key), 'key must be a typed array')
2340 assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes")
2341
2342 const res = binding.crypto_kdf_derive_from_key(subkey, subkeyId, ctx, key)
2343
2344 if (res !== 0) throw new Error('status: ' + res)
2345}
2346
2347// crypto_hash
2348
2349exports.crypto_hash = function (out, input) {
2350 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2351 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2352 assert(out.byteLength === binding.crypto_hash_BYTES, "out must be 'crypto_hash_BYTES' bytes")
2353
2354 const res = binding.crypto_hash(out, input)
2355
2356 if (res !== 0) throw new Error('status: ' + res)
2357}
2358
2359exports.crypto_hash_sha256 = function (out, input) {
2360 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2361 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2362 assert(
2363 out.byteLength === binding.crypto_hash_sha256_BYTES,
2364 "out must be 'crypto_hash_sha256_BYTES' bytes"
2365 )
2366
2367 const res = binding.crypto_hash_sha256(out, input)
2368
2369 if (res !== 0) throw new Error('status: ' + res)
2370}
2371
2372exports.crypto_hash_sha256_init = function (state) {
2373 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2374 assert(
2375 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2376 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2377 )
2378
2379 const res = binding.crypto_hash_sha256_init(state)
2380
2381 if (res !== 0) throw new Error('status: ' + res)
2382}
2383
2384exports.crypto_hash_sha256_update = function (state, input) {
2385 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2386 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2387 assert(
2388 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2389 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2390 )
2391
2392 const res = binding.crypto_hash_sha256_update(state, input)
2393
2394 if (res !== 0) throw new Error('status: ' + res)
2395}
2396
2397exports.crypto_hash_sha256_final = function (state, out) {
2398 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2399 assert(
2400 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2401 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2402 )
2403 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2404 assert(
2405 out.byteLength === binding.crypto_hash_sha256_BYTES,
2406 "out must be 'crypto_hash_sha256_BYTES' bytes"
2407 )
2408
2409 const res = binding.crypto_hash_sha256_final(state, out)
2410
2411 if (res !== 0) throw new Error('status: ' + res)
2412}
2413
2414exports.crypto_hash_sha512 = function (out, input) {
2415 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2416 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2417 assert(
2418 out.byteLength === binding.crypto_hash_sha512_BYTES,
2419 "out must be 'crypto_hash_sha512_BYTES' bytes"
2420 )
2421
2422 const res = binding.crypto_hash_sha512(out, input)
2423
2424 if (res !== 0) throw new Error('status: ' + res)
2425}
2426
2427exports.crypto_hash_sha512_init = function (state) {
2428 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2429 assert(
2430 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2431 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2432 )
2433
2434 const res = binding.crypto_hash_sha512_init(state)
2435
2436 if (res !== 0) throw new Error('status: ' + res)
2437}
2438
2439exports.crypto_hash_sha512_update = function (state, input) {
2440 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2441 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2442 assert(
2443 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2444 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2445 )
2446
2447 const res = binding.crypto_hash_sha512_update(state, input)
2448
2449 if (res !== 0) throw new Error('status: ' + res)
2450}
2451
2452exports.crypto_hash_sha512_final = function (state, out) {
2453 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2454 assert(
2455 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2456 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2457 )
2458 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2459 assert(
2460 out.byteLength === binding.crypto_hash_sha512_BYTES,
2461 "out must be 'crypto_hash_sha512_BYTES' bytes"
2462 )
2463
2464 const res = binding.crypto_hash_sha512_final(state, out)
2465
2466 if (res !== 0) throw new Error('status: ' + res)
2467}
2468
2469// crypto_aead
2470
2471exports.crypto_aead_xchacha20poly1305_ietf_keygen = function (k) {
2472 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2473 assert(
2474 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2475 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2476 )
2477
2478 binding.crypto_aead_xchacha20poly1305_ietf_keygen(k)
2479}
2480
2481exports.crypto_aead_xchacha20poly1305_ietf_encrypt = function (c, m, ad, nsec, npub, k) {
2482 if (!ad) ad = undefined
2483
2484 assert(nsec === null, 'nsec must always be set to null')
2485 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2486 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2487 assert(
2488 c.byteLength === m.byteLength + binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2489 "c must be 'm.byteLength + crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2490 )
2491 assert(c.byteLength <= 0xffffffff, 'c.byteLength must be a 32bit integer')
2492 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2493 assert(
2494 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2495 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2496 )
2497 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2498 assert(
2499 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2500 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2501 )
2502
2503 const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt(c, m, ad, npub, k)
2504
2505 if (res < 0) throw new Error('could not encrypt data')
2506
2507 return res
2508}
2509
2510exports.crypto_aead_xchacha20poly1305_ietf_decrypt = function (m, nsec, c, ad, npub, k) {
2511 if (!ad) ad = undefined
2512
2513 assert(nsec === null, 'nsec must always be set to null')
2514 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2515 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2516 assert(
2517 m.byteLength === c.byteLength - binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2518 "m must be 'c.byteLength - crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2519 )
2520 assert(m.byteLength <= 0xffffffff, 'm.byteLength must be a 32bit integer')
2521 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2522 assert(
2523 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2524 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2525 )
2526 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2527 assert(
2528 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2529 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2530 )
2531
2532 const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt(m, c, ad, npub, k)
2533
2534 if (res < 0) throw new Error('could not verify data')
2535
2536 return res
2537}
2538
2539exports.crypto_aead_xchacha20poly1305_ietf_encrypt_detached = function (
2540 c,
2541 mac,
2542 m,
2543 ad,
2544 nsec,
2545 npub,
2546 k
2547) {
2548 if (!ad) ad = undefined
2549
2550 assert(nsec === null, 'nsec must always be set to null')
2551 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2552 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2553 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2554 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2555 assert(
2556 mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2557 "mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2558 )
2559 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2560 assert(
2561 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2562 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2563 )
2564 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2565 assert(
2566 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2567 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2568 )
2569
2570 const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k)
2571
2572 if (res < 0) throw new Error('could not encrypt data')
2573
2574 return res
2575}
2576
2577exports.crypto_aead_xchacha20poly1305_ietf_decrypt_detached = function (
2578 m,
2579 nsec,
2580 c,
2581 mac,
2582 ad,
2583 npub,
2584 k
2585) {
2586 if (!ad) ad = undefined
2587
2588 assert(nsec === null, 'nsec must always be set to null')
2589 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2590 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2591 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
2592 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2593 assert(
2594 mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2595 "mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2596 )
2597 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2598 assert(
2599 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2600 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2601 )
2602 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2603 assert(
2604 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2605 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2606 )
2607
2608 const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k)
2609
2610 if (res !== 0) throw new Error('could not verify data')
2611}
2612
2613exports.crypto_aead_chacha20poly1305_ietf_keygen = function (k) {
2614 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2615 assert(
2616 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2617 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2618 )
2619
2620 binding.crypto_aead_chacha20poly1305_ietf_keygen(k)
2621}
2622
2623exports.crypto_aead_chacha20poly1305_ietf_encrypt = function (c, m, ad, nsec, npub, k) {
2624 if (!ad) ad = undefined
2625
2626 assert(nsec === null, 'nsec must always be set to null')
2627 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2628 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2629 assert(
2630 c.byteLength === m.byteLength + binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2631 "c must be 'm.byteLength + crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2632 )
2633 assert(c.byteLength <= 0xffffffff, 'c.byteLength must be a 32bit integer')
2634 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2635 assert(
2636 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2637 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2638 )
2639 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2640 assert(
2641 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2642 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2643 )
2644
2645 const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, ad, npub, k)
2646
2647 if (res < 0) throw new Error('could not encrypt data')
2648
2649 return res
2650}
2651
2652exports.crypto_aead_chacha20poly1305_ietf_decrypt = function (m, nsec, c, ad, npub, k) {
2653 if (!ad) ad = undefined
2654
2655 assert(nsec === null, 'nsec must always be set to null')
2656 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2657 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2658 assert(
2659 m.byteLength === c.byteLength - binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2660 "m must be 'c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2661 )
2662 assert(m.byteLength <= 0xffffffff, 'm.byteLength must be a 32bit integer')
2663 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2664 assert(
2665 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2666 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2667 )
2668 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2669 assert(
2670 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2671 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2672 )
2673
2674 const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt(m, c, ad, npub, k)
2675
2676 if (res < 0) throw new Error('could not verify data')
2677
2678 return res
2679}
2680
2681exports.crypto_aead_chacha20poly1305_ietf_encrypt_detached = function (
2682 c,
2683 mac,
2684 m,
2685 ad,
2686 nsec,
2687 npub,
2688 k
2689) {
2690 if (!ad) ad = undefined
2691
2692 assert(nsec === null, 'nsec must always be set to null')
2693 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2694 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2695 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2696 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2697 assert(
2698 mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2699 "mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2700 )
2701 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2702 assert(
2703 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2704 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2705 )
2706 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2707 assert(
2708 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2709 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2710 )
2711
2712 const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k)
2713
2714 if (res < 0) throw new Error('could not encrypt data')
2715
2716 return res
2717}
2718
2719exports.crypto_aead_chacha20poly1305_ietf_decrypt_detached = function (
2720 m,
2721 nsec,
2722 c,
2723 mac,
2724 ad,
2725 npub,
2726 k
2727) {
2728 if (!ad) ad = undefined
2729
2730 assert(nsec === null, 'nsec must always be set to null')
2731 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2732 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2733 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
2734 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2735 assert(
2736 mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2737 "mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2738 )
2739 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2740 assert(
2741 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2742 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2743 )
2744 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2745 assert(
2746 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2747 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2748 )
2749
2750 const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k)
2751
2752 if (res !== 0) throw new Error('could not verify data')
2753}
2754
2755// crypto_stream
2756
2757exports.crypto_stream_xor_wrap_init = function (state, n, k) {
2758 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2759 assert(
2760 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2761 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2762 )
2763 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2764 assert(
2765 n.byteLength === binding.crypto_stream_NONCEBYTES,
2766 "n must be 'crypto_stream_NONCEBYTES' bytes"
2767 )
2768 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2769 assert(
2770 k.byteLength === binding.crypto_stream_KEYBYTES,
2771 "k must be 'crypto_stream_KEYBYTES' bytes"
2772 )
2773
2774 binding.crypto_stream_xor_wrap_init(state, n, k)
2775}
2776
2777exports.crypto_stream_xor_wrap_update = function (state, c, m) {
2778 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2779 assert(
2780 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2781 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2782 )
2783 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2784 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2785 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2786
2787 binding.crypto_stream_xor_wrap_update(state, c, m)
2788}
2789
2790exports.crypto_stream_xor_wrap_final = function (state) {
2791 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2792 assert(
2793 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2794 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2795 )
2796
2797 binding.crypto_stream_xor_wrap_final(state)
2798}
2799
2800exports.crypto_stream_chacha20_xor_wrap_init = function (state, n, k) {
2801 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2802 assert(
2803 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2804 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2805 )
2806 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2807 assert(
2808 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
2809 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
2810 )
2811 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2812 assert(
2813 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
2814 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
2815 )
2816
2817 binding.crypto_stream_chacha20_xor_wrap_init(state, n, k)
2818}
2819
2820exports.crypto_stream_chacha20_xor_wrap_update = function (state, c, m) {
2821 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2822 assert(
2823 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2824 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2825 )
2826 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2827 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2828 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2829
2830 binding.crypto_stream_chacha20_xor_wrap_update(state, c, m)
2831}
2832
2833exports.crypto_stream_chacha20_xor_wrap_final = function (state) {
2834 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2835 assert(
2836 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2837 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2838 )
2839
2840 binding.crypto_stream_chacha20_xor_wrap_final(state)
2841}
2842
2843exports.crypto_stream_chacha20_ietf_xor_wrap_init = function (state, n, k) {
2844 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2845 assert(
2846 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2847 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2848 )
2849 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2850 assert(
2851 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
2852 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
2853 )
2854 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2855 assert(
2856 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
2857 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
2858 )
2859
2860 binding.crypto_stream_chacha20_ietf_xor_wrap_init(state, n, k)
2861}
2862
2863exports.crypto_stream_chacha20_ietf_xor_wrap_update = function (state, c, m) {
2864 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2865 assert(
2866 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2867 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2868 )
2869 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2870 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2871 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2872
2873 binding.crypto_stream_chacha20_ietf_xor_wrap_update(state, c, m)
2874}
2875
2876exports.crypto_stream_chacha20_ietf_xor_wrap_final = function (state) {
2877 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2878 assert(
2879 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2880 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2881 )
2882
2883 binding.crypto_stream_chacha20_ietf_xor_wrap_final(state)
2884}
2885
2886exports.crypto_stream_xchacha20_xor_wrap_init = function (state, n, k) {
2887 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2888 assert(
2889 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2890 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2891 )
2892 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2893 assert(
2894 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
2895 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
2896 )
2897 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2898 assert(
2899 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
2900 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
2901 )
2902
2903 binding.crypto_stream_xchacha20_xor_wrap_init(state, n, k)
2904}
2905
2906exports.crypto_stream_xchacha20_xor_wrap_update = function (state, c, m) {
2907 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2908 assert(
2909 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2910 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2911 )
2912 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2913 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2914 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2915
2916 binding.crypto_stream_xchacha20_xor_wrap_update(state, c, m)
2917}
2918
2919exports.crypto_stream_xchacha20_xor_wrap_final = function (state) {
2920 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2921 assert(
2922 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2923 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2924 )
2925
2926 binding.crypto_stream_xchacha20_xor_wrap_final(state)
2927}
2928
2929exports.crypto_stream_salsa20_xor_wrap_init = function (state, n, k) {
2930 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2931 assert(
2932 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2933 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2934 )
2935 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2936 assert(
2937 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
2938 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
2939 )
2940 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2941 assert(
2942 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
2943 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
2944 )
2945
2946 binding.crypto_stream_salsa20_xor_wrap_init(state, n, k)
2947}
2948
2949exports.crypto_stream_salsa20_xor_wrap_update = function (state, c, m) {
2950 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2951 assert(
2952 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2953 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2954 )
2955 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2956 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2957 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2958
2959 binding.crypto_stream_salsa20_xor_wrap_update(state, c, m)
2960}
2961
2962exports.crypto_stream_salsa20_xor_wrap_final = function (state) {
2963 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2964 assert(
2965 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2966 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2967 )
2968
2969 binding.crypto_stream_salsa20_xor_wrap_final(state)
2970}
2971
2972// experimental
2973
2974exports.extension_tweak_ed25519_base = function (n, p, ns) {
2975 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2976 assert(
2977 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
2978 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
2979 )
2980 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2981 assert(
2982 p.byteLength === binding.extension_tweak_ed25519_BYTES,
2983 "p must be 'extension_tweak_ed25519_BYTES' bytes"
2984 )
2985
2986 binding.extension_tweak_ed25519_base(n, p, ns)
2987}
2988
2989exports.extension_tweak_ed25519_sign_detached = function (sig, m, scalar, pk) {
2990 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
2991 assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes")
2992 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2993 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
2994 assert(
2995 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
2996 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
2997 )
2998
2999 if (pk) {
3000 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3001 assert(
3002 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3003 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3004 )
3005 }
3006
3007 const res = binding.extension_tweak_ed25519_sign_detached(sig, m, scalar, pk)
3008
3009 if (res !== 0) throw new Error('failed to compute signature')
3010}
3011
3012exports.extension_tweak_ed25519_sk_to_scalar = function (n, sk) {
3013 assert(ArrayBuffer.isView(n), 'n must be a typed array')
3014 assert(
3015 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3016 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3017 )
3018 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
3019 assert(
3020 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
3021 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
3022 )
3023
3024 binding.extension_tweak_ed25519_sk_to_scalar(n, sk)
3025}
3026
3027exports.extension_tweak_ed25519_scalar = function (scalarOut, scalar, ns) {
3028 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3029 assert(
3030 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3031 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3032 )
3033 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
3034 assert(
3035 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3036 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3037 )
3038
3039 binding.extension_tweak_ed25519_scalar(scalarOut, scalar, ns)
3040}
3041
3042exports.extension_tweak_ed25519_pk = function (tpk, pk, ns) {
3043 assert(ArrayBuffer.isView(tpk), 'tpk must be a typed array')
3044 assert(
3045 tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3046 "tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3047 )
3048 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3049 assert(
3050 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3051 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3052 )
3053
3054 const res = binding.extension_tweak_ed25519_pk(tpk, pk, ns)
3055
3056 if (res !== 0) throw new Error('failed to tweak public key')
3057}
3058
3059exports.extension_tweak_ed25519_keypair = function (pk, scalarOut, scalarIn, ns) {
3060 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3061 assert(
3062 pk.byteLength === binding.extension_tweak_ed25519_BYTES,
3063 "pk must be 'extension_tweak_ed25519_BYTES' bytes"
3064 )
3065 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3066 assert(
3067 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3068 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3069 )
3070 assert(ArrayBuffer.isView(scalarIn), 'scalarIn must be a typed array')
3071 assert(
3072 scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3073 "scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3074 )
3075
3076 binding.extension_tweak_ed25519_keypair(pk, scalarOut, scalarIn, ns)
3077}
3078
3079exports.extension_tweak_ed25519_scalar_add = function (scalarOut, scalar, n) {
3080 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3081 assert(
3082 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3083 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3084 )
3085 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
3086 assert(
3087 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3088 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3089 )
3090 assert(ArrayBuffer.isView(n), 'n must be a typed array')
3091 assert(
3092 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3093 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3094 )
3095
3096 binding.extension_tweak_ed25519_scalar_add(scalarOut, scalar, n)
3097}
3098
3099exports.extension_tweak_ed25519_pk_add = function (tpk, pk, p) {
3100 assert(ArrayBuffer.isView(tpk), 'tpk must be a typed array')
3101 assert(
3102 tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3103 "tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3104 )
3105 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3106 assert(
3107 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3108 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3109 )
3110 assert(ArrayBuffer.isView(p), 'p must be a typed array')
3111 assert(
3112 p.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3113 "p must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3114 )
3115
3116 const res = binding.extension_tweak_ed25519_pk_add(tpk, pk, p)
3117
3118 if (res !== 0) throw new Error('failed to add tweak to public key')
3119}
3120
3121exports.extension_tweak_ed25519_keypair_add = function (pk, scalarOut, scalarIn, tweak) {
3122 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3123 assert(
3124 pk.byteLength === binding.extension_tweak_ed25519_BYTES,
3125 "pk must be 'extension_tweak_ed25519_BYTES' bytes"
3126 )
3127 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3128 assert(
3129 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3130 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3131 )
3132 assert(ArrayBuffer.isView(scalarIn), 'scalarIn must be a typed array')
3133 assert(
3134 scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3135 "scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3136 )
3137 assert(ArrayBuffer.isView(tweak), 'tweak must be a typed array')
3138 assert(
3139 tweak.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3140 "tweak must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3141 )
3142
3143 const res = binding.extension_tweak_ed25519_keypair_add(pk, scalarOut, scalarIn, tweak)
3144
3145 if (res !== 0) throw new Error('failed to add tweak to keypair')
3146}
3147
3148exports.extension_pbkdf2_sha512_async = function (out, passwd, salt, iter, outlen, callback) {
3149 assert(
3150 iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
3151 "iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
3152 )
3153 assert(
3154 outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
3155 "outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
3156 )
3157 assert(ArrayBuffer.isView(out), 'out must be a typed array')
3158 assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes")
3159 assert(out.byteLength > 0, 'out must not be empty')
3160 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
3161 assert(passwd.byteLength > 0, 'passwd must not be empty')
3162 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
3163 assert(salt.byteLength > 0, 'salt must not be empty')
3164
3165 const [done, promise] = checkStatus(callback)
3166
3167 binding.extension_pbkdf2_sha512_async(
3168 out.buffer,
3169 out.byteOffset,
3170 out.byteLength,
3171
3172 passwd.buffer,
3173 passwd.byteOffset,
3174 passwd.byteLength,
3175
3176 salt.buffer,
3177 salt.byteOffset,
3178 salt.byteLength,
3179
3180 iter,
3181 outlen,
3182
3183 done
3184 )
3185
3186 return promise
3187}
3188
3189exports.extension_pbkdf2_sha512 = function (out, passwd, salt, iter, outlen) {
3190 assert(
3191 iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
3192 "iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
3193 )
3194 assert(
3195 outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
3196 "outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
3197 )
3198 assert(ArrayBuffer.isView(out), 'out must be a typed array')
3199 assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes")
3200 assert(out.byteLength > 0, 'out must not be empty')
3201 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
3202 assert(passwd.byteLength > 0, 'passwd must not be empty')
3203 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
3204 assert(salt.byteLength > 0, 'salt must not be empty')
3205
3206 const res = binding.extension_pbkdf2_sha512(out, passwd, salt, iter, outlen)
3207
3208 if (res !== 0) throw new Error('failed to add tweak to public key')
3209}
3210
3211function checkStatus(callback, booleanResult = false) {
3212 let done, promise
3213
3214 if (typeof callback === 'function') {
3215 done = function (status) {
3216 if (booleanResult) callback(null, status === 0)
3217 else if (status === 0) callback(null)
3218 else callback(new Error('status: ' + status))
3219 }
3220 } else {
3221 promise = new Promise(function (resolve, reject) {
3222 done = function (status) {
3223 if (booleanResult) resolve(status === 0)
3224 else if (status === 0) resolve()
3225 else reject(new Error('status: ' + status))
3226 }
3227 })
3228 }
3229
3230 return [done, promise]
3231}
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/package.json +62 -0
……@@ -0,0 +1,62 @@
1{
2 "name": "sodium-native",
3 "version": "5.1.0",
4 "description": "Low level bindings for libsodium",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "binding.cc",
9 "binding.js",
10 "extensions",
11 "prebuilds",
12 "CMakeLists.txt"
13 ],
14 "imports": {
15 "assert": {
16 "bare": "bare-assert",
17 "node": "assert"
18 }
19 },
20 "addon": true,
21 "dependencies": {
22 "bare-assert": "^1.2.0",
23 "require-addon": "^1.1.0",
24 "which-runtime": "^1.2.1"
25 },
26 "devDependencies": {
27 "bare-compat-napi": "^1.3.5",
28 "brittle": "^3.16.2",
29 "cmake-bare": "^1.6.1",
30 "cmake-fetch": "^1.4.3",
31 "cmake-napi": "^1.2.1",
32 "prettier": "^3.6.2",
33 "prettier-config-holepunch": "^2.0.0"
34 },
35 "scripts": {
36 "test": "prettier . --check && npm run test:node && npm run test:bare",
37 "test:node": "node test/all.js",
38 "test:bare": "bare test/all.js"
39 },
40 "standard": {
41 "ignore": [
42 "/test/fixtures/*.js"
43 ]
44 },
45 "engines": {
46 "bare": ">=1.16.0"
47 },
48 "repository": {
49 "type": "git",
50 "url": "git+https://github.com/holepunchto/sodium-native.git"
51 },
52 "contributors": [
53 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
54 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
55 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
56 ],
57 "license": "MIT",
58 "bugs": {
59 "url": "https://github.com/holepunchto/sodium-native/issues"
60 },
61 "homepage": "https://github.com/holepunchto/sodium-native"
62}
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/android-arm/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/android-arm/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/android-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/android-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/android-ia32/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/android-ia32/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/android-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/android-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/ios-arm64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/ios-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/ios-x64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/win32-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-native/prebuilds/win32-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/LICENSE.md +7 -0
……@@ -0,0 +1,7 @@
1Copyright 2017 Mathias Buus & Emil Bay
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/README.md +288 -0
……@@ -0,0 +1,288 @@
1# sodium-universal
2
3Universal wrapper for `sodium-javascript` and `sodium-native` working in Node.js and the Browser
4
5```sh
6npm install sodium-universal
7```
8
9`sodium-native` ships with prebuilds for macOS, Windows, and Linux.
10
11Note that the module itself is generated on a prepublish hook.
12
13## Usage
14
15```js
16var sodium = require('sodium-universal')
17
18var rnd = Buffer.allocUnsafe(12) // Cryptographically random data
19sodium.randombytes_buf(rnd)
20
21console.log(rnd.toString('hex'))
22
23```
24
25Works seamlessly with Node.js:
26
27```sh
28$ node example.js
29c7dbd46a6cc84ff2e0d1285c
30```
31
32And the browser:
33
34First install the peer dep, `sodium-javascript`.
35
36```sh
37npm install --save sodium-javascript
38```
39
40And then browserify
41
42```sh
43browserify example.js > bundle.js
44```
45
46## Introduction
47
48[`libsodium`](https://download.libsodium.org/doc/) is a collection of cryptographic primitives, providing a low-level foundation to build higher-level cryptographic applications and protocols. It is often put in contrast to RSA based cryptography and OpenSSL, even though they all share overlapping algorithms and target slightly different audiences. Sodium is a collection of modern collection of primitives, fulfilling the same cryptographic tasks, but based on simpler and more efficient algorithms.
49
50This library provides seamless bindings to [`sodium-native`](https://github.com/sodium-friends/sodium-native), which is the original C implementation of `libsodium` exposed as a Node native module. For the browser we expose [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript), using the `package.json` [`browser`](https://github.com/defunctzombie/package-browser-field-spec) field, which is supported by most bundlers.
51
52## API
53
54Please refer to [`sodium-native`](https://github.com/sodium-friends/sodium-native#api) and [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript#api). Note that the two modules do not yet have feature parity, where `sodium-native` is the more featureful of the two.
55
56## Compatibilty
57
58<!-- Generated by build-scripts/symbols.js with
59 sodium-native@3.2.0
60 sodium-javascript@0.6.0 -->
61| C Library Symbol | `sodium-native` | `sodium-javascript` |
62|:--------------------------------------------------------:|:--------------------:|:--------------------:|
63| `crypto_aead_chacha20poly1305_ietf_ABYTES` | :white_check_mark: | :white_check_mark: |
64| `crypto_aead_chacha20poly1305_ietf_decrypt` | :white_check_mark: | :white_check_mark: |
65| `crypto_aead_chacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :white_check_mark: |
66| `crypto_aead_chacha20poly1305_ietf_encrypt` | :white_check_mark: | :white_check_mark: |
67| `crypto_aead_chacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :white_check_mark: |
68| `crypto_aead_chacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
69| `crypto_aead_chacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
70| `crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
71| `crypto_aead_chacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :white_check_mark: |
72| `crypto_aead_chacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :white_check_mark: |
73| `crypto_aead_xchacha20poly1305_ietf_ABYTES` | :white_check_mark: | :small_red_triangle: |
74| `crypto_aead_xchacha20poly1305_ietf_decrypt` | :white_check_mark: | :small_red_triangle: |
75| `crypto_aead_xchacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :small_red_triangle: |
76| `crypto_aead_xchacha20poly1305_ietf_encrypt` | :white_check_mark: | :small_red_triangle: |
77| `crypto_aead_xchacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :small_red_triangle: |
78| `crypto_aead_xchacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
79| `crypto_aead_xchacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
80| `crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
81| `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :small_red_triangle: |
82| `crypto_aead_xchacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :small_red_triangle: |
83| `crypto_auth` | :white_check_mark: | :small_red_triangle: |
84| `crypto_auth_BYTES` | :white_check_mark: | :small_red_triangle: |
85| `crypto_auth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
86| `crypto_auth_verify` | :white_check_mark: | :small_red_triangle: |
87| `crypto_box_BEFORENMBYTES` | :small_red_triangle: | :white_check_mark: |
88| `crypto_box_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
89| `crypto_box_detached` | :white_check_mark: | :small_red_triangle: |
90| `crypto_box_easy` | :white_check_mark: | :small_red_triangle: |
91| `crypto_box_keypair` | :white_check_mark: | :white_check_mark: |
92| `crypto_box_MACBYTES` | :white_check_mark: | :small_red_triangle: |
93| `crypto_box_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
94| `crypto_box_open_detached` | :white_check_mark: | :small_red_triangle: |
95| `crypto_box_open_easy` | :white_check_mark: | :small_red_triangle: |
96| `crypto_box_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
97| `crypto_box_seal` | :white_check_mark: | :white_check_mark: |
98| `crypto_box_seal_open` | :white_check_mark: | :white_check_mark: |
99| `crypto_box_SEALBYTES` | :white_check_mark: | :white_check_mark: |
100| `crypto_box_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
101| `crypto_box_seed_keypair` | :white_check_mark: | :white_check_mark: |
102| `crypto_box_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
103| `crypto_box_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
104| `crypto_core_ed25519_add` | :white_check_mark: | :small_red_triangle: |
105| `crypto_core_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
106| `crypto_core_ed25519_from_uniform` | :white_check_mark: | :small_red_triangle: |
107| `crypto_core_ed25519_is_valid_point` | :white_check_mark: | :small_red_triangle: |
108| `crypto_core_ed25519_NONREDUCEDSCALARBYTES` | :white_check_mark: | :small_red_triangle: |
109| `crypto_core_ed25519_scalar_add` | :white_check_mark: | :small_red_triangle: |
110| `crypto_core_ed25519_scalar_complement` | :white_check_mark: | :small_red_triangle: |
111| `crypto_core_ed25519_scalar_invert` | :white_check_mark: | :small_red_triangle: |
112| `crypto_core_ed25519_scalar_negate` | :white_check_mark: | :small_red_triangle: |
113| `crypto_core_ed25519_scalar_random` | :white_check_mark: | :small_red_triangle: |
114| `crypto_core_ed25519_scalar_reduce` | :white_check_mark: | :small_red_triangle: |
115| `crypto_core_ed25519_scalar_sub` | :white_check_mark: | :small_red_triangle: |
116| `crypto_core_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
117| `crypto_core_ed25519_sub` | :white_check_mark: | :small_red_triangle: |
118| `crypto_core_ed25519_UNIFORMBYTES` | :white_check_mark: | :small_red_triangle: |
119| `crypto_generichash` | :white_check_mark: | :white_check_mark: |
120| `crypto_generichash_BYTES` | :white_check_mark: | :white_check_mark: |
121| `crypto_generichash_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
122| `crypto_generichash_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
123| `crypto_generichash_final` | :white_check_mark: | :small_red_triangle: |
124| `crypto_generichash_init` | :white_check_mark: | :small_red_triangle: |
125| `crypto_generichash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
126| `crypto_generichash_KEYBYTES_MAX` | :white_check_mark: | :white_check_mark: |
127| `crypto_generichash_KEYBYTES_MIN` | :white_check_mark: | :white_check_mark: |
128| `crypto_generichash_keygen` | :white_check_mark: | :small_red_triangle: |
129| `crypto_generichash_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
130| `crypto_generichash_update` | :white_check_mark: | :small_red_triangle: |
131| `crypto_hash` | :white_check_mark: | :white_check_mark: |
132| `crypto_hash_BYTES` | :white_check_mark: | :white_check_mark: |
133| `crypto_hash_sha256` | :white_check_mark: | :white_check_mark: |
134| `crypto_hash_sha256_BYTES` | :white_check_mark: | :white_check_mark: |
135| `crypto_hash_sha256_final` | :white_check_mark: | :small_red_triangle: |
136| `crypto_hash_sha256_init` | :white_check_mark: | :small_red_triangle: |
137| `crypto_hash_sha256_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
138| `crypto_hash_sha256_update` | :white_check_mark: | :small_red_triangle: |
139| `crypto_hash_sha512` | :white_check_mark: | :white_check_mark: |
140| `crypto_hash_sha512_BYTES` | :white_check_mark: | :white_check_mark: |
141| `crypto_hash_sha512_final` | :white_check_mark: | :small_red_triangle: |
142| `crypto_hash_sha512_init` | :white_check_mark: | :small_red_triangle: |
143| `crypto_hash_sha512_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
144| `crypto_hash_sha512_update` | :white_check_mark: | :small_red_triangle: |
145| `crypto_kdf_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
146| `crypto_kdf_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
147| `crypto_kdf_CONTEXTBYTES` | :white_check_mark: | :white_check_mark: |
148| `crypto_kdf_derive_from_key` | :white_check_mark: | :white_check_mark: |
149| `crypto_kdf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
150| `crypto_kdf_keygen` | :white_check_mark: | :white_check_mark: |
151| `crypto_kx_client_session_keys` | :white_check_mark: | :small_red_triangle: |
152| `crypto_kx_keypair` | :white_check_mark: | :white_check_mark: |
153| `crypto_kx_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
154| `crypto_kx_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
155| `crypto_kx_seed_keypair` | :white_check_mark: | :white_check_mark: |
156| `crypto_kx_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
157| `crypto_kx_server_session_keys` | :white_check_mark: | :small_red_triangle: |
158| `crypto_kx_SESSIONKEYBYTES` | :white_check_mark: | :small_red_triangle: |
159| `crypto_onetimeauth` | :white_check_mark: | :white_check_mark: |
160| `crypto_onetimeauth_BYTES` | :white_check_mark: | :small_red_triangle: |
161| `crypto_onetimeauth_final` | :white_check_mark: | :small_red_triangle: |
162| `crypto_onetimeauth_init` | :white_check_mark: | :small_red_triangle: |
163| `crypto_onetimeauth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
164| `crypto_onetimeauth_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
165| `crypto_onetimeauth_update` | :white_check_mark: | :small_red_triangle: |
166| `crypto_onetimeauth_verify` | :white_check_mark: | :white_check_mark: |
167| `crypto_pwhash` | :white_check_mark: | :small_red_triangle: |
168| `crypto_pwhash_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
169| `crypto_pwhash_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
170| `crypto_pwhash_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
171| `crypto_pwhash_scryptsalsa208sha256` | :white_check_mark: | :small_red_triangle: |
172| `crypto_pwhash_scryptsalsa208sha256_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
173| `crypto_pwhash_scryptsalsa208sha256_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
174| `crypto_pwhash_scryptsalsa208sha256_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
175| `crypto_pwhash_scryptsalsa208sha256_str` | :white_check_mark: | :small_red_triangle: |
176| `crypto_pwhash_scryptsalsa208sha256_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
177| `crypto_pwhash_scryptsalsa208sha256_str_verify` | :white_check_mark: | :small_red_triangle: |
178| `crypto_pwhash_scryptsalsa208sha256_STRBYTES` | :white_check_mark: | :small_red_triangle: |
179| `crypto_pwhash_str` | :white_check_mark: | :small_red_triangle: |
180| `crypto_pwhash_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
181| `crypto_pwhash_str_verify` | :white_check_mark: | :small_red_triangle: |
182| `crypto_pwhash_STRBYTES` | :white_check_mark: | :small_red_triangle: |
183| `crypto_scalarmult` | :white_check_mark: | :white_check_mark: |
184| `crypto_scalarmult_base` | :white_check_mark: | :white_check_mark: |
185| `crypto_scalarmult_BYTES` | :white_check_mark: | :white_check_mark: |
186| `crypto_scalarmult_ed25519` | :white_check_mark: | :small_red_triangle: |
187| `crypto_scalarmult_ed25519_base` | :white_check_mark: | :small_red_triangle: |
188| `crypto_scalarmult_ed25519_base_noclamp` | :white_check_mark: | :small_red_triangle: |
189| `crypto_scalarmult_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
190| `crypto_scalarmult_ed25519_noclamp` | :white_check_mark: | :small_red_triangle: |
191| `crypto_scalarmult_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
192| `crypto_scalarmult_SCALARBYTES` | :white_check_mark: | :white_check_mark: |
193| `crypto_secretbox` | :small_red_triangle: | :white_check_mark: |
194| `crypto_secretbox_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
195| `crypto_secretbox_detached` | :white_check_mark: | :white_check_mark: |
196| `crypto_secretbox_easy` | :white_check_mark: | :white_check_mark: |
197| `crypto_secretbox_KEYBYTES` | :white_check_mark: | :white_check_mark: |
198| `crypto_secretbox_MACBYTES` | :white_check_mark: | :white_check_mark: |
199| `crypto_secretbox_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
200| `crypto_secretbox_open` | :small_red_triangle: | :white_check_mark: |
201| `crypto_secretbox_open_detached` | :white_check_mark: | :white_check_mark: |
202| `crypto_secretbox_open_easy` | :white_check_mark: | :white_check_mark: |
203| `crypto_secretbox_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
204| `crypto_secretstream_xchacha20poly1305_ABYTES` | :white_check_mark: | :small_red_triangle: |
205| `crypto_secretstream_xchacha20poly1305_HEADERBYTES` | :white_check_mark: | :small_red_triangle: |
206| `crypto_secretstream_xchacha20poly1305_init_pull` | :white_check_mark: | :small_red_triangle: |
207| `crypto_secretstream_xchacha20poly1305_init_push` | :white_check_mark: | :small_red_triangle: |
208| `crypto_secretstream_xchacha20poly1305_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
209| `crypto_secretstream_xchacha20poly1305_keygen` | :white_check_mark: | :small_red_triangle: |
210| `crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
211| `crypto_secretstream_xchacha20poly1305_pull` | :white_check_mark: | :small_red_triangle: |
212| `crypto_secretstream_xchacha20poly1305_push` | :white_check_mark: | :small_red_triangle: |
213| `crypto_secretstream_xchacha20poly1305_rekey` | :white_check_mark: | :small_red_triangle: |
214| `crypto_secretstream_xchacha20poly1305_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
215| `crypto_shorthash` | :white_check_mark: | :white_check_mark: |
216| `crypto_shorthash_BYTES` | :white_check_mark: | :white_check_mark: |
217| `crypto_shorthash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
218| `crypto_sign` | :white_check_mark: | :white_check_mark: |
219| `crypto_sign_BYTES` | :white_check_mark: | :white_check_mark: |
220| `crypto_sign_detached` | :white_check_mark: | :white_check_mark: |
221| `crypto_sign_ed25519_pk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
222| `crypto_sign_ed25519_sk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
223| `crypto_sign_ed25519_sk_to_pk` | :white_check_mark: | :small_red_triangle: |
224| `crypto_sign_keypair` | :white_check_mark: | :white_check_mark: |
225| `crypto_sign_open` | :white_check_mark: | :white_check_mark: |
226| `crypto_sign_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
227| `crypto_sign_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
228| `crypto_sign_seed_keypair` | :white_check_mark: | :white_check_mark: |
229| `crypto_sign_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
230| `crypto_sign_verify_detached` | :white_check_mark: | :white_check_mark: |
231| `crypto_stream` | :white_check_mark: | :white_check_mark: |
232| `crypto_stream_chacha20` | :white_check_mark: | :white_check_mark: |
233| `crypto_stream_chacha20_ietf` | :white_check_mark: | :white_check_mark: |
234| `crypto_stream_chacha20_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
235| `crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
236| `crypto_stream_chacha20_ietf_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
237| `crypto_stream_chacha20_ietf_xor` | :white_check_mark: | :white_check_mark: |
238| `crypto_stream_chacha20_ietf_xor_ic` | :white_check_mark: | :white_check_mark: |
239| `crypto_stream_chacha20_KEYBYTES` | :white_check_mark: | :white_check_mark: |
240| `crypto_stream_chacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
241| `crypto_stream_chacha20_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
242| `crypto_stream_chacha20_xor` | :white_check_mark: | :white_check_mark: |
243| `crypto_stream_chacha20_xor_ic` | :white_check_mark: | :white_check_mark: |
244| `crypto_stream_KEYBYTES` | :white_check_mark: | :white_check_mark: |
245| `crypto_stream_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
246| `crypto_stream_salsa20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
247| `crypto_stream_salsa20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
248| `crypto_stream_salsa20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
249| `crypto_stream_salsa20_xor` | :white_check_mark: | :small_red_triangle: |
250| `crypto_stream_salsa20_xor_ic` | :white_check_mark: | :small_red_triangle: |
251| `crypto_stream_xchacha20` | :white_check_mark: | :small_red_triangle: |
252| `crypto_stream_xchacha20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
253| `crypto_stream_xchacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
254| `crypto_stream_xchacha20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
255| `crypto_stream_xchacha20_xor` | :white_check_mark: | :small_red_triangle: |
256| `crypto_stream_xchacha20_xor_ic` | :white_check_mark: | :small_red_triangle: |
257| `crypto_stream_xor` | :white_check_mark: | :white_check_mark: |
258| `crypto_verify_16` | :small_red_triangle: | :white_check_mark: |
259| `crypto_verify_32` | :small_red_triangle: | :white_check_mark: |
260| `randombytes_buf` | :white_check_mark: | :white_check_mark: |
261| `randombytes_buf_deterministic` | :white_check_mark: | :small_red_triangle: |
262| `randombytes_random` | :white_check_mark: | :small_red_triangle: |
263| `randombytes_SEEDBYTES` | :white_check_mark: | :small_red_triangle: |
264| `randombytes_uniform` | :white_check_mark: | :small_red_triangle: |
265| `sodium_add` | :white_check_mark: | :small_red_triangle: |
266| `sodium_compare` | :white_check_mark: | :small_red_triangle: |
267| `sodium_free` | :white_check_mark: | :small_red_triangle: |
268| `sodium_increment` | :white_check_mark: | :small_red_triangle: |
269| `sodium_is_zero` | :white_check_mark: | :white_check_mark: |
270| `sodium_malloc` | :white_check_mark: | :white_check_mark: |
271| `sodium_memcmp` | :white_check_mark: | :white_check_mark: |
272| `sodium_memzero` | :white_check_mark: | :white_check_mark: |
273| `sodium_mlock` | :white_check_mark: | :small_red_triangle: |
274| `sodium_mprotect_noaccess` | :white_check_mark: | :small_red_triangle: |
275| `sodium_mprotect_readonly` | :white_check_mark: | :small_red_triangle: |
276| `sodium_mprotect_readwrite` | :white_check_mark: | :small_red_triangle: |
277| `sodium_munlock` | :white_check_mark: | :small_red_triangle: |
278| `sodium_pad` | :white_check_mark: | :small_red_triangle: |
279| `sodium_sub` | :white_check_mark: | :small_red_triangle: |
280| `sodium_unpad` | :white_check_mark: | :small_red_triangle: |
281
282### Missing altogether (Ctrl + F friendly)
283
284`crypto_aead_aes256gcm_ABYTES`, `crypto_aead_aes256gcm_beforenm`, `crypto_aead_aes256gcm_decrypt`, `crypto_aead_aes256gcm_decrypt_afternm`, `crypto_aead_aes256gcm_decrypt_detached`, `crypto_aead_aes256gcm_decrypt_detached_afternm`, `crypto_aead_aes256gcm_encrypt`, `crypto_aead_aes256gcm_encrypt_afternm`, `crypto_aead_aes256gcm_encrypt_detached`, `crypto_aead_aes256gcm_encrypt_detached_afternm`, `crypto_aead_aes256gcm_is_available`, `crypto_aead_aes256gcm_KEYBYTES`, `crypto_aead_aes256gcm_keygen`, `crypto_aead_aes256gcm_MESSAGEBYTES_MAX`, `crypto_aead_aes256gcm_NPUBBYTES`, `crypto_aead_aes256gcm_NSECBYTES`, `crypto_aead_aes256gcm_STATEBYTES`, `crypto_aead_chacha20poly1305_ABYTES`, `crypto_aead_chacha20poly1305_decrypt`, `crypto_aead_chacha20poly1305_decrypt_detached`, `crypto_aead_chacha20poly1305_encrypt`, `crypto_aead_chacha20poly1305_encrypt_detached`, `crypto_aead_chacha20poly1305_KEYBYTES`, `crypto_aead_chacha20poly1305_keygen`, `crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX`, `crypto_aead_chacha20poly1305_NPUBBYTES`, `crypto_aead_chacha20poly1305_NSECBYTES`, `crypto_auth_hmacsha256`, `crypto_auth_hmacsha256_BYTES`, `crypto_auth_hmacsha256_final`, `crypto_auth_hmacsha256_init`, `crypto_auth_hmacsha256_KEYBYTES`, `crypto_auth_hmacsha256_keygen`, `crypto_auth_hmacsha256_STATEBYTES`, `crypto_auth_hmacsha256_update`, `crypto_auth_hmacsha256_verify`, `crypto_auth_hmacsha512`, `crypto_auth_hmacsha512256`, `crypto_auth_hmacsha512256_BYTES`, `crypto_auth_hmacsha512256_final`, `crypto_auth_hmacsha512256_init`, `crypto_auth_hmacsha512256_KEYBYTES`, `crypto_auth_hmacsha512256_keygen`, `crypto_auth_hmacsha512256_STATEBYTES`, `crypto_auth_hmacsha512256_update`, `crypto_auth_hmacsha512256_verify`, `crypto_auth_hmacsha512_BYTES`, `crypto_auth_hmacsha512_final`, `crypto_auth_hmacsha512_init`, `crypto_auth_hmacsha512_KEYBYTES`, `crypto_auth_hmacsha512_keygen`, `crypto_auth_hmacsha512_STATEBYTES`, `crypto_auth_hmacsha512_update`, `crypto_auth_hmacsha512_verify`, `crypto_auth_keygen`, `crypto_auth_primitive`, `crypto_box`, `crypto_box_afternm`, `crypto_box_beforenm`, `crypto_box_curve25519xchacha20poly1305_beforenm`, `crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xchacha20poly1305_detached`, `crypto_box_curve25519xchacha20poly1305_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_easy`, `crypto_box_curve25519xchacha20poly1305_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_keypair`, `crypto_box_curve25519xchacha20poly1305_MACBYTES`, `crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xchacha20poly1305_NONCEBYTES`, `crypto_box_curve25519xchacha20poly1305_open_detached`, `crypto_box_curve25519xchacha20poly1305_open_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_open_easy`, `crypto_box_curve25519xchacha20poly1305_open_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seal`, `crypto_box_curve25519xchacha20poly1305_seal_open`, `crypto_box_curve25519xchacha20poly1305_SEALBYTES`, `crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seed_keypair`, `crypto_box_curve25519xchacha20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305`, `crypto_box_curve25519xsalsa20poly1305_afternm`, `crypto_box_curve25519xsalsa20poly1305_beforenm`, `crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES`, `crypto_box_curve25519xsalsa20poly1305_keypair`, `crypto_box_curve25519xsalsa20poly1305_MACBYTES`, `crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xsalsa20poly1305_NONCEBYTES`, `crypto_box_curve25519xsalsa20poly1305_open`, `crypto_box_curve25519xsalsa20poly1305_open_afternm`, `crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_seed_keypair`, `crypto_box_curve25519xsalsa20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305_ZEROBYTES`, `crypto_box_detached_afternm`, `crypto_box_easy_afternm`, `crypto_box_MESSAGEBYTES_MAX`, `crypto_box_open`, `crypto_box_open_afternm`, `crypto_box_open_detached_afternm`, `crypto_box_open_easy_afternm`, `crypto_box_primitive`, `crypto_core_ed25519_from_hash`, `crypto_core_ed25519_HASHBYTES`, `crypto_core_ed25519_random`, `crypto_core_ed25519_scalar_mul`, `crypto_core_hchacha20`, `crypto_core_hchacha20_CONSTBYTES`, `crypto_core_hchacha20_INPUTBYTES`, `crypto_core_hchacha20_KEYBYTES`, `crypto_core_hchacha20_OUTPUTBYTES`, `crypto_core_hsalsa20`, `crypto_core_hsalsa20_CONSTBYTES`, `crypto_core_hsalsa20_INPUTBYTES`, `crypto_core_hsalsa20_KEYBYTES`, `crypto_core_hsalsa20_OUTPUTBYTES`, `crypto_core_ristretto255_add`, `crypto_core_ristretto255_BYTES`, `crypto_core_ristretto255_from_hash`, `crypto_core_ristretto255_HASHBYTES`, `crypto_core_ristretto255_is_valid_point`, `crypto_core_ristretto255_NONREDUCEDSCALARBYTES`, `crypto_core_ristretto255_random`, `crypto_core_ristretto255_scalar_add`, `crypto_core_ristretto255_scalar_complement`, `crypto_core_ristretto255_scalar_invert`, `crypto_core_ristretto255_scalar_mul`, `crypto_core_ristretto255_scalar_negate`, `crypto_core_ristretto255_scalar_random`, `crypto_core_ristretto255_scalar_reduce`, `crypto_core_ristretto255_scalar_sub`, `crypto_core_ristretto255_SCALARBYTES`, `crypto_core_ristretto255_sub`, `crypto_core_salsa20`, `crypto_core_salsa2012`, `crypto_core_salsa2012_CONSTBYTES`, `crypto_core_salsa2012_INPUTBYTES`, `crypto_core_salsa2012_KEYBYTES`, `crypto_core_salsa2012_OUTPUTBYTES`, `crypto_core_salsa208`, `crypto_core_salsa208_CONSTBYTES`, `crypto_core_salsa208_INPUTBYTES`, `crypto_core_salsa208_KEYBYTES`, `crypto_core_salsa208_OUTPUTBYTES`, `crypto_core_salsa20_CONSTBYTES`, `crypto_core_salsa20_INPUTBYTES`, `crypto_core_salsa20_KEYBYTES`, `crypto_core_salsa20_OUTPUTBYTES`, `crypto_generichash_blake2b`, `crypto_generichash_blake2b_BYTES`, `crypto_generichash_blake2b_BYTES_MAX`, `crypto_generichash_blake2b_BYTES_MIN`, `crypto_generichash_blake2b_final`, `crypto_generichash_blake2b_init`, `crypto_generichash_blake2b_init_salt_personal`, `crypto_generichash_blake2b_KEYBYTES`, `crypto_generichash_blake2b_KEYBYTES_MAX`, `crypto_generichash_blake2b_KEYBYTES_MIN`, `crypto_generichash_blake2b_keygen`, `crypto_generichash_blake2b_PERSONALBYTES`, `crypto_generichash_blake2b_salt_personal`, `crypto_generichash_blake2b_SALTBYTES`, `crypto_generichash_blake2b_STATEBYTES`, `crypto_generichash_blake2b_update`, `crypto_generichash_primitive`, `crypto_hash_primitive`, `crypto_kdf_blake2b_BYTES_MAX`, `crypto_kdf_blake2b_BYTES_MIN`, `crypto_kdf_blake2b_CONTEXTBYTES`, `crypto_kdf_blake2b_derive_from_key`, `crypto_kdf_blake2b_KEYBYTES`, `crypto_kdf_primitive`, `crypto_kx_primitive`, `crypto_onetimeauth_keygen`, `crypto_onetimeauth_poly1305`, `crypto_onetimeauth_poly1305_BYTES`, `crypto_onetimeauth_poly1305_final`, `crypto_onetimeauth_poly1305_init`, `crypto_onetimeauth_poly1305_KEYBYTES`, `crypto_onetimeauth_poly1305_keygen`, `crypto_onetimeauth_poly1305_STATEBYTES`, `crypto_onetimeauth_poly1305_update`, `crypto_onetimeauth_poly1305_verify`, `crypto_onetimeauth_primitive`, `crypto_pwhash_alg_argon2i13`, `crypto_pwhash_alg_argon2id13`, `crypto_pwhash_alg_default`, `crypto_pwhash_argon2i`, `crypto_pwhash_argon2i_alg_argon2i13`, `crypto_pwhash_argon2i_BYTES_MAX`, `crypto_pwhash_argon2i_BYTES_MIN`, `crypto_pwhash_argon2i_memlimit_interactive`, `crypto_pwhash_argon2i_memlimit_max`, `crypto_pwhash_argon2i_memlimit_min`, `crypto_pwhash_argon2i_memlimit_moderate`, `crypto_pwhash_argon2i_memlimit_sensitive`, `crypto_pwhash_argon2i_opslimit_interactive`, `crypto_pwhash_argon2i_opslimit_max`, `crypto_pwhash_argon2i_opslimit_min`, `crypto_pwhash_argon2i_opslimit_moderate`, `crypto_pwhash_argon2i_opslimit_sensitive`, `crypto_pwhash_argon2i_passwd_max`, `crypto_pwhash_argon2i_passwd_min`, `crypto_pwhash_argon2i_SALTBYTES`, `crypto_pwhash_argon2i_str`, `crypto_pwhash_argon2i_str_needs_rehash`, `crypto_pwhash_argon2i_str_verify`, `crypto_pwhash_argon2i_STRBYTES`, `crypto_pwhash_argon2i_strprefix`, `crypto_pwhash_argon2id`, `crypto_pwhash_argon2id_alg_argon2id13`, `crypto_pwhash_argon2id_BYTES_MAX`, `crypto_pwhash_argon2id_BYTES_MIN`, `crypto_pwhash_argon2id_memlimit_interactive`, `crypto_pwhash_argon2id_memlimit_max`, `crypto_pwhash_argon2id_memlimit_min`, `crypto_pwhash_argon2id_memlimit_moderate`, `crypto_pwhash_argon2id_memlimit_sensitive`, `crypto_pwhash_argon2id_opslimit_interactive`, `crypto_pwhash_argon2id_opslimit_max`, `crypto_pwhash_argon2id_opslimit_min`, `crypto_pwhash_argon2id_opslimit_moderate`, `crypto_pwhash_argon2id_opslimit_sensitive`, `crypto_pwhash_argon2id_passwd_max`, `crypto_pwhash_argon2id_passwd_min`, `crypto_pwhash_argon2id_SALTBYTES`, `crypto_pwhash_argon2id_str`, `crypto_pwhash_argon2id_str_needs_rehash`, `crypto_pwhash_argon2id_str_verify`, `crypto_pwhash_argon2id_STRBYTES`, `crypto_pwhash_argon2id_strprefix`, `crypto_pwhash_memlimit_interactive`, `crypto_pwhash_memlimit_max`, `crypto_pwhash_memlimit_min`, `crypto_pwhash_memlimit_moderate`, `crypto_pwhash_memlimit_sensitive`, `crypto_pwhash_opslimit_interactive`, `crypto_pwhash_opslimit_max`, `crypto_pwhash_opslimit_min`, `crypto_pwhash_opslimit_moderate`, `crypto_pwhash_opslimit_sensitive`, `crypto_pwhash_passwd_max`, `crypto_pwhash_passwd_min`, `crypto_pwhash_primitive`, `crypto_pwhash_scryptsalsa208sha256_ll`, `crypto_pwhash_scryptsalsa208sha256_memlimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_memlimit_max`, `crypto_pwhash_scryptsalsa208sha256_memlimit_min`, `crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_max`, `crypto_pwhash_scryptsalsa208sha256_opslimit_min`, `crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_passwd_max`, `crypto_pwhash_scryptsalsa208sha256_passwd_min`, `crypto_pwhash_scryptsalsa208sha256_strprefix`, `crypto_pwhash_str_alg`, `crypto_pwhash_strprefix`, `crypto_scalarmult_curve25519`, `crypto_scalarmult_curve25519_base`, `crypto_scalarmult_curve25519_BYTES`, `crypto_scalarmult_curve25519_SCALARBYTES`, `crypto_scalarmult_primitive`, `crypto_scalarmult_ristretto255`, `crypto_scalarmult_ristretto255_base`, `crypto_scalarmult_ristretto255_BYTES`, `crypto_scalarmult_ristretto255_SCALARBYTES`, `crypto_secretbox_keygen`, `crypto_secretbox_MESSAGEBYTES_MAX`, `crypto_secretbox_primitive`, `crypto_secretbox_xchacha20poly1305_detached`, `crypto_secretbox_xchacha20poly1305_easy`, `crypto_secretbox_xchacha20poly1305_KEYBYTES`, `crypto_secretbox_xchacha20poly1305_MACBYTES`, `crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xchacha20poly1305_NONCEBYTES`, `crypto_secretbox_xchacha20poly1305_open_detached`, `crypto_secretbox_xchacha20poly1305_open_easy`, `crypto_secretbox_xsalsa20poly1305`, `crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES`, `crypto_secretbox_xsalsa20poly1305_KEYBYTES`, `crypto_secretbox_xsalsa20poly1305_keygen`, `crypto_secretbox_xsalsa20poly1305_MACBYTES`, `crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xsalsa20poly1305_NONCEBYTES`, `crypto_secretbox_xsalsa20poly1305_open`, `crypto_secretbox_xsalsa20poly1305_ZEROBYTES`, `crypto_secretstream_xchacha20poly1305_tag_final`, `crypto_secretstream_xchacha20poly1305_tag_message`, `crypto_secretstream_xchacha20poly1305_tag_push`, `crypto_secretstream_xchacha20poly1305_tag_rekey`, `crypto_shorthash_keygen`, `crypto_shorthash_primitive`, `crypto_shorthash_siphash24`, `crypto_shorthash_siphash24_BYTES`, `crypto_shorthash_siphash24_KEYBYTES`, `crypto_shorthash_siphashx24`, `crypto_shorthash_siphashx24_BYTES`, `crypto_shorthash_siphashx24_KEYBYTES`, `crypto_sign_ed25519`, `crypto_sign_ed25519_BYTES`, `crypto_sign_ed25519_detached`, `crypto_sign_ed25519_keypair`, `crypto_sign_ed25519_MESSAGEBYTES_MAX`, `crypto_sign_ed25519_open`, `crypto_sign_ed25519_PUBLICKEYBYTES`, `crypto_sign_ed25519_SECRETKEYBYTES`, `crypto_sign_ed25519_seed_keypair`, `crypto_sign_ed25519_SEEDBYTES`, `crypto_sign_ed25519_sk_to_seed`, `crypto_sign_ed25519_verify_detached`, `crypto_sign_ed25519ph_final_create`, `crypto_sign_ed25519ph_final_verify`, `crypto_sign_ed25519ph_init`, `crypto_sign_ed25519ph_STATEBYTES`, `crypto_sign_ed25519ph_update`, `crypto_sign_edwards25519sha512batch`, `crypto_sign_edwards25519sha512batch_keypair`, `crypto_sign_edwards25519sha512batch_open`, `crypto_sign_final_create`, `crypto_sign_final_verify`, `crypto_sign_init`, `crypto_sign_MESSAGEBYTES_MAX`, `crypto_sign_primitive`, `crypto_sign_STATEBYTES`, `crypto_sign_update`, `crypto_stream_chacha20_ietf_keygen`, `crypto_stream_chacha20_keygen`, `crypto_stream_keygen`, `crypto_stream_MESSAGEBYTES_MAX`, `crypto_stream_primitive`, `crypto_stream_salsa20`, `crypto_stream_salsa2012`, `crypto_stream_salsa2012_KEYBYTES`, `crypto_stream_salsa2012_keygen`, `crypto_stream_salsa2012_MESSAGEBYTES_MAX`, `crypto_stream_salsa2012_NONCEBYTES`, `crypto_stream_salsa2012_xor`, `crypto_stream_salsa208`, `crypto_stream_salsa208_KEYBYTES`, `crypto_stream_salsa208_keygen`, `crypto_stream_salsa208_MESSAGEBYTES_MAX`, `crypto_stream_salsa208_NONCEBYTES`, `crypto_stream_salsa208_xor`, `crypto_stream_salsa20_keygen`, `crypto_stream_xchacha20_keygen`, `crypto_stream_xsalsa20`, `crypto_stream_xsalsa20_KEYBYTES`, `crypto_stream_xsalsa20_keygen`, `crypto_stream_xsalsa20_MESSAGEBYTES_MAX`, `crypto_stream_xsalsa20_NONCEBYTES`, `crypto_stream_xsalsa20_xor`, `crypto_stream_xsalsa20_xor_ic`, `crypto_verify_16_BYTES`, `crypto_verify_32_BYTES`, `crypto_verify_64`, `crypto_verify_64_BYTES`, `randombytes`, `randombytes_close`, `randombytes_implementation_name`, `randombytes_internal_implementation`, `randombytes_set_implementation`, `randombytes_stir`, `randombytes_sysrandom_implementation`, `sodium_allocarray`, `sodium_base642bin`, `sodium_base64_encoded_len`, `sodium_bin2base64`, `sodium_bin2hex`, `sodium_hex2bin`, `sodium_init`, `sodium_library_minimal`, `sodium_library_version_major`, `sodium_library_version_minor`, `sodium_misuse`, `sodium_runtime_has_aesni`, `sodium_runtime_has_avx`, `sodium_runtime_has_avx2`, `sodium_runtime_has_avx512f`, `sodium_runtime_has_neon`, `sodium_runtime_has_pclmul`, `sodium_runtime_has_rdrand`, `sodium_runtime_has_sse2`, `sodium_runtime_has_sse3`, `sodium_runtime_has_sse41`, `sodium_runtime_has_ssse3`, `sodium_set_misuse_handler`, `sodium_stackzero`, `sodium_version_string`
285
286## License
287
288[MIT](LICENSE.md)
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/build-scripts/generate.js +33 -0
……@@ -0,0 +1,33 @@
1#!/usr/bin/env node
2
3const fs = require('fs')
4const path = require('path')
5const root = path.dirname(require.resolve('sodium-javascript/package.json'))
6
7const tmp = "module.exports = require('sodium-native')\n"
8
9function recurse (dir) {
10 const ls = fs.readdirSync(dir)
11 const subdir = path.relative(root, dir)
12 if (subdir) fs.mkdirSync(subdir, { recursive: true })
13
14 for (const file of ls) {
15 if (file === 'internal') recurse(path.join(dir, file))
16 if (!/\.js$/i.test(file)) continue
17 if (file === 'example.js') continue
18 if (file === 'test.js') continue
19
20 fs.writeFileSync(path.join(__dirname, '..', subdir, file), tmp)
21 }
22}
23
24recurse(root)
25
26const pkg = require('sodium-javascript/package.json')
27const myPkg = require('../package.json')
28
29for (const key of Object.keys(pkg.dependencies)) {
30 myPkg.dependencies[key] = pkg.dependencies[key]
31}
32
33fs.writeFileSync(path.join(__dirname, '../package.json'), JSON.stringify(myPkg, null, 2) + '\n')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/build-scripts/symbols.js +32 -0
……@@ -0,0 +1,32 @@
1var exec = require('child_process').execSync
2var path = require('path')
3
4var symbols = exec(`nm -gU "${path.join(require.resolve('sodium-native'), '../prebuilds/darwin-x64/libsodium.dylib')}"`).toString().trim().split('\n')
5var native = new Set(Object.keys(require('sodium-native')).sort())
6var js = new Set(Object.keys(require('sodium-javascript')).sort())
7
8symbols = symbols.map(l => l.split(' ').pop().replace(/^_/, '').replace(/_[^_]*bytes.*/, (s) => s.toUpperCase()))
9
10var missing = []
11
12console.log(`
13<!-- Generated by build-scripts/symbols.js with
14 sodium-native@${require('sodium-native/package.json').version}
15 sodium-javascript@${require('sodium-javascript/package.json').version} -->\
16`)
17
18const max = symbols.filter(s => native.has(s) || js.has(s)).map(s => s.length).reduce((a, b) => Math.max(a, b))
19const lines = ':-' + ''.padEnd(max, '--') + '-:'
20const center = s => s.padStart(Math.floor((max + s.length) / 2), ' ').padEnd(max, ' ')
21
22console.log(`| ${center('C Library Symbol')} | \`sodium-native\` | \`sodium-javascript\` |`)
23console.log(`|${lines}|:--------------------:|:--------------------:|`)
24
25for (var i = 0; i < symbols.length; i++) {
26 var s = symbols[i]
27 if (!(native.has(s) || js.has(s))) missing.push(s)
28 else console.log(`| \`${(s + '`').padEnd(max + 1, ' ')} | ${native.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} | ${js.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} |`)
29}
30
31console.log('\n### Missing altogether (Ctrl + F friendly)\n')
32console.log(missing.map(s => '`' + s + '`').join(', '))
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/build-scripts/transform.js +26 -0
……@@ -0,0 +1,26 @@
1const fs = require('fs')
2const path = require('path')
3const { Transform, PassThrough } = require('stream')
4
5module.exports = function (file, opts) {
6 const basedir = path.resolve(__dirname, '..')
7 const relname = path.relative(basedir, file)
8
9 if (opts._flags.browserField === false) {
10 return new PassThrough()
11 }
12
13 return new Transform({
14 transform (data, enc, cb) {
15 cb()
16 },
17 flush (cb) {
18 const filename = require.resolve('sodium-javascript/' + relname)
19 fs.readFile(filename, (err, buf) => {
20 if (err) return cb(err)
21 this.push(buf)
22 cb(null)
23 })
24 }
25 })
26}
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_aead.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_auth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_box.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_generichash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_hash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_hash_sha256.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_kdf.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_kx.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_onetimeauth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_scalarmult.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_secretbox.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_secretstream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_shorthash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_sign.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_stream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_stream_chacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/crypto_verify.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/helpers.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/index.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/internal/ed25519.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/internal/hchacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/internal/poly1305.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/memory.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/package.json +49 -0
……@@ -0,0 +1,49 @@
1{
2 "name": "sodium-universal",
3 "version": "5.0.1",
4 "description": "Universal wrapper for sodium-javascript and sodium-native working in Node.js and the Browser",
5 "main": "index.js",
6 "dependencies": {
7 "sodium-native": "^5.0.1"
8 },
9 "peerDependencies": {
10 "sodium-javascript": "~0.8.0"
11 },
12 "peerDependenciesMeta": {
13 "sodium-javascript": {
14 "optional": true
15 }
16 },
17 "scripts": {
18 "prepublish": "./build-scripts/generate.js"
19 },
20 "browser": {
21 "sodium-native": "sodium-javascript"
22 },
23 "browserify": {
24 "transform": [
25 "./build-scripts/transform.js"
26 ]
27 },
28 "repository": {
29 "type": "git",
30 "url": "git+https://github.com/holepunchto/sodium-universal.git"
31 },
32 "keywords": [
33 "libsodium",
34 "sodium",
35 "sodium-native",
36 "sodium-javascript",
37 "browserify"
38 ],
39 "contributors": [
40 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
41 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
42 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
43 ],
44 "license": "MIT",
45 "bugs": {
46 "url": "https://github.com/holepunchto/sodium-universal/issues"
47 },
48 "homepage": "https://github.com/holepunchto/sodium-universal#readme"
49}
node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal/randombytes.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/@hyperswarm/secret-stream/package.json +42 -0
……@@ -0,0 +1,42 @@
1{
2 "name": "@hyperswarm/secret-stream",
3 "version": "6.9.1",
4 "description": "Secret stream backed by Noise and libsodium's secretstream",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "lib/**.js"
9 ],
10 "dependencies": {
11 "b4a": "^1.1.0",
12 "hypercore-crypto": "^3.3.1",
13 "noise-curve-ed": "^2.0.1",
14 "noise-handshake": "^4.0.0",
15 "sodium-secretstream": "^1.1.0",
16 "sodium-universal": "^5.0.0",
17 "streamx": "^2.14.0",
18 "timeout-refresh": "^2.0.0",
19 "unslab": "^1.3.0"
20 },
21 "devDependencies": {
22 "brittle": "^3.3.0",
23 "prettier": "^3.6.2",
24 "prettier-config-holepunch": "^2.0.0",
25 "udx-native": "^1.13.2"
26 },
27 "scripts": {
28 "format": "prettier --write .",
29 "lint": "prettier --check .",
30 "test": "brittle test.js"
31 },
32 "repository": {
33 "type": "git",
34 "url": "https://github.com/holepunchto/hyperswarm-secret-stream.git"
35 },
36 "author": "Mathias Buus (@mafintosh)",
37 "license": "Apache-2.0",
38 "bugs": {
39 "url": "https://github.com/holepunchto/hyperswarm-secret-stream/issues"
40 },
41 "homepage": "https://github.com/holepunchto/hyperswarm-secret-stream"
42}
node_modules/b4a/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/b4a/README.md +153 -0
……@@ -0,0 +1,153 @@
1# Buffer for Array
2
3Buffer for Array (B4A) provides a set of functions for bridging the gap between the Node.js `Buffer` class and the `Uint8Array` class. A browser compatibility layer is also included, making it possible to use B4A in both Node.js and browsers without having to worry about whether you're dealing with buffers or typed arrays.
4
5## Installation
6
7```sh
8npm i b4a
9```
10
11### React Native
12
13When imported from React Native `b4a` will make use of `react-native-b4a` for optimised buffer operations when available. All you need to do is install it:
14
15```sh
16npm i react-native-b4a
17```
18
19## API
20
21#### `b4a.isBuffer(value)`
22
23See https://nodejs.org/api/buffer.html#static-method-bufferisbufferobj
24
25This will also return `true` when passed a `Uint8Array`.
26
27#### `b4a.isEncoding(encoding)`
28
29See https://nodejs.org/api/buffer.html#static-method-bufferisencodingencoding
30
31#### `b4a.alloc(size[, fill[, encoding]])`
32
33See https://nodejs.org/api/buffer.html#static-method-bufferallocsize-fill-encoding
34
35#### `b4a.allocUnsafe(size)`
36
37See https://nodejs.org/api/buffer.html#static-method-bufferallocunsafesize
38
39#### `b4a.allocUnsafeSlow(size)`
40
41See https://nodejs.org/api/buffer.html#static-method-bufferallocunsafeslowsize
42
43#### `b4a.byteLength(string)`
44
45See https://nodejs.org/api/buffer.html#static-method-bufferbytelengthstring-encoding
46
47#### `b4a.compare(buf1, buf2)`
48
49See https://nodejs.org/api/buffer.html#static-method-buffercomparebuf1-buf2
50
51#### `b4a.concat(buffers[, totalLength])`
52
53See https://nodejs.org/api/buffer.html#static-method-bufferconcatlist-totallength
54
55#### `b4a.copy(source, target[, targetStart[, sourceStart[, sourceEnd]]])`
56
57See https://nodejs.org/api/buffer.html#bufcopytarget-targetstart-sourcestart-sourceend
58
59#### `b4a.equals(buf1, buf2)`
60
61See https://nodejs.org/api/buffer.html#bufequalsotherbuffer
62
63#### `b4a.fill(buffer, value[, offset[, end]][, encoding])`
64
65See https://nodejs.org/api/buffer.html#buffillvalue-offset-end-encoding
66
67#### `b4a.from(array)`
68
69See https://nodejs.org/api/buffer.html#static-method-bufferfromarray
70
71#### `b4a.from(arrayBuffer[, byteOffset[, length]])`
72
73See https://nodejs.org/api/buffer.html#static-method-bufferfromarraybuffer-byteoffset-length
74
75#### `b4a.from(buffer)`
76
77See https://nodejs.org/api/buffer.html#static-method-bufferfrombuffer
78
79#### `b4a.from(string[, encoding])`
80
81See https://nodejs.org/api/buffer.html#static-method-bufferfromstring-encoding
82
83#### `b4a.includes(buffer, value[, byteOffset][, encoding])`
84
85See https://nodejs.org/api/buffer.html#bufincludesvalue-byteoffset-encoding
86
87#### `b4a.indexOf(buffer, value[, byteOffset][, encoding])`
88
89See https://nodejs.org/api/buffer.html#bufindexofvalue-byteoffset-encoding
90
91#### `b4a.lastIndexOf(buffer, value[, byteOffset][, encoding])`
92
93See https://nodejs.org/api/buffer.html#buflastindexofvalue-byteoffset-encoding
94
95#### `b4a.swap16(buffer)`
96
97See https://nodejs.org/api/buffer.html#bufswap16
98
99#### `b4a.swap32(buffer)`
100
101See https://nodejs.org/api/buffer.html#bufswap32
102
103#### `b4a.swap64(buffer)`
104
105See https://nodejs.org/api/buffer.html#bufswap64
106
107#### `b4a.toBuffer(buffer)`
108
109Convert a buffer to its canonical representation. In Node.js, the canonical representation is a `Buffer`. In the browser, the canonical representation is a `Uint8Array`.
110
111#### `b4a.toString(buffer, [encoding[, start[, end]]])`
112
113See https://nodejs.org/api/buffer.html#buftostringencoding-start-end
114
115#### `b4a.write(buffer, string[, offset[, length]][, encoding])`
116
117See https://nodejs.org/api/buffer.html#bufwritestring-offset-length-encoding
118
119#### `b4a.writeDoubleLE(buffer, value[, offset])`
120
121See https://nodejs.org/api/buffer.html#bufwritedoublelevalue-offset
122
123#### `b4a.writeFloatLE(buffer, value[, offset])`
124
125See https://nodejs.org/api/buffer.html#bufwritefloatlevalue-offset
126
127#### `b4a.writeUInt32LE(buffer, value[, offset])`
128
129https://nodejs.org/api/buffer.html#bufwriteuint32levalue-offset
130
131#### `b4a.writeInt32LE(buffer, value[, offset])`
132
133See https://nodejs.org/api/buffer.html#bufwriteint32levalue-offset
134
135#### `b4a.readDoubleLE(buffer[, offset])`
136
137See https://nodejs.org/api/buffer.html#bufreaddoubleleoffset
138
139#### `b4a.readFloatLE(buffer[, offset])`
140
141See https://nodejs.org/api/buffer.html#bufreadfloatleoffset
142
143#### `b4a.readUInt32LE(buffer[, offset])`
144
145See https://nodejs.org/api/buffer.html#bufreaduint32leoffset
146
147#### `b4a.readInt32LE(buffer[, offset])`
148
149See https://nodejs.org/api/buffer.html#bufreadint32leoffset
150
151## License
152
153Apache 2.0
node_modules/b4a/browser.js +567 -0
……@@ -0,0 +1,567 @@
1const ascii = require('./lib/ascii')
2const base64 = require('./lib/base64')
3const hex = require('./lib/hex')
4const latin1 = require('./lib/latin1')
5const utf8 = require('./lib/utf8')
6const utf16le = require('./lib/utf16le')
7
8const LE = new Uint8Array(Uint16Array.of(0xff).buffer)[0] === 0xff
9
10function codecFor(encoding) {
11 switch (encoding) {
12 case 'ascii':
13 return ascii
14 case 'base64':
15 return base64
16 case 'hex':
17 return hex
18 case 'binary':
19 case 'latin1':
20 return latin1
21 case 'utf8':
22 case 'utf-8':
23 case undefined:
24 case null:
25 return utf8
26 case 'ucs2':
27 case 'ucs-2':
28 case 'utf16le':
29 case 'utf-16le':
30 return utf16le
31 default:
32 throw new Error(`Unknown encoding '${encoding}'`)
33 }
34}
35
36function isBuffer(value) {
37 return value instanceof Uint8Array
38}
39
40function isEncoding(encoding) {
41 try {
42 codecFor(encoding)
43 return true
44 } catch {
45 return false
46 }
47}
48
49function alloc(size, fill, encoding) {
50 const buffer = new Uint8Array(size)
51 if (fill !== undefined) {
52 exports.fill(buffer, fill, 0, buffer.byteLength, encoding)
53 }
54 return buffer
55}
56
57function allocUnsafe(size) {
58 return new Uint8Array(size)
59}
60
61function allocUnsafeSlow(size) {
62 return new Uint8Array(size)
63}
64
65function byteLength(string, encoding) {
66 return codecFor(encoding).byteLength(string)
67}
68
69function compare(a, b) {
70 if (a === b) return 0
71
72 const len = Math.min(a.byteLength, b.byteLength)
73
74 a = new DataView(a.buffer, a.byteOffset, a.byteLength)
75 b = new DataView(b.buffer, b.byteOffset, b.byteLength)
76
77 let i = 0
78
79 for (let n = len - (len % 4); i < n; i += 4) {
80 const x = a.getUint32(i, LE)
81 const y = b.getUint32(i, LE)
82 if (x !== y) break
83 }
84
85 for (; i < len; i++) {
86 const x = a.getUint8(i)
87 const y = b.getUint8(i)
88 if (x < y) return -1
89 if (x > y) return 1
90 }
91
92 return a.byteLength > b.byteLength ? 1 : a.byteLength < b.byteLength ? -1 : 0
93}
94
95function concat(buffers, length) {
96 if (length === undefined) {
97 length = buffers.reduce((len, buffer) => len + buffer.byteLength, 0)
98 }
99
100 const result = new Uint8Array(length)
101
102 let offset = 0
103
104 for (const buffer of buffers) {
105 if (offset + buffer.byteLength > result.byteLength) {
106 result.set(buffer.subarray(0, result.byteLength - offset), offset)
107 return result
108 }
109
110 result.set(buffer, offset)
111 offset += buffer.byteLength
112 }
113
114 return result
115}
116
117function copy(
118 source,
119 target,
120 targetStart = 0,
121 sourceStart = 0,
122 sourceEnd = source.byteLength
123) {
124 if (targetStart < 0) targetStart = 0
125 if (targetStart >= target.byteLength) return 0
126
127 const targetLength = target.byteLength - targetStart
128
129 if (sourceStart < 0) sourceStart = 0
130 if (sourceStart >= source.byteLength) return 0
131
132 if (sourceEnd <= sourceStart) return 0
133 if (sourceEnd > source.byteLength) sourceEnd = source.byteLength
134
135 if (sourceEnd - sourceStart > targetLength) {
136 sourceEnd = sourceStart + targetLength
137 }
138
139 const sourceLength = sourceEnd - sourceStart
140
141 if (source === target) {
142 target.copyWithin(targetStart, sourceStart, sourceEnd)
143 } else {
144 if (sourceStart !== 0 || sourceEnd !== source.byteLength) {
145 source = source.subarray(sourceStart, sourceEnd)
146 }
147
148 target.set(source, targetStart)
149 }
150
151 return sourceLength
152}
153
154function equals(a, b) {
155 if (a === b) return true
156 if (a.byteLength !== b.byteLength) return false
157
158 return compare(a, b) === 0
159}
160
161function fill(
162 buffer,
163 value,
164 offset = 0,
165 end = buffer.byteLength,
166 encoding = 'utf8'
167) {
168 if (typeof value === 'string') {
169 if (typeof offset === 'string') {
170 // fill(string, encoding)
171 encoding = offset
172 offset = 0
173 end = buffer.byteLength
174 } else if (typeof end === 'string') {
175 // fill(string, offset, encoding)
176 encoding = end
177 end = buffer.byteLength
178 }
179 } else if (typeof value === 'number') {
180 value = value & 0xff
181 } else if (typeof value === 'boolean') {
182 value = +value
183 }
184
185 if (offset < 0) offset = 0
186 if (offset >= buffer.byteLength) return buffer
187
188 if (end <= offset) return buffer
189 if (end > buffer.byteLength) end = buffer.byteLength
190
191 if (typeof value === 'number') return buffer.fill(value, offset, end)
192
193 if (typeof value === 'string') value = exports.from(value, encoding)
194
195 const len = value.byteLength
196
197 for (let i = 0, n = end - offset; i < n; ++i) {
198 buffer[i + offset] = value[i % len]
199 }
200
201 return buffer
202}
203
204function from(value, encodingOrOffset, length) {
205 // from(string, encoding)
206 if (typeof value === 'string') return fromString(value, encodingOrOffset)
207
208 // from(array)
209 if (Array.isArray(value)) return fromArray(value)
210
211 // from(buffer)
212 if (ArrayBuffer.isView(value)) return fromBuffer(value)
213
214 // from(arrayBuffer[, byteOffset[, length]])
215 return fromArrayBuffer(value, encodingOrOffset, length)
216}
217
218function fromString(string, encoding) {
219 const codec = codecFor(encoding)
220 const buffer = new Uint8Array(codec.byteLength(string))
221 codec.write(buffer, string)
222 return buffer
223}
224
225function fromArray(array) {
226 const buffer = new Uint8Array(array.length)
227 buffer.set(array)
228 return buffer
229}
230
231function fromBuffer(buffer) {
232 const copy = new Uint8Array(buffer.byteLength)
233 copy.set(buffer)
234 return copy
235}
236
237function fromArrayBuffer(arrayBuffer, byteOffset, length) {
238 return new Uint8Array(arrayBuffer, byteOffset, length)
239}
240
241function includes(buffer, value, byteOffset, encoding) {
242 return indexOf(buffer, value, byteOffset, encoding) !== -1
243}
244
245function indexOf(buffer, value, byteOffset, encoding) {
246 return bidirectionalIndexOf(
247 buffer,
248 value,
249 byteOffset,
250 encoding,
251 true /* first */
252 )
253}
254
255function lastIndexOf(buffer, value, byteOffset, encoding) {
256 return bidirectionalIndexOf(
257 buffer,
258 value,
259 byteOffset,
260 encoding,
261 false /* last */
262 )
263}
264
265function bidirectionalIndexOf(buffer, value, byteOffset, encoding, first) {
266 if (buffer.byteLength === 0) return -1
267
268 if (typeof byteOffset === 'string') {
269 encoding = byteOffset
270 byteOffset = 0
271 } else if (byteOffset === undefined) {
272 byteOffset = first ? 0 : buffer.length - 1
273 } else if (byteOffset < 0) {
274 byteOffset += buffer.byteLength
275 }
276
277 if (byteOffset >= buffer.byteLength) {
278 if (first) return -1
279 else byteOffset = buffer.byteLength - 1
280 } else if (byteOffset < 0) {
281 if (first) byteOffset = 0
282 else return -1
283 }
284
285 if (typeof value === 'string') {
286 value = from(value, encoding)
287 } else if (typeof value === 'number') {
288 value = value & 0xff
289
290 if (first) {
291 return buffer.indexOf(value, byteOffset)
292 } else {
293 return buffer.lastIndexOf(value, byteOffset)
294 }
295 }
296
297 if (value.byteLength === 0) return -1
298
299 if (first) {
300 let foundIndex = -1
301
302 for (let i = byteOffset; i < buffer.byteLength; i++) {
303 if (buffer[i] === value[foundIndex === -1 ? 0 : i - foundIndex]) {
304 if (foundIndex === -1) foundIndex = i
305 if (i - foundIndex + 1 === value.byteLength) return foundIndex
306 } else {
307 if (foundIndex !== -1) i -= i - foundIndex
308 foundIndex = -1
309 }
310 }
311 } else {
312 if (byteOffset + value.byteLength > buffer.byteLength) {
313 byteOffset = buffer.byteLength - value.byteLength
314 }
315
316 for (let i = byteOffset; i >= 0; i--) {
317 let found = true
318
319 for (let j = 0; j < value.byteLength; j++) {
320 if (buffer[i + j] !== value[j]) {
321 found = false
322 break
323 }
324 }
325
326 if (found) return i
327 }
328 }
329
330 return -1
331}
332
333function swap(buffer, n, m) {
334 const i = buffer[n]
335 buffer[n] = buffer[m]
336 buffer[m] = i
337}
338
339function swap16(buffer) {
340 const len = buffer.byteLength
341
342 if (len % 2 !== 0)
343 throw new RangeError('Buffer size must be a multiple of 16-bits')
344
345 for (let i = 0; i < len; i += 2) swap(buffer, i, i + 1)
346
347 return buffer
348}
349
350function swap32(buffer) {
351 const len = buffer.byteLength
352
353 if (len % 4 !== 0)
354 throw new RangeError('Buffer size must be a multiple of 32-bits')
355
356 for (let i = 0; i < len; i += 4) {
357 swap(buffer, i, i + 3)
358 swap(buffer, i + 1, i + 2)
359 }
360
361 return buffer
362}
363
364function swap64(buffer) {
365 const len = buffer.byteLength
366
367 if (len % 8 !== 0)
368 throw new RangeError('Buffer size must be a multiple of 64-bits')
369
370 for (let i = 0; i < len; i += 8) {
371 swap(buffer, i, i + 7)
372 swap(buffer, i + 1, i + 6)
373 swap(buffer, i + 2, i + 5)
374 swap(buffer, i + 3, i + 4)
375 }
376
377 return buffer
378}
379
380function toBuffer(buffer) {
381 return buffer
382}
383
384function toString(
385 buffer,
386 encoding = 'utf8',
387 start = 0,
388 end = buffer.byteLength
389) {
390 // toString(buffer)
391 if (arguments.length === 1) return utf8.toString(buffer)
392
393 // toString(buffer, encoding)
394 if (arguments.length === 2) return codecFor(encoding).toString(buffer)
395
396 if (start < 0) start = 0
397 if (start >= buffer.byteLength) return ''
398
399 if (end <= start) return ''
400 if (end > buffer.byteLength) end = buffer.byteLength
401
402 if (start !== 0 || end !== buffer.byteLength) {
403 buffer = buffer.subarray(start, end)
404 }
405
406 return codecFor(encoding).toString(buffer)
407}
408
409function write(buffer, string, offset, length, encoding) {
410 // write(buffer, string)
411 if (arguments.length === 2) return utf8.write(buffer, string)
412
413 if (typeof offset === 'string') {
414 // write(buffer, string, encoding)
415 encoding = offset
416 offset = 0
417 length = buffer.byteLength
418 } else if (typeof length === 'string') {
419 // write(buffer, string, offset, encoding)
420 encoding = length
421 length = buffer.byteLength - offset
422 }
423
424 length = Math.min(length, exports.byteLength(string, encoding))
425
426 let start = offset
427 if (start < 0) start = 0
428 if (start >= buffer.byteLength) return 0
429
430 let end = offset + length
431 if (end <= start) return 0
432 if (end > buffer.byteLength) end = buffer.byteLength
433
434 if (start !== 0 || end !== buffer.byteLength) {
435 buffer = buffer.subarray(start, end)
436 }
437
438 return codecFor(encoding).write(buffer, string)
439}
440
441function readDoubleBE(buffer, offset = 0) {
442 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
443 return view.getFloat64(offset, false)
444}
445
446function readDoubleLE(buffer, offset = 0) {
447 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
448 return view.getFloat64(offset, true)
449}
450
451function readFloatBE(buffer, offset = 0) {
452 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
453 return view.getFloat32(offset, false)
454}
455
456function readFloatLE(buffer, offset = 0) {
457 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
458 return view.getFloat32(offset, true)
459}
460
461function readInt32BE(buffer, offset = 0) {
462 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
463 return view.getInt32(offset, false)
464}
465
466function readInt32LE(buffer, offset = 0) {
467 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
468 return view.getInt32(offset, true)
469}
470
471function readUInt32BE(buffer, offset = 0) {
472 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
473 return view.getUint32(offset, false)
474}
475
476function readUInt32LE(buffer, offset = 0) {
477 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
478 return view.getUint32(offset, true)
479}
480
481function writeDoubleBE(buffer, value, offset = 0) {
482 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
483 view.setFloat64(offset, value, false)
484 return offset + 8
485}
486
487function writeDoubleLE(buffer, value, offset = 0) {
488 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
489 view.setFloat64(offset, value, true)
490 return offset + 8
491}
492
493function writeFloatBE(buffer, value, offset = 0) {
494 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
495 view.setFloat32(offset, value, false)
496 return offset + 4
497}
498
499function writeFloatLE(buffer, value, offset = 0) {
500 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
501 view.setFloat32(offset, value, true)
502 return offset + 4
503}
504
505function writeInt32BE(buffer, value, offset = 0) {
506 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
507 view.setInt32(offset, value, false)
508 return offset + 4
509}
510
511function writeInt32LE(buffer, value, offset = 0) {
512 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
513 view.setInt32(offset, value, true)
514 return offset + 4
515}
516
517function writeUInt32BE(buffer, value, offset = 0) {
518 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
519 view.setUint32(offset, value, false)
520 return offset + 4
521}
522
523function writeUInt32LE(buffer, value, offset = 0) {
524 const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
525 view.setUint32(offset, value, true)
526 return offset + 4
527}
528
529module.exports = exports = {
530 isBuffer,
531 isEncoding,
532 alloc,
533 allocUnsafe,
534 allocUnsafeSlow,
535 byteLength,
536 compare,
537 concat,
538 copy,
539 equals,
540 fill,
541 from,
542 includes,
543 indexOf,
544 lastIndexOf,
545 swap16,
546 swap32,
547 swap64,
548 toBuffer,
549 toString,
550 write,
551 readDoubleBE,
552 readDoubleLE,
553 readFloatBE,
554 readFloatLE,
555 readInt32BE,
556 readInt32LE,
557 readUInt32BE,
558 readUInt32LE,
559 writeDoubleBE,
560 writeDoubleLE,
561 writeFloatBE,
562 writeFloatLE,
563 writeInt32BE,
564 writeInt32LE,
565 writeUInt32BE,
566 writeUInt32LE
567}
node_modules/b4a/index.js +188 -0
……@@ -0,0 +1,188 @@
1function isBuffer(value) {
2 return Buffer.isBuffer(value) || value instanceof Uint8Array
3}
4
5function isEncoding(encoding) {
6 return Buffer.isEncoding(encoding)
7}
8
9function alloc(size, fill, encoding) {
10 return Buffer.alloc(size, fill, encoding)
11}
12
13function allocUnsafe(size) {
14 return Buffer.allocUnsafe(size)
15}
16
17function allocUnsafeSlow(size) {
18 return Buffer.allocUnsafeSlow(size)
19}
20
21function byteLength(string, encoding) {
22 return Buffer.byteLength(string, encoding)
23}
24
25function compare(a, b) {
26 return Buffer.compare(a, b)
27}
28
29function concat(buffers, totalLength) {
30 return Buffer.concat(buffers, totalLength)
31}
32
33function copy(source, target, targetStart, start, end) {
34 return toBuffer(source).copy(target, targetStart, start, end)
35}
36
37function equals(a, b) {
38 return toBuffer(a).equals(b)
39}
40
41function fill(buffer, value, offset, end, encoding) {
42 return toBuffer(buffer).fill(value, offset, end, encoding)
43}
44
45function from(value, encodingOrOffset, length) {
46 return Buffer.from(value, encodingOrOffset, length)
47}
48
49function includes(buffer, value, byteOffset, encoding) {
50 return toBuffer(buffer).includes(value, byteOffset, encoding)
51}
52
53function indexOf(buffer, value, byfeOffset, encoding) {
54 return toBuffer(buffer).indexOf(value, byfeOffset, encoding)
55}
56
57function lastIndexOf(buffer, value, byteOffset, encoding) {
58 return toBuffer(buffer).lastIndexOf(value, byteOffset, encoding)
59}
60
61function swap16(buffer) {
62 return toBuffer(buffer).swap16()
63}
64
65function swap32(buffer) {
66 return toBuffer(buffer).swap32()
67}
68
69function swap64(buffer) {
70 return toBuffer(buffer).swap64()
71}
72
73function toBuffer(buffer) {
74 if (Buffer.isBuffer(buffer)) return buffer
75 return Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength)
76}
77
78function toString(buffer, encoding, start, end) {
79 return toBuffer(buffer).toString(encoding, start, end)
80}
81
82function write(buffer, string, offset, length, encoding) {
83 return toBuffer(buffer).write(string, offset, length, encoding)
84}
85
86function readDoubleBE(buffer, offset) {
87 return toBuffer(buffer).readDoubleBE(offset)
88}
89
90function readDoubleLE(buffer, offset) {
91 return toBuffer(buffer).readDoubleLE(offset)
92}
93
94function readFloatBE(buffer, offset) {
95 return toBuffer(buffer).readFloatBE(offset)
96}
97
98function readFloatLE(buffer, offset) {
99 return toBuffer(buffer).readFloatLE(offset)
100}
101
102function readInt32BE(buffer, offset) {
103 return toBuffer(buffer).readInt32BE(offset)
104}
105
106function readInt32LE(buffer, offset) {
107 return toBuffer(buffer).readInt32LE(offset)
108}
109
110function readUInt32BE(buffer, offset) {
111 return toBuffer(buffer).readUInt32BE(offset)
112}
113
114function readUInt32LE(buffer, offset) {
115 return toBuffer(buffer).readUInt32LE(offset)
116}
117
118function writeDoubleBE(buffer, value, offset) {
119 return toBuffer(buffer).writeDoubleBE(value, offset)
120}
121
122function writeDoubleLE(buffer, value, offset) {
123 return toBuffer(buffer).writeDoubleLE(value, offset)
124}
125
126function writeFloatBE(buffer, value, offset) {
127 return toBuffer(buffer).writeFloatBE(value, offset)
128}
129
130function writeFloatLE(buffer, value, offset) {
131 return toBuffer(buffer).writeFloatLE(value, offset)
132}
133
134function writeInt32BE(buffer, value, offset) {
135 return toBuffer(buffer).writeInt32BE(value, offset)
136}
137
138function writeInt32LE(buffer, value, offset) {
139 return toBuffer(buffer).writeInt32LE(value, offset)
140}
141
142function writeUInt32BE(buffer, value, offset) {
143 return toBuffer(buffer).writeUInt32BE(value, offset)
144}
145
146function writeUInt32LE(buffer, value, offset) {
147 return toBuffer(buffer).writeUInt32LE(value, offset)
148}
149
150module.exports = {
151 isBuffer,
152 isEncoding,
153 alloc,
154 allocUnsafe,
155 allocUnsafeSlow,
156 byteLength,
157 compare,
158 concat,
159 copy,
160 equals,
161 fill,
162 from,
163 includes,
164 indexOf,
165 lastIndexOf,
166 swap16,
167 swap32,
168 swap64,
169 toBuffer,
170 toString,
171 write,
172 readDoubleBE,
173 readDoubleLE,
174 readFloatBE,
175 readFloatLE,
176 readInt32BE,
177 readInt32LE,
178 readUInt32BE,
179 readUInt32LE,
180 writeDoubleBE,
181 writeDoubleLE,
182 writeFloatBE,
183 writeFloatLE,
184 writeInt32BE,
185 writeInt32LE,
186 writeUInt32BE,
187 writeUInt32LE
188}
node_modules/b4a/lib/ascii.js +31 -0
……@@ -0,0 +1,31 @@
1function byteLength(string) {
2 return string.length
3}
4
5function toString(buffer) {
6 const len = buffer.byteLength
7
8 let result = ''
9
10 for (let i = 0; i < len; i++) {
11 result += String.fromCharCode(buffer[i] & 0x7f)
12 }
13
14 return result
15}
16
17function write(buffer, string) {
18 const len = buffer.byteLength
19
20 for (let i = 0; i < len; i++) {
21 buffer[i] = string.charCodeAt(i)
22 }
23
24 return len
25}
26
27module.exports = {
28 byteLength,
29 toString,
30 write
31}
node_modules/b4a/lib/base64.js +65 -0
……@@ -0,0 +1,65 @@
1const alphabet =
2 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
3
4const codes = new Uint8Array(256)
5
6for (let i = 0; i < alphabet.length; i++) {
7 codes[alphabet.charCodeAt(i)] = i
8}
9
10codes[/* - */ 0x2d] = 62
11codes[/* _ */ 0x5f] = 63
12
13function byteLength(string) {
14 let len = string.length
15
16 if (string.charCodeAt(len - 1) === 0x3d) len--
17 if (len > 1 && string.charCodeAt(len - 1) === 0x3d) len--
18
19 return (len * 3) >>> 2
20}
21
22function toString(buffer) {
23 const len = buffer.byteLength
24
25 let result = ''
26
27 for (let i = 0; i < len; i += 3) {
28 result +=
29 alphabet[buffer[i] >> 2] +
30 alphabet[((buffer[i] & 3) << 4) | (buffer[i + 1] >> 4)] +
31 alphabet[((buffer[i + 1] & 15) << 2) | (buffer[i + 2] >> 6)] +
32 alphabet[buffer[i + 2] & 63]
33 }
34
35 if (len % 3 === 2) {
36 result = result.substring(0, result.length - 1) + '='
37 } else if (len % 3 === 1) {
38 result = result.substring(0, result.length - 2) + '=='
39 }
40
41 return result
42}
43
44function write(buffer, string) {
45 const len = buffer.byteLength
46
47 for (let i = 0, j = 0; j < len; i += 4) {
48 const a = codes[string.charCodeAt(i)]
49 const b = codes[string.charCodeAt(i + 1)]
50 const c = codes[string.charCodeAt(i + 2)]
51 const d = codes[string.charCodeAt(i + 3)]
52
53 buffer[j++] = (a << 2) | (b >> 4)
54 buffer[j++] = ((b & 15) << 4) | (c >> 2)
55 buffer[j++] = ((c & 3) << 6) | (d & 63)
56 }
57
58 return len
59}
60
61module.exports = {
62 byteLength,
63 toString,
64 write
65}
node_modules/b4a/lib/hex.js +51 -0
……@@ -0,0 +1,51 @@
1function byteLength(string) {
2 return string.length >>> 1
3}
4
5function toString(buffer) {
6 const len = buffer.byteLength
7
8 buffer = new DataView(buffer.buffer, buffer.byteOffset, len)
9
10 let result = ''
11 let i = 0
12
13 for (let n = len - (len % 4); i < n; i += 4) {
14 result += buffer.getUint32(i).toString(16).padStart(8, '0')
15 }
16
17 for (; i < len; i++) {
18 result += buffer.getUint8(i).toString(16).padStart(2, '0')
19 }
20
21 return result
22}
23
24function write(buffer, string) {
25 const len = buffer.byteLength
26
27 for (let i = 0; i < len; i++) {
28 const a = hexValue(string.charCodeAt(i * 2))
29 const b = hexValue(string.charCodeAt(i * 2 + 1))
30
31 if (a === undefined || b === undefined) {
32 return buffer.subarray(0, i)
33 }
34
35 buffer[i] = (a << 4) | b
36 }
37
38 return len
39}
40
41module.exports = {
42 byteLength,
43 toString,
44 write
45}
46
47function hexValue(char) {
48 if (char >= 0x30 && char <= 0x39) return char - 0x30
49 if (char >= 0x41 && char <= 0x46) return char - 0x41 + 10
50 if (char >= 0x61 && char <= 0x66) return char - 0x61 + 10
51}
node_modules/b4a/lib/latin1.js +31 -0
……@@ -0,0 +1,31 @@
1function byteLength(string) {
2 return string.length
3}
4
5function toString(buffer) {
6 const len = buffer.byteLength
7
8 let result = ''
9
10 for (let i = 0; i < len; i++) {
11 result += String.fromCharCode(buffer[i])
12 }
13
14 return result
15}
16
17function write(buffer, string) {
18 const len = buffer.byteLength
19
20 for (let i = 0; i < len; i++) {
21 buffer[i] = string.charCodeAt(i)
22 }
23
24 return len
25}
26
27module.exports = {
28 byteLength,
29 toString,
30 write
31}
node_modules/b4a/lib/utf16le.js +40 -0
……@@ -0,0 +1,40 @@
1function byteLength(string) {
2 return string.length * 2
3}
4
5function toString(buffer) {
6 const len = buffer.byteLength
7
8 let result = ''
9
10 for (let i = 0; i < len - 1; i += 2) {
11 result += String.fromCharCode(buffer[i] + buffer[i + 1] * 256)
12 }
13
14 return result
15}
16
17function write(buffer, string) {
18 const len = buffer.byteLength
19
20 let units = len
21
22 for (let i = 0; i < string.length; ++i) {
23 if ((units -= 2) < 0) break
24
25 const c = string.charCodeAt(i)
26 const hi = c >> 8
27 const lo = c % 256
28
29 buffer[i * 2] = lo
30 buffer[i * 2 + 1] = hi
31 }
32
33 return len
34}
35
36module.exports = {
37 byteLength,
38 toString,
39 write
40}
node_modules/b4a/lib/utf8.js +141 -0
……@@ -0,0 +1,141 @@
1function byteLength(string) {
2 let length = 0
3
4 for (let i = 0, n = string.length; i < n; i++) {
5 const code = string.charCodeAt(i)
6
7 if (code >= 0xd800 && code <= 0xdbff && i + 1 < n) {
8 const code = string.charCodeAt(i + 1)
9
10 if (code >= 0xdc00 && code <= 0xdfff) {
11 length += 4
12 i++
13 continue
14 }
15 }
16
17 if (code <= 0x7f) length += 1
18 else if (code <= 0x7ff) length += 2
19 else length += 3
20 }
21
22 return length
23}
24
25let toString
26
27if (typeof TextDecoder !== 'undefined') {
28 const decoder = new TextDecoder()
29
30 toString = function toString(buffer) {
31 return decoder.decode(buffer)
32 }
33} else {
34 toString = function toString(buffer) {
35 const len = buffer.byteLength
36
37 let output = ''
38 let i = 0
39
40 while (i < len) {
41 let byte = buffer[i]
42
43 if (byte <= 0x7f) {
44 output += String.fromCharCode(byte)
45 i++
46 continue
47 }
48
49 let bytesNeeded = 0
50 let codePoint = 0
51
52 if (byte <= 0xdf) {
53 bytesNeeded = 1
54 codePoint = byte & 0x1f
55 } else if (byte <= 0xef) {
56 bytesNeeded = 2
57 codePoint = byte & 0x0f
58 } else if (byte <= 0xf4) {
59 bytesNeeded = 3
60 codePoint = byte & 0x07
61 }
62
63 if (len - i - bytesNeeded > 0) {
64 let k = 0
65
66 while (k < bytesNeeded) {
67 byte = buffer[i + k + 1]
68 codePoint = (codePoint << 6) | (byte & 0x3f)
69 k += 1
70 }
71 } else {
72 codePoint = 0xfffd
73 bytesNeeded = len - i
74 }
75
76 output += String.fromCodePoint(codePoint)
77 i += bytesNeeded + 1
78 }
79
80 return output
81 }
82}
83
84let write
85
86if (typeof TextEncoder !== 'undefined') {
87 const encoder = new TextEncoder()
88
89 write = function write(buffer, string) {
90 return encoder.encodeInto(string, buffer).written
91 }
92} else {
93 write = function write(buffer, string) {
94 const len = buffer.byteLength
95
96 let i = 0
97 let j = 0
98
99 while (i < string.length) {
100 const code = string.codePointAt(i)
101
102 if (code <= 0x7f) {
103 buffer[j++] = code
104 i++
105 continue
106 }
107
108 let count = 0
109 let bits = 0
110
111 if (code <= 0x7ff) {
112 count = 6
113 bits = 0xc0
114 } else if (code <= 0xffff) {
115 count = 12
116 bits = 0xe0
117 } else if (code <= 0x1fffff) {
118 count = 18
119 bits = 0xf0
120 }
121
122 buffer[j++] = bits | (code >> count)
123 count -= 6
124
125 while (count >= 0) {
126 buffer[j++] = 0x80 | ((code >> count) & 0x3f)
127 count -= 6
128 }
129
130 i += code >= 0x10000 ? 2 : 1
131 }
132
133 return len
134 }
135}
136
137module.exports = {
138 byteLength,
139 toString,
140 write
141}
node_modules/b4a/package.json +49 -0
……@@ -0,0 +1,49 @@
1{
2 "name": "b4a",
3 "version": "1.8.0",
4 "description": "Bridging the gap between buffers and typed arrays",
5 "exports": {
6 "./package": "./package.json",
7 ".": {
8 "react-native": "./react-native.js",
9 "browser": "./browser.js",
10 "default": "./index.js"
11 }
12 },
13 "files": [
14 "browser.js",
15 "index.js",
16 "react-native.js",
17 "lib"
18 ],
19 "scripts": {
20 "test": "npm run lint && npm run test:bare && npm run test:node",
21 "test:bare": "bare test.mjs",
22 "test:node": "node test.mjs",
23 "lint": "prettier . --check"
24 },
25 "repository": {
26 "type": "git",
27 "url": "git+https://github.com/holepunchto/b4a.git"
28 },
29 "author": "Holepunch",
30 "license": "Apache-2.0",
31 "bugs": {
32 "url": "https://github.com/holepunchto/b4a/issues"
33 },
34 "homepage": "https://github.com/holepunchto/b4a#readme",
35 "devDependencies": {
36 "brittle": "^3.5.2",
37 "nanobench": "^3.0.0",
38 "prettier": "^3.6.2",
39 "prettier-config-holepunch": "^1.0.0"
40 },
41 "peerDependencies": {
42 "react-native-b4a": "*"
43 },
44 "peerDependenciesMeta": {
45 "react-native-b4a": {
46 "optional": true
47 }
48 }
49}
node_modules/b4a/react-native.js +5 -0
……@@ -0,0 +1,5 @@
1try {
2 module.exports = require('react-native-b4a')
3} catch {
4 module.exports = require('./browser')
5}
node_modules/bare-addon-resolve/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-addon-resolve/README.md +156 -0
……@@ -0,0 +1,156 @@
1# bare-addon-resolve
2
3Low-level addon resolution algorithm for Bare. The algorithm is implemented as a generator function that yields either package manifests to be read or resolution candidates to be tested by the caller. As a convenience, the main export is a synchronous and asynchronous iterable that relies on package manifests being read by a callback. For asynchronous iteration, the callback may return promises which will be awaited before being passed to the generator.
4
5```
6npm i bare-addon-resolve
7```
8
9## Usage
10
11For synchronous resolution:
12
13```js
14const resolve = require('bare-addon-resolve')
15
16function readPackage(url) {
17 // Read and parse `url` if it exists, otherwise `null`
18}
19
20for (const resolution of resolve('./addon', new URL('file:///directory/'), readPackage)) {
21 console.log(resolution)
22}
23```
24
25For asynchronous resolution:
26
27```js
28const resolve = require('bare-addon-resolve')
29
30async function readPackage(url) {
31 // Read and parse `url` if it exists, otherwise `null`
32}
33
34for await (const resolution of resolve('./addon', new URL('file:///directory/'), readPackage)) {
35 console.log(resolution)
36}
37```
38
39## API
40
41#### `const resolver = resolve(specifier, parentURL[, options][, readPackage])`
42
43Resolve `specifier` relative to `parentURL`, which must be a WHATWG `URL` instance. `readPackage` is called with a `URL` instance for every package manifest to be read and must either return the parsed JSON package manifest, if it exists, or `null`. If `readPackage` returns a promise, synchronous iteration is not supported.
44
45Options include:
46
47```js
48options = {
49 // A list of builtin addon specifiers. If matched, the protocol of the
50 // resolved URL will be `builtinProtocol`.
51 builtins: [],
52 // The protocol to use for resolved builtin addon specifiers.
53 builtinProtocol: 'builtin:',
54 // Whether or not addons linked ahead-of-time should be resolved.
55 linked: true,
56 // The protocol to use for addons linked ahead-of-time.
57 linkedProtocol: 'linked:',
58 // The supported import conditions. "default" is always recognized.
59 conditions: [],
60 // An array reference which will contain the matched conditions when yielding
61 // resolutions.
62 matchedConditions: [],
63 // The `<platform>-<arch>` combinations to look for when resolving dynamic
64 // addons. If empty, only builtin specifiers can be resolved. In Bare,
65 // pass `[Bare.Addon.host]`.
66 hosts: [],
67 // The file extensions to look for when resolving dynamic addons.
68 extensions: [],
69 // A map of preresolved imports with keys being serialized directory URLs and
70 // values being "imports" maps.
71 resolutions
72}
73```
74
75#### `for (const resolution of resolver)`
76
77Synchronously iterate the addon resolution candidates. The resolved addon is the first candidate that exists as a file on the file system.
78
79#### `for await (const resolution of resolver)`
80
81Asynchronously iterate the addon resolution candidates. If `readPackage` returns promises, these will be awaited. The same comments as `for (const resolution of resolver)` apply.
82
83### Algorithm
84
85The following generator functions implement the resolution algorithm. The yielded values have the following shape:
86
87**Package manifest**
88
89```js
90next.value = {
91 package: URL
92}
93```
94
95If the package manifest identified by `next.value.package` exists, `generator.next()` must be passed the parsed JSON value of the manifest. If it does not exist, pass `null` instead.
96
97**Resolution candidate**
98
99```js
100next.value = {
101 resolution: URL
102}
103```
104
105If the addon identified by `next.value.resolution` exists, `generator.next()` may be passed `true` to signal that the resolution for the current set of conditions has been identified. If it does not exist, pass `false` instead.
106
107To drive the generator functions, a loop like the following can be used:
108
109```js
110const generator = resolve.addon(specifier, parentURL)
111
112let next = generator.next()
113
114while (next.done !== true) {
115 const value = next.value
116
117 if (value.package) {
118 // Read and parse `value.package` if it exists, otherwise `null`
119 let info
120
121 next = generator.next(info)
122 } else {
123 const resolution = value.resolution
124
125 // `true` if `resolution` was the correct candidate, otherwise `false`
126 let resolved
127
128 next = generator.next(resolved)
129 }
130}
131```
132
133Options are the same as `resolve()` for all functions.
134
135> [!WARNING]
136> These functions are currently subject to change between minor releases. If using them directly, make sure to specify a tilde range (`~1.2.3`) when declaring the module dependency.
137
138#### `const generator = resolve.addon(specifier, parentURL[, options])`
139
140#### `const generator = resolve.url(url, parentURL[, options])`
141
142#### `const generator = resolve.package(packageSpecifier, packageVersion, parentURL[, options])`
143
144#### `const generator = resolve.packageSelf(packageName, packageSubpath, packageVersion, parentURL[, options])`
145
146#### `const generator = resolve.preresolved(directoryURL, resolutions[, options])`
147
148#### `const generator = resolve.file(filename, parentURL[, options])`
149
150#### `const generator = resolve.directory(dirname, version, parentURL[, options])`
151
152#### `const generator = resolve.linked(name, version[, options])`
153
154## License
155
156Apache-2.0
node_modules/bare-addon-resolve/index.d.ts +85 -0
……@@ -0,0 +1,85 @@
1import URL from 'bare-url'
2import { constants, type Builtins, type Conditions, type ResolutionsMap } from 'bare-module-resolve'
3
4type JSON = string | number | boolean | JSON[] | { [key: string]: JSON }
5
6interface ResolveOptions {
7 builtinProtocol?: string
8 builtins?: Builtins
9 conditions?: Conditions
10 extensions?: string[]
11 host?: string
12 hosts?: string[]
13 linked?: boolean
14 linkedProtocol?: string
15 matchedConditions?: string[]
16 resolutions?: ResolutionsMap
17}
18
19declare function resolve(
20 specifier: string,
21 parentURL: URL,
22 readPackage?: (url: URL) => JSON | null
23): Iterable<URL>
24
25declare function resolve(
26 specifier: string,
27 parentURL: URL,
28 readPackage: (url: URL) => Promise<JSON | null>
29): AsyncIterable<URL>
30
31declare function resolve(
32 specifier: string,
33 parentURL: URL,
34 opts: ResolveOptions,
35 readPackage?: (url: URL) => JSON | null
36): Iterable<URL>
37
38declare function resolve(
39 specifier: string,
40 parentURL: URL,
41 opts: ResolveOptions,
42 readPackage: (url: URL) => Promise<JSON | null>
43): AsyncIterable<URL>
44
45declare namespace resolve {
46 export { constants, type ResolveOptions }
47
48 export type Resolver = Generator<
49 { resolution: URL } | { package: URL },
50 number,
51 void | boolean | JSON | null
52 >
53
54 export function addon(specifier: string, parentURL: URL, opts?: ResolveOptions): Resolver
55
56 export function url(specifier: string, parentURL: URL, opts?: ResolveOptions): Resolver
57
58 export function package(
59 packageSpecifier: string,
60 packageVersion: string,
61 parentURL: URL,
62 opts?: ResolveOptions
63 ): Resolver
64
65 export function packageSelf(
66 packageName: string,
67 packageSubpath: string,
68 packageVersion: string,
69 parentURL: URL,
70 opts?: ResolveOptions
71 ): Resolver
72
73 export function file(filename: string, parentURL: URL, opts?: ResolveOptions): Resolver
74
75 export function directory(
76 dirname: string,
77 version: string,
78 parentURL: URL,
79 opts?: ResolveOptions
80 ): Resolver
81
82 export function linked(name: string, version?: string, opts?: ResolveOptions): Resolver
83}
84
85export = resolve
node_modules/bare-addon-resolve/index.js +471 -0
……@@ -0,0 +1,471 @@
1const resolve = require('bare-module-resolve')
2const { Version } = require('bare-semver')
3const errors = require('./lib/errors')
4
5module.exports = exports = function resolve(specifier, parentURL, opts, readPackage) {
6 if (typeof opts === 'function') {
7 readPackage = opts
8 opts = {}
9 } else if (typeof readPackage !== 'function') {
10 readPackage = defaultReadPackage
11 }
12
13 return {
14 *[Symbol.iterator]() {
15 const generator = exports.addon(specifier, parentURL, opts)
16
17 let next = generator.next()
18
19 while (next.done !== true) {
20 const value = next.value
21
22 if (value.package) {
23 next = generator.next(readPackage(value.package))
24 } else {
25 next = generator.next(yield value.resolution)
26 }
27 }
28
29 return next.value
30 },
31
32 async *[Symbol.asyncIterator]() {
33 const generator = exports.addon(specifier, parentURL, opts)
34
35 let next = generator.next()
36
37 while (next.done !== true) {
38 const value = next.value
39
40 if (value.package) {
41 next = generator.next(await readPackage(value.package))
42 } else {
43 next = generator.next(yield value.resolution)
44 }
45 }
46
47 return next.value
48 }
49 }
50}
51
52function defaultReadPackage() {
53 return null
54}
55
56const { UNRESOLVED, YIELDED, RESOLVED } = resolve.constants
57
58exports.constants = {
59 UNRESOLVED,
60 YIELDED,
61 RESOLVED
62}
63
64exports.addon = function* (specifier, parentURL, opts = {}) {
65 const { resolutions = null } = opts
66
67 if (exports.startsWithWindowsDriveLetter(specifier)) {
68 specifier = '/' + specifier
69 }
70
71 let status
72
73 if (resolutions) {
74 status = yield* resolve.preresolved(specifier, resolutions, parentURL, opts)
75
76 if (status) return status
77 }
78
79 status = yield* exports.url(specifier, parentURL, opts)
80
81 if (status) return status
82
83 let version = null
84
85 const i = specifier.lastIndexOf('@')
86
87 if (i > 0) {
88 version = specifier.substring(i + 1)
89
90 try {
91 Version.parse(version)
92
93 specifier = specifier.substring(0, i)
94 } catch {
95 version = null
96 }
97 }
98
99 if (
100 specifier === '.' ||
101 specifier === '..' ||
102 specifier[0] === '/' ||
103 specifier[0] === '\\' ||
104 specifier.startsWith('./') ||
105 specifier.startsWith('.\\') ||
106 specifier.startsWith('../') ||
107 specifier.startsWith('..\\')
108 ) {
109 status = yield* exports.file(specifier, parentURL, opts)
110
111 if (status === RESOLVED) return status
112
113 return yield* exports.directory(specifier, version, parentURL, opts)
114 }
115
116 return yield* exports.package(specifier, version, parentURL, opts)
117}
118
119exports.url = function* (url, parentURL, opts = {}) {
120 let resolution
121 try {
122 resolution = new URL(url)
123 } catch {
124 return UNRESOLVED
125 }
126
127 const resolved = yield { resolution }
128
129 return resolved ? RESOLVED : YIELDED
130}
131
132exports.package = function* (packageSpecifier, packageVersion, parentURL, opts = {}) {
133 if (packageSpecifier === '') {
134 throw errors.INVALID_ADDON_SPECIFIER(
135 `Addon specifier '${packageSpecifier}' is not a valid package name`
136 )
137 }
138
139 let packageName
140
141 if (packageSpecifier[0] !== '@') {
142 packageName = packageSpecifier.split('/', 1).join()
143 } else {
144 if (!packageSpecifier.includes('/')) {
145 throw errors.INVALID_ADDON_SPECIFIER(
146 `Addon specifier '${packageSpecifier}' is not a valid package name`
147 )
148 }
149
150 packageName = packageSpecifier.split('/', 2).join('/')
151 }
152
153 if (packageName[0] === '.' || packageName.includes('\\') || packageName.includes('%')) {
154 throw errors.INVALID_ADDON_SPECIFIER(
155 `Addon specifier '${packageSpecifier}' is not a valid package name`
156 )
157 }
158
159 const packageSubpath = '.' + packageSpecifier.substring(packageName.length)
160
161 const status = yield* exports.packageSelf(
162 packageName,
163 packageSubpath,
164 packageVersion,
165 parentURL,
166 opts
167 )
168
169 if (status) return status
170
171 parentURL = new URL(parentURL.href)
172
173 do {
174 const packageURL = new URL('node_modules/' + packageName + '/', parentURL)
175
176 parentURL.pathname = parentURL.pathname.substring(0, parentURL.pathname.lastIndexOf('/'))
177
178 const info = yield { package: new URL('package.json', packageURL) }
179
180 if (info) {
181 return yield* exports.directory(packageSubpath, packageVersion, packageURL, opts)
182 }
183 } while (parentURL.pathname !== '' && parentURL.pathname !== '/')
184
185 return UNRESOLVED
186}
187
188exports.packageSelf = function* (
189 packageName,
190 packageSubpath,
191 packageVersion,
192 parentURL,
193 opts = {}
194) {
195 for (const packageURL of resolve.lookupPackageScope(parentURL, opts)) {
196 const info = yield { package: packageURL }
197
198 if (info) {
199 if (info.name === packageName) {
200 return yield* exports.directory(packageSubpath, packageVersion, packageURL, opts)
201 }
202
203 break
204 }
205 }
206
207 return UNRESOLVED
208}
209
210exports.lookupPrebuildsScope = function* lookupPrebuildsScope(url, opts = {}) {
211 const scopeURL = new URL(url.href)
212
213 do {
214 yield new URL('prebuilds/', scopeURL)
215
216 scopeURL.pathname = scopeURL.pathname.substring(0, scopeURL.pathname.lastIndexOf('/'))
217
218 if (
219 scopeURL.pathname.length === 3 &&
220 exports.isWindowsDriveLetter(scopeURL.pathname.substring(1))
221 ) {
222 break
223 }
224 } while (scopeURL.pathname !== '' && scopeURL.pathname !== '/')
225}
226
227exports.file = function* (filename, parentURL, opts = {}) {
228 if (
229 filename === '.' ||
230 filename === '..' ||
231 filename[filename.length - 1] === '/' ||
232 filename[filename.length - 1] === '\\'
233 ) {
234 return UNRESOLVED
235 }
236
237 if (parentURL.protocol === 'file:' && /%2f|%5c/i.test(filename)) {
238 throw errors.INVALID_ADDON_SPECIFIER(`Addon specifier '${filename}' is invalid`)
239 }
240
241 const { extensions = [] } = opts
242
243 let status = UNRESOLVED
244
245 for (let ext of extensions) {
246 if (filename.endsWith(ext)) ext = ''
247
248 if (yield { resolution: new URL(filename + ext, parentURL) }) {
249 return RESOLVED
250 }
251
252 status = YIELDED
253 }
254
255 return status
256}
257
258exports.directory = function* (dirname, version, parentURL, opts = {}) {
259 const {
260 host = null, // Shorthand for single host resolution
261 hosts = host !== null ? [host] : [],
262 builtins = [],
263 matchedConditions = []
264 } = opts
265
266 let directoryURL
267
268 if (dirname[dirname.length - 1] === '/' || dirname[dirname.length - 1] === '\\') {
269 directoryURL = new URL(dirname, parentURL)
270 } else {
271 directoryURL = new URL(dirname + '/', parentURL)
272 }
273
274 const unversioned = version === null
275
276 let name = null
277
278 const info = yield { package: new URL('package.json', directoryURL) }
279
280 if (info) {
281 if (typeof info.name === 'string' && info.name !== '') {
282 if (info.name.includes('__')) {
283 throw errors.INVALID_PACKAGE_NAME(`Package name '${info.name}' is invalid`)
284 }
285
286 name = info.name.replace(/\//g, '__').replace(/^@/, '')
287 } else {
288 return UNRESOLVED
289 }
290
291 if (typeof info.version === 'string' && info.version !== '') {
292 if (version !== null && info.version !== version) return UNRESOLVED
293
294 version = info.version
295 }
296 } else {
297 return UNRESOLVED
298 }
299
300 let status
301
302 status = yield* resolve.builtinTarget(name, version, builtins, opts)
303
304 if (status) return status
305
306 for (const prebuildsURL of exports.lookupPrebuildsScope(directoryURL, opts)) {
307 status = UNRESOLVED
308
309 for (const host of hosts) {
310 const conditions = host.split('-')
311
312 const universal = supportsUniversalPrebuilds(host)
313 ? conditions.with(1, 'universal').join('-')
314 : null
315
316 matchedConditions.push(...conditions)
317
318 if (version !== null) {
319 status |= yield* exports.file(host + '/' + name + '@' + version, prebuildsURL, opts)
320
321 if (universal) {
322 status |= yield* exports.file(universal + '/' + name + '@' + version, prebuildsURL, opts)
323 }
324 }
325
326 if (unversioned) {
327 status |= yield* exports.file(host + '/' + name, prebuildsURL, opts)
328
329 if (universal) {
330 status |= yield* exports.file(universal + '/' + name, prebuildsURL, opts)
331 }
332 }
333
334 for (const _ of conditions) matchedConditions.pop()
335 }
336
337 if (status === RESOLVED) return status
338 }
339
340 return yield* exports.linked(name, version, opts)
341}
342
343exports.linked = function* (name, version = null, opts = {}) {
344 const {
345 linked = true,
346 host = null, // Shorthand for single host resolution
347 hosts = host !== null ? [host] : [],
348 matchedConditions = []
349 } = opts
350
351 if (linked === false || hosts.length === 0) return UNRESOLVED
352
353 let status = UNRESOLVED
354
355 for (const host of hosts) {
356 const [platform = null] = host.split('-', 1)
357
358 if (platform === null) continue
359
360 matchedConditions.push(platform)
361
362 status |= yield* platformArtefact(name, version, platform, opts)
363
364 matchedConditions.pop()
365 }
366
367 return status
368}
369
370function* platformArtefact(name, version = null, platform, opts = {}) {
371 const { linkedProtocol = 'linked:' } = opts
372
373 if (platform === 'darwin' || platform === 'ios') {
374 if (version !== null) {
375 if (
376 yield {
377 resolution: new URL(`${linkedProtocol}${name}.${version}.framework/${name}.${version}`)
378 }
379 ) {
380 return RESOLVED
381 }
382
383 if (platform === 'darwin') {
384 if (
385 yield {
386 resolution: new URL(`${linkedProtocol}lib${name}.${version}.dylib`)
387 }
388 ) {
389 return RESOLVED
390 }
391 }
392 }
393
394 if (
395 yield {
396 resolution: new URL(`${linkedProtocol}${name}.framework/${name}`)
397 }
398 ) {
399 return RESOLVED
400 }
401
402 if (platform === 'darwin') {
403 if (
404 yield {
405 resolution: new URL(`${linkedProtocol}lib${name}.dylib`)
406 }
407 ) {
408 return RESOLVED
409 }
410 }
411
412 return YIELDED
413 }
414
415 if (platform === 'linux' || platform === 'android') {
416 if (version !== null) {
417 if (
418 yield {
419 resolution: new URL(`${linkedProtocol}lib${name}.${version}.so`)
420 }
421 ) {
422 return RESOLVED
423 }
424 }
425
426 if (
427 yield {
428 resolution: new URL(`${linkedProtocol}lib${name}.so`)
429 }
430 ) {
431 return RESOLVED
432 }
433
434 return YIELDED
435 }
436
437 if (platform === 'win32') {
438 if (version !== null) {
439 if (
440 yield {
441 resolution: new URL(`${linkedProtocol}${name}-${version}.dll`)
442 }
443 ) {
444 return RESOLVED
445 }
446 }
447
448 if (
449 yield {
450 resolution: new URL(`${linkedProtocol}${name}.dll`)
451 }
452 ) {
453 return RESOLVED
454 }
455 }
456
457 return UNRESOLVED
458}
459
460exports.isWindowsDriveLetter = resolve.isWindowsDriveLetter
461
462exports.startsWithWindowsDriveLetter = resolve.startsWithWindowsDriveLetter
463
464function supportsUniversalPrebuilds(host) {
465 return (
466 host === 'darwin-arm64' ||
467 host === 'darwin-x64' ||
468 host === 'ios-arm64-simulator' ||
469 host === 'ios-x64-simulator'
470 )
471}
node_modules/bare-addon-resolve/lib/errors.d.ts +8 -0
……@@ -0,0 +1,8 @@
1declare class AddonResolveError extends Error {
2 readonly code: string
3
4 static INVALID_ADDON_SPECIFIER(msg: string): AddonResolveError
5 static INVALID_PACKAGE_NAME(msg: string): AddonResolveError
6}
7
8export = AddonResolveError
node_modules/bare-addon-resolve/lib/errors.js +30 -0
……@@ -0,0 +1,30 @@
1module.exports = class AddonResolveError extends Error {
2 constructor(msg, code, fn = AddonResolveError) {
3 super(`${code}: ${msg}`)
4 this.code = code
5
6 if (Error.captureStackTrace) {
7 Error.captureStackTrace(this, fn)
8 }
9 }
10
11 get name() {
12 return 'AddonResolveError'
13 }
14
15 static INVALID_ADDON_SPECIFIER(msg) {
16 return new AddonResolveError(
17 msg,
18 'INVALID_ADDON_SPECIFIER',
19 AddonResolveError.INVALID_ADDON_SPECIFIER
20 )
21 }
22
23 static INVALID_PACKAGE_NAME(msg) {
24 return new AddonResolveError(
25 msg,
26 'INVALID_PACKAGE_NAME',
27 AddonResolveError.INVALID_PACKAGE_NAME
28 )
29 }
30}
node_modules/bare-addon-resolve/package.json +52 -0
……@@ -0,0 +1,52 @@
1{
2 "name": "bare-addon-resolve",
3 "version": "1.10.0",
4 "description": "Low-level addon resolution algorithm for Bare",
5 "exports": {
6 "./package": "./package.json",
7 ".": {
8 "types": "./index.d.ts",
9 "default": "./index.js"
10 },
11 "./errors": {
12 "types": "./lib/errors.d.ts",
13 "default": "./lib/errors.js"
14 }
15 },
16 "files": [
17 "index.js",
18 "index.d.ts",
19 "lib"
20 ],
21 "scripts": {
22 "test": "prettier . --check && bare test.js"
23 },
24 "repository": {
25 "type": "git",
26 "url": "git+https://github.com/holepunchto/bare-addon-resolve.git"
27 },
28 "author": "Holepunch",
29 "license": "Apache-2.0",
30 "bugs": {
31 "url": "https://github.com/holepunchto/bare-addon-resolve/issues"
32 },
33 "homepage": "https://github.com/holepunchto/bare-addon-resolve#readme",
34 "dependencies": {
35 "bare-module-resolve": "^1.10.0",
36 "bare-semver": "^1.0.0"
37 },
38 "devDependencies": {
39 "bare-url": "^2.1.3",
40 "brittle": "^3.2.1",
41 "prettier": "^3.3.3",
42 "prettier-config-holepunch": "^2.0.0"
43 },
44 "peerDependencies": {
45 "bare-url": "*"
46 },
47 "peerDependenciesMeta": {
48 "bare-url": {
49 "optional": true
50 }
51 }
52}
node_modules/bare-ansi-escapes/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-ansi-escapes/README.md +19 -0
……@@ -0,0 +1,19 @@
1# bare-ansi-escapes
2
3Parse and produce ANSI escape sequences.
4
5```
6npm i bare-ansi-escapes
7```
8
9## Usage
10
11```js
12const KeyDecoder = require('bare-ansi-escapes/key-decoder')
13
14readableStream.pipe(new KeyDecoder()).on('data', (key) => console.log(key))
15```
16
17## License
18
19Apache-2.0
node_modules/bare-ansi-escapes/index.d.ts +50 -0
……@@ -0,0 +1,50 @@
1export const constants: { ESC: string; CSI: string; SGR: (n: number) => string }
2
3export const cursorHide: string
4export const cursorShow: string
5
6export function cursorUp(n?: number): string
7export function cursorDown(n?: number): string
8export function cursorForward(n?: number): string
9export function cursorBack(n?: number): string
10export function cursorNextLine(n?: number): string
11export function cursorPreviousLine(n?: number): string
12
13export function cursorPosition(column: number, row?: number): string
14
15export const eraseDisplayEnd: string
16export const eraseDisplayStart: string
17export const eraseDisplay: string
18export const eraseLineEnd: string
19export const eraseLineStart: string
20export const eraseLine: string
21
22export function scrollUp(n?: number): string
23export function scrollDown(n?: number): string
24
25export const modifierReset: string
26export const modifierBold: string
27export const modifierDim: string
28export const modifierItalic: string
29export const modifierUnderline: string
30export const modifierNormal: string
31export const modifierNotItalic: string
32export const modifierNotUnderline: string
33
34export const colorBlack: string
35export const colorRed: string
36export const colorGreen: string
37export const colorYellow: string
38export const colorBlue: string
39export const colorMagenta: string
40export const colorCyan: string
41export const colorWhite: string
42export const colorDefault: string
43export const colorBrightBlack: string
44export const colorBrightRed: string
45export const colorBrightGreen: string
46export const colorBrightYellow: string
47export const colorBrightBlue: string
48export const colorBrightMagenta: string
49export const colorBrightCyan: string
50export const colorBrightWhite: string
node_modules/bare-ansi-escapes/index.js +90 -0
……@@ -0,0 +1,90 @@
1const ESC = '\x1b'
2const CSI = ESC + '['
3const SGR = (n) => CSI + n + 'm'
4
5exports.constants = {
6 ESC,
7 CSI,
8 SGR
9}
10
11// https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_(Control_Sequence_Introducer)_sequences
12
13exports.cursorHide = CSI + '?25l'
14exports.cursorShow = CSI + '?25h'
15
16exports.cursorUp = function cursorUp(n = 1) {
17 return CSI + n + 'A'
18}
19
20exports.cursorDown = function cursorDown(n = 1) {
21 return CSI + n + 'B'
22}
23
24exports.cursorForward = function cursorForward(n = 1) {
25 return CSI + n + 'C'
26}
27
28exports.cursorBack = function cursorBack(n = 1) {
29 return CSI + n + 'D'
30}
31
32exports.cursorNextLine = function cursorNextLine(n = 1) {
33 return CSI + n + 'E'
34}
35
36exports.cursorPreviousLine = function cursorPreviousLine(n = 1) {
37 return CSI + n + 'F'
38}
39
40exports.cursorPosition = function cursorPosition(column, row = 0) {
41 if (row === 0) return CSI + (column + 1) + 'G'
42
43 return CSI + (row + 1) + ';' + (column + 1) + 'H'
44}
45
46exports.eraseDisplayEnd = CSI + 'J'
47exports.eraseDisplayStart = CSI + '1J'
48exports.eraseDisplay = CSI + '2J'
49exports.eraseLineEnd = CSI + 'K'
50exports.eraseLineStart = CSI + '1K'
51exports.eraseLine = CSI + '2K'
52
53exports.scrollUp = function scrollUp(n = 1) {
54 return CSI + n + 'S'
55}
56
57exports.scrollDown = function scrollDown(n = 1) {
58 return CSI + n + 'T'
59}
60
61// https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
62
63exports.modifierReset = SGR(0)
64exports.modifierBold = SGR(1)
65exports.modifierDim = SGR(2)
66exports.modifierItalic = SGR(3)
67exports.modifierUnderline = SGR(4)
68exports.modifierNormal = SGR(22)
69exports.modifierNotItalic = SGR(23)
70exports.modifierNotUnderline = SGR(24)
71
72// https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
73
74exports.colorBlack = SGR(30)
75exports.colorRed = SGR(31)
76exports.colorGreen = SGR(32)
77exports.colorYellow = SGR(33)
78exports.colorBlue = SGR(34)
79exports.colorMagenta = SGR(35)
80exports.colorCyan = SGR(36)
81exports.colorWhite = SGR(37)
82exports.colorDefault = SGR(39)
83exports.colorBrightBlack = SGR(90)
84exports.colorBrightRed = SGR(91)
85exports.colorBrightGreen = SGR(92)
86exports.colorBrightYellow = SGR(93)
87exports.colorBrightBlue = SGR(94)
88exports.colorBrightMagenta = SGR(95)
89exports.colorBrightCyan = SGR(96)
90exports.colorBrightWhite = SGR(97)
node_modules/bare-ansi-escapes/key-decoder.d.ts +44 -0
……@@ -0,0 +1,44 @@
1import { Transform, TransformEvents } from 'bare-stream'
2import { BufferEncoding } from 'bare-buffer'
3
4interface KeyDecoderOptions {
5 encoding?: BufferEncoding
6 escapeCodeTimeout?: number
7}
8
9interface KeyDecoderEvents extends TransformEvents {
10 data: [key: Key]
11}
12
13interface KeyDecoder<M extends KeyDecoderEvents = KeyDecoderEvents>
14 extends Transform<M> {
15 readonly encoding: BufferEncoding
16}
17
18declare class KeyDecoder {
19 constructor(opts?: KeyDecoderOptions)
20}
21
22interface Key {
23 readonly name: string
24 readonly sequence: string
25 readonly ctrl: boolean
26 readonly meta: boolean
27 readonly shift: boolean
28}
29
30declare class Key {
31 constructor(
32 name: string | number,
33 sequence: string,
34 ctrl: boolean,
35 meta: boolean,
36 shift: boolean
37 )
38}
39
40declare namespace KeyDecoder {
41 export type { KeyDecoderOptions, KeyDecoderEvents, Key }
42}
43
44export = KeyDecoder
node_modules/bare-ansi-escapes/key-decoder.js +480 -0
……@@ -0,0 +1,480 @@
1const { Transform } = require('bare-stream')
2
3const {
4 constants: { ESC }
5} = require('.')
6
7// https://en.wikipedia.org/wiki/ANSI_escape_code#Terminal_input_sequences
8
9module.exports = class KeyDecoder extends Transform {
10 constructor(opts = {}) {
11 const { encoding = 'utf8', escapeCodeTimeout = 500 } = opts
12
13 super()
14
15 this.encoding = encoding
16
17 this._escapeDelay = escapeCodeTimeout
18 this._escapeTimer = null
19
20 this._parser = parseKeys(this)
21 this._parser.next()
22 }
23
24 _transform(data, encoding, cb) {
25 clearTimeout(this._escapeTimer)
26
27 if (data[0] > 127 && data.length === 1) {
28 data[0] -= 128
29 data = ESC + data.toString(this.encoding)
30 } else {
31 data = data.toString(this.encoding)
32 }
33
34 let n = 0
35
36 for (const c of data) {
37 n += c.length
38
39 this._parser.next(c)
40
41 if (n === data.length && c === ESC) {
42 this._escapeTimer = setTimeout(
43 this._escape.bind(this),
44 this._escapeDelay
45 )
46 }
47 }
48
49 cb(null)
50 }
51
52 _escape() {
53 this._parser.next('')
54 }
55}
56
57class Key {
58 constructor(name, sequence, ctrl, meta, shift) {
59 this.name = typeof name === 'number' ? String.fromCharCode(name) : name
60 this.sequence = sequence
61 this.ctrl = ctrl
62 this.meta = meta
63 this.shift = shift
64 }
65}
66
67function charLengthAt(str, i) {
68 if (str.length <= i) {
69 return 1
70 }
71
72 return str.codePointAt(i) >= 0x10000 ? 2 : 1
73}
74
75function* parseKeys(stream) {
76 while (true) {
77 let c = yield
78 let s = c
79 let escaped = false
80
81 let name = null
82 let ctrl = false
83 let meta = false
84 let shift = false
85
86 if (c === ESC) {
87 escaped = true
88
89 s += c = yield
90
91 if (c === ESC) {
92 s += c = yield
93 }
94 }
95
96 if (escaped && (c === 'O' || c === '[')) {
97 let code = c
98 let modifier = 0
99
100 if (c === 'O') {
101 s += c = yield
102
103 if (c >= '0' && c <= '9') {
104 modifier = (c >> 0) - 1
105 s += c = yield
106 }
107
108 code += c
109 } else if (c === '[') {
110 s += c = yield
111
112 if (c === '[') {
113 code += c
114 s += c = yield
115 }
116
117 const start = s.length - 1
118
119 if (c >= '0' && c <= '9') {
120 s += c = yield
121
122 if (c >= '0' && c <= '9') {
123 s += c = yield
124
125 if (c >= '0' && c <= '9') {
126 s += c = yield
127 }
128 }
129 }
130
131 if (c === ';') {
132 s += c = yield
133
134 if (c >= '0' && c <= '9') {
135 s += yield
136 }
137 }
138
139 const cmd = s.slice(start)
140
141 let match
142
143 if ((match = /^(?:(\d\d?)(?:;(\d))?([~^$])|(\d{3}~))$/.exec(cmd))) {
144 if (match[4]) {
145 code += match[4]
146 } else {
147 code += match[1] + match[3]
148 modifier = (match[2] || 1) - 1
149 }
150 } else if ((match = /^((\d;)?(\d))?([A-Za-z])$/.exec(cmd))) {
151 code += match[4]
152 modifier = (match[3] || 1) - 1
153 } else {
154 code += cmd
155 }
156 }
157
158 ctrl = !!(modifier & 4)
159 meta = !!(modifier & 10)
160 shift = !!(modifier & 1)
161
162 switch (code) {
163 /* xterm/gnome ESC [ letter (with modifier) */
164 case '[P':
165 name = 'f1'
166 break
167 case '[Q':
168 name = 'f2'
169 break
170 case '[R':
171 name = 'f3'
172 break
173 case '[S':
174 name = 'f4'
175 break
176
177 /* xterm/gnome ESC O letter (without modifier) */
178 case 'OP':
179 name = 'f1'
180 break
181 case 'OQ':
182 name = 'f2'
183 break
184 case 'OR':
185 name = 'f3'
186 break
187 case 'OS':
188 name = 'f4'
189 break
190
191 /* xterm/rxvt ESC [ number ~ */
192 case '[11~':
193 name = 'f1'
194 break
195 case '[12~':
196 name = 'f2'
197 break
198 case '[13~':
199 name = 'f3'
200 break
201 case '[14~':
202 name = 'f4'
203 break
204
205 /* paste bracket mode */
206 case '[200~':
207 name = 'paste-start'
208 break
209 case '[201~':
210 name = 'paste-end'
211 break
212
213 /* from Cygwin and used in libuv */
214 case '[[A':
215 name = 'f1'
216 break
217 case '[[B':
218 name = 'f2'
219 break
220 case '[[C':
221 name = 'f3'
222 break
223 case '[[D':
224 name = 'f4'
225 break
226 case '[[E':
227 name = 'f5'
228 break
229
230 /* common */
231 case '[15~':
232 name = 'f5'
233 break
234 case '[17~':
235 name = 'f6'
236 break
237 case '[18~':
238 name = 'f7'
239 break
240 case '[19~':
241 name = 'f8'
242 break
243 case '[20~':
244 name = 'f9'
245 break
246 case '[21~':
247 name = 'f10'
248 break
249 case '[23~':
250 name = 'f11'
251 break
252 case '[24~':
253 name = 'f12'
254 break
255
256 /* xterm ESC [ letter */
257 case '[A':
258 name = 'up'
259 break
260 case '[B':
261 name = 'down'
262 break
263 case '[C':
264 name = 'right'
265 break
266 case '[D':
267 name = 'left'
268 break
269 case '[E':
270 name = 'clear'
271 break
272 case '[F':
273 name = 'end'
274 break
275 case '[H':
276 name = 'home'
277 break
278
279 /* xterm/gnome ESC O letter */
280 case 'OA':
281 name = 'up'
282 break
283 case 'OB':
284 name = 'down'
285 break
286 case 'OC':
287 name = 'right'
288 break
289 case 'OD':
290 name = 'left'
291 break
292 case 'OE':
293 name = 'clear'
294 break
295 case 'OF':
296 name = 'end'
297 break
298 case 'OH':
299 name = 'home'
300 break
301
302 /* xterm/rxvt ESC [ number ~ */
303 case '[1~':
304 name = 'home'
305 break
306 case '[2~':
307 name = 'insert'
308 break
309 case '[3~':
310 name = 'delete'
311 break
312 case '[4~':
313 name = 'end'
314 break
315 case '[5~':
316 name = 'pageup'
317 break
318 case '[6~':
319 name = 'pagedown'
320 break
321
322 /* putty */
323 case '[[5~':
324 name = 'pageup'
325 break
326 case '[[6~':
327 name = 'pagedown'
328 break
329
330 /* rxvt */
331 case '[7~':
332 name = 'home'
333 break
334 case '[8~':
335 name = 'end'
336 break
337
338 /* rxvt keys with modifiers */
339 case '[a':
340 name = 'up'
341 shift = true
342 break
343 case '[b':
344 name = 'down'
345 shift = true
346 break
347 case '[c':
348 name = 'right'
349 shift = true
350 break
351 case '[d':
352 name = 'left'
353 shift = true
354 break
355 case '[e':
356 name = 'clear'
357 shift = true
358 break
359
360 case '[2$':
361 name = 'insert'
362 shift = true
363 break
364 case '[3$':
365 name = 'delete'
366 shift = true
367 break
368 case '[5$':
369 name = 'pageup'
370 shift = true
371 break
372 case '[6$':
373 name = 'pagedown'
374 shift = true
375 break
376 case '[7$':
377 name = 'home'
378 shift = true
379 break
380 case '[8$':
381 name = 'end'
382 shift = true
383 break
384
385 case 'Oa':
386 name = 'up'
387 ctrl = true
388 break
389 case 'Ob':
390 name = 'down'
391 ctrl = true
392 break
393 case 'Oc':
394 name = 'right'
395 ctrl = true
396 break
397 case 'Od':
398 name = 'left'
399 ctrl = true
400 break
401 case 'Oe':
402 name = 'clear'
403 ctrl = true
404 break
405
406 case '[2^':
407 name = 'insert'
408 ctrl = true
409 break
410 case '[3^':
411 name = 'delete'
412 ctrl = true
413 break
414 case '[5^':
415 name = 'pageup'
416 ctrl = true
417 break
418 case '[6^':
419 name = 'pagedown'
420 ctrl = true
421 break
422 case '[7^':
423 name = 'home'
424 ctrl = true
425 break
426 case '[8^':
427 name = 'end'
428 ctrl = true
429 break
430
431 case '[Z':
432 name = 'tab'
433 shift = true
434 break
435 default:
436 name = 'undefined'
437 break
438 }
439 } else if (c === '\r') {
440 name = 'return'
441 meta = escaped
442 } else if (c === '\n') {
443 name = 'linefeed'
444 meta = escaped
445 } else if (c === '\t') {
446 name = 'tab'
447 meta = escaped
448 } else if (c === '\b' || c === '\x7f') {
449 name = 'backspace'
450 meta = escaped
451 } else if (c === ESC) {
452 name = 'escape'
453 meta = escaped
454 } else if (c === ' ') {
455 name = 'space'
456 meta = escaped
457 } else if (!escaped && c <= '\x1a') {
458 name = String.fromCharCode(c.charCodeAt(0) + 'a'.charCodeAt(0) - 1)
459 ctrl = true
460 } else if (/^[0-9A-Za-z]$/.exec(c) !== null) {
461 name = c.toLowerCase()
462 shift = /^[A-Z]$/.exec(c) !== null
463 meta = escaped
464 } else if (escaped) {
465 name = c.length ? null : 'escape'
466 meta = true
467 }
468
469 const sequence = s
470
471 if (
472 s.length > 0 &&
473 (name !== null || escaped || charLengthAt(s, 0) === s.length)
474 ) {
475 stream.push(
476 new Key(name === null ? sequence : name, sequence, ctrl, meta, shift)
477 )
478 }
479 }
480}
node_modules/bare-ansi-escapes/package.json +52 -0
……@@ -0,0 +1,52 @@
1{
2 "name": "bare-ansi-escapes",
3 "version": "2.2.3",
4 "description": "Parse and produce ANSI escape sequences",
5 "exports": {
6 "./package": "./package.json",
7 ".": {
8 "types": "./index.d.ts",
9 "default": "./index.js"
10 },
11 "./key-decoder": {
12 "types": "./key-decoder.d.ts",
13 "default": "./key-decoder.js"
14 }
15 },
16 "files": [
17 "index.js",
18 "index.d.ts",
19 "key-decoder.js",
20 "key-decoder.d.ts"
21 ],
22 "scripts": {
23 "test": "prettier . --check && bare test.js"
24 },
25 "repository": {
26 "type": "git",
27 "url": "git+https://github.com/holepunchto/bare-ansi-escapes.git"
28 },
29 "author": "Holepunch",
30 "license": "Apache-2.0",
31 "bugs": {
32 "url": "https://github.com/holepunchto/bare-ansi-escapes/issues"
33 },
34 "homepage": "https://github.com/holepunchto/bare-ansi-escapes#readme",
35 "dependencies": {
36 "bare-stream": "^2.6.5"
37 },
38 "devDependencies": {
39 "bare-buffer": "^3.0.2",
40 "brittle": "^3.3.2",
41 "prettier": "^3.4.2",
42 "prettier-config-standard": "^7.0.0"
43 },
44 "peerDependencies": {
45 "bare-buffer": "*"
46 },
47 "peerDependenciesMeta": {
48 "bare-buffer": {
49 "optional": true
50 }
51 }
52}
node_modules/bare-assert/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-assert/README.md +11 -0
……@@ -0,0 +1,11 @@
1# bare-assert
2
3Assertion library for JavaScript.
4
5```
6npm i bare-assert
7```
8
9## License
10
11Apache-2.0
node_modules/bare-assert/index.d.ts +44 -0
……@@ -0,0 +1,44 @@
1declare function assert(value: any, message?: string | Error): void
2
3declare namespace assert {
4 export class AssertionError extends Error {
5 constructor(opts?: {
6 message?: string
7 actual?: any
8 expected?: any
9 operator?: string
10 })
11
12 actual?: any
13 expected?: any
14 operator?: string
15 }
16
17 export function ok(value: any, message?: string | Error): void
18
19 export function equal(
20 actual: any,
21 expected: any,
22 message?: string | Error
23 ): void
24
25 export function notEqual(
26 actual: any,
27 expected: any,
28 message?: string | Error
29 ): void
30
31 export function strictEqual(
32 actual: any,
33 expected: any,
34 message?: string | Error
35 ): void
36
37 export function notStrictEqual(
38 actual: any,
39 expected: any,
40 message?: string | Error
41 ): void
42}
43
44export = assert
node_modules/bare-assert/index.js +95 -0
……@@ -0,0 +1,95 @@
1const inspect = require('bare-inspect')
2
3class AssertionError extends Error {
4 constructor(opts = {}) {
5 let { message = null, actual, expected, operator } = opts
6
7 if (message === null) {
8 message = `${inspect(actual)} ${operator} ${inspect(expected)}`
9 }
10
11 super(message)
12
13 this.actual = actual
14 this.expected = expected
15 this.operator = operator
16 }
17
18 get name() {
19 return 'AssertionError'
20 }
21
22 get code() {
23 'ASSERTION'
24 }
25}
26
27function assertFail(opts, fn) {
28 if (opts.message instanceof Error) throw opts.message
29
30 const err = new AssertionError(opts)
31
32 if (Error.captureStackTrace) Error.captureStackTrace(err, fn)
33
34 throw err
35}
36
37module.exports = exports = function assert(actual, message) {
38 if (actual) return
39
40 assertFail({ message, actual, expected: true, operator: '==' }, assert)
41}
42
43exports.AssertionError = AssertionError
44
45exports.fail = function fail(message) {
46 if (message === undefined) message = 'Failed'
47
48 assertFail({ message, operator: 'fail' }, fail)
49}
50
51exports.ok = function ok(actual, message) {
52 if (actual) return
53
54 assertFail({ message, actual, expected: true, operator: '==' }, ok)
55}
56
57exports.notOk = function ok(actual, message) {
58 if (!actual) return
59
60 assertFail({ message, actual, expected: false, operator: '==' }, ok)
61}
62
63exports.equal = function equal(actual, expected, message) {
64 if (actual == expected || (actual !== actual && expected !== expected)) {
65 return
66 }
67
68 assertFail({ message, actual, expected, operator: '==' }, equal)
69}
70
71exports.notEqual = function notEqual(actual, expected, message) {
72 if (actual != expected && (actual === actual || expected === expected)) {
73 return
74 }
75
76 assertFail({ message, actual, expected, operator: '!=' }, notEqual)
77}
78
79exports.strictEqual = function strictEqual(actual, expected, message) {
80 if (Object.is(actual, expected)) return
81
82 assertFail(
83 { message, actual, expected, operator: 'strictEqual' },
84 strictEqual
85 )
86}
87
88exports.notStrictEqual = function notStrictEqual(actual, expected, message) {
89 if (!Object.is(actual, expected)) return
90
91 assertFail(
92 { message, actual, expected, operator: 'notStrictEqual' },
93 notStrictEqual
94 )
95}
node_modules/bare-assert/package.json +37 -0
……@@ -0,0 +1,37 @@
1{
2 "name": "bare-assert",
3 "version": "1.2.0",
4 "description": "Assertion library for JavaScript",
5 "exports": {
6 ".": {
7 "types": "./index.d.ts",
8 "default": "./index.js"
9 },
10 "./package": "./package.json"
11 },
12 "files": [
13 "index.js",
14 "index.d.ts"
15 ],
16 "scripts": {
17 "test": "prettier . --check && bare test.js"
18 },
19 "repository": {
20 "type": "git",
21 "url": "git+https://github.com/holepunchto/bare-assert.git"
22 },
23 "author": "Holepunch",
24 "license": "Apache-2.0",
25 "bugs": {
26 "url": "https://github.com/holepunchto/bare-assert/issues"
27 },
28 "homepage": "https://github.com/holepunchto/bare-assert#readme",
29 "dependencies": {
30 "bare-inspect": "^3.1.2"
31 },
32 "devDependencies": {
33 "brittle": "^3.1.1",
34 "prettier": "^3.4.2",
35 "prettier-config-standard": "^7.0.0"
36 }
37}
node_modules/bare-events/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-events/README.md +25 -0
……@@ -0,0 +1,25 @@
1# bare-events
2
3Event emitters for JavaScript.
4
5```
6npm install bare-events
7```
8
9## Usage
10
11```js
12const EventEmitter = require('bare-events')
13
14const e = new EventEmitter()
15
16e.on('hello', function (data) {
17 console.log(data)
18})
19
20e.emit('hello', 'world')
21```
22
23## License
24
25Apache-2.0
node_modules/bare-events/global.d.ts +15 -0
……@@ -0,0 +1,15 @@
1import * as events from './web'
2
3type EventConstructor = typeof events.Event
4type CustomEventConstructor = typeof events.CustomEvent
5type EventTargetConstructor = typeof events.EventTarget
6
7declare global {
8 type Event = events.Event
9 type CustomEvent<T = any> = events.CustomEvent<T>
10 type EventTarget = events.EventTarget
11
12 const Event: EventConstructor
13 const CustomEvent: CustomEventConstructor
14 const EventTarget: EventTargetConstructor
15}
node_modules/bare-events/global.js +5 -0
……@@ -0,0 +1,5 @@
1const events = require('./web')
2
3global.Event = events.Event
4global.CustomEvent = events.CustomEvent
5global.EventTarget = events.EventTarget
node_modules/bare-events/index.d.ts +81 -0
……@@ -0,0 +1,81 @@
1import { AbortSignal } from 'bare-abort-controller'
2
3interface EventMap {
4 [event: string | symbol]: unknown[]
5}
6
7interface EventHandler<in A extends unknown[] = unknown[], out R = unknown> {
8 (...args: A): R
9}
10
11declare class EventEmitterError extends Error {
12 static OPERATION_ABORTED(cause: Error, msg?: string): EventEmitterError
13 static UNHANDLED_ERROR(cause: Error, msg?: string): EventEmitterError
14}
15
16interface EventEmitter<in out M extends EventMap = EventMap> {
17 addListener<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
18
19 addOnceListener<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
20
21 prependListener<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
22
23 prependOnceListener<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
24
25 removeListener<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
26
27 removeAllListeners<E extends keyof M>(name?: E): this
28
29 on<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
30
31 once<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
32
33 off<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
34
35 emit<E extends keyof M>(name: E, ...args: M[E]): boolean
36
37 listeners<E extends keyof M, R>(name: E): EventHandler<M[E], R>
38
39 listenerCount<E extends keyof M>(name: E): number
40
41 getMaxListeners(): number
42 setMaxListeners(n: number): void
43}
44
45declare class EventEmitter<in out M extends EventMap = EventMap> {}
46
47declare namespace EventEmitter {
48 export function on<M extends EventMap, E extends keyof M>(
49 emitter: EventEmitter<M>,
50 name: E,
51 opts?: { signal?: AbortSignal }
52 ): AsyncIterableIterator<M[E]>
53
54 export function once<M extends EventMap, E extends keyof M>(
55 emitter: EventEmitter<M>,
56 name: E,
57 opts?: { signal?: AbortSignal }
58 ): Promise<M[E]>
59
60 export function forward<F extends EventMap, E extends keyof F, T extends Pick<F, E>>(
61 from: EventEmitter<F>,
62 to: EventEmitter<T>,
63 names: E | E[],
64 opts?: { emit?: (name: E, ...args: T[E]) => void }
65 ): void
66
67 export function listenerCount<M extends EventMap, E extends keyof M>(
68 emitter: EventEmitter<M>,
69 name: E
70 ): number
71
72 export function getMaxListeners(emitter: EventEmitter): number
73
74 export function setMaxListeners(n: number, ...emitters: EventEmitter[]): void
75
76 export let defaultMaxListeners: number
77
78 export { EventEmitter, EventEmitterError as errors, EventMap, EventHandler }
79}
80
81export = EventEmitter
node_modules/bare-events/index.js +367 -0
……@@ -0,0 +1,367 @@
1const errors = require('./lib/errors')
2
3class EventListener {
4 constructor() {
5 this.list = []
6 this.count = 0
7 }
8
9 append(ctx, name, fn, once) {
10 this.count++
11 ctx.emit('newListener', name, fn) // Emit BEFORE adding
12 this.list.push([fn, once])
13 }
14
15 prepend(ctx, name, fn, once) {
16 this.count++
17 ctx.emit('newListener', name, fn) // Emit BEFORE adding
18 this.list.unshift([fn, once])
19 }
20
21 remove(ctx, name, fn) {
22 for (let i = 0, n = this.list.length; i < n; i++) {
23 const l = this.list[i]
24
25 if (l[0] === fn) {
26 this.list.splice(i, 1)
27
28 if (this.count === 1) delete ctx._events[name]
29
30 ctx.emit('removeListener', name, fn) // Emit AFTER removing
31
32 this.count--
33 return
34 }
35 }
36 }
37
38 removeAll(ctx, name) {
39 const list = [...this.list]
40 this.list = []
41
42 if (this.count === list.length) delete ctx._events[name]
43
44 for (let i = list.length - 1; i >= 0; i--) {
45 ctx.emit('removeListener', name, list[i][0]) // Emit AFTER removing
46 }
47
48 this.count -= list.length
49 }
50
51 emit(ctx, name, ...args) {
52 const list = [...this.list]
53
54 for (let i = 0, n = list.length; i < n; i++) {
55 const l = list[i]
56
57 if (l[1] === true) this.remove(ctx, name, l[0])
58
59 Reflect.apply(l[0], ctx, args)
60 }
61
62 return list.length > 0
63 }
64}
65
66function appendListener(ctx, name, fn, once) {
67 if (ctx._events === undefined) ctx._events = Object.create(null)
68 const e = ctx._events[name] || (ctx._events[name] = new EventListener())
69 e.append(ctx, name, fn, once)
70 return ctx
71}
72
73function prependListener(ctx, name, fn, once) {
74 if (ctx._events === undefined) ctx._events = Object.create(null)
75 const e = ctx._events[name] || (ctx._events[name] = new EventListener())
76 e.prepend(ctx, name, fn, once)
77 return ctx
78}
79
80function removeListener(ctx, name, fn) {
81 if (ctx._events === undefined) return ctx
82 const e = ctx._events[name]
83 if (e !== undefined) e.remove(ctx, name, fn)
84 return ctx
85}
86
87function throwUnhandledError(...args) {
88 let err
89
90 if (args.length > 0) err = args[0]
91
92 if (err instanceof Error === false) err = errors.UNHANDLED_ERROR(err)
93
94 if (Error.captureStackTrace) {
95 Error.captureStackTrace(err, exports.prototype.emit)
96 }
97
98 queueMicrotask(() => {
99 throw err
100 })
101}
102
103module.exports = exports = class EventEmitter {
104 constructor() {
105 this._events = Object.create(null)
106 }
107
108 addListener(name, fn) {
109 return appendListener(this, name, fn, false)
110 }
111
112 addOnceListener(name, fn) {
113 return appendListener(this, name, fn, true)
114 }
115
116 prependListener(name, fn) {
117 return prependListener(this, name, fn, false)
118 }
119
120 prependOnceListener(name, fn) {
121 return prependListener(this, name, fn, true)
122 }
123
124 removeListener(name, fn) {
125 return removeListener(this, name, fn)
126 }
127
128 on(name, fn) {
129 return appendListener(this, name, fn, false)
130 }
131
132 once(name, fn) {
133 return appendListener(this, name, fn, true)
134 }
135
136 off(name, fn) {
137 return removeListener(this, name, fn)
138 }
139
140 emit(name, ...args) {
141 if (name === 'error' && this._events !== undefined && this._events.error === undefined) {
142 throwUnhandledError(...args)
143 }
144
145 if (this._events === undefined) return false
146 const e = this._events[name]
147 return e === undefined ? false : e.emit(this, name, ...args)
148 }
149
150 listeners(name) {
151 if (this._events === undefined) return []
152 const e = this._events[name]
153 return e === undefined ? [] : [...e.list]
154 }
155
156 listenerCount(name) {
157 if (this._events === undefined) return 0
158 const e = this._events[name]
159 return e === undefined ? 0 : e.list.length
160 }
161
162 getMaxListeners() {
163 return EventEmitter.defaultMaxListeners
164 }
165
166 setMaxListeners(n) {}
167
168 removeAllListeners(name) {
169 if (arguments.length === 0) {
170 for (const key of Reflect.ownKeys(this._events)) {
171 if (key === 'removeListener') continue
172 this.removeAllListeners(key)
173 }
174 this.removeAllListeners('removeListener')
175 } else {
176 const e = this._events[name]
177 if (e !== undefined) e.removeAll(this, name)
178 }
179 return this
180 }
181}
182
183exports.EventEmitter = exports
184
185exports.errors = errors
186
187exports.defaultMaxListeners = 10
188
189exports.on = function on(emitter, name, opts = {}) {
190 const { signal } = opts
191
192 if (signal && signal.aborted) {
193 throw errors.OPERATION_ABORTED(signal.reason)
194 }
195
196 let error = null
197 let done = false
198
199 const events = []
200 const promises = []
201
202 if (name !== 'error') emitter.on('error', onerror)
203
204 if (signal) signal.addEventListener('abort', onabort)
205
206 emitter.on(name, onevent)
207
208 return {
209 next() {
210 if (events.length) {
211 return Promise.resolve({ value: events.shift(), done: false })
212 }
213
214 if (error) {
215 const err = error
216
217 error = null
218
219 return Promise.reject(err)
220 }
221
222 if (done) return onclose()
223
224 return new Promise((resolve, reject) => promises.push({ resolve, reject }))
225 },
226
227 return() {
228 return onclose()
229 },
230
231 throw(err) {
232 return onerror(err)
233 },
234
235 [Symbol.asyncIterator]() {
236 return this
237 }
238 }
239
240 function onevent(...args) {
241 if (promises.length) {
242 promises.shift().resolve({ value: args, done: false })
243 } else {
244 events.push(args)
245 }
246 }
247
248 function onerror(err) {
249 emitter.off(name, onevent).off('error', onerror)
250
251 if (promises.length) {
252 promises.shift().reject(err)
253 } else {
254 error = err
255 }
256
257 return Promise.resolve({ done: true })
258 }
259
260 function onabort() {
261 signal.removeEventListener('abort', onabort)
262
263 onerror(errors.OPERATION_ABORTED(signal.reason))
264 }
265
266 function onclose() {
267 emitter.off(name, onevent)
268
269 if (name !== 'error') emitter.off('error', onerror)
270
271 if (signal) signal.removeEventListener('abort', onabort)
272
273 done = true
274
275 if (promises.length) promises.shift().resolve({ done: true })
276
277 return Promise.resolve({ done: true })
278 }
279}
280
281exports.once = function once(emitter, name, opts = {}) {
282 const { signal } = opts
283
284 if (signal && signal.aborted) {
285 return Promise.reject(errors.OPERATION_ABORTED(signal.reason))
286 }
287
288 return new Promise((resolve, reject) => {
289 if (name !== 'error') emitter.on('error', onerror)
290
291 if (signal) signal.addEventListener('abort', onabort)
292
293 emitter.once(name, onevent)
294
295 function onevent(...args) {
296 if (name !== 'error') emitter.off('error', onerror)
297
298 if (signal) signal.removeEventListener('abort', onabort)
299
300 resolve(args)
301 }
302
303 function onerror(err) {
304 emitter.off(name, onevent)
305
306 if (name !== 'error') emitter.off('error', onerror)
307
308 reject(err)
309 }
310
311 function onabort() {
312 signal.removeEventListener('abort', onabort)
313
314 onerror(errors.OPERATION_ABORTED(signal.reason))
315 }
316 })
317}
318
319exports.forward = function forward(from, to, names, opts = {}) {
320 if (typeof names === 'string') names = [names]
321
322 const { emit = to.emit.bind(to) } = opts
323
324 const listeners = names.map(
325 (name) =>
326 function onevent(...args) {
327 emit(name, ...args)
328 }
329 )
330
331 to.on('newListener', (name) => {
332 const i = names.indexOf(name)
333
334 if (i !== -1 && to.listenerCount(name) === 0) {
335 from.on(name, listeners[i])
336 }
337 }).on('removeListener', (name) => {
338 const i = names.indexOf(name)
339
340 if (i !== -1 && to.listenerCount(name) === 0) {
341 from.off(name, listeners[i])
342 }
343 })
344}
345
346exports.listenerCount = function listenerCount(emitter, name) {
347 return emitter.listenerCount(name)
348}
349
350exports.getMaxListeners = function getMaxListeners(emitter) {
351 if (typeof emitter.getMaxListeners === 'function') {
352 return emitter.getMaxListeners()
353 }
354
355 return exports.defaultMaxListeners
356}
357
358exports.setMaxListeners = function setMaxListeners(n, ...emitters) {
359 if (emitters.length === 0) exports.defaultMaxListeners = n
360 else {
361 for (const emitter of emitters) {
362 if (typeof emitter.setMaxListeners === 'function') {
363 emitter.setMaxListeners(n)
364 }
365 }
366 }
367}
node_modules/bare-events/lib/errors.js +26 -0
……@@ -0,0 +1,26 @@
1module.exports = class EventEmitterError extends Error {
2 constructor(msg, code, fn = EventEmitterError, opts) {
3 super(`${code}: ${msg}`, opts)
4 this.code = code
5
6 if (Error.captureStackTrace) {
7 Error.captureStackTrace(this, fn)
8 }
9 }
10
11 get name() {
12 return 'EventEmitterError'
13 }
14
15 static OPERATION_ABORTED(cause, msg = 'Operation aborted') {
16 return new EventEmitterError(msg, 'OPERATION_ABORTED', EventEmitterError.OPERATION_ABORTED, {
17 cause
18 })
19 }
20
21 static UNHANDLED_ERROR(cause, msg = 'Unhandled error') {
22 return new EventEmitterError(msg, 'UNHANDLED_ERROR', EventEmitterError.UNHANDLED_ERROR, {
23 cause
24 })
25 }
26}
node_modules/bare-events/package.json +61 -0
……@@ -0,0 +1,61 @@
1{
2 "name": "bare-events",
3 "version": "2.8.2",
4 "description": "Event emitters for JavaScript",
5 "exports": {
6 "./package": "./package.json",
7 ".": {
8 "types": "./index.d.ts",
9 "default": "./index.js"
10 },
11 "./global": {
12 "types": "./global.d.ts",
13 "default": "./global.js"
14 },
15 "./web": {
16 "types": "./web.d.ts",
17 "default": "./web.js"
18 },
19 "./errors": "./lib/errors.js"
20 },
21 "files": [
22 "index.js",
23 "index.d.ts",
24 "global.js",
25 "global.d.ts",
26 "web.js",
27 "web.d.ts",
28 "lib"
29 ],
30 "scripts": {
31 "test": "npm run lint && npm run test:bare && npm run test:node",
32 "test:bare": "bare test.js",
33 "test:node": "node test.js",
34 "lint": "prettier . --check"
35 },
36 "repository": {
37 "type": "git",
38 "url": "git+https://github.com/holepunchto/bare-events.git"
39 },
40 "author": "Holepunch",
41 "license": "Apache-2.0",
42 "bugs": {
43 "url": "https://github.com/holepunchto/bare-events/issues"
44 },
45 "homepage": "https://github.com/holepunchto/bare-events#readme",
46 "devDependencies": {
47 "bare-abort-controller": "^1.0.0",
48 "brittle": "^3.3.2",
49 "prettier": "^3.4.2",
50 "prettier-config-holepunch": "^2.0.0",
51 "uncaughts": "^1.1.1"
52 },
53 "peerDependencies": {
54 "bare-abort-controller": "*"
55 },
56 "peerDependenciesMeta": {
57 "bare-abort-controller": {
58 "optional": true
59 }
60 }
61}
node_modules/bare-events/web.d.ts +79 -0
……@@ -0,0 +1,79 @@
1interface AbortSignal extends EventTarget {}
2
3export interface EventOptions {
4 bubbles?: boolean
5 cancelable?: boolean
6 composed?: boolean
7}
8
9export interface Event {
10 readonly type: string
11 readonly target: EventTarget | null
12 readonly currentTarget: EventTarget | null
13 readonly bubbles: boolean
14 readonly cancelable: boolean
15 readonly composed: boolean
16 readonly defaultPrevented: boolean
17 readonly isTrusted: boolean
18
19 preventDefault(): void
20 stopPropagation(): void
21 stopImmediatePropagation(): void
22}
23
24export class Event {
25 constructor(type: string, options?: EventOptions)
26}
27
28export interface CustomEventOptions<T = any> extends EventOptions {
29 detail?: T
30}
31
32export interface CustomEvent<T = any> extends Event {
33 readonly detail: T
34}
35
36export class CustomEvent<T = any> {
37 constructor(type: string, options?: CustomEventOptions<T>)
38}
39
40export interface AddEventListenerOptions {
41 capture?: boolean
42 passive?: boolean
43 once?: boolean
44 signal?: AbortSignal | null
45}
46
47export interface RemoveEventListenerOptions {
48 capture?: boolean
49}
50
51export interface EventTarget {
52 addEventListener(
53 type: string,
54 callback: EventListener,
55 options?: AddEventListenerOptions | boolean
56 ): void
57
58 removeEventListener(
59 type: string,
60 callback: EventListener,
61 options?: RemoveEventListenerOptions | boolean
62 ): void
63
64 dispatchEvent(event: Event): boolean
65}
66
67export class EventTarget {
68 constructor()
69}
70
71export type EventListener = EventCallback | EventHandler
72
73export interface EventCallback {
74 (event: Event): void
75}
76
77export interface EventHandler {
78 handleEvent(event: Event): void
79}
node_modules/bare-events/web.js +335 -0
……@@ -0,0 +1,335 @@
1// Event state
2const BUBBLES = 0x1
3const CANCELABLE = 0x2
4const COMPOSED = 0x4
5const CANCELED = 0x8
6const DISPATCH = 0x10
7const STOP = 0x20
8
9// EventTarget state
10const CAPTURE = 0x1
11const PASSIVE = 0x2
12const ONCE = 0x4
13
14// https://dom.spec.whatwg.org/#event
15class Event {
16 // https://dom.spec.whatwg.org/#dom-event-event
17 constructor(type, options = {}) {
18 const { bubbles = false, cancelable = false, composed = false } = options
19
20 this._type = type
21 this._target = null
22 this._state = 0
23
24 if (bubbles) this._state |= BUBBLES
25 if (cancelable) this._state |= CANCELABLE
26 if (composed) this._state |= COMPOSED
27 }
28
29 // https://dom.spec.whatwg.org/#dom-event-type
30 get type() {
31 return this._type
32 }
33
34 // https://dom.spec.whatwg.org/#dom-event-target
35 get target() {
36 return this._target
37 }
38
39 // https://dom.spec.whatwg.org/#dom-event-currenttarget
40 get currentTarget() {
41 return null
42 }
43
44 // https://dom.spec.whatwg.org/#dom-event-bubbles
45 get bubbles() {
46 return (this._state & BUBBLES) !== 0
47 }
48
49 // https://dom.spec.whatwg.org/#dom-event-cancelable
50 get cancelable() {
51 return (this._state & CANCELABLE) !== 0
52 }
53
54 // https://dom.spec.whatwg.org/#dom-event-composed
55 get composed() {
56 return (this._state & COMPOSED) !== 0
57 }
58
59 // https://dom.spec.whatwg.org/#dom-event-defaultprevented
60 get defaultPrevented() {
61 return (this._state & CANCELED) !== 0
62 }
63
64 // https://dom.spec.whatwg.org/#dom-event-istrusted
65 get isTrusted() {
66 return false
67 }
68
69 // https://dom.spec.whatwg.org/#dom-event-preventdefault
70 preventDefault() {
71 if (this._state & CANCELABLE) this._state |= CANCELED
72 }
73
74 // https://dom.spec.whatwg.org/#dom-event-stoppropagation
75 stopPropagation() {}
76
77 // https://dom.spec.whatwg.org/#dom-event-stopimmediatepropagation
78 stopImmediatePropagation() {
79 this._state |= STOP
80 }
81
82 toJSON() {
83 return {
84 type: this.type,
85 target: this.target,
86 bubbles: this.bubbles,
87 cancelable: this.cancelable,
88 composed: this.composed,
89 defaultPrevented: this.defaultPrevented,
90 isTrusted: this.isTrusted
91 }
92 }
93
94 [Symbol.for('bare.inspect')]() {
95 return {
96 __proto__: { constructor: Event },
97
98 type: this.type,
99 target: this.target,
100 bubbles: this.bubbles,
101 cancelable: this.cancelable,
102 composed: this.composed,
103 defaultPrevented: this.defaultPrevented,
104 isTrusted: this.isTrusted
105 }
106 }
107}
108
109exports.Event = Event
110
111// https://dom.spec.whatwg.org/#customevent
112exports.CustomEvent = class CustomEvent extends Event {
113 constructor(type, options = {}) {
114 super(type, options)
115
116 const { detail = null } = options
117
118 this._detail = detail
119 }
120
121 // https://dom.spec.whatwg.org/#dom-customevent-detail
122 get detail() {
123 return this._detail
124 }
125}
126
127// https://dom.spec.whatwg.org/#eventtarget
128exports.EventTarget = class EventTarget {
129 // https://dom.spec.whatwg.org/#dom-eventtarget-eventtarget
130 constructor() {
131 this._listeners = new Map()
132 }
133
134 // https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener
135 addEventListener(type, callback = null, options = {}) {
136 if (typeof options === 'boolean') options = { capture: options }
137
138 const { capture = false, passive = false, once = false, signal = null } = options
139
140 if (signal !== null && signal.aborted) return
141 if (callback === null) return
142
143 const listener = new EventListener(type, callback, capture, passive, once, signal)
144
145 const listeners = this._listeners.get(type)
146
147 if (listeners === undefined) this._listeners.set(type, listener)
148 else {
149 for (const existing of listeners) {
150 if (callback === existing.callback && capture === existing.capture) {
151 return // Duplicate listener
152 }
153 }
154
155 listener.link(listeners)
156
157 if (signal !== null) {
158 signal.addEventListener('abort', onabort)
159
160 function onabort() {
161 listener.unlink()
162 }
163 }
164 }
165 }
166
167 // https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener
168 removeEventListener(type, callback = null, options = {}) {
169 if (typeof options === 'boolean') options = { capture: options }
170
171 const { capture = false } = options
172
173 const listeners = this._listeners.get(type)
174
175 if (listeners === undefined) return
176
177 for (const existing of listeners) {
178 if (callback === existing.callback && capture === existing.capture) {
179 const next = existing.unlink()
180
181 if (listeners === existing) this._listeners.set(type, next)
182
183 return
184 }
185 }
186 }
187
188 // https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent
189 dispatchEvent(event) {
190 event._target = this
191 event._state |= DISPATCH
192
193 const listeners = this._listeners.get(event.type)
194
195 try {
196 if (listeners === undefined) return true
197
198 for (const listener of listeners) {
199 // https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke
200
201 if (listener.once) listener.unlink()
202
203 let callback = listener.callback
204 let context = this
205
206 if (typeof callback === 'object') {
207 context = callback
208 callback = callback.handleEvent
209 }
210
211 Reflect.apply(callback, context, [event])
212
213 if (event._state & STOP) break
214 }
215
216 return (event._state & CANCELED) === 0
217 } finally {
218 event._state &= ~DISPATCH
219 event._state &= ~STOP
220 }
221 }
222
223 toJSON() {
224 return {}
225 }
226
227 [Symbol.for('bare.inspect')]() {
228 return {
229 __proto__: { constructor: EventTarget }
230 }
231 }
232}
233
234// https://dom.spec.whatwg.org/#concept-event-listener
235class EventListener {
236 constructor(type, callback, capture, passive, once, signal) {
237 this._type = type
238 this._callback = callback
239 this._signal = signal
240 this._state = 0
241
242 if (capture) this._state |= CAPTURE
243 if (passive) this._state |= PASSIVE
244 if (once) this._state |= ONCE
245
246 this._previous = this
247 this._next = this
248 }
249
250 get type() {
251 return this._type
252 }
253
254 get callback() {
255 return this._callback
256 }
257
258 get capture() {
259 return (this._state & CAPTURE) !== 0
260 }
261
262 get passive() {
263 return (this._state & PASSIVE) !== 0
264 }
265
266 get once() {
267 return (this._state & ONCE) !== 0
268 }
269
270 get removed() {
271 return this._previous === this && this._next === this
272 }
273
274 link(listener) {
275 const next = this._next
276 const previous = listener._previous
277
278 this._next = listener
279 listener._previous = this
280
281 previous._next = next
282 next._previous = previous
283
284 return listener
285 }
286
287 unlink() {
288 if (this.removed) return this
289
290 const next = this._next
291 const previous = this._previous
292
293 this._next = this
294 this._previous = this
295
296 previous._next = next
297 next._previous = previous
298
299 return next
300 }
301
302 *[Symbol.iterator]() {
303 let current = this
304
305 while (true) {
306 const next = current._next
307 yield current
308 if (next === this) break
309 current = next
310 }
311 }
312
313 toJSON() {
314 return {
315 type: this.type,
316 capture: this.capture,
317 passive: this.passive,
318 once: this.once,
319 removed: this.removed
320 }
321 }
322
323 [Symbol.for('bare.inspect')]() {
324 return {
325 __proto__: { constructor: EventListener },
326
327 type: this.type,
328 callback: this.callback,
329 capture: this.capture,
330 passive: this.passive,
331 once: this.once,
332 removed: this.removed
333 }
334 }
335}
node_modules/bare-fs/CMakeLists.txt +13 -0
……@@ -0,0 +1,13 @@
1cmake_minimum_required(VERSION 4.0)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4
5project(bare_fs C)
6
7add_bare_module(bare_fs)
8
9target_sources(
10 ${bare_fs}
11 PRIVATE
12 binding.c
13)
node_modules/bare-fs/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-fs/README.md +29 -0
……@@ -0,0 +1,29 @@
1# bare-fs
2
3Native file system operations for Javascript.
4
5```
6npm i bare-fs
7```
8
9## Usage
10
11```js
12const fs = require('bare-fs')
13
14const fd = await fs.open('hello.txt')
15
16const buffer = Buffer.alloc(1024)
17
18try {
19 const length = await fs.read(fd, buffer)
20
21 console.log('Read', length, 'bytes')
22} finally {
23 await fs.close(fd)
24}
25```
26
27## License
28
29Apache-2.0
node_modules/bare-fs/binding.c +2273 -0
……@@ -0,0 +1,2273 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4#include <stdbool.h>
5#include <stdint.h>
6#include <stdlib.h>
7#include <string.h>
8#include <utf.h>
9#include <uv.h>
10
11#ifndef _MSC_VER
12#include <unistd.h>
13#endif
14
15typedef struct {
16 uv_fs_t handle;
17
18 js_env_t *env;
19 js_ref_t *ctx;
20 js_ref_t *on_result;
21
22 bool exiting;
23 bool inflight;
24
25 js_deferred_teardown_t *teardown;
26} bare_fs_req_t;
27
28typedef utf8_t bare_fs_path_t[4096 + 1 /* NULL */];
29
30typedef struct {
31 uv_dir_t *handle;
32} bare_fs_dir_t;
33
34typedef struct {
35 uv_fs_event_t handle;
36
37 js_env_t *env;
38 js_ref_t *ctx;
39 js_ref_t *on_event;
40 js_ref_t *on_close;
41
42 bool exiting;
43 bool closing;
44
45 js_deferred_teardown_t *teardown;
46} bare_fs_watcher_t;
47
48typedef uv_dirent_t bare_fs_dirent_t;
49
50enum {
51 bare_fs_async = true,
52 bare_fs_sync = false
53};
54
55static inline void
56bare_fs__request_destroy(bare_fs_req_t *req) {
57 int err;
58
59 js_env_t *env = req->env;
60
61 js_deferred_teardown_t *teardown = req->teardown;
62
63 uv_fs_req_cleanup(&req->handle);
64
65 err = js_delete_reference(env, req->on_result);
66 assert(err == 0);
67
68 err = js_delete_reference(env, req->ctx);
69 assert(err == 0);
70
71 err = js_finish_deferred_teardown_callback(teardown);
72 assert(err == 0);
73}
74
75static void
76bare_fs__on_request_teardown(js_deferred_teardown_t *handle, void *data) {
77 int err;
78
79 bare_fs_req_t *req = (bare_fs_req_t *) data;
80
81 req->exiting = true;
82
83 if (req->inflight) {
84 err = uv_cancel((uv_req_t *) &req->handle);
85 if (err < 0) return;
86 }
87
88 bare_fs__request_destroy(req);
89}
90
91static inline void
92bare_fs__on_request_result(uv_fs_t *handle) {
93 int err;
94
95 bare_fs_req_t *req = (bare_fs_req_t *) handle;
96
97 req->inflight = false;
98
99 if (req->exiting) return bare_fs__request_destroy(req);
100
101 js_env_t *env = req->env;
102
103 js_handle_scope_t *scope;
104 err = js_open_handle_scope(env, &scope);
105 assert(err == 0);
106
107 js_value_t *ctx;
108 err = js_get_reference_value(env, req->ctx, &ctx);
109 assert(err == 0);
110
111 js_value_t *on_result;
112 err = js_get_reference_value(env, req->on_result, &on_result);
113 assert(err == 0);
114
115 int status = handle->result;
116
117 js_value_t *args[2];
118
119 if (status < 0) {
120 js_value_t *code;
121 err = js_create_string_utf8(env, (utf8_t *) uv_err_name(status), -1, &code);
122 assert(err == 0);
123
124 js_value_t *message;
125 err = js_create_string_utf8(env, (utf8_t *) uv_strerror(status), -1, &message);
126 assert(err == 0);
127
128 err = js_create_error(env, code, message, &args[0]);
129 assert(err == 0);
130 } else {
131 err = js_get_null(env, &args[0]);
132 assert(err == 0);
133 }
134
135 err = js_create_int32(env, status, &args[1]);
136 assert(err == 0);
137
138 err = js_call_function(env, ctx, on_result, 2, args, NULL);
139 (void) err;
140
141 err = js_close_handle_scope(env, scope);
142 assert(err == 0);
143}
144
145static inline int
146bare_fs__request_pending(js_env_t *env, bare_fs_req_t *req, bool async, int *result) {
147 int err;
148
149 if (async) {
150 req->inflight = true;
151
152 return 0;
153 }
154
155 int status = req->handle.result;
156
157 if (status < 0) {
158 err = js_throw_error(env, uv_err_name(status), uv_strerror(status));
159 assert(err == 0);
160
161 return -1;
162 }
163
164 if (result) *result = status;
165
166 return 1;
167}
168
169static js_value_t *
170bare_fs_request_init(js_env_t *env, js_callback_info_t *info) {
171 int err;
172
173 size_t argc = 2;
174 js_value_t *argv[2];
175
176 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
177 assert(err == 0);
178
179 assert(argc == 2);
180
181 js_value_t *handle;
182
183 bare_fs_req_t *req;
184 err = js_create_arraybuffer(env, sizeof(bare_fs_req_t), (void **) &req, &handle);
185 assert(err == 0);
186
187 req->env = env;
188 req->exiting = false;
189 req->inflight = false;
190
191 err = js_create_reference(env, argv[0], 1, &req->ctx);
192 assert(err == 0);
193
194 err = js_create_reference(env, argv[1], 1, &req->on_result);
195 assert(err == 0);
196
197 err = js_add_deferred_teardown_callback(env, bare_fs__on_request_teardown, (void *) req, &req->teardown);
198 assert(err == 0);
199
200 return handle;
201}
202
203static js_value_t *
204bare_fs_request_destroy(js_env_t *env, js_callback_info_t *info) {
205 int err;
206
207 size_t argc = 1;
208 js_value_t *argv[1];
209
210 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
211 assert(err == 0);
212
213 assert(argc == 1);
214
215 bare_fs_req_t *req;
216 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
217 assert(err == 0);
218
219 bare_fs__request_destroy(req);
220
221 return NULL;
222}
223
224static js_value_t *
225bare_fs_request_reset(js_env_t *env, js_callback_info_t *info) {
226 int err;
227
228 size_t argc = 1;
229 js_value_t *argv[1];
230
231 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
232 assert(err == 0);
233
234 assert(argc == 1);
235
236 bare_fs_req_t *req;
237 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
238 assert(err == 0);
239
240 uv_fs_req_cleanup(&req->handle);
241
242 return NULL;
243}
244
245static js_value_t *
246bare_fs_request_result_stat(js_env_t *env, js_callback_info_t *info) {
247 int err;
248
249 size_t argc = 1;
250 js_value_t *argv[1];
251
252 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
253 assert(err == 0);
254
255 assert(argc == 1);
256
257 bare_fs_req_t *req;
258 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
259 assert(err == 0);
260
261 js_value_t *result;
262 err = js_create_array_with_length(env, 14, &result);
263 assert(err == 0);
264
265 uint32_t i = 0;
266
267#define V(property) \
268 { \
269 js_value_t *value; \
270 err = js_create_int64(env, req->handle.statbuf.st_##property, &value); \
271 assert(err == 0); \
272\
273 err = js_set_element(env, result, i++, value); \
274 assert(err == 0); \
275 }
276 V(dev)
277 V(mode)
278 V(nlink)
279 V(uid)
280 V(gid)
281 V(rdev)
282 V(blksize)
283 V(ino)
284 V(size)
285 V(blocks)
286#undef V
287
288#define V(property) \
289 { \
290 uv_timespec_t time = req->handle.statbuf.st_##property; \
291\
292 js_value_t *value; \
293 err = js_create_int64(env, time.tv_sec * 1000 + time.tv_nsec / 1000000, &value); \
294 assert(err == 0); \
295\
296 err = js_set_element(env, result, i++, value); \
297 assert(err == 0); \
298 }
299 V(atim)
300 V(mtim)
301 V(ctim)
302 V(birthtim)
303#undef V
304
305 return result;
306}
307
308static js_value_t *
309bare_fs_request_result_string(js_env_t *env, js_callback_info_t *info) {
310 int err;
311
312 size_t argc = 1;
313 js_value_t *argv[1];
314
315 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
316 assert(err == 0);
317
318 assert(argc == 1);
319
320 bare_fs_req_t *req;
321 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
322 assert(err == 0);
323
324 size_t len = strlen(req->handle.ptr);
325
326 js_value_t *result;
327
328 void *data;
329 err = js_create_arraybuffer(env, len, (void *) &data, &result);
330 assert(err == 0);
331
332 strncpy(data, req->handle.ptr, len);
333
334 return result;
335}
336
337static js_value_t *
338bare_fs_request_result_dir(js_env_t *env, js_callback_info_t *info) {
339 int err;
340
341 size_t argc = 1;
342 js_value_t *argv[1];
343
344 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
345 assert(err == 0);
346
347 assert(argc == 1);
348
349 bare_fs_req_t *req;
350 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
351 assert(err == 0);
352
353 js_value_t *result;
354
355 bare_fs_dir_t *dir;
356 err = js_create_arraybuffer(env, sizeof(bare_fs_dir_t), (void **) &dir, &result);
357 assert(err == 0);
358
359 dir->handle = req->handle.ptr;
360
361 return result;
362}
363
364static js_value_t *
365bare_fs_request_result_dirents(js_env_t *env, js_callback_info_t *info) {
366 int err;
367
368 size_t argc = 1;
369 js_value_t *argv[1];
370
371 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
372 assert(err == 0);
373
374 assert(argc == 1);
375
376 bare_fs_req_t *req;
377 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
378 assert(err == 0);
379
380 size_t len = req->handle.result;
381
382 js_value_t *result;
383 err = js_create_array_with_length(env, len, &result);
384 assert(err == 0);
385
386 uv_dir_t *dir = req->handle.ptr;
387
388 for (uint32_t i = 0; i < len; i++) {
389 uv_dirent_t *dirent = &dir->dirents[i];
390
391 js_value_t *entry;
392 err = js_create_object(env, &entry);
393 assert(err == 0);
394
395 err = js_set_element(env, result, i, entry);
396 assert(err == 0);
397
398 size_t name_len = strlen(dirent->name);
399
400 js_value_t *name;
401
402 void *data;
403 err = js_create_arraybuffer(env, name_len, &data, &name);
404 assert(err == 0);
405
406 memcpy(data, dirent->name, name_len);
407
408 err = js_set_named_property(env, entry, "name", name);
409 assert(err == 0);
410
411 js_value_t *type;
412 err = js_create_uint32(env, dirent->type, &type);
413 assert(err == 0);
414
415 err = js_set_named_property(env, entry, "type", type);
416 assert(err == 0);
417 }
418
419 return result;
420}
421
422static void
423bare_fs__on_open(uv_fs_t *handle) {
424 int err;
425
426 bare_fs_req_t *req = (bare_fs_req_t *) handle;
427
428 int status = handle->result;
429
430 if (req->exiting && status >= 0) {
431 int fd = status;
432
433 uv_fs_req_cleanup(handle);
434
435 err = uv_fs_close(handle->loop, handle, fd, NULL);
436 assert(err == 0);
437 }
438
439 bare_fs__on_request_result(handle);
440}
441
442static inline js_value_t *
443bare_fs__open(js_env_t *env, js_callback_info_t *info, bool async) {
444 int err;
445
446 size_t argc = 4;
447 js_value_t *argv[4];
448
449 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
450 assert(err == 0);
451
452 assert(argc == 4);
453
454 bare_fs_req_t *req;
455 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
456 assert(err == 0);
457
458 bare_fs_path_t path;
459 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
460 assert(err == 0);
461
462 int32_t flags;
463 err = js_get_value_int32(env, argv[2], &flags);
464 assert(err == 0);
465
466 int32_t mode;
467 err = js_get_value_int32(env, argv[3], &mode);
468 assert(err == 0);
469
470 uv_loop_t *loop;
471 err = js_get_env_loop(env, &loop);
472 assert(err == 0);
473
474 err = uv_fs_open(loop, &req->handle, (char *) path, flags, mode, async ? bare_fs__on_open : NULL);
475 (void) err;
476
477 int status;
478 err = bare_fs__request_pending(env, req, async, &status);
479 if (err != 1) return NULL;
480
481 js_value_t *result;
482 err = js_create_int32(env, status, &result);
483 assert(err == 0);
484
485 return result;
486}
487
488static js_value_t *
489bare_fs_open(js_env_t *env, js_callback_info_t *info) {
490 return bare_fs__open(env, info, bare_fs_async);
491}
492
493static js_value_t *
494bare_fs_open_sync(js_env_t *env, js_callback_info_t *info) {
495 return bare_fs__open(env, info, bare_fs_sync);
496}
497
498static void
499bare_fs__on_close(uv_fs_t *handle) {
500 bare_fs__on_request_result(handle);
501}
502
503static inline js_value_t *
504bare_fs__close(js_env_t *env, js_callback_info_t *info, bool async) {
505 int err;
506
507 size_t argc = 2;
508 js_value_t *argv[2];
509
510 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
511 assert(err == 0);
512
513 assert(argc == 2);
514
515 bare_fs_req_t *req;
516 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
517 assert(err == 0);
518
519 uint32_t fd;
520 err = js_get_value_uint32(env, argv[1], &fd);
521 assert(err == 0);
522
523 uv_loop_t *loop;
524 err = js_get_env_loop(env, &loop);
525 assert(err == 0);
526
527 err = uv_fs_close(loop, &req->handle, fd, async ? bare_fs__on_close : NULL);
528 (void) err;
529
530 err = bare_fs__request_pending(env, req, async, NULL);
531 (void) err;
532
533 return NULL;
534}
535
536static js_value_t *
537bare_fs_close(js_env_t *env, js_callback_info_t *info) {
538 return bare_fs__close(env, info, bare_fs_async);
539}
540
541static js_value_t *
542bare_fs_close_sync(js_env_t *env, js_callback_info_t *info) {
543 return bare_fs__close(env, info, bare_fs_sync);
544}
545
546static void
547bare_fs__on_access(uv_fs_t *handle) {
548 bare_fs__on_request_result(handle);
549}
550
551static inline js_value_t *
552bare_fs__access(js_env_t *env, js_callback_info_t *info, bool async) {
553 int err;
554
555 size_t argc = 3;
556 js_value_t *argv[3];
557
558 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
559 assert(err == 0);
560
561 assert(argc == 3);
562
563 bare_fs_req_t *req;
564 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
565 assert(err == 0);
566
567 bare_fs_path_t path;
568 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
569 assert(err == 0);
570
571 int32_t mode;
572 err = js_get_value_int32(env, argv[2], &mode);
573 assert(err == 0);
574
575 uv_loop_t *loop;
576 err = js_get_env_loop(env, &loop);
577 assert(err == 0);
578
579 err = uv_fs_access(loop, &req->handle, (char *) path, mode, async ? bare_fs__on_access : NULL);
580 (void) err;
581
582 err = bare_fs__request_pending(env, req, async, NULL);
583 (void) err;
584
585 return NULL;
586}
587
588static js_value_t *
589bare_fs_access(js_env_t *env, js_callback_info_t *info) {
590 return bare_fs__access(env, info, bare_fs_async);
591}
592
593static js_value_t *
594bare_fs_access_sync(js_env_t *env, js_callback_info_t *info) {
595 return bare_fs__access(env, info, bare_fs_sync);
596}
597
598static void
599bare_fs__on_read(uv_fs_t *handle) {
600 bare_fs__on_request_result(handle);
601}
602
603static inline js_value_t *
604bare_fs__read(js_env_t *env, js_callback_info_t *info, bool async) {
605 int err;
606
607 size_t argc = 6;
608 js_value_t *argv[6];
609
610 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
611 assert(err == 0);
612
613 assert(argc == 6);
614
615 bare_fs_req_t *req;
616 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
617 assert(err == 0);
618
619 uint32_t fd;
620 err = js_get_value_uint32(env, argv[1], &fd);
621 assert(err == 0);
622
623 uint8_t *data;
624 size_t data_len;
625 err = js_get_typedarray_info(env, argv[2], NULL, (void **) &data, &data_len, NULL, NULL);
626 assert(err == 0);
627
628 uint32_t offset;
629 err = js_get_value_uint32(env, argv[3], &offset);
630 assert(err == 0);
631
632 uint32_t len;
633 err = js_get_value_uint32(env, argv[4], &len);
634 assert(err == 0);
635
636 if (offset >= data_len) len = 0;
637 else if (offset + len >= data_len) len = data_len - offset;
638
639 int64_t pos;
640 err = js_get_value_int64(env, argv[5], &pos);
641 assert(err == 0);
642
643 uv_loop_t *loop;
644 err = js_get_env_loop(env, &loop);
645 assert(err == 0);
646
647 uv_buf_t buf = uv_buf_init((void *) (data + offset), len);
648
649 err = uv_fs_read(loop, &req->handle, fd, &buf, 1, pos, async ? bare_fs__on_read : NULL);
650 (void) err;
651
652 int status;
653 err = bare_fs__request_pending(env, req, async, &status);
654 if (err != 1) return NULL;
655
656 js_value_t *result;
657 err = js_create_int32(env, status, &result);
658 assert(err == 0);
659
660 return result;
661}
662
663static js_value_t *
664bare_fs_read(js_env_t *env, js_callback_info_t *info) {
665 return bare_fs__read(env, info, bare_fs_async);
666}
667
668static js_value_t *
669bare_fs_read_sync(js_env_t *env, js_callback_info_t *info) {
670 return bare_fs__read(env, info, bare_fs_sync);
671}
672
673static void
674bare_fs__on_readv(uv_fs_t *handle) {
675 bare_fs__on_request_result(handle);
676}
677
678static inline js_value_t *
679bare_fs__readv(js_env_t *env, js_callback_info_t *info, bool async) {
680 int err;
681
682 size_t argc = 4;
683 js_value_t *argv[4];
684
685 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
686 assert(err == 0);
687
688 assert(argc == 4);
689
690 bare_fs_req_t *req;
691 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
692 assert(err == 0);
693
694 uint32_t fd;
695 err = js_get_value_uint32(env, argv[1], &fd);
696 assert(err == 0);
697
698 int64_t pos;
699 err = js_get_value_int64(env, argv[3], &pos);
700 assert(err == 0);
701
702 uv_loop_t *loop;
703 err = js_get_env_loop(env, &loop);
704 assert(err == 0);
705
706 js_value_t *arr = argv[2];
707
708 uint32_t bufs_len;
709 err = js_get_array_length(env, arr, &bufs_len);
710 assert(err == 0);
711
712 uv_buf_t *bufs = malloc(sizeof(uv_buf_t) * bufs_len);
713
714 js_value_t **elements = malloc(bufs_len * sizeof(js_value_t *));
715 err = js_get_array_elements(env, arr, elements, bufs_len, 0, NULL);
716 assert(err == 0);
717
718 for (uint32_t i = 0; i < bufs_len; i++) {
719 js_value_t *item = elements[i];
720
721 uv_buf_t *buf = &bufs[i];
722 err = js_get_typedarray_info(env, item, NULL, (void **) &buf->base, (size_t *) &buf->len, NULL, NULL);
723 assert(err == 0);
724 }
725
726 err = uv_fs_read(loop, &req->handle, fd, bufs, bufs_len, pos, async ? bare_fs__on_readv : NULL);
727 (void) err;
728
729 free(elements);
730 free(bufs);
731
732 int status;
733 err = bare_fs__request_pending(env, req, async, &status);
734 if (err != 1) return NULL;
735
736 js_value_t *result;
737 err = js_create_int32(env, status, &result);
738 assert(err == 0);
739
740 return result;
741}
742
743static js_value_t *
744bare_fs_readv(js_env_t *env, js_callback_info_t *info) {
745 return bare_fs__readv(env, info, bare_fs_async);
746}
747
748static js_value_t *
749bare_fs_readv_sync(js_env_t *env, js_callback_info_t *info) {
750 return bare_fs__readv(env, info, bare_fs_sync);
751}
752
753static void
754bare_fs__on_write(uv_fs_t *handle) {
755 bare_fs__on_request_result(handle);
756}
757
758static inline js_value_t *
759bare_fs__write(js_env_t *env, js_callback_info_t *info, bool async) {
760 int err;
761
762 size_t argc = 6;
763 js_value_t *argv[6];
764
765 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
766 assert(err == 0);
767
768 assert(argc == 6);
769
770 bare_fs_req_t *req;
771 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
772 assert(err == 0);
773
774 uint32_t fd;
775 err = js_get_value_uint32(env, argv[1], &fd);
776 assert(err == 0);
777
778 uint8_t *data;
779 size_t data_len;
780 err = js_get_typedarray_info(env, argv[2], NULL, (void **) &data, &data_len, NULL, NULL);
781 assert(err == 0);
782
783 uint32_t offset;
784 err = js_get_value_uint32(env, argv[3], &offset);
785 assert(err == 0);
786
787 uint32_t len;
788 err = js_get_value_uint32(env, argv[4], &len);
789 assert(err == 0);
790
791 if (offset >= data_len) len = 0;
792 else if (offset + len >= data_len) len = data_len - offset;
793
794 int64_t pos;
795 err = js_get_value_int64(env, argv[5], &pos);
796 assert(err == 0);
797
798 uv_loop_t *loop;
799 err = js_get_env_loop(env, &loop);
800 assert(err == 0);
801
802 uv_buf_t buf = uv_buf_init((void *) (data + offset), len);
803
804 err = uv_fs_write(loop, &req->handle, fd, &buf, 1, pos, async ? bare_fs__on_write : NULL);
805 (void) err;
806
807 int status;
808 err = bare_fs__request_pending(env, req, async, &status);
809 if (err != 1) return NULL;
810
811 js_value_t *result;
812 err = js_create_int32(env, status, &result);
813 assert(err == 0);
814
815 return result;
816}
817
818static js_value_t *
819bare_fs_write(js_env_t *env, js_callback_info_t *info) {
820 return bare_fs__write(env, info, bare_fs_async);
821}
822
823static js_value_t *
824bare_fs_write_sync(js_env_t *env, js_callback_info_t *info) {
825 return bare_fs__write(env, info, bare_fs_sync);
826}
827
828static void
829bare_fs__on_writev(uv_fs_t *handle) {
830 bare_fs__on_request_result(handle);
831}
832
833static inline js_value_t *
834bare_fs__writev(js_env_t *env, js_callback_info_t *info, bool async) {
835 int err;
836
837 size_t argc = 4;
838 js_value_t *argv[4];
839
840 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
841 assert(err == 0);
842
843 assert(argc == 4);
844
845 bare_fs_req_t *req;
846 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
847 assert(err == 0);
848
849 uint32_t fd;
850 err = js_get_value_uint32(env, argv[1], &fd);
851 assert(err == 0);
852
853 int64_t pos;
854 err = js_get_value_int64(env, argv[3], &pos);
855 assert(err == 0);
856
857 uv_loop_t *loop;
858 err = js_get_env_loop(env, &loop);
859 assert(err == 0);
860
861 js_value_t *arr = argv[2];
862
863 uint32_t bufs_len;
864 err = js_get_array_length(env, arr, &bufs_len);
865 assert(err == 0);
866
867 uv_buf_t *bufs = malloc(sizeof(uv_buf_t) * bufs_len);
868
869 js_value_t **elements = malloc(bufs_len * sizeof(js_value_t *));
870
871 err = js_get_array_elements(env, arr, elements, bufs_len, 0, NULL);
872 assert(err == 0);
873
874 for (uint32_t i = 0; i < bufs_len; i++) {
875 js_value_t *item = elements[i];
876
877 uv_buf_t *buf = &bufs[i];
878 err = js_get_typedarray_info(env, item, NULL, (void **) &buf->base, (size_t *) &buf->len, NULL, NULL);
879 assert(err == 0);
880 }
881
882 err = uv_fs_write(loop, &req->handle, fd, bufs, bufs_len, pos, async ? bare_fs__on_writev : NULL);
883 (void) err;
884
885 free(elements);
886 free(bufs);
887
888 int status;
889 err = bare_fs__request_pending(env, req, async, &status);
890 if (err != 1) return NULL;
891
892 js_value_t *result;
893 err = js_create_int32(env, status, &result);
894 assert(err == 0);
895
896 return result;
897}
898
899static js_value_t *
900bare_fs_writev(js_env_t *env, js_callback_info_t *info) {
901 return bare_fs__writev(env, info, bare_fs_async);
902}
903
904static js_value_t *
905bare_fs_writev_sync(js_env_t *env, js_callback_info_t *info) {
906 return bare_fs__writev(env, info, bare_fs_sync);
907}
908
909static void
910bare_fs__on_ftruncate(uv_fs_t *handle) {
911 bare_fs__on_request_result(handle);
912}
913
914static inline js_value_t *
915bare_fs__ftruncate(js_env_t *env, js_callback_info_t *info, bool async) {
916 int err;
917
918 size_t argc = 3;
919 js_value_t *argv[3];
920
921 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
922 assert(err == 0);
923
924 assert(argc == 3);
925
926 bare_fs_req_t *req;
927 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
928 assert(err == 0);
929
930 uint32_t fd;
931 err = js_get_value_uint32(env, argv[1], &fd);
932 assert(err == 0);
933
934 int64_t len;
935 err = js_get_value_int64(env, argv[2], &len);
936 assert(err == 0);
937
938 uv_loop_t *loop;
939 err = js_get_env_loop(env, &loop);
940 assert(err == 0);
941
942 err = uv_fs_ftruncate(loop, &req->handle, fd, len, async ? bare_fs__on_ftruncate : NULL);
943 (void) err;
944
945 err = bare_fs__request_pending(env, req, async, NULL);
946 (void) err;
947
948 return NULL;
949}
950
951static js_value_t *
952bare_fs_ftruncate(js_env_t *env, js_callback_info_t *info) {
953 return bare_fs__ftruncate(env, info, bare_fs_async);
954}
955
956static js_value_t *
957bare_fs_ftruncate_sync(js_env_t *env, js_callback_info_t *info) {
958 return bare_fs__ftruncate(env, info, bare_fs_sync);
959}
960
961static void
962bare_fs__on_chmod(uv_fs_t *handle) {
963 bare_fs__on_request_result(handle);
964}
965
966static inline js_value_t *
967bare_fs__chmod(js_env_t *env, js_callback_info_t *info, bool async) {
968 int err;
969
970 size_t argc = 3;
971 js_value_t *argv[3];
972
973 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
974 assert(err == 0);
975
976 assert(argc == 3);
977
978 bare_fs_req_t *req;
979 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
980 assert(err == 0);
981
982 bare_fs_path_t path;
983 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
984 assert(err == 0);
985
986 int32_t mode;
987 err = js_get_value_int32(env, argv[2], &mode);
988 assert(err == 0);
989
990 uv_loop_t *loop;
991 err = js_get_env_loop(env, &loop);
992 assert(err == 0);
993
994 err = uv_fs_chmod(loop, &req->handle, (char *) path, mode, async ? bare_fs__on_chmod : NULL);
995 (void) err;
996
997 err = bare_fs__request_pending(env, req, async, NULL);
998 (void) err;
999
1000 return NULL;
1001}
1002
1003static js_value_t *
1004bare_fs_chmod(js_env_t *env, js_callback_info_t *info) {
1005 return bare_fs__chmod(env, info, bare_fs_async);
1006}
1007
1008static js_value_t *
1009bare_fs_chmod_sync(js_env_t *env, js_callback_info_t *info) {
1010 return bare_fs__chmod(env, info, bare_fs_sync);
1011}
1012
1013static void
1014bare_fs__on_fchmod(uv_fs_t *handle) {
1015 bare_fs__on_request_result(handle);
1016}
1017
1018static inline js_value_t *
1019bare_fs__fchmod(js_env_t *env, js_callback_info_t *info, bool async) {
1020 int err;
1021
1022 size_t argc = 3;
1023 js_value_t *argv[3];
1024
1025 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1026 assert(err == 0);
1027
1028 assert(argc == 3);
1029
1030 bare_fs_req_t *req;
1031 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1032 assert(err == 0);
1033
1034 uint32_t fd;
1035 err = js_get_value_uint32(env, argv[1], &fd);
1036 assert(err == 0);
1037
1038 int32_t mode;
1039 err = js_get_value_int32(env, argv[2], &mode);
1040 assert(err == 0);
1041
1042 uv_loop_t *loop;
1043 err = js_get_env_loop(env, &loop);
1044 assert(err == 0);
1045
1046 err = uv_fs_fchmod(loop, &req->handle, fd, mode, async ? bare_fs__on_fchmod : NULL);
1047 (void) err;
1048
1049 err = bare_fs__request_pending(env, req, async, NULL);
1050 (void) err;
1051
1052 return NULL;
1053}
1054
1055static js_value_t *
1056bare_fs_fchmod(js_env_t *env, js_callback_info_t *info) {
1057 return bare_fs__fchmod(env, info, bare_fs_async);
1058}
1059
1060static js_value_t *
1061bare_fs_fchmod_sync(js_env_t *env, js_callback_info_t *info) {
1062 return bare_fs__fchmod(env, info, bare_fs_sync);
1063}
1064
1065static void
1066bare_fs__on_utimes(uv_fs_t *handle) {
1067 bare_fs__on_request_result(handle);
1068}
1069
1070static inline js_value_t *
1071bare_fs__utimes(js_env_t *env, js_callback_info_t *info, bool async) {
1072 int err;
1073
1074 size_t argc = 4;
1075 js_value_t *argv[4];
1076
1077 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1078 assert(err == 0);
1079
1080 assert(argc == 4);
1081
1082 bare_fs_req_t *req;
1083 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1084 assert(err == 0);
1085
1086 bare_fs_path_t path;
1087 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
1088 assert(err == 0);
1089
1090 double atime;
1091 err = js_get_value_double(env, argv[2], &atime);
1092 assert(err == 0);
1093
1094 double mtime;
1095 err = js_get_value_double(env, argv[3], &mtime);
1096 assert(err == 0);
1097
1098 uv_loop_t *loop;
1099 err = js_get_env_loop(env, &loop);
1100 assert(err == 0);
1101
1102 err = uv_fs_utime(loop, &req->handle, (char *) path, atime, mtime, async ? bare_fs__on_utimes : NULL);
1103 (void) err;
1104
1105 err = bare_fs__request_pending(env, req, async, NULL);
1106 (void) err;
1107
1108 return NULL;
1109}
1110
1111static js_value_t *
1112bare_fs_utimes(js_env_t *env, js_callback_info_t *info) {
1113 return bare_fs__utimes(env, info, bare_fs_async);
1114}
1115
1116static js_value_t *
1117bare_fs_utimes_sync(js_env_t *env, js_callback_info_t *info) {
1118 return bare_fs__utimes(env, info, bare_fs_sync);
1119}
1120
1121static void
1122bare_fs__on_rename(uv_fs_t *handle) {
1123 bare_fs__on_request_result(handle);
1124}
1125
1126static inline js_value_t *
1127bare_fs__rename(js_env_t *env, js_callback_info_t *info, bool async) {
1128 int err;
1129
1130 size_t argc = 3;
1131 js_value_t *argv[3];
1132
1133 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1134 assert(err == 0);
1135
1136 assert(argc == 3);
1137
1138 bare_fs_req_t *req;
1139 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1140 assert(err == 0);
1141
1142 bare_fs_path_t src;
1143 err = js_get_value_string_utf8(env, argv[1], src, sizeof(bare_fs_path_t), NULL);
1144 assert(err == 0);
1145
1146 bare_fs_path_t dst;
1147 err = js_get_value_string_utf8(env, argv[2], dst, sizeof(bare_fs_path_t), NULL);
1148 assert(err == 0);
1149
1150 uv_loop_t *loop;
1151 err = js_get_env_loop(env, &loop);
1152 assert(err == 0);
1153
1154 err = uv_fs_rename(loop, &req->handle, (char *) src, (char *) dst, async ? bare_fs__on_rename : NULL);
1155 (void) err;
1156
1157 err = bare_fs__request_pending(env, req, async, NULL);
1158 (void) err;
1159
1160 return NULL;
1161}
1162
1163static js_value_t *
1164bare_fs_rename(js_env_t *env, js_callback_info_t *info) {
1165 return bare_fs__rename(env, info, bare_fs_async);
1166}
1167
1168static js_value_t *
1169bare_fs_rename_sync(js_env_t *env, js_callback_info_t *info) {
1170 return bare_fs__rename(env, info, bare_fs_sync);
1171}
1172
1173static void
1174bare_fs__on_copyfile(uv_fs_t *handle) {
1175 bare_fs__on_request_result(handle);
1176}
1177
1178static inline js_value_t *
1179bare_fs__copyfile(js_env_t *env, js_callback_info_t *info, bool async) {
1180 int err;
1181
1182 size_t argc = 4;
1183 js_value_t *argv[4];
1184
1185 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1186 assert(err == 0);
1187
1188 assert(argc == 4);
1189
1190 bare_fs_req_t *req;
1191 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1192 assert(err == 0);
1193
1194 bare_fs_path_t src;
1195 err = js_get_value_string_utf8(env, argv[1], src, sizeof(bare_fs_path_t), NULL);
1196 assert(err == 0);
1197
1198 bare_fs_path_t dst;
1199 err = js_get_value_string_utf8(env, argv[2], dst, sizeof(bare_fs_path_t), NULL);
1200 assert(err == 0);
1201
1202 int32_t mode;
1203 err = js_get_value_int32(env, argv[3], &mode);
1204 assert(err == 0);
1205
1206 uv_loop_t *loop;
1207 err = js_get_env_loop(env, &loop);
1208 assert(err == 0);
1209
1210 err = uv_fs_copyfile(loop, &req->handle, (char *) src, (char *) dst, mode, async ? bare_fs__on_copyfile : NULL);
1211 (void) err;
1212
1213 err = bare_fs__request_pending(env, req, async, NULL);
1214 (void) err;
1215
1216 return NULL;
1217}
1218
1219static js_value_t *
1220bare_fs_copyfile(js_env_t *env, js_callback_info_t *info) {
1221 return bare_fs__copyfile(env, info, bare_fs_async);
1222}
1223
1224static js_value_t *
1225bare_fs_copyfile_sync(js_env_t *env, js_callback_info_t *info) {
1226 return bare_fs__copyfile(env, info, bare_fs_sync);
1227}
1228
1229static void
1230bare_fs__on_mkdir(uv_fs_t *handle) {
1231 bare_fs__on_request_result(handle);
1232}
1233
1234static inline js_value_t *
1235bare_fs__mkdir(js_env_t *env, js_callback_info_t *info, bool async) {
1236 int err;
1237
1238 size_t argc = 3;
1239 js_value_t *argv[3];
1240
1241 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1242 assert(err == 0);
1243
1244 assert(argc == 3);
1245
1246 bare_fs_req_t *req;
1247 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1248 assert(err == 0);
1249
1250 bare_fs_path_t path;
1251 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
1252 assert(err == 0);
1253
1254 int32_t mode;
1255 err = js_get_value_int32(env, argv[2], &mode);
1256 assert(err == 0);
1257
1258 uv_loop_t *loop;
1259 err = js_get_env_loop(env, &loop);
1260 assert(err == 0);
1261
1262 err = uv_fs_mkdir(loop, &req->handle, (char *) path, mode, async ? bare_fs__on_mkdir : NULL);
1263 (void) err;
1264
1265 err = bare_fs__request_pending(env, req, async, NULL);
1266 (void) err;
1267
1268 return NULL;
1269}
1270
1271static js_value_t *
1272bare_fs_mkdir(js_env_t *env, js_callback_info_t *info) {
1273 return bare_fs__mkdir(env, info, bare_fs_async);
1274}
1275
1276static js_value_t *
1277bare_fs_mkdir_sync(js_env_t *env, js_callback_info_t *info) {
1278 return bare_fs__mkdir(env, info, bare_fs_sync);
1279}
1280
1281static void
1282bare_fs__on_rmdir(uv_fs_t *handle) {
1283 bare_fs__on_request_result(handle);
1284}
1285
1286static inline js_value_t *
1287bare_fs__rmdir(js_env_t *env, js_callback_info_t *info, bool async) {
1288 int err;
1289
1290 size_t argc = 2;
1291 js_value_t *argv[2];
1292
1293 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1294 assert(err == 0);
1295
1296 assert(argc == 2);
1297
1298 bare_fs_req_t *req;
1299 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1300 assert(err == 0);
1301
1302 bare_fs_path_t path;
1303 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
1304 assert(err == 0);
1305
1306 uv_loop_t *loop;
1307 err = js_get_env_loop(env, &loop);
1308 assert(err == 0);
1309
1310 err = uv_fs_rmdir(loop, &req->handle, (char *) path, async ? bare_fs__on_rmdir : NULL);
1311 (void) err;
1312
1313 err = bare_fs__request_pending(env, req, async, NULL);
1314 (void) err;
1315
1316 return NULL;
1317}
1318
1319static js_value_t *
1320bare_fs_rmdir(js_env_t *env, js_callback_info_t *info) {
1321 return bare_fs__rmdir(env, info, bare_fs_async);
1322}
1323
1324static js_value_t *
1325bare_fs_rmdir_sync(js_env_t *env, js_callback_info_t *info) {
1326 return bare_fs__rmdir(env, info, bare_fs_sync);
1327}
1328
1329static void
1330bare_fs__on_stat(uv_fs_t *handle) {
1331 bare_fs__on_request_result(handle);
1332}
1333
1334static inline js_value_t *
1335bare_fs__stat(js_env_t *env, js_callback_info_t *info, bool async) {
1336 int err;
1337
1338 size_t argc = 2;
1339 js_value_t *argv[2];
1340
1341 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1342 assert(err == 0);
1343
1344 assert(argc == 2);
1345
1346 bare_fs_req_t *req;
1347 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1348 assert(err == 0);
1349
1350 bare_fs_path_t path;
1351 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
1352 assert(err == 0);
1353
1354 uv_loop_t *loop;
1355 err = js_get_env_loop(env, &loop);
1356 assert(err == 0);
1357
1358 err = uv_fs_stat(loop, &req->handle, (char *) path, async ? bare_fs__on_stat : NULL);
1359 (void) err;
1360
1361 err = bare_fs__request_pending(env, req, async, NULL);
1362 (void) err;
1363
1364 return NULL;
1365}
1366
1367static js_value_t *
1368bare_fs_stat(js_env_t *env, js_callback_info_t *info) {
1369 return bare_fs__stat(env, info, bare_fs_async);
1370}
1371
1372static js_value_t *
1373bare_fs_stat_sync(js_env_t *env, js_callback_info_t *info) {
1374 return bare_fs__stat(env, info, bare_fs_sync);
1375}
1376
1377static void
1378bare_fs__on_lstat(uv_fs_t *handle) {
1379 bare_fs__on_request_result(handle);
1380}
1381
1382static inline js_value_t *
1383bare_fs__lstat(js_env_t *env, js_callback_info_t *info, bool async) {
1384 int err;
1385
1386 size_t argc = 2;
1387 js_value_t *argv[2];
1388
1389 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1390 assert(err == 0);
1391
1392 assert(argc == 2);
1393
1394 bare_fs_req_t *req;
1395 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1396 assert(err == 0);
1397
1398 bare_fs_path_t path;
1399 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
1400 assert(err == 0);
1401
1402 uv_loop_t *loop;
1403 err = js_get_env_loop(env, &loop);
1404 assert(err == 0);
1405
1406 err = uv_fs_lstat(loop, &req->handle, (char *) path, async ? bare_fs__on_lstat : NULL);
1407 (void) err;
1408
1409 err = bare_fs__request_pending(env, req, async, NULL);
1410 (void) err;
1411
1412 return NULL;
1413}
1414
1415static js_value_t *
1416bare_fs_lstat(js_env_t *env, js_callback_info_t *info) {
1417 return bare_fs__lstat(env, info, bare_fs_async);
1418}
1419
1420static js_value_t *
1421bare_fs_lstat_sync(js_env_t *env, js_callback_info_t *info) {
1422 return bare_fs__lstat(env, info, bare_fs_sync);
1423}
1424
1425static void
1426bare_fs__on_fstat(uv_fs_t *handle) {
1427 bare_fs__on_request_result(handle);
1428}
1429
1430static inline js_value_t *
1431bare_fs__fstat(js_env_t *env, js_callback_info_t *info, bool async) {
1432 int err;
1433
1434 size_t argc = 2;
1435 js_value_t *argv[2];
1436
1437 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1438 assert(err == 0);
1439
1440 assert(argc == 2);
1441
1442 bare_fs_req_t *req;
1443 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1444 assert(err == 0);
1445
1446 uint32_t fd;
1447 err = js_get_value_uint32(env, argv[1], &fd);
1448 assert(err == 0);
1449
1450 uv_loop_t *loop;
1451 err = js_get_env_loop(env, &loop);
1452 assert(err == 0);
1453
1454 err = uv_fs_fstat(loop, &req->handle, fd, async ? bare_fs__on_fstat : NULL);
1455 (void) err;
1456
1457 err = bare_fs__request_pending(env, req, async, NULL);
1458 (void) err;
1459
1460 return NULL;
1461}
1462
1463static js_value_t *
1464bare_fs_fstat(js_env_t *env, js_callback_info_t *info) {
1465 return bare_fs__fstat(env, info, bare_fs_async);
1466}
1467
1468static js_value_t *
1469bare_fs_fstat_sync(js_env_t *env, js_callback_info_t *info) {
1470 return bare_fs__fstat(env, info, bare_fs_sync);
1471}
1472
1473static void
1474bare_fs__on_unlink(uv_fs_t *handle) {
1475 bare_fs__on_request_result(handle);
1476}
1477
1478static inline js_value_t *
1479bare_fs__unlink(js_env_t *env, js_callback_info_t *info, bool async) {
1480 int err;
1481
1482 size_t argc = 2;
1483 js_value_t *argv[2];
1484
1485 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1486 assert(err == 0);
1487
1488 assert(argc == 2);
1489
1490 bare_fs_req_t *req;
1491 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1492 assert(err == 0);
1493
1494 bare_fs_path_t path;
1495 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
1496 assert(err == 0);
1497
1498 uv_loop_t *loop;
1499 err = js_get_env_loop(env, &loop);
1500 assert(err == 0);
1501
1502 err = uv_fs_unlink(loop, &req->handle, (char *) path, async ? bare_fs__on_unlink : NULL);
1503 (void) err;
1504
1505 err = bare_fs__request_pending(env, req, async, NULL);
1506 (void) err;
1507
1508 return NULL;
1509}
1510
1511static js_value_t *
1512bare_fs_unlink(js_env_t *env, js_callback_info_t *info) {
1513 return bare_fs__unlink(env, info, bare_fs_async);
1514}
1515
1516static js_value_t *
1517bare_fs_unlink_sync(js_env_t *env, js_callback_info_t *info) {
1518 return bare_fs__unlink(env, info, bare_fs_sync);
1519}
1520
1521static void
1522bare_fs__on_realpath(uv_fs_t *handle) {
1523 bare_fs__on_request_result(handle);
1524}
1525
1526static inline js_value_t *
1527bare_fs__realpath(js_env_t *env, js_callback_info_t *info, bool async) {
1528 int err;
1529
1530 size_t argc = 2;
1531 js_value_t *argv[2];
1532
1533 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1534 assert(err == 0);
1535
1536 assert(argc == 2);
1537
1538 bare_fs_req_t *req;
1539 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1540 assert(err == 0);
1541
1542 bare_fs_path_t path;
1543 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
1544 assert(err == 0);
1545
1546 uv_loop_t *loop;
1547 err = js_get_env_loop(env, &loop);
1548 assert(err == 0);
1549
1550 err = uv_fs_realpath(loop, &req->handle, (char *) path, async ? bare_fs__on_realpath : NULL);
1551 (void) err;
1552
1553 err = bare_fs__request_pending(env, req, async, NULL);
1554 (void) err;
1555
1556 return NULL;
1557}
1558
1559static js_value_t *
1560bare_fs_realpath(js_env_t *env, js_callback_info_t *info) {
1561 return bare_fs__realpath(env, info, bare_fs_async);
1562}
1563
1564static js_value_t *
1565bare_fs_realpath_sync(js_env_t *env, js_callback_info_t *info) {
1566 return bare_fs__realpath(env, info, bare_fs_sync);
1567}
1568
1569static void
1570bare_fs__on_readlink(uv_fs_t *handle) {
1571 bare_fs__on_request_result(handle);
1572}
1573
1574static inline js_value_t *
1575bare_fs__readlink(js_env_t *env, js_callback_info_t *info, bool async) {
1576 int err;
1577
1578 size_t argc = 2;
1579 js_value_t *argv[2];
1580
1581 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1582 assert(err == 0);
1583
1584 assert(argc == 2);
1585
1586 bare_fs_req_t *req;
1587 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1588 assert(err == 0);
1589
1590 bare_fs_path_t path;
1591 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
1592 assert(err == 0);
1593
1594 uv_loop_t *loop;
1595 err = js_get_env_loop(env, &loop);
1596 assert(err == 0);
1597
1598 err = uv_fs_readlink(loop, &req->handle, (char *) path, async ? bare_fs__on_readlink : NULL);
1599 (void) err;
1600
1601 err = bare_fs__request_pending(env, req, async, NULL);
1602 (void) err;
1603
1604 return NULL;
1605}
1606
1607static js_value_t *
1608bare_fs_readlink(js_env_t *env, js_callback_info_t *info) {
1609 return bare_fs__readlink(env, info, bare_fs_async);
1610}
1611
1612static js_value_t *
1613bare_fs_readlink_sync(js_env_t *env, js_callback_info_t *info) {
1614 return bare_fs__readlink(env, info, bare_fs_sync);
1615}
1616
1617static void
1618bare_fs__on_symlink(uv_fs_t *handle) {
1619 bare_fs__on_request_result(handle);
1620}
1621
1622static inline js_value_t *
1623bare_fs__symlink(js_env_t *env, js_callback_info_t *info, bool async) {
1624 int err;
1625
1626 size_t argc = 4;
1627 js_value_t *argv[4];
1628
1629 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1630 assert(err == 0);
1631
1632 assert(argc == 4);
1633
1634 bare_fs_req_t *req;
1635 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1636 assert(err == 0);
1637
1638 bare_fs_path_t target;
1639 err = js_get_value_string_utf8(env, argv[1], target, sizeof(bare_fs_path_t), NULL);
1640 assert(err == 0);
1641
1642 bare_fs_path_t path;
1643 err = js_get_value_string_utf8(env, argv[2], path, sizeof(bare_fs_path_t), NULL);
1644 assert(err == 0);
1645
1646 int32_t flags;
1647 err = js_get_value_int32(env, argv[3], &flags);
1648 assert(err == 0);
1649
1650 uv_loop_t *loop;
1651 err = js_get_env_loop(env, &loop);
1652 assert(err == 0);
1653
1654 err = uv_fs_symlink(loop, &req->handle, (char *) target, (char *) path, flags, async ? bare_fs__on_symlink : NULL);
1655 (void) err;
1656
1657 err = bare_fs__request_pending(env, req, async, NULL);
1658 (void) err;
1659
1660 return NULL;
1661}
1662
1663static js_value_t *
1664bare_fs_symlink(js_env_t *env, js_callback_info_t *info) {
1665 return bare_fs__symlink(env, info, bare_fs_async);
1666}
1667
1668static js_value_t *
1669bare_fs_symlink_sync(js_env_t *env, js_callback_info_t *info) {
1670 return bare_fs__symlink(env, info, bare_fs_sync);
1671}
1672
1673static void
1674bare_fs__on_opendir(uv_fs_t *handle) {
1675 int err;
1676
1677 bare_fs_req_t *req = (bare_fs_req_t *) handle;
1678
1679 int status = handle->result;
1680
1681 if (req->exiting && status >= 0) {
1682 uv_dir_t *dir = handle->ptr;
1683
1684 uv_fs_req_cleanup(handle);
1685
1686 err = uv_fs_closedir(handle->loop, handle, dir, NULL);
1687 assert(err == 0);
1688 }
1689
1690 bare_fs__on_request_result(handle);
1691}
1692
1693static inline js_value_t *
1694bare_fs__opendir(js_env_t *env, js_callback_info_t *info, bool async) {
1695 int err;
1696
1697 size_t argc = 2;
1698 js_value_t *argv[2];
1699
1700 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1701 assert(err == 0);
1702
1703 assert(argc == 2);
1704
1705 bare_fs_req_t *req;
1706 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1707 assert(err == 0);
1708
1709 bare_fs_path_t path;
1710 err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL);
1711 assert(err == 0);
1712
1713 uv_loop_t *loop;
1714 err = js_get_env_loop(env, &loop);
1715 assert(err == 0);
1716
1717 err = uv_fs_opendir(loop, &req->handle, (char *) path, async ? bare_fs__on_opendir : NULL);
1718 (void) err;
1719
1720 err = bare_fs__request_pending(env, req, async, NULL);
1721 (void) err;
1722
1723 return NULL;
1724}
1725
1726static js_value_t *
1727bare_fs_opendir(js_env_t *env, js_callback_info_t *info) {
1728 return bare_fs__opendir(env, info, bare_fs_async);
1729}
1730
1731static js_value_t *
1732bare_fs_opendir_sync(js_env_t *env, js_callback_info_t *info) {
1733 return bare_fs__opendir(env, info, bare_fs_sync);
1734}
1735
1736static void
1737bare_fs__on_readdir(uv_fs_t *handle) {
1738 bare_fs__on_request_result(handle);
1739}
1740
1741static inline js_value_t *
1742bare_fs__readdir(js_env_t *env, js_callback_info_t *info, bool async) {
1743 int err;
1744
1745 size_t argc = 3;
1746 js_value_t *argv[3];
1747
1748 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1749 assert(err == 0);
1750
1751 assert(argc == 3);
1752
1753 bare_fs_req_t *req;
1754 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1755 assert(err == 0);
1756
1757 bare_fs_dir_t *dir;
1758 err = js_get_arraybuffer_info(env, argv[1], (void **) &dir, NULL);
1759 assert(err == 0);
1760
1761 uint32_t capacity;
1762 err = js_get_value_uint32(env, argv[2], &capacity);
1763 assert(err == 0);
1764
1765 js_value_t *result;
1766
1767 bare_fs_dirent_t *dirents;
1768 err = js_create_arraybuffer(env, capacity * sizeof(bare_fs_dirent_t), (void **) &dirents, &result);
1769 assert(err == 0);
1770
1771 uv_loop_t *loop;
1772 err = js_get_env_loop(env, &loop);
1773 assert(err == 0);
1774
1775 dir->handle->dirents = dirents;
1776 dir->handle->nentries = capacity;
1777
1778 err = uv_fs_readdir(loop, &req->handle, dir->handle, async ? bare_fs__on_readdir : NULL);
1779 (void) err;
1780
1781 err = bare_fs__request_pending(env, req, async, NULL);
1782 (void) err;
1783
1784 return result;
1785}
1786
1787static js_value_t *
1788bare_fs_readdir(js_env_t *env, js_callback_info_t *info) {
1789 return bare_fs__readdir(env, info, bare_fs_async);
1790}
1791
1792static js_value_t *
1793bare_fs_readdir_sync(js_env_t *env, js_callback_info_t *info) {
1794 return bare_fs__readdir(env, info, bare_fs_sync);
1795}
1796
1797static void
1798bare_fs__on_closedir(uv_fs_t *handle) {
1799 bare_fs__on_request_result(handle);
1800}
1801
1802static inline js_value_t *
1803bare_fs__closedir(js_env_t *env, js_callback_info_t *info, bool async) {
1804 int err;
1805
1806 size_t argc = 2;
1807 js_value_t *argv[2];
1808
1809 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1810 assert(err == 0);
1811
1812 assert(argc == 2);
1813
1814 bare_fs_req_t *req;
1815 err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL);
1816 assert(err == 0);
1817
1818 bare_fs_dir_t *dir;
1819 err = js_get_arraybuffer_info(env, argv[1], (void **) &dir, NULL);
1820 assert(err == 0);
1821
1822 uv_loop_t *loop;
1823 err = js_get_env_loop(env, &loop);
1824 assert(err == 0);
1825
1826 err = uv_fs_closedir(loop, &req->handle, dir->handle, async ? bare_fs__on_closedir : NULL);
1827 (void) err;
1828
1829 err = bare_fs__request_pending(env, req, async, NULL);
1830 (void) err;
1831
1832 return NULL;
1833}
1834
1835static js_value_t *
1836bare_fs_closedir(js_env_t *env, js_callback_info_t *info) {
1837 return bare_fs__closedir(env, info, bare_fs_async);
1838}
1839
1840static js_value_t *
1841bare_fs_closedir_sync(js_env_t *env, js_callback_info_t *info) {
1842 return bare_fs__closedir(env, info, bare_fs_sync);
1843}
1844
1845static void
1846bare_fs__on_watcher_event(uv_fs_event_t *handle, const char *filename, int events, int status) {
1847 int err;
1848
1849 bare_fs_watcher_t *watcher = (bare_fs_watcher_t *) handle;
1850
1851 if (watcher->exiting) return;
1852
1853 js_env_t *env = watcher->env;
1854
1855 js_handle_scope_t *scope;
1856 err = js_open_handle_scope(env, &scope);
1857 assert(err == 0);
1858
1859 js_value_t *ctx;
1860 err = js_get_reference_value(env, watcher->ctx, &ctx);
1861 assert(err == 0);
1862
1863 js_value_t *on_event;
1864 err = js_get_reference_value(env, watcher->on_event, &on_event);
1865 assert(err == 0);
1866
1867 js_value_t *args[3];
1868
1869 if (status < 0) {
1870 js_value_t *code;
1871 err = js_create_string_utf8(env, (utf8_t *) uv_err_name(status), -1, &code);
1872 assert(err == 0);
1873
1874 js_value_t *message;
1875 err = js_create_string_utf8(env, (utf8_t *) uv_strerror(status), -1, &message);
1876 assert(err == 0);
1877
1878 err = js_create_error(env, code, message, &args[0]);
1879 assert(err == 0);
1880
1881 err = js_create_int32(env, 0, &args[1]);
1882 assert(err == 0);
1883
1884 err = js_get_null(env, &args[2]);
1885 assert(err == 0);
1886 } else {
1887 err = js_get_null(env, &args[0]);
1888 assert(err == 0);
1889
1890 err = js_create_int32(env, events, &args[1]);
1891 assert(err == 0);
1892
1893 size_t len = strlen(filename);
1894
1895 void *data;
1896 err = js_create_arraybuffer(env, len, &data, &args[2]);
1897 assert(err == 0);
1898
1899 memcpy(data, (void *) filename, len);
1900 }
1901
1902 err = js_call_function(env, ctx, on_event, 3, args, NULL);
1903 (void) err;
1904
1905 err = js_close_handle_scope(env, scope);
1906 assert(err == 0);
1907}
1908
1909static void
1910bare_fs__on_watcher_close(uv_handle_t *handle) {
1911 int err;
1912
1913 bare_fs_watcher_t *watcher = (bare_fs_watcher_t *) handle;
1914
1915 js_env_t *env = watcher->env;
1916
1917 js_deferred_teardown_t *teardown = watcher->teardown;
1918
1919 if (watcher->exiting) {
1920 err = js_delete_reference(env, watcher->on_event);
1921 assert(err == 0);
1922
1923 err = js_delete_reference(env, watcher->on_close);
1924 assert(err == 0);
1925
1926 err = js_delete_reference(env, watcher->ctx);
1927 assert(err == 0);
1928 } else {
1929 js_handle_scope_t *scope;
1930 err = js_open_handle_scope(env, &scope);
1931 assert(err == 0);
1932
1933 js_value_t *ctx;
1934 err = js_get_reference_value(env, watcher->ctx, &ctx);
1935 assert(err == 0);
1936
1937 js_value_t *on_close;
1938 err = js_get_reference_value(env, watcher->on_close, &on_close);
1939 assert(err == 0);
1940
1941 err = js_delete_reference(env, watcher->on_event);
1942 assert(err == 0);
1943
1944 err = js_delete_reference(env, watcher->on_close);
1945 assert(err == 0);
1946
1947 err = js_delete_reference(env, watcher->ctx);
1948 assert(err == 0);
1949
1950 err = js_call_function(env, ctx, on_close, 0, NULL, NULL);
1951 (void) err;
1952
1953 err = js_close_handle_scope(env, scope);
1954 assert(err == 0);
1955 }
1956
1957 err = js_finish_deferred_teardown_callback(teardown);
1958 assert(err == 0);
1959}
1960
1961static void
1962bare_fs__on_watcher_teardown(js_deferred_teardown_t *handle, void *data) {
1963 bare_fs_watcher_t *watcher = (bare_fs_watcher_t *) data;
1964
1965 watcher->exiting = true;
1966
1967 if (watcher->closing) return;
1968
1969 uv_close((uv_handle_t *) &watcher->handle, bare_fs__on_watcher_close);
1970}
1971
1972static js_value_t *
1973bare_fs_watcher_init(js_env_t *env, js_callback_info_t *info) {
1974 int err;
1975
1976 size_t argc = 5;
1977 js_value_t *argv[5];
1978
1979 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1980 assert(err == 0);
1981
1982 assert(argc == 5);
1983
1984 bare_fs_path_t path;
1985 err = js_get_value_string_utf8(env, argv[0], path, sizeof(bare_fs_path_t), NULL);
1986 assert(err == 0);
1987
1988 bool recursive;
1989 err = js_get_value_bool(env, argv[1], &recursive);
1990 assert(err == 0);
1991
1992 js_value_t *result;
1993
1994 bare_fs_watcher_t *watcher;
1995 err = js_create_arraybuffer(env, sizeof(bare_fs_watcher_t), (void **) &watcher, &result);
1996 assert(err == 0);
1997
1998 uv_loop_t *loop;
1999 err = js_get_env_loop(env, &loop);
2000 assert(err == 0);
2001
2002 err = uv_fs_event_init(loop, &watcher->handle);
2003
2004 if (err < 0) {
2005 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
2006 assert(err == 0);
2007
2008 return NULL;
2009 }
2010
2011 err = uv_fs_event_start(&watcher->handle, bare_fs__on_watcher_event, (char *) path, recursive ? UV_FS_EVENT_RECURSIVE : 0);
2012 assert(err == 0);
2013
2014 watcher->env = env;
2015 watcher->closing = false;
2016 watcher->exiting = false;
2017
2018 err = js_create_reference(env, argv[2], 1, &watcher->ctx);
2019 assert(err == 0);
2020
2021 err = js_create_reference(env, argv[3], 1, &watcher->on_event);
2022 assert(err == 0);
2023
2024 err = js_create_reference(env, argv[4], 1, &watcher->on_close);
2025 assert(err == 0);
2026
2027 err = js_add_deferred_teardown_callback(env, bare_fs__on_watcher_teardown, (void *) watcher, &watcher->teardown);
2028 assert(err == 0);
2029
2030 return result;
2031}
2032
2033static js_value_t *
2034bare_fs_watcher_close(js_env_t *env, js_callback_info_t *info) {
2035 int err;
2036
2037 size_t argc = 1;
2038 js_value_t *argv[1];
2039
2040 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
2041 assert(err == 0);
2042
2043 assert(argc == 1);
2044
2045 bare_fs_watcher_t *watcher;
2046 err = js_get_arraybuffer_info(env, argv[0], (void **) &watcher, NULL);
2047 assert(err == 0);
2048
2049 err = uv_fs_event_stop(&watcher->handle);
2050 assert(err == 0);
2051
2052 watcher->closing = true;
2053
2054 uv_close((uv_handle_t *) &watcher->handle, bare_fs__on_watcher_close);
2055
2056 return NULL;
2057}
2058
2059static js_value_t *
2060bare_fs_watcher_ref(js_env_t *env, js_callback_info_t *info) {
2061 int err;
2062
2063 size_t argc = 1;
2064 js_value_t *argv[1];
2065
2066 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
2067 assert(err == 0);
2068
2069 assert(argc == 1);
2070
2071 bare_fs_watcher_t *watcher;
2072 err = js_get_arraybuffer_info(env, argv[0], (void **) &watcher, NULL);
2073 assert(err == 0);
2074
2075 uv_ref((uv_handle_t *) &watcher->handle);
2076
2077 return NULL;
2078}
2079
2080static js_value_t *
2081bare_fs_watcher_unref(js_env_t *env, js_callback_info_t *info) {
2082 int err;
2083
2084 size_t argc = 1;
2085 js_value_t *argv[1];
2086
2087 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
2088 assert(err == 0);
2089
2090 assert(argc == 1);
2091
2092 bare_fs_watcher_t *watcher;
2093 err = js_get_arraybuffer_info(env, argv[0], (void **) &watcher, NULL);
2094 assert(err == 0);
2095
2096 uv_unref((uv_handle_t *) &watcher->handle);
2097
2098 return NULL;
2099}
2100
2101static js_value_t *
2102bare_fs_exports(js_env_t *env, js_value_t *exports) {
2103 int err;
2104
2105#define V(name, fn) \
2106 { \
2107 js_value_t *val; \
2108 err = js_create_function(env, name, -1, fn, NULL, &val); \
2109 assert(err == 0); \
2110 err = js_set_named_property(env, exports, name, val); \
2111 assert(err == 0); \
2112 }
2113
2114 V("requestInit", bare_fs_request_init)
2115 V("requestDestroy", bare_fs_request_destroy)
2116 V("requestReset", bare_fs_request_reset)
2117 V("requestResultStat", bare_fs_request_result_stat)
2118 V("requestResultString", bare_fs_request_result_string)
2119 V("requestResultDir", bare_fs_request_result_dir)
2120 V("requestResultDirents", bare_fs_request_result_dirents)
2121
2122 V("open", bare_fs_open)
2123 V("openSync", bare_fs_open_sync)
2124 V("close", bare_fs_close)
2125 V("closeSync", bare_fs_close_sync)
2126 V("access", bare_fs_access)
2127 V("accessSync", bare_fs_access_sync)
2128 V("read", bare_fs_read)
2129 V("readSync", bare_fs_read_sync)
2130 V("readv", bare_fs_readv)
2131 V("readvSync", bare_fs_readv_sync)
2132 V("write", bare_fs_write)
2133 V("writeSync", bare_fs_write_sync)
2134 V("writev", bare_fs_writev)
2135 V("writevSync", bare_fs_writev_sync)
2136 V("ftruncate", bare_fs_ftruncate)
2137 V("ftruncateSync", bare_fs_ftruncate_sync)
2138 V("chmod", bare_fs_chmod)
2139 V("chmodSync", bare_fs_chmod_sync)
2140 V("fchmod", bare_fs_fchmod)
2141 V("fchmodSync", bare_fs_fchmod_sync)
2142 V("utimes", bare_fs_utimes)
2143 V("utimesSync", bare_fs_utimes_sync)
2144 V("rename", bare_fs_rename)
2145 V("renameSync", bare_fs_rename_sync)
2146 V("copyfile", bare_fs_copyfile)
2147 V("copyfileSync", bare_fs_copyfile_sync)
2148 V("mkdir", bare_fs_mkdir)
2149 V("mkdirSync", bare_fs_mkdir_sync)
2150 V("rmdir", bare_fs_rmdir)
2151 V("rmdirSync", bare_fs_rmdir_sync)
2152 V("stat", bare_fs_stat)
2153 V("statSync", bare_fs_stat_sync)
2154 V("lstat", bare_fs_lstat)
2155 V("lstatSync", bare_fs_lstat_sync)
2156 V("fstat", bare_fs_fstat)
2157 V("fstatSync", bare_fs_fstat_sync)
2158 V("unlink", bare_fs_unlink)
2159 V("unlinkSync", bare_fs_unlink_sync)
2160 V("realpath", bare_fs_realpath)
2161 V("realpathSync", bare_fs_realpath_sync)
2162 V("readlink", bare_fs_readlink)
2163 V("readlinkSync", bare_fs_readlink_sync)
2164 V("symlink", bare_fs_symlink)
2165 V("symlinkSync", bare_fs_symlink_sync)
2166 V("opendir", bare_fs_opendir)
2167 V("opendirSync", bare_fs_opendir_sync)
2168 V("readdir", bare_fs_readdir)
2169 V("readdirSync", bare_fs_readdir_sync)
2170 V("closedir", bare_fs_closedir)
2171 V("closedirSync", bare_fs_closedir_sync)
2172
2173 V("watcherInit", bare_fs_watcher_init)
2174 V("watcherClose", bare_fs_watcher_close)
2175 V("watcherRef", bare_fs_watcher_ref)
2176 V("watcherUnref", bare_fs_watcher_unref)
2177#undef V
2178
2179#define V(name) \
2180 { \
2181 js_value_t *val; \
2182 err = js_create_uint32(env, name, &val); \
2183 assert(err == 0); \
2184 err = js_set_named_property(env, exports, #name, val); \
2185 assert(err == 0); \
2186 }
2187
2188 V(O_RDWR)
2189 V(O_RDONLY)
2190 V(O_WRONLY)
2191 V(O_CREAT)
2192 V(O_TRUNC)
2193 V(O_APPEND)
2194
2195#ifdef F_OK
2196 V(F_OK)
2197#endif
2198#ifdef R_OK
2199 V(R_OK)
2200#endif
2201#ifdef W_OK
2202 V(W_OK)
2203#endif
2204#ifdef X_OK
2205 V(X_OK)
2206#endif
2207
2208 V(S_IFMT)
2209 V(S_IFREG)
2210 V(S_IFDIR)
2211 V(S_IFCHR)
2212 V(S_IFLNK)
2213#ifdef S_IFBLK
2214 V(S_IFBLK)
2215#endif
2216#ifdef S_IFIFO
2217 V(S_IFIFO)
2218#endif
2219#ifdef S_IFSOCK
2220 V(S_IFSOCK)
2221#endif
2222
2223#ifdef S_IRUSR
2224 V(S_IRUSR)
2225#endif
2226#ifdef S_IWUSR
2227 V(S_IWUSR)
2228#endif
2229#ifdef S_IXUSR
2230 V(S_IXUSR)
2231#endif
2232#ifdef S_IRGRP
2233 V(S_IRGRP)
2234#endif
2235#ifdef S_IWGRP
2236 V(S_IWGRP)
2237#endif
2238#ifdef S_IXGRP
2239 V(S_IXGRP)
2240#endif
2241#ifdef S_IROTH
2242 V(S_IROTH)
2243#endif
2244#ifdef S_IWOTH
2245 V(S_IWOTH)
2246#endif
2247#ifdef S_IXOTH
2248 V(S_IXOTH)
2249#endif
2250
2251 V(UV_DIRENT_UNKNOWN)
2252 V(UV_DIRENT_FILE)
2253 V(UV_DIRENT_DIR)
2254 V(UV_DIRENT_LINK)
2255 V(UV_DIRENT_FIFO)
2256 V(UV_DIRENT_SOCKET)
2257 V(UV_DIRENT_CHAR)
2258 V(UV_DIRENT_BLOCK)
2259
2260 V(UV_FS_COPYFILE_EXCL)
2261 V(UV_FS_COPYFILE_FICLONE)
2262 V(UV_FS_COPYFILE_FICLONE_FORCE)
2263 V(UV_FS_SYMLINK_DIR)
2264 V(UV_FS_SYMLINK_JUNCTION)
2265
2266 V(UV_RENAME)
2267 V(UV_CHANGE)
2268#undef V
2269
2270 return exports;
2271}
2272
2273BARE_MODULE(bare_fs, bare_fs_exports)
node_modules/bare-fs/binding.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require.addon()
node_modules/bare-fs/index.d.ts +1115 -0
……@@ -0,0 +1,1115 @@
1import EventEmitter, { EventMap } from 'bare-events'
2import Buffer, { BufferEncoding } from 'bare-buffer'
3import URL from 'bare-url'
4import { Readable, Writable } from 'bare-stream'
5import promises from './promises'
6import constants from './lib/constants'
7
8export { promises, constants }
9
10type Path = string | Buffer | URL
11
12type Flag =
13 | 'a'
14 | 'a+'
15 | 'as'
16 | 'as+'
17 | 'ax'
18 | 'ax+'
19 | 'r'
20 | 'r+'
21 | 'rs'
22 | 'rs+'
23 | 'sa'
24 | 'sa+'
25 | 'sr'
26 | 'sr+'
27 | 'w'
28 | 'w+'
29 | 'wx'
30 | 'wx+'
31 | 'xa'
32 | 'xa+'
33 | 'xw'
34 | 'xw+'
35
36interface Callback<A extends unknown[] = []> {
37 (err: Error | null, ...args: A): void
38}
39
40export interface Dir<T extends string | Buffer = string | Buffer>
41 extends Iterable<Dirent>, AsyncIterable<Dirent> {
42 readonly path: string
43
44 read(): Promise<Dirent<T> | null>
45 read(cb: Callback<[dirent: Dirent<T> | null]>): void
46 readSync(): Dirent<T> | null
47
48 close(): Promise<void>
49 close(cb: Callback): void
50 closeSync(): void
51}
52
53export class Dir {
54 private constructor(path: string, handle: ArrayBuffer, opts?: OpendirOptions)
55}
56
57export interface Dirent<T extends string | Buffer = string | Buffer> {
58 readonly path: string
59 readonly name: T
60 readonly type: number
61
62 isFile(): boolean
63 isDirectory(): boolean
64 isSymbolicLink(): boolean
65 isFIFO(): boolean
66 isSocket(): boolean
67 isCharacterDevice(): boolean
68 isBlockDevice(): boolean
69}
70
71export class Dirent<T extends string | Buffer = string | Buffer> {
72 private constructor(path: string, name: T, type: number)
73}
74
75export interface Stats {
76 readonly dev: number
77 readonly mode: number
78 readonly nlink: number
79 readonly uid: number
80 readonly gid: number
81 readonly rdev: number
82 readonly blksize: number
83 readonly ino: number
84 readonly size: number
85 readonly blocks: number
86 readonly atimeMs: Date
87 readonly mtimeMs: Date
88 readonly ctimeMs: Date
89 readonly birthtimeMs: Date
90
91 isDirectory(): boolean
92 isFile(): boolean
93 isBlockDevice(): boolean
94 isCharacterDevice(): boolean
95 isFIFO(): boolean
96 isSymbolicLink(): boolean
97 isSocket(): boolean
98}
99
100export class Stats {
101 private constructor(
102 dev: number,
103 mode: number,
104 nlink: number,
105 uid: number,
106 gid: number,
107 rdev: number,
108 blksize: number,
109 ino: number,
110 size: number,
111 blocks: number,
112 atimeMs: number,
113 mtimeMs: number,
114 ctimeMs: number,
115 birthtimeMs: number
116 )
117}
118
119export interface ReadStreamOptions {
120 fd?: number
121 flags?: Flag
122 mode?: number
123 start?: number
124 end?: number
125}
126
127export interface ReadStream extends Readable {
128 readonly path: string | null
129 readonly fd: number
130 readonly flags: Flag
131 readonly mode: number
132}
133
134export class ReadStream {
135 private constructor(path: Path | null, opts?: WriteStreamOptions)
136}
137
138export function createReadStream(path: Path | null, opts?: ReadStreamOptions): ReadStream
139
140export interface WriteStreamOptions {
141 fd?: number
142 flags?: Flag
143 mode?: number
144}
145
146export interface WriteStream extends Writable {
147 readonly path: string | null
148 readonly fd: number
149 readonly flags: Flag
150 readonly mode: number
151}
152
153export class WriteStream {
154 private constructor(path: Path | null, opts?: WriteStreamOptions)
155}
156
157export function createWriteStream(path: Path | null, opts?: WriteStreamOptions): WriteStream
158
159export interface WatcherOptions {
160 persistent?: boolean
161 recursive?: boolean
162 encoding?: BufferEncoding | 'buffer'
163}
164
165export type WatcherEventType = 'rename' | 'change'
166
167export interface WatcherEvents<T extends string | Buffer = string | Buffer> extends EventMap {
168 error: [err: Error]
169 change: [eventType: WatcherEventType, filename: T]
170 close: []
171}
172
173export interface Watcher<T extends string | Buffer = string | Buffer>
174 extends
175 EventEmitter<WatcherEvents<T>>,
176 AsyncIterable<{ eventType: WatcherEventType; filename: T }> {
177 close(): void
178 ref(): void
179 unref(): void
180}
181
182export class Watcher {
183 private constructor(path: Path, opts: WatcherOptions)
184}
185
186export function access(filepath: Path, mode?: number): Promise<void>
187
188export function access(filepath: Path, mode: number, cb: Callback): void
189
190export function access(filepath: Path, cb: Callback): void
191
192export function accessSync(filepath: Path, mode?: number): void
193
194export interface AppendFileOptions {
195 encoding?: BufferEncoding
196 flag?: string
197 mode?: number
198}
199
200export function appendFile(
201 filepath: Path,
202 data: string | Buffer | ArrayBufferView,
203 opts?: AppendFileOptions
204): Promise<void>
205
206export function appendFile(
207 filepath: Path,
208 data: string | Buffer | ArrayBufferView,
209 encoding: BufferEncoding
210): Promise<void>
211
212export function appendFile(
213 filepath: Path,
214 data: string | Buffer | ArrayBufferView,
215 opts: AppendFileOptions,
216 cb: Callback
217): void
218
219export function appendFile(
220 filepath: Path,
221 data: string | Buffer | ArrayBufferView,
222 encoding: BufferEncoding,
223 cb: Callback
224): void
225
226export function appendFile(
227 filepath: Path,
228 data: string | Buffer | ArrayBufferView,
229 cb: Callback
230): void
231
232export function appendFileSync(
233 filepath: Path,
234 data: string | Buffer | ArrayBufferView,
235 opts?: AppendFileOptions
236): void
237
238export function appendFileSync(
239 filepath: Path,
240 data: string | Buffer | ArrayBufferView,
241 encoding: BufferEncoding
242): void
243
244export function chmod(filepath: Path, mode: string | number): Promise<void>
245
246export function chmod(filepath: Path, mode: string | number, cb: Callback): void
247
248export function chmodSync(filepath: Path, mode: string | number): void
249
250export function close(fd: number): Promise<void>
251
252export function close(fd: number, cb: Callback): void
253
254export function closeSync(fd: number): void
255
256export function copyFile(src: Path, dst: Path, mode?: number): Promise<void>
257
258export function copyFile(src: Path, dst: Path, mode: number, cb: Callback): void
259
260export function copyFile(src: Path, dst: Path, cb: Callback): void
261
262export function copyFileSync(src: Path, dst: Path, mode?: number): void
263
264export interface CpOptions {
265 recursive?: boolean
266}
267
268export function cp(src: Path, dst: Path, opts?: CpOptions): Promise<void>
269
270export function cp(src: Path, dst: Path, opts: CpOptions, cb: Callback): void
271
272export function cp(src: Path, dst: Path, cb: Callback): void
273
274export function exists(filepath: Path): Promise<boolean>
275
276export function exists(filepath: Path, cb: (exists: boolean) => void): void
277
278export function existsSync(filepath: Path): boolean
279
280export function fchmod(fd: number, mode: string | number): Promise<void>
281
282export function fchmod(fd: number, mode: string | number, cb: Callback): void
283
284export function fchmodSync(fd: number, mode: string | number): void
285
286export function fstat(fd: number): Promise<Stats>
287
288export function fstat(fd: number, cb: Callback<[stats: Stats | null]>): void
289
290export function fstatSync(fd: number): Stats
291
292export function ftruncate(fd: number, len?: number): Promise<void>
293
294export function ftruncate(fd: number, len: number, cb: Callback): void
295
296export function ftruncate(fd: number, cb: Callback): void
297
298export function ftruncateSync(fd: number, len?: number): void
299
300export function lstat(filepath: Path): Promise<Stats>
301
302export function lstat(filepath: Path, cb: Callback<[stats: Stats | null]>): void
303
304export function lstatSync(filepath: Path): Stats
305
306export interface MkdirOptions {
307 mode?: number
308 recursive?: boolean
309}
310
311export function mkdir(filepath: Path, opts?: MkdirOptions): Promise<void>
312
313export function mkdir(filepath: Path, mode: number): Promise<void>
314
315export function mkdir(filepath: Path, opts: MkdirOptions, cb: Callback): void
316
317export function mkdir(filepath: Path, mode: number, cb: Callback): void
318
319export function mkdir(filepath: Path, cb: Callback): void
320
321export function mkdirSync(filepath: Path, opts?: MkdirOptions): void
322
323export function mkdirSync(filepath: Path, mode: number): void
324
325export function open(filepath: Path, flags?: Flag | number, mode?: string | number): Promise<number>
326
327export function open(
328 filepath: Path,
329 flags: Flag | number,
330 mode: string | number,
331 cb: Callback<[fd: number]>
332): void
333
334export function open(filepath: Path, flags: Flag | number, cb: Callback<[fd: number]>): void
335
336export function open(filepath: Path, cb: Callback<[fd: number]>): void
337
338export function openSync(filepath: Path, flags?: Flag | number, mode?: string | number): number
339
340export interface OpendirOptions {
341 encoding?: BufferEncoding | 'buffer'
342 bufferSize?: number
343}
344
345export function opendir(
346 filepath: Path,
347 opts: OpendirOptions & { encoding?: BufferEncoding }
348): Promise<Dir<string>>
349
350export function opendir(
351 filepath: Path,
352 opts: OpendirOptions & { encoding: 'buffer' }
353): Promise<Dir<Buffer>>
354
355export function opendir(filepath: Path, opts: OpendirOptions): Promise<Dir>
356
357export function opendir(filepath: Path, encoding: BufferEncoding): Promise<Dir<string>>
358
359export function opendir(filepath: Path, encoding: 'buffer'): Promise<Dir<Buffer>>
360
361export function opendir(filepath: Path, encoding: BufferEncoding | 'buffer'): Promise<Dir>
362
363export function opendir(filepath: Path): Promise<Dir<string>>
364
365export function opendir(
366 filepath: Path,
367 opts: OpendirOptions & { encoding?: BufferEncoding },
368 cb: Callback<[dir: Dir<string> | null]>
369): void
370
371export function opendir(
372 filepath: Path,
373 opts: OpendirOptions & { encoding: 'buffer' },
374 cb: Callback<[dir: Dir<Buffer> | null]>
375): void
376
377export function opendir(filepath: Path, opts: OpendirOptions, cb: Callback<[dir: Dir | null]>): void
378
379export function opendir(
380 filepath: Path,
381 encoding: BufferEncoding,
382 cb: Callback<[dir: Dir<string> | null]>
383): void
384
385export function opendir(
386 filepath: Path,
387 encoding: 'buffer',
388 cb: Callback<[dir: Dir<Buffer> | null]>
389): void
390
391export function opendir(
392 filepath: Path,
393 encoding: BufferEncoding | 'buffer',
394 cb: Callback<[dir: Dir | null]>
395): void
396
397export function opendir(filepath: Path, cb: Callback<[dir: Dir<string> | null]>): void
398
399export function opendirSync(
400 filepath: Path,
401 opts: OpendirOptions & { encoding?: BufferEncoding }
402): Dir<string>
403
404export function opendirSync(
405 filepath: Path,
406 opts: OpendirOptions & { encoding: 'buffer' }
407): Dir<Buffer>
408
409export function opendirSync(filepath: Path, opts: OpendirOptions): Dir
410
411export function opendirSync(filepath: Path, encoding: BufferEncoding): Dir<string>
412
413export function opendirSync(filepath: Path, encoding: 'buffer'): Dir<Buffer>
414
415export function opendirSync(filepath: Path, encoding: BufferEncoding | 'buffer'): Dir
416
417export function opendirSync(filepath: Path): Dir<string>
418
419export function read(
420 fd: number,
421 buffer: Buffer | ArrayBufferView,
422 offset?: number,
423 len?: number,
424 pos?: number
425): Promise<number>
426
427export function read(
428 fd: number,
429 buffer: Buffer | ArrayBufferView,
430 offset: number,
431 len: number,
432 pos: number,
433 cb: Callback<[len: number]>
434): void
435
436export function read(
437 fd: number,
438 buffer: Buffer | ArrayBufferView,
439 offset: number,
440 len: number,
441 cb: Callback<[len: number]>
442): void
443
444export function read(
445 fd: number,
446 buffer: Buffer | ArrayBufferView,
447 offset: number,
448 cb: Callback<[len: number]>
449): void
450
451export function read(
452 fd: number,
453 buffer: Buffer | ArrayBufferView,
454 cb: Callback<[len: number]>
455): void
456
457export function readSync(
458 fd: number,
459 buffer: Buffer | ArrayBufferView,
460 offset?: number,
461 len?: number,
462 pos?: number
463): number
464
465export interface ReadFileOptions {
466 encoding?: BufferEncoding | 'buffer'
467 flag?: Flag
468}
469
470export function readFile(
471 filepath: Path,
472 opts: ReadFileOptions & { encoding: BufferEncoding }
473): Promise<string>
474
475export function readFile(
476 filepath: Path,
477 opts: ReadFileOptions & { encoding?: 'buffer' }
478): Promise<Buffer>
479
480export function readFile(filepath: Path, opts: ReadFileOptions): Promise<string | Buffer>
481
482export function readFile(filepath: Path, encoding: BufferEncoding): Promise<string>
483
484export function readFile(filepath: Path, encoding: 'buffer'): Promise<Buffer>
485
486export function readFile(
487 filepath: Path,
488 encoding?: BufferEncoding | 'buffer'
489): Promise<string | Buffer>
490
491export function readFile(filepath: Path): Promise<Buffer>
492
493export function readFile(
494 filepath: Path,
495 opts: ReadFileOptions & { encoding: BufferEncoding },
496 cb: Callback<[buffer?: string]>
497): void
498
499export function readFile(
500 filepath: Path,
501 opts: ReadFileOptions & { encoding?: 'buffer' },
502 cb: Callback<[buffer?: Buffer]>
503): void
504
505export function readFile(
506 filepath: Path,
507 opts: ReadFileOptions,
508 cb: Callback<[buffer?: string | Buffer]>
509): void
510
511export function readFile(
512 filepath: Path,
513 encoding: BufferEncoding,
514 cb: Callback<[buffer?: string]>
515): void
516
517export function readFile(filepath: Path, encoding: 'buffer', cb: Callback<[buffer?: Buffer]>): void
518
519export function readFile(
520 filepath: Path,
521 encoding: BufferEncoding | 'buffer',
522 cb: Callback<[buffer?: string | Buffer]>
523): void
524
525export function readFile(filepath: Path, cb: Callback<[buffer?: Buffer]>): void
526
527export function readFileSync(
528 filepath: Path,
529 opts: ReadFileOptions & { encoding: BufferEncoding }
530): string
531
532export function readFileSync(
533 filepath: Path,
534 opts: ReadFileOptions & { encoding?: 'buffer' }
535): Buffer
536
537export function readFileSync(filepath: Path, opts: ReadFileOptions): string | Buffer
538
539export function readFileSync(filepath: Path, encoding: BufferEncoding): string
540
541export function readFileSync(filepath: Path, encoding: 'buffer'): Buffer
542
543export function readFileSync(filepath: Path, encoding?: BufferEncoding | 'buffer'): string | Buffer
544
545export function readFileSync(filepath: Path): Buffer
546
547export interface ReaddirOptions extends OpendirOptions {
548 withFileTypes?: boolean
549}
550export function readdir(
551 filepath: Path,
552 opts: ReaddirOptions & { encoding?: BufferEncoding }
553): Promise<Dir<string>[] | string[]>
554
555export function readdir(
556 filepath: Path,
557 opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes: true }
558): Promise<Dir<string>[]>
559
560export function readdir(
561 filepath: Path,
562 opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes?: false }
563): Promise<string[]>
564
565export function readdir(
566 filepath: Path,
567 opts: ReaddirOptions & { encoding: 'buffer' }
568): Promise<Dir<Buffer>[] | Buffer[]>
569
570export function readdir(
571 filepath: Path,
572 opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes: true }
573): Promise<Dir<Buffer>[]>
574
575export function readdir(
576 filepath: Path,
577 opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes?: false }
578): Promise<Buffer[]>
579
580export function readdir(
581 filepath: Path,
582 opts: ReaddirOptions & { withFileTypes: true }
583): Promise<Dir<string | Buffer>[]>
584
585export function readdir(
586 filepath: Path,
587 opts: ReaddirOptions & { withFileTypes?: false }
588): Promise<string[] | Buffer[]>
589
590export function readdir(filepath: Path, opts: ReaddirOptions): Promise<Dir[] | string[] | Buffer[]>
591
592export function readdir(filepath: Path, encoding: BufferEncoding): Promise<string[]>
593
594export function readdir(filepath: Path, encoding: 'buffer'): Promise<Buffer[]>
595
596export function readdir(
597 filepath: Path,
598 encoding: BufferEncoding | 'buffer'
599): Promise<string[] | Buffer[]>
600
601export function readdir(filepath: Path): Promise<string[]>
602
603export function readdir(
604 filepath: Path,
605 opts: ReaddirOptions & { encoding?: BufferEncoding },
606 cb: Callback<[entries: Dir<string>[] | string[] | null]>
607): void
608
609export function readdir(
610 filepath: Path,
611 opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes: true },
612 cb: Callback<[entries: Dir<string>[] | null]>
613): void
614
615export function readdir(
616 filepath: Path,
617 opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes?: false },
618 cb: Callback<[entries: string[] | null]>
619): void
620
621export function readdir(
622 filepath: Path,
623 opts: ReaddirOptions & { encoding: 'buffer' },
624 cb: Callback<[entries: Dir<Buffer>[] | Buffer[] | null]>
625): void
626
627export function readdir(
628 filepath: Path,
629 opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes: true },
630 cb: Callback<[entries: Dir<Buffer>[] | null]>
631): void
632
633export function readdir(
634 filepath: Path,
635 opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes?: false },
636 cb: Callback<[entries: Buffer[] | null]>
637): void
638
639export function readdir(
640 filepath: Path,
641 opts: ReaddirOptions & { withFileTypes: true },
642 cb: Callback<[entries: Dir<string | Buffer>[] | null]>
643): void
644
645export function readdir(
646 filepath: Path,
647 opts: ReaddirOptions & { withFileTypes?: false },
648 cb: Callback<[entries: string[] | Buffer[] | null]>
649): void
650
651export function readdir(
652 filepath: Path,
653 opts: ReaddirOptions,
654 cb: Callback<[entries: Dir[] | string[] | Buffer[] | null]>
655): void
656
657export function readdir(
658 filepath: Path,
659 encoding: BufferEncoding,
660 cb: Callback<[entries: string[] | null]>
661): void
662
663export function readdir(
664 filepath: Path,
665 encoding: 'buffer',
666 cb: Callback<[entries: Buffer[] | null]>
667): void
668
669export function readdir(
670 filepath: Path,
671 encoding: BufferEncoding | 'buffer',
672 cb: Callback<[entries: string[] | Buffer[] | null]>
673): void
674
675export function readdir(filepath: Path, cb: Callback<[entries: string[] | null]>): void
676
677export function readdirSync(
678 filepath: Path,
679 opts: ReaddirOptions & { encoding?: BufferEncoding }
680): Dir<string>[] | string[]
681
682export function readdirSync(
683 filepath: Path,
684 opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes: true }
685): Dir<string>[]
686
687export function readdirSync(
688 filepath: Path,
689 opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes?: false }
690): string[]
691
692export function readdirSync(
693 filepath: Path,
694 opts: ReaddirOptions & { encoding: 'buffer' }
695): Dir<Buffer>[] | Buffer[]
696
697export function readdirSync(
698 filepath: Path,
699 opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes: true }
700): Dir<Buffer>[]
701
702export function readdirSync(
703 filepath: Path,
704 opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes?: false }
705): Buffer[]
706
707export function readdirSync(
708 filepath: Path,
709 opts: ReaddirOptions & { withFileTypes: true }
710): Dir<string | Buffer>[]
711
712export function readdirSync(
713 filepath: Path,
714 opts: ReaddirOptions & { withFileTypes?: false }
715): string[] | Buffer[]
716
717export function readdirSync(filepath: Path, opts: ReaddirOptions): Dir[] | string[] | Buffer[]
718
719export function readdirSync(filepath: Path, encoding: BufferEncoding): string[]
720
721export function readdirSync(filepath: Path, encoding: 'buffer'): Buffer[]
722
723export function readdirSync(
724 filepath: Path,
725 encoding: BufferEncoding | 'buffer'
726): string[] | Buffer[]
727
728export function readdirSync(filepath: Path): string[]
729
730export interface ReadlinkOptions {
731 encoding?: BufferEncoding | 'buffer'
732}
733
734export function readlink(
735 filepath: Path,
736 opts: ReadlinkOptions & { encoding?: BufferEncoding }
737): Promise<string>
738
739export function readlink(
740 filepath: Path,
741 opts: ReadlinkOptions & { encoding: 'buffer' }
742): Promise<Buffer>
743
744export function readlink(filepath: Path, opts: ReadlinkOptions): Promise<string | Buffer>
745
746export function readlink(filepath: Path, encoding: BufferEncoding): Promise<string>
747
748export function readlink(filepath: Path, encoding: 'buffer'): Promise<Buffer>
749
750export function readlink(
751 filepath: Path,
752 encoding: BufferEncoding | 'buffer'
753): Promise<string | Buffer>
754
755export function readlink(filepath: Path): Promise<string>
756
757export function readlink(
758 filepath: Path,
759 opts: ReadlinkOptions & { encoding?: BufferEncoding },
760 cb: Callback<[link: string | null]>
761): void
762
763export function readlink(
764 filepath: Path,
765 opts: ReadlinkOptions & { encoding: 'buffer' },
766 cb: Callback<[link: Buffer | null]>
767): void
768
769export function readlink(
770 filepath: Path,
771 opts: ReadlinkOptions,
772 cb: Callback<[link: string | Buffer | null]>
773): void
774
775export function readlink(
776 filepath: Path,
777 encoding: BufferEncoding,
778 cb: Callback<[link: string | null]>
779): void
780
781export function readlink(
782 filepath: Path,
783 encoding: 'buffer',
784 cb: Callback<[link: Buffer | null]>
785): void
786
787export function readlink(
788 filepath: Path,
789 encoding: BufferEncoding | 'buffer',
790 cb: Callback<[link: string | Buffer | null]>
791): void
792
793export function readlink(filepath: Path, cb: Callback<[link: string | null]>): void
794
795export function readlinkSync(
796 filepath: Path,
797 opts: ReadlinkOptions & { encoding?: BufferEncoding }
798): string
799
800export function readlinkSync(filepath: Path, opts: ReadlinkOptions & { encoding: 'buffer' }): Buffer
801
802export function readlinkSync(filepath: Path, opts: ReadlinkOptions): string | Buffer
803
804export function readlinkSync(filepath: Path, encoding: BufferEncoding): string
805
806export function readlinkSync(filepath: Path, encoding: 'buffer'): Buffer
807
808export function readlinkSync(filepath: Path, encoding: BufferEncoding | 'buffer'): string | Buffer
809
810export function readlinkSync(filepath: Path): string
811
812export function readv(fd: number, buffers: ArrayBufferView[], position?: number): Promise<number>
813
814export function readv(
815 fd: number,
816 buffers: ArrayBufferView[],
817 position: number,
818 cb: Callback<[len: number]>
819): void
820
821export function readv(fd: number, buffers: ArrayBufferView[], cb: Callback<[len: number]>): void
822
823export function readvSync(fd: number, buffers: ArrayBufferView[], position?: number): number
824
825export interface RealpathOptions {
826 encoding?: BufferEncoding | 'buffer'
827}
828
829export function realpath(
830 filepath: Path,
831 opts: RealpathOptions & { encoding?: BufferEncoding }
832): Promise<string>
833
834export function realpath(
835 filepath: Path,
836 opts: RealpathOptions & { encoding: 'buffer' }
837): Promise<Buffer>
838
839export function realpath(filepath: Path, opts: RealpathOptions): Promise<string | Buffer>
840
841export function realpath(filepath: Path, encoding: BufferEncoding): Promise<string>
842
843export function realpath(filepath: Path, encoding: 'buffer'): Promise<Buffer>
844
845export function realpath(
846 filepath: Path,
847 encoding: BufferEncoding | 'buffer'
848): Promise<string | Buffer>
849
850export function realpath(filepath: Path): Promise<string>
851
852export function realpath(
853 filepath: Path,
854 opts: RealpathOptions & { encoding?: BufferEncoding },
855 cb: Callback<[path: string | null]>
856): void
857
858export function realpath(
859 filepath: Path,
860 opts: RealpathOptions & { encoding: 'buffer' },
861 cb: Callback<[path: Buffer | null]>
862): void
863
864export function realpath(
865 filepath: Path,
866 opts: RealpathOptions,
867 cb: Callback<[path: string | Buffer | null]>
868): void
869
870export function realpath(
871 filepath: Path,
872 encoding: BufferEncoding,
873 cb: Callback<[path: string | null]>
874): void
875
876export function realpath(
877 filepath: Path,
878 encoding: 'buffer',
879 cb: Callback<[path: Buffer | null]>
880): void
881
882export function realpath(
883 filepath: Path,
884 encoding: BufferEncoding | 'buffer',
885 cb: Callback<[path: string | Buffer | null]>
886): void
887
888export function realpath(filepath: Path, cb: Callback<[path: string | null]>): void
889
890export function realpathSync(
891 filepath: Path,
892 opts: RealpathOptions & { encoding?: BufferEncoding }
893): string
894
895export function realpathSync(filepath: Path, opts: RealpathOptions & { encoding: 'buffer' }): Buffer
896
897export function realpathSync(filepath: Path, opts: RealpathOptions): string | Buffer
898
899export function realpathSync(filepath: Path, encoding: BufferEncoding): string
900
901export function realpathSync(filepath: Path, encoding: 'buffer'): Buffer
902
903export function realpathSync(filepath: Path, encoding: BufferEncoding | 'buffer'): string | Buffer
904
905export function realpathSync(filepath: Path): string
906
907export function rename(src: string, dst: string): Promise<void>
908
909export function rename(src: string, dst: string, cb: Callback): void
910
911export function renameSync(src: string, dst: string): void
912
913export interface RmOptions {
914 force?: boolean
915 recursive?: boolean
916}
917
918export function rm(filepath: Path, opts?: RmOptions): Promise<void>
919
920export function rm(filepath: Path, opts: RmOptions, cb: Callback): void
921
922export function rm(filepath: Path, cb: Callback): void
923
924export function rmSync(filepath: Path, opts?: RmOptions): void
925
926export function rmdir(filepath: Path, cb: Callback): void
927
928export function rmdirSync(filepath: Path): void
929
930export function stat(filepath: Path): Promise<Stats>
931
932export function stat(filepath: Path, cb: Callback<[stats: Stats | null]>): void
933
934export function statSync(filepath: Path): Stats
935
936export function symlink(target: Path, filepath: Path, type?: string | number): Promise<void>
937
938export function symlink(target: Path, filepath: Path, type: string | number, cb: Callback): void
939
940export function symlink(target: string, filepath: Path, cb: Callback): void
941
942export function symlinkSync(target: string, filepath: Path, type?: string | number): void
943
944export function unlink(filepath: Path): Promise<void>
945
946export function unlink(filepath: Path, cb: Callback): void
947
948export function unlinkSync(filepath: Path): void
949
950export function watch(
951 filepath: Path,
952 opts: WatcherOptions & { encoding?: BufferEncoding },
953 cb: (eventType: WatcherEventType, filename: string) => void
954): Watcher<string>
955
956export function watch(
957 filepath: Path,
958 opts: WatcherOptions & { encoding: 'buffer' },
959 cb: (eventType: WatcherEventType, filename: Buffer) => void
960): Watcher<Buffer>
961
962export function watch(
963 filepath: Path,
964 opts: WatcherOptions,
965 cb: (eventType: WatcherEventType, filename: string | Buffer) => void
966): Watcher
967
968export function watch(
969 filepath: Path,
970 encoding: BufferEncoding,
971 cb: (evenType: WatcherEventType, filename: string) => void
972): Watcher<string>
973
974export function watch(
975 filepath: Path,
976 encoding: 'buffer',
977 cb: (evenType: WatcherEventType, filename: Buffer) => void
978): Watcher<Buffer>
979
980export function watch(
981 filepath: Path,
982 encoding: BufferEncoding | 'buffer',
983 cb: (evenType: WatcherEventType, filename: string | Buffer) => void
984): Watcher
985
986export function watch(
987 filepath: Path,
988 cb: (eventType: WatcherEventType, filename: string) => void
989): Watcher<string>
990
991export function write(
992 fd: number,
993 data: Buffer | ArrayBufferView,
994 offset?: number,
995 len?: number,
996 pos?: number
997): Promise<number>
998
999export function write(
1000 fd: number,
1001 data: string,
1002 pos?: number,
1003 encoding?: BufferEncoding
1004): Promise<number>
1005
1006export function write(
1007 fd: number,
1008 data: Buffer | ArrayBufferView,
1009 offset: number,
1010 len: number,
1011 pos: number,
1012 cb: Callback<[len: number]>
1013): void
1014
1015export function write(
1016 fd: number,
1017 data: Buffer | ArrayBufferView,
1018 offset: number,
1019 len: number,
1020 cb: Callback<[len: number]>
1021): void
1022
1023export function write(
1024 fd: number,
1025 data: string,
1026 pos: number,
1027 encoding: BufferEncoding,
1028 cb: Callback<[len: number]>
1029): void
1030
1031export function write(
1032 fd: number,
1033 data: Buffer | ArrayBufferView,
1034 offset: number,
1035 cb: Callback<[len: number]>
1036): void
1037
1038export function write(fd: number, data: string, pos: number, cb: Callback<[len: number]>): void
1039
1040export function write(fd: number, data: Buffer | ArrayBufferView, cb: Callback<[len: number]>): void
1041
1042export function write(fd: number, data: string, cb: Callback<[len: number]>): void
1043
1044export function writeSync(
1045 fd: number,
1046 data: Buffer | ArrayBufferView,
1047 offset?: number,
1048 len?: number,
1049 pos?: number
1050): number
1051
1052export function writeSync(fd: number, data: string, pos?: number, encoding?: BufferEncoding): number
1053
1054export interface WriteFileOptions {
1055 encoding?: BufferEncoding
1056 flag?: Flag
1057 mode?: number
1058}
1059
1060export function writeFile(
1061 filepath: Path,
1062 data: string | Buffer | ArrayBufferView,
1063 opts?: WriteFileOptions
1064): Promise<void>
1065
1066export function writeFile(
1067 filepath: Path,
1068 data: string | Buffer | ArrayBufferView,
1069 encoding: BufferEncoding
1070): Promise<void>
1071
1072export function writeFile(
1073 filepath: Path,
1074 data: string | Buffer | ArrayBufferView,
1075 opts: WriteFileOptions,
1076 cb: Callback
1077): void
1078
1079export function writeFile(
1080 filepath: Path,
1081 data: string | Buffer | ArrayBufferView,
1082 encoding: BufferEncoding,
1083 cb: Callback
1084): void
1085
1086export function writeFile(
1087 filepath: Path,
1088 data: string | Buffer | ArrayBufferView,
1089 cb: Callback
1090): void
1091
1092export function writeFileSync(
1093 filepath: Path,
1094 data: string | Buffer | ArrayBufferView,
1095 opts?: WriteFileOptions
1096): void
1097
1098export function writeFileSync(
1099 filepath: Path,
1100 data: string | Buffer | ArrayBufferView,
1101 encoding: BufferEncoding
1102): void
1103
1104export function writev(fd: number, buffers: ArrayBufferView[], pos?: number): Promise<number>
1105
1106export function writev(
1107 fd: number,
1108 buffers: ArrayBufferView[],
1109 pos: number,
1110 cb: Callback<[len: number]>
1111): void
1112
1113export function writev(fd: number, buffers: ArrayBufferView[], cb: Callback<[len: number]>): void
1114
1115export function writevSync(fd: number, buffers: ArrayBufferView[], pos?: number): number
node_modules/bare-fs/index.js +2425 -0
……@@ -0,0 +1,2425 @@
1const FIFO = require('fast-fifo')
2const EventEmitter = require('bare-events')
3const path = require('bare-path')
4const { isURL, fileURLToPath } = require('bare-url')
5const { Readable, Writable } = require('bare-stream')
6const binding = require('./binding')
7const constants = require('./lib/constants')
8const FileError = require('./lib/errors')
9
10const isWindows = Bare.platform === 'win32'
11
12exports.constants = constants
13
14class FileRequest {
15 static borrow() {
16 if (this._free.length > 0) return this._free.pop()
17 return new FileRequest()
18 }
19
20 static return(req) {
21 if (this._free.length < 32) this._free.push(req.reset())
22 else req.destroy()
23 }
24
25 constructor() {
26 this._reset()
27 this._handle = binding.requestInit(this, this._onresult)
28 }
29
30 get handle() {
31 return this._handle
32 }
33
34 retain(value) {
35 this._retain = value // Tie the lifetime of `value` to the lifetime of `this`
36 }
37
38 reset() {
39 if (this._handle === null) return this
40
41 binding.requestReset(this._handle)
42
43 this._reset()
44
45 return this
46 }
47
48 destroy() {
49 if (this._handle === null) return this
50
51 binding.requestDestroy(this._handle)
52
53 this._reset()
54 this._handle = null
55
56 return this
57 }
58
59 then(resolve, reject) {
60 return this._promise.then(resolve, reject)
61 }
62
63 return() {
64 if (this._handle === null) return this
65
66 FileRequest.return(this)
67
68 return this
69 }
70
71 _reset() {
72 this._promise = new Promise((resolve, reject) => {
73 this._resolve = resolve
74 this._reject = reject
75 })
76 this._retain = null
77 }
78
79 _onresult(err, status) {
80 if (err) this._reject(err)
81 else this._resolve(status)
82 }
83}
84
85FileRequest._free = []
86
87function ok(result, cb) {
88 if (typeof result === 'function') {
89 cb = result
90 result = undefined
91 }
92
93 if (cb) cb(null, result)
94 else return result
95}
96
97function fail(err, cb) {
98 if (cb) cb(err)
99 else throw err
100}
101
102function done(err, result, cb) {
103 if (typeof result === 'function') {
104 cb = result
105 result = undefined
106 }
107
108 if (err) fail(err, cb)
109 else return ok(result, cb)
110}
111
112async function open(filepath, flags = 'r', mode = 0o666, cb) {
113 if (typeof flags === 'function') {
114 cb = flags
115 flags = 'r'
116 mode = 0o666
117 } else if (typeof mode === 'function') {
118 cb = mode
119 mode = 0o666
120 }
121
122 if (typeof flags === 'string') flags = toFlags(flags)
123 if (typeof mode === 'string') mode = toMode(mode)
124
125 filepath = toNamespacedPath(filepath)
126
127 const req = FileRequest.borrow()
128
129 let fd
130 let err = null
131 try {
132 binding.open(req.handle, filepath, flags, mode)
133
134 fd = await req
135 } catch (e) {
136 err = new FileError(e.message, {
137 operation: 'open',
138 code: e.code,
139 path: filepath
140 })
141 } finally {
142 req.return()
143 }
144
145 return done(err, fd, cb)
146}
147
148function openSync(filepath, flags = 'r', mode = 0o666) {
149 if (typeof flags === 'string') flags = toFlags(flags)
150 if (typeof mode === 'string') mode = toMode(mode)
151
152 filepath = toNamespacedPath(filepath)
153
154 const req = FileRequest.borrow()
155
156 try {
157 return binding.openSync(req.handle, filepath, flags, mode)
158 } catch (e) {
159 throw new FileError(e.message, {
160 operation: 'open',
161 code: e.code,
162 path: filepath
163 })
164 } finally {
165 req.return()
166 }
167}
168
169async function close(fd, cb) {
170 const req = FileRequest.borrow()
171
172 let err = null
173 try {
174 binding.close(req.handle, fd)
175
176 await req
177 } catch (e) {
178 err = new FileError(e.message, { operation: 'close', code: e.code, fd })
179 } finally {
180 req.return()
181 }
182
183 return done(err, cb)
184}
185
186function closeSync(fd) {
187 const req = FileRequest.borrow()
188
189 try {
190 binding.closeSync(req.handle, fd)
191 } catch (e) {
192 throw new FileError(e.message, { operation: 'close', code: e.code, fd })
193 } finally {
194 req.return()
195 }
196}
197
198async function access(filepath, mode = constants.F_OK, cb) {
199 if (typeof mode === 'function') {
200 cb = mode
201 mode = constants.F_OK
202 }
203
204 filepath = toNamespacedPath(filepath)
205
206 const req = FileRequest.borrow()
207
208 let err = null
209 try {
210 binding.access(req.handle, filepath, mode)
211
212 await req
213 } catch (e) {
214 err = new FileError(e.message, {
215 operation: 'access',
216 code: e.code,
217 path: filepath
218 })
219 } finally {
220 req.return()
221 }
222
223 return done(err, cb)
224}
225
226function accessSync(filepath, mode = constants.F_OK) {
227 filepath = toNamespacedPath(filepath)
228
229 const req = FileRequest.borrow()
230
231 try {
232 binding.accessSync(req.handle, filepath, mode)
233 } catch (e) {
234 throw new FileError(e.message, {
235 operation: 'access',
236 code: e.code,
237 path: filepath
238 })
239 } finally {
240 req.return()
241 }
242}
243
244async function exists(filepath, cb) {
245 let ok = true
246 try {
247 await access(filepath)
248 } catch {
249 ok = false
250 }
251
252 return done(null, ok, cb)
253}
254
255function existsSync(filepath) {
256 try {
257 accessSync(filepath)
258 } catch {
259 return false
260 }
261
262 return true
263}
264
265async function read(fd, buffer, offset = 0, len = buffer.byteLength - offset, pos = -1, cb) {
266 if (typeof offset === 'function') {
267 cb = offset
268 offset = 0
269 len = buffer.byteLength
270 pos = -1
271 } else if (typeof len === 'function') {
272 cb = len
273 len = buffer.byteLength - offset
274 pos = -1
275 } else if (typeof pos === 'function') {
276 cb = pos
277 pos = -1
278 }
279
280 if (typeof pos !== 'number') pos = -1
281
282 const req = FileRequest.borrow()
283
284 let bytes
285 let err = null
286 try {
287 binding.read(req.handle, fd, buffer, offset, len, pos)
288
289 bytes = await req
290 } catch (e) {
291 err = new FileError(e.message, { operation: 'read', code: e.code, fd })
292 } finally {
293 req.return()
294 }
295
296 return done(err, bytes, cb)
297}
298
299function readSync(fd, buffer, offset = 0, len = buffer.byteLength - offset, pos = -1) {
300 const req = FileRequest.borrow()
301
302 try {
303 return binding.readSync(req.handle, fd, buffer, offset, len, pos)
304 } catch (e) {
305 throw new FileError(e.message, { operation: 'read', code: e.code, fd })
306 } finally {
307 req.return()
308 }
309}
310
311async function readv(fd, buffers, pos = -1, cb) {
312 if (typeof pos === 'function') {
313 cb = pos
314 pos = -1
315 }
316
317 if (typeof pos !== 'number') pos = -1
318
319 const req = FileRequest.borrow()
320
321 let bytes
322 let err = null
323 try {
324 binding.readv(req.handle, fd, buffers, pos)
325
326 bytes = await req
327 } catch (e) {
328 err = new FileError(e.message, { operation: 'readv', code: e.code, fd })
329 } finally {
330 req.return()
331 }
332
333 return done(err, bytes, cb)
334}
335
336function readvSync(fd, buffers, pos = -1) {
337 if (typeof pos !== 'number') pos = -1
338
339 const req = FileRequest.borrow()
340
341 try {
342 return binding.readvSync(req.handle, fd, buffers, pos)
343 } catch (e) {
344 throw new FileError(e.message, { operation: 'readv', code: e.code, fd })
345 } finally {
346 req.return()
347 }
348}
349
350async function write(fd, data, offset, len, pos = -1, cb) {
351 if (typeof data === 'string') {
352 let encoding = len
353 cb = pos
354 pos = offset
355
356 if (typeof pos === 'function') {
357 cb = pos
358 pos = -1
359 encoding = 'utf8'
360 } else if (typeof encoding === 'function') {
361 cb = encoding
362 encoding = 'utf8'
363 }
364
365 if (typeof pos === 'string') {
366 encoding = pos
367 pos = -1
368 }
369
370 data = Buffer.from(data, encoding)
371 offset = 0
372 len = data.byteLength
373 } else if (typeof offset === 'function') {
374 cb = offset
375 offset = 0
376 len = data.byteLength
377 pos = -1
378 } else if (typeof len === 'function') {
379 cb = len
380 len = data.byteLength - offset
381 pos = -1
382 } else if (typeof pos === 'function') {
383 cb = pos
384 pos = -1
385 }
386
387 if (typeof offset !== 'number') offset = 0
388 if (typeof len !== 'number') len = data.byteLength - offset
389 if (typeof pos !== 'number') pos = -1
390
391 const req = FileRequest.borrow()
392
393 let bytes
394 let err = null
395 try {
396 binding.write(req.handle, fd, data, offset, len, pos)
397
398 bytes = await req
399 } catch (e) {
400 err = new FileError(e.message, { operation: 'write', code: e.code, fd })
401 } finally {
402 req.return()
403 }
404
405 return done(err, bytes, cb)
406}
407
408function writeSync(fd, data, offset, len, pos = -1) {
409 if (typeof data === 'string') {
410 let encoding = len
411 pos = offset
412
413 if (typeof pos === 'string') {
414 encoding = pos
415 pos = -1
416 }
417
418 data = Buffer.from(data, encoding)
419 offset = 0
420 len = data.byteLength
421 }
422
423 if (typeof offset !== 'number') offset = 0
424 if (typeof len !== 'number') len = data.byteLength - offset
425 if (typeof pos !== 'number') pos = -1
426
427 const req = FileRequest.borrow()
428
429 try {
430 return binding.writeSync(req.handle, fd, data, offset, len, pos)
431 } catch (e) {
432 throw new FileError(e.message, { operation: 'write', code: e.code, fd })
433 } finally {
434 req.return()
435 }
436}
437
438async function writev(fd, buffers, pos = -1, cb) {
439 if (typeof pos === 'function') {
440 cb = pos
441 pos = -1
442 }
443
444 if (typeof pos !== 'number') pos = -1
445
446 const req = FileRequest.borrow()
447
448 let bytes
449 let err = null
450 try {
451 binding.writev(req.handle, fd, buffers, pos)
452
453 bytes = await req
454 } catch (e) {
455 err = new FileError(e.message, { operation: 'writev', code: e.code, fd })
456 } finally {
457 req.return()
458 }
459
460 return done(err, bytes, cb)
461}
462
463function writevSync(fd, buffers, pos = -1) {
464 if (typeof pos !== 'number') pos = -1
465
466 const req = FileRequest.borrow()
467
468 try {
469 return binding.writevSync(req.handle, fd, buffers, pos)
470 } catch (e) {
471 throw new FileError(e.message, { operation: 'writev', code: e.code, fd })
472 } finally {
473 req.return()
474 }
475}
476
477async function stat(filepath, cb) {
478 filepath = toNamespacedPath(filepath)
479
480 const req = FileRequest.borrow()
481
482 let st
483 let err = null
484 try {
485 binding.stat(req.handle, filepath)
486
487 await req
488
489 st = new Stats(...binding.requestResultStat(req.handle))
490 } catch (e) {
491 err = new FileError(e.message, {
492 operation: 'stat',
493 code: e.code,
494 path: filepath
495 })
496 } finally {
497 req.return()
498 }
499
500 return done(err, st, cb)
501}
502
503function statSync(filepath) {
504 filepath = toNamespacedPath(filepath)
505
506 const req = FileRequest.borrow()
507
508 try {
509 binding.statSync(req.handle, filepath)
510
511 return new Stats(...binding.requestResultStat(req.handle))
512 } catch (e) {
513 throw new FileError(e.message, {
514 operation: 'stat',
515 code: e.code,
516 path: filepath
517 })
518 } finally {
519 req.return()
520 }
521}
522
523async function lstat(filepath, cb) {
524 filepath = toNamespacedPath(filepath)
525
526 const req = FileRequest.borrow()
527
528 let st
529 let err = null
530 try {
531 binding.lstat(req.handle, filepath)
532
533 await req
534
535 st = new Stats(...binding.requestResultStat(req.handle))
536 } catch (e) {
537 err = new FileError(e.message, {
538 operation: 'lstat',
539 code: e.code,
540 path: filepath
541 })
542 } finally {
543 req.return()
544 }
545
546 return done(err, st, cb)
547}
548
549function lstatSync(filepath) {
550 filepath = toNamespacedPath(filepath)
551
552 const req = FileRequest.borrow()
553
554 try {
555 binding.lstatSync(req.handle, filepath)
556
557 return new Stats(...binding.requestResultStat(req.handle))
558 } catch (e) {
559 throw new FileError(e.message, {
560 operation: 'lstat',
561 code: e.code,
562 path: filepath
563 })
564 } finally {
565 req.return()
566 }
567}
568
569async function fstat(fd, cb) {
570 const req = FileRequest.borrow()
571
572 let st
573 let err = null
574 try {
575 binding.fstat(req.handle, fd)
576
577 await req
578
579 st = new Stats(...binding.requestResultStat(req.handle))
580 } catch (e) {
581 err = new FileError(e.message, { operation: 'fstat', code: e.code, fd })
582 } finally {
583 req.return()
584 }
585
586 return done(err, st, cb)
587}
588
589function fstatSync(fd) {
590 const req = FileRequest.borrow()
591
592 try {
593 binding.fstatSync(req.handle, fd)
594
595 return new Stats(...binding.requestResultStat(req.handle))
596 } catch (e) {
597 throw new FileError(e.message, { operation: 'fstat', code: e.code, fd })
598 } finally {
599 req.return()
600 }
601}
602
603async function ftruncate(fd, len = 0, cb) {
604 if (typeof len === 'function') {
605 cb = len
606 len = 0
607 }
608
609 if (typeof len !== 'number') len = 0
610
611 const req = FileRequest.borrow()
612
613 let err = null
614 try {
615 binding.ftruncate(req.handle, fd, len)
616
617 await req
618 } catch (e) {
619 err = new FileError(e.message, { operation: 'ftruncate', code: e.code, fd })
620 } finally {
621 req.return()
622 }
623
624 return done(err, cb)
625}
626
627function ftruncateSync(fd, len = 0) {
628 if (typeof len !== 'number') len = 0
629
630 const req = FileRequest.borrow()
631
632 try {
633 binding.ftruncateSync(req.handle, fd, len)
634 } catch (e) {
635 throw new FileError(e.message, { operation: 'ftruncate', code: e.code, fd })
636 } finally {
637 req.return()
638 }
639}
640
641async function chmod(filepath, mode, cb) {
642 if (typeof mode === 'string') mode = toMode(mode)
643
644 filepath = toNamespacedPath(filepath)
645
646 const req = FileRequest.borrow()
647
648 let err = null
649 try {
650 binding.chmod(req.handle, filepath, mode)
651
652 await req
653 } catch (e) {
654 err = new FileError(e.message, {
655 operation: 'chmod',
656 code: e.code,
657 path: filepath
658 })
659 } finally {
660 req.return()
661 }
662
663 return done(err, cb)
664}
665
666function chmodSync(filepath, mode) {
667 if (typeof mode === 'string') mode = toMode(mode)
668
669 filepath = toNamespacedPath(filepath)
670
671 const req = FileRequest.borrow()
672
673 try {
674 binding.chmodSync(req.handle, filepath, mode)
675 } catch (e) {
676 throw new FileError(e.message, {
677 operation: 'chmod',
678 code: e.code,
679 path: filepath
680 })
681 } finally {
682 req.return()
683 }
684}
685
686async function fchmod(fd, mode, cb) {
687 if (typeof mode === 'string') mode = toMode(mode)
688
689 const req = FileRequest.borrow()
690
691 let err = null
692 try {
693 binding.fchmod(req.handle, fd, mode)
694
695 await req
696 } catch (e) {
697 err = new FileError(e.message, { operation: 'fchmod', code: e.code, fd })
698 } finally {
699 req.return()
700 }
701
702 return done(err, cb)
703}
704
705function fchmodSync(fd, mode) {
706 if (typeof mode === 'string') mode = toMode(mode)
707
708 const req = FileRequest.borrow()
709
710 try {
711 binding.fchmodSync(req.handle, fd, mode)
712 } catch (e) {
713 throw new FileError(e.message, { operation: 'fchmod', code: e.code, fd })
714 } finally {
715 req.return()
716 }
717}
718
719async function utimes(filepath, atime, mtime, cb) {
720 if (typeof atime !== 'number') atime = atime.getTime() / 1000
721 if (typeof mtime !== 'number') mtime = mtime.getTime() / 1000
722
723 filepath = toNamespacedPath(filepath)
724
725 const req = FileRequest.borrow()
726
727 let err = null
728 try {
729 binding.utimes(req.handle, filepath, atime, mtime)
730
731 await req
732 } catch (e) {
733 err = new FileError(e.message, {
734 operation: 'utimes',
735 code: e.code,
736 path: filepath
737 })
738 } finally {
739 req.return()
740 }
741
742 return done(err, cb)
743}
744
745function utimesSync(filepath, atime, mtime) {
746 if (typeof atime !== 'number') atime = atime.getTime() / 1000
747 if (typeof mtime !== 'number') mtime = mtime.getTime() / 1000
748
749 filepath = toNamespacedPath(filepath)
750
751 const req = FileRequest.borrow()
752
753 try {
754 binding.utimesSync(req.handle, filepath, atime, mtime)
755 } catch (e) {
756 throw new FileError(e.message, {
757 operation: 'utimes',
758 code: e.code,
759 path: filepath
760 })
761 } finally {
762 req.return()
763 }
764}
765
766async function mkdir(filepath, opts, cb) {
767 if (typeof opts === 'function') {
768 cb = opts
769 opts = { mode: 0o777 }
770 }
771
772 if (typeof opts === 'number') opts = { mode: opts }
773 else if (!opts) opts = {}
774
775 const mode = typeof opts.mode === 'number' ? opts.mode : 0o777
776
777 filepath = toNamespacedPath(filepath)
778
779 if (opts.recursive) {
780 let err = null
781 try {
782 try {
783 await mkdir(filepath, { mode })
784 } catch (err) {
785 if (err.code !== 'ENOENT') {
786 if (!(await stat(filepath)).isDirectory()) throw err
787 } else {
788 while (filepath.endsWith(path.sep)) filepath = filepath.slice(0, -1)
789 const i = filepath.lastIndexOf(path.sep)
790 if (i <= 0) throw err
791
792 await mkdir(filepath.slice(0, i), { mode, recursive: true })
793
794 try {
795 await mkdir(filepath, { mode })
796 } catch (err) {
797 if (!(await stat(filepath)).isDirectory()) throw err
798 }
799 }
800 }
801 } catch (e) {
802 err = e
803 }
804
805 return done(err, cb)
806 }
807
808 const req = FileRequest.borrow()
809
810 let err = null
811 try {
812 binding.mkdir(req.handle, filepath, mode)
813
814 await req
815 } catch (e) {
816 err = new FileError(e.message, {
817 operation: 'mkdir',
818 code: e.code,
819 path: filepath
820 })
821 } finally {
822 req.return()
823 }
824
825 return done(err, cb)
826}
827
828function mkdirSync(filepath, opts) {
829 if (typeof opts === 'number') opts = { mode: opts }
830 else if (!opts) opts = {}
831
832 const mode = typeof opts.mode === 'number' ? opts.mode : 0o777
833
834 filepath = toNamespacedPath(filepath)
835
836 if (opts.recursive) {
837 try {
838 mkdirSync(filepath, { mode })
839 } catch (err) {
840 if (err.code !== 'ENOENT') {
841 if (!statSync(filepath).isDirectory()) throw err
842 } else {
843 while (filepath.endsWith(path.sep)) filepath = filepath.slice(0, -1)
844 const i = filepath.lastIndexOf(path.sep)
845 if (i <= 0) throw err
846
847 mkdirSync(filepath.slice(0, i), { mode, recursive: true })
848
849 try {
850 mkdirSync(filepath, { mode })
851 } catch (err) {
852 if (!statSync(filepath).isDirectory()) throw err
853 }
854 }
855 }
856
857 return
858 }
859
860 const req = FileRequest.borrow()
861
862 try {
863 binding.mkdirSync(req.handle, filepath, mode)
864 } catch (e) {
865 throw new FileError(e.message, {
866 operation: 'mkdir',
867 code: e.code,
868 path: filepath
869 })
870 } finally {
871 req.return()
872 }
873}
874
875async function rmdir(filepath, cb) {
876 filepath = toNamespacedPath(filepath)
877
878 const req = FileRequest.borrow()
879
880 let err = null
881 try {
882 binding.rmdir(req.handle, filepath)
883
884 await req
885 } catch (e) {
886 err = new FileError(e.message, {
887 operation: 'rmdir',
888 code: e.code,
889 path: filepath
890 })
891 } finally {
892 req.return()
893 }
894
895 return done(err, cb)
896}
897
898function rmdirSync(filepath) {
899 filepath = toNamespacedPath(filepath)
900
901 const req = FileRequest.borrow()
902
903 try {
904 binding.rmdirSync(req.handle, filepath)
905 } catch (e) {
906 throw new FileError(e.message, {
907 operation: 'rmdir',
908 code: e.code,
909 path: filepath
910 })
911 } finally {
912 req.return()
913 }
914}
915
916async function rm(filepath, opts, cb) {
917 if (typeof opts === 'function') {
918 cb = opts
919 opts = {}
920 }
921
922 if (!opts) opts = {}
923
924 filepath = toNamespacedPath(filepath)
925
926 let err = null
927 try {
928 const st = await lstat(filepath)
929
930 if (st.isDirectory()) {
931 if (opts.recursive) {
932 try {
933 await rmdir(filepath)
934 } catch (err) {
935 if (err.code !== 'ENOTEMPTY') throw err
936
937 const files = await readdir(filepath)
938
939 for (const file of files) {
940 await rm(filepath + path.sep + file, opts)
941 }
942
943 await rmdir(filepath)
944 }
945 } else {
946 throw new FileError('is a directory', {
947 operation: 'rm',
948 code: 'EISDIR',
949 path: filepath
950 })
951 }
952 } else {
953 await unlink(filepath)
954 }
955 } catch (e) {
956 if (e.code !== 'ENOENT' || !opts.force) err = e
957 }
958
959 return done(err, cb)
960}
961
962function rmSync(filepath, opts) {
963 if (!opts) opts = {}
964
965 filepath = toNamespacedPath(filepath)
966
967 try {
968 const st = lstatSync(filepath)
969
970 if (st.isDirectory()) {
971 if (opts.recursive) {
972 try {
973 rmdirSync(filepath)
974 } catch (err) {
975 if (err.code !== 'ENOTEMPTY') throw err
976
977 const files = readdirSync(filepath)
978
979 for (const file of files) {
980 rmSync(filepath + path.sep + file, opts)
981 }
982
983 rmdirSync(filepath)
984 }
985 } else {
986 throw new FileError('is a directory', {
987 operation: 'rm',
988 code: 'EISDIR',
989 path: filepath
990 })
991 }
992 } else {
993 unlinkSync(filepath)
994 }
995 } catch (err) {
996 if (err.code !== 'ENOENT' || !opts.force) throw err
997 }
998}
999
1000async function unlink(filepath, cb) {
1001 filepath = toNamespacedPath(filepath)
1002
1003 const req = FileRequest.borrow()
1004
1005 let err = null
1006 try {
1007 binding.unlink(req.handle, filepath)
1008
1009 await req
1010 } catch (e) {
1011 err = new FileError(e.message, {
1012 operation: 'unlink',
1013 code: e.code,
1014 path: filepath
1015 })
1016 } finally {
1017 req.return()
1018 }
1019
1020 return done(err, cb)
1021}
1022
1023function unlinkSync(filepath) {
1024 filepath = toNamespacedPath(filepath)
1025
1026 const req = FileRequest.borrow()
1027
1028 try {
1029 binding.unlinkSync(req.handle, filepath)
1030 } catch (e) {
1031 throw new FileError(e.message, {
1032 operation: 'unlink',
1033 code: e.code,
1034 path: filepath
1035 })
1036 } finally {
1037 req.return()
1038 }
1039}
1040
1041async function rename(src, dst, cb) {
1042 src = toNamespacedPath(src)
1043 dst = toNamespacedPath(dst)
1044
1045 const req = FileRequest.borrow()
1046
1047 let err = null
1048 try {
1049 binding.rename(req.handle, src, dst)
1050
1051 await req
1052 } catch (e) {
1053 err = new FileError(e.message, {
1054 operation: 'rename',
1055 code: e.code,
1056 path: src,
1057 destination: dst
1058 })
1059 } finally {
1060 req.return()
1061 }
1062
1063 return done(err, cb)
1064}
1065
1066function renameSync(src, dst) {
1067 src = toNamespacedPath(src)
1068 dst = toNamespacedPath(dst)
1069
1070 const req = FileRequest.borrow()
1071
1072 try {
1073 binding.renameSync(req.handle, src, dst)
1074 } catch (e) {
1075 throw new FileError(e.message, {
1076 operation: 'rename',
1077 code: e.code,
1078 path: src,
1079 destination: dst
1080 })
1081 } finally {
1082 req.return()
1083 }
1084}
1085
1086async function copyFile(src, dst, mode = 0, cb) {
1087 if (typeof mode === 'function') {
1088 cb = mode
1089 mode = 0
1090 }
1091
1092 src = toNamespacedPath(src)
1093 dst = toNamespacedPath(dst)
1094
1095 const req = FileRequest.borrow()
1096
1097 let err = null
1098 try {
1099 binding.copyfile(req.handle, src, dst, mode)
1100
1101 await req
1102 } catch (e) {
1103 err = new FileError(e.message, {
1104 operation: 'copyfile',
1105 code: e.code,
1106 path: src,
1107 destination: dst
1108 })
1109 } finally {
1110 req.return()
1111 }
1112
1113 return done(err, cb)
1114}
1115
1116function copyFileSync(src, dst, mode = 0) {
1117 src = toNamespacedPath(src)
1118 dst = toNamespacedPath(dst)
1119
1120 const req = FileRequest.borrow()
1121
1122 try {
1123 binding.copyfileSync(req.handle, src, dst, mode)
1124 } catch (e) {
1125 throw new FileError(e.message, {
1126 operation: 'copyfile',
1127 code: e.code,
1128 path: src,
1129 destination: dst
1130 })
1131 } finally {
1132 req.return()
1133 }
1134}
1135
1136async function cp(src, dst, opts, cb) {
1137 if (typeof opts === 'function') {
1138 cb = opts
1139 opts = {}
1140 }
1141
1142 if (!opts) opts = {}
1143
1144 src = toNamespacedPath(src)
1145 dst = toNamespacedPath(dst)
1146
1147 let err = null
1148 try {
1149 const st = await lstat(src)
1150
1151 if (st.isDirectory()) {
1152 if (opts.recursive !== true) {
1153 throw new FileError('is a directory', {
1154 operation: 'cp',
1155 code: 'EISDIR',
1156 path: src
1157 })
1158 }
1159
1160 try {
1161 await lstat(dst)
1162 } catch (e) {
1163 if (e.code === 'ENOENT') {
1164 await mkdir(dst, { mode: st.mode, recursive: true })
1165 } else {
1166 throw e
1167 }
1168 }
1169
1170 const dir = await opendir(src)
1171 for await (const { name } of dir) {
1172 await cp(path.join(src, name), path.join(dst, name), opts)
1173 }
1174 } else if (st.isFile()) {
1175 await copyFile(src, dst)
1176 await chmod(dst, st.mode)
1177 }
1178 } catch (e) {
1179 err = e
1180 }
1181
1182 return done(err, cb)
1183}
1184
1185async function realpath(filepath, opts, cb) {
1186 if (typeof opts === 'function') {
1187 cb = opts
1188 opts = {}
1189 }
1190
1191 if (typeof opts === 'string') opts = { encoding: opts }
1192 else if (!opts) opts = {}
1193
1194 const { encoding = 'utf8' } = opts
1195
1196 filepath = toNamespacedPath(filepath)
1197
1198 const req = FileRequest.borrow()
1199
1200 let res
1201 let err = null
1202 try {
1203 binding.realpath(req.handle, filepath)
1204
1205 await req
1206
1207 res = Buffer.from(binding.requestResultString(req.handle))
1208
1209 if (encoding !== 'buffer') res = res.toString(encoding)
1210 } catch (e) {
1211 err = new FileError(e.message, {
1212 operation: 'realpath',
1213 code: e.code,
1214 path: filepath
1215 })
1216 } finally {
1217 req.return()
1218 }
1219
1220 return done(err, res, cb)
1221}
1222
1223function realpathSync(filepath, opts) {
1224 if (typeof opts === 'string') opts = { encoding: opts }
1225 else if (!opts) opts = {}
1226
1227 const { encoding = 'utf8' } = opts
1228
1229 filepath = toNamespacedPath(filepath)
1230
1231 const req = FileRequest.borrow()
1232
1233 try {
1234 binding.realpathSync(req.handle, filepath)
1235
1236 let res = Buffer.from(binding.requestResultString(req.handle))
1237
1238 if (encoding !== 'buffer') res = res.toString(encoding)
1239
1240 return res
1241 } catch (e) {
1242 throw new FileError(e.message, {
1243 operation: 'realpath',
1244 code: e.code,
1245 path: filepath
1246 })
1247 } finally {
1248 req.return()
1249 }
1250}
1251
1252async function readlink(filepath, opts, cb) {
1253 if (typeof opts === 'function') {
1254 cb = opts
1255 opts = {}
1256 }
1257
1258 if (typeof opts === 'string') opts = { encoding: opts }
1259 else if (!opts) opts = {}
1260
1261 const { encoding = 'utf8' } = opts
1262
1263 filepath = toNamespacedPath(filepath)
1264
1265 const req = FileRequest.borrow()
1266
1267 let res
1268 let err = null
1269 try {
1270 binding.readlink(req.handle, filepath)
1271
1272 await req
1273
1274 res = Buffer.from(binding.requestResultString(req.handle))
1275
1276 if (encoding !== 'buffer') res = res.toString(encoding)
1277 } catch (e) {
1278 err = new FileError(e.message, {
1279 operation: 'readlink',
1280 code: e.code,
1281 path: filepath
1282 })
1283 } finally {
1284 req.return()
1285 }
1286
1287 return done(err, res, cb)
1288}
1289
1290function readlinkSync(filepath, opts) {
1291 if (typeof opts === 'string') opts = { encoding: opts }
1292 else if (!opts) opts = {}
1293
1294 const { encoding = 'utf8' } = opts
1295
1296 filepath = toNamespacedPath(filepath)
1297
1298 const req = FileRequest.borrow()
1299
1300 try {
1301 binding.readlinkSync(req.handle, filepath)
1302
1303 let res = Buffer.from(binding.requestResultString(req.handle))
1304
1305 if (encoding !== 'buffer') res = res.toString(encoding)
1306
1307 return res
1308 } catch (e) {
1309 throw new FileError(e.message, {
1310 operation: 'readlink',
1311 code: e.code,
1312 path: filepath
1313 })
1314 } finally {
1315 req.return()
1316 }
1317}
1318
1319function normalizeSymlinkTarget(target, type, filepath) {
1320 if (isWindows) {
1321 if (type === constants.UV_FS_SYMLINK_JUNCTION) target = path.resolve(filepath, '..', target)
1322
1323 if (path.isAbsolute(target)) return path.toNamespacedPath(target)
1324
1325 return target.replace(/\//g, path.sep)
1326 }
1327
1328 return target
1329}
1330
1331async function symlink(target, filepath, type, cb) {
1332 if (typeof type === 'function') {
1333 cb = type
1334 type = null
1335 }
1336
1337 filepath = toNamespacedPath(filepath)
1338
1339 if (typeof type === 'string') {
1340 switch (type) {
1341 case 'file':
1342 default:
1343 type = 0
1344 break
1345 case 'dir':
1346 type = constants.UV_FS_SYMLINK_DIR
1347 break
1348 case 'junction':
1349 type = constants.UV_FS_SYMLINK_JUNCTION
1350 break
1351 }
1352 } else if (typeof type !== 'number') {
1353 if (isWindows) {
1354 target = path.resolve(filepath, '..', target)
1355
1356 try {
1357 type = (await stat(target)).isDirectory()
1358 ? constants.UV_FS_SYMLINK_DIR
1359 : constants.UV_FS_SYMLINK_JUNCTION
1360 } catch {
1361 type = 0
1362 }
1363 } else {
1364 type = 0
1365 }
1366 }
1367
1368 target = normalizeSymlinkTarget(target, type, filepath)
1369
1370 const req = FileRequest.borrow()
1371
1372 let err = null
1373 try {
1374 binding.symlink(req.handle, target, filepath, type)
1375
1376 await req
1377 } catch (e) {
1378 err = new FileError(e.message, {
1379 operation: 'symlink',
1380 code: e.code,
1381 path: target,
1382 destination: filepath
1383 })
1384 } finally {
1385 req.return()
1386 }
1387
1388 return done(err, cb)
1389}
1390
1391function symlinkSync(target, filepath, type) {
1392 filepath = toNamespacedPath(filepath)
1393
1394 if (typeof type === 'string') {
1395 switch (type) {
1396 case 'file':
1397 default:
1398 type = 0
1399 break
1400 case 'dir':
1401 type = constants.UV_FS_SYMLINK_DIR
1402 break
1403 case 'junction':
1404 type = constants.UV_FS_SYMLINK_JUNCTION
1405 break
1406 }
1407 } else if (typeof type !== 'number') {
1408 if (isWindows) {
1409 target = path.resolve(filepath, '..', target)
1410
1411 try {
1412 type = statSync(target).isDirectory()
1413 ? constants.UV_FS_SYMLINK_DIR
1414 : constants.UV_FS_SYMLINK_JUNCTION
1415 } catch {
1416 type = 0
1417 }
1418 } else {
1419 type = 0
1420 }
1421 }
1422
1423 target = normalizeSymlinkTarget(target, type, filepath)
1424
1425 const req = FileRequest.borrow()
1426
1427 try {
1428 binding.symlinkSync(req.handle, target, filepath, type)
1429 } catch (e) {
1430 throw new FileError(e.message, {
1431 operation: 'symlink',
1432 code: e.code,
1433 path: target,
1434 destination: filepath
1435 })
1436 } finally {
1437 req.return()
1438 }
1439}
1440
1441async function opendir(filepath, opts, cb) {
1442 if (typeof opts === 'function') {
1443 cb = opts
1444 opts = {}
1445 }
1446
1447 if (typeof opts === 'string') opts = { encoding: opts }
1448 else if (!opts) opts = {}
1449
1450 filepath = toNamespacedPath(filepath)
1451
1452 const req = FileRequest.borrow()
1453
1454 let dir
1455 let err = null
1456 try {
1457 binding.opendir(req.handle, filepath)
1458
1459 await req
1460
1461 dir = new Dir(filepath, binding.requestResultDir(req.handle), opts)
1462 } catch (e) {
1463 err = new FileError(e.message, {
1464 operation: 'opendir',
1465 code: e.code,
1466 path: filepath
1467 })
1468 } finally {
1469 req.return()
1470 }
1471
1472 return done(err, dir, cb)
1473}
1474
1475function opendirSync(filepath, opts) {
1476 if (typeof opts === 'string') opts = { encoding: opts }
1477 else if (!opts) opts = {}
1478
1479 filepath = toNamespacedPath(filepath)
1480
1481 const req = FileRequest.borrow()
1482
1483 try {
1484 binding.opendirSync(req.handle, filepath)
1485
1486 return new Dir(filepath, binding.requestResultDir(req.handle), opts)
1487 } catch (e) {
1488 throw new FileError(e.message, {
1489 operation: 'opendir',
1490 code: e.code,
1491 path: filepath
1492 })
1493 } finally {
1494 req.return()
1495 }
1496}
1497
1498async function readdir(filepath, opts, cb) {
1499 if (typeof opts === 'function') {
1500 cb = opts
1501 opts = {}
1502 }
1503
1504 if (typeof opts === 'string') opts = { encoding: opts }
1505 else if (!opts) opts = {}
1506
1507 const { withFileTypes = false } = opts
1508
1509 filepath = toNamespacedPath(filepath)
1510
1511 let result = []
1512 let err = null
1513 try {
1514 const dir = await opendir(filepath)
1515
1516 for await (const entry of dir) {
1517 result.push(withFileTypes ? entry : entry.name)
1518 }
1519 } catch (e) {
1520 result = []
1521 err = e
1522 }
1523
1524 return done(err, result, cb)
1525}
1526
1527function readdirSync(filepath, opts) {
1528 if (typeof opts === 'string') opts = { encoding: opts }
1529 else if (!opts) opts = {}
1530
1531 const { withFileTypes = false } = opts
1532
1533 filepath = toNamespacedPath(filepath)
1534
1535 const dir = opendirSync(filepath, opts)
1536 const result = []
1537
1538 for (const entry of dir) {
1539 result.push(withFileTypes ? entry : entry.name)
1540 }
1541
1542 return result
1543}
1544
1545async function readFile(filepath, opts, cb) {
1546 if (typeof opts === 'function') {
1547 cb = opts
1548 opts = {}
1549 }
1550
1551 if (typeof opts === 'string') opts = { encoding: opts }
1552 else if (!opts) opts = {}
1553
1554 const { encoding = 'buffer' } = opts
1555
1556 let fd = -1
1557 let buffer = null
1558 let err = null
1559 try {
1560 fd = await open(filepath, opts.flag || 'r')
1561
1562 const st = await fstat(fd)
1563
1564 let len = 0
1565
1566 if (st.size === 0) {
1567 const buffers = []
1568
1569 while (true) {
1570 buffer = Buffer.allocUnsafe(8192)
1571 const r = await read(fd, buffer)
1572 len += r
1573 if (r === 0) break
1574 buffers.push(buffer.subarray(0, r))
1575 }
1576
1577 buffer = Buffer.concat(buffers)
1578 } else {
1579 buffer = Buffer.allocUnsafe(st.size)
1580
1581 while (true) {
1582 const r = await read(fd, len ? buffer.subarray(len) : buffer)
1583 len += r
1584 if (r === 0 || len === buffer.byteLength) break
1585 }
1586
1587 if (len !== buffer.byteLength) buffer = buffer.subarray(0, len)
1588 }
1589
1590 if (encoding !== 'buffer') buffer = buffer.toString(encoding)
1591 } catch (e) {
1592 err = e
1593 } finally {
1594 if (fd !== -1) await close(fd)
1595 }
1596
1597 return done(err, buffer, cb)
1598}
1599
1600function readFileSync(filepath, opts) {
1601 if (typeof opts === 'string') opts = { encoding: opts }
1602 else if (!opts) opts = {}
1603
1604 const { encoding = 'buffer' } = opts
1605
1606 let fd = -1
1607 try {
1608 fd = openSync(filepath, opts.flag || 'r')
1609
1610 const st = fstatSync(fd)
1611
1612 let buffer
1613 let len = 0
1614
1615 if (st.size === 0) {
1616 const buffers = []
1617
1618 while (true) {
1619 buffer = Buffer.allocUnsafe(8192)
1620 const r = readSync(fd, buffer)
1621 len += r
1622 if (r === 0) break
1623 buffers.push(buffer.subarray(0, r))
1624 }
1625
1626 buffer = Buffer.concat(buffers)
1627 } else {
1628 buffer = Buffer.allocUnsafe(st.size)
1629
1630 while (true) {
1631 const r = readSync(fd, len ? buffer.subarray(len) : buffer)
1632 len += r
1633 if (r === 0 || len === buffer.byteLength) break
1634 }
1635
1636 if (len !== buffer.byteLength) buffer = buffer.subarray(0, len)
1637 }
1638
1639 if (encoding !== 'buffer') buffer = buffer.toString(encoding)
1640
1641 return buffer
1642 } finally {
1643 if (fd !== -1) closeSync(fd)
1644 }
1645}
1646
1647async function writeFile(filepath, data, opts, cb) {
1648 if (typeof opts === 'function') {
1649 cb = opts
1650 opts = {}
1651 }
1652
1653 if (typeof opts === 'string') opts = { encoding: opts }
1654 else if (!opts) opts = {}
1655
1656 if (typeof data === 'string') data = Buffer.from(data, opts.encoding)
1657
1658 let fd = -1
1659 let len = 0
1660 let err = null
1661 try {
1662 fd = await open(filepath, opts.flag || 'w', opts.mode || 0o666)
1663
1664 while (true) {
1665 len += await write(fd, len ? data.subarray(len) : data)
1666 if (len === data.byteLength) break
1667 }
1668 } catch (e) {
1669 err = e
1670 } finally {
1671 if (fd !== -1) await close(fd)
1672 }
1673
1674 return done(err, len, cb)
1675}
1676
1677function writeFileSync(filepath, data, opts) {
1678 if (typeof opts === 'string') opts = { encoding: opts }
1679 else if (!opts) opts = {}
1680
1681 if (typeof data === 'string') data = Buffer.from(data, opts.encoding)
1682
1683 let fd = -1
1684 try {
1685 fd = openSync(filepath, opts.flag || 'w', opts.mode || 0o666)
1686
1687 let len = 0
1688
1689 while (true) {
1690 len += writeSync(fd, len ? data.subarray(len) : data)
1691 if (len === data.byteLength) break
1692 }
1693 } finally {
1694 if (fd !== -1) closeSync(fd)
1695 }
1696}
1697
1698function appendFile(filepath, data, opts, cb) {
1699 if (typeof opts === 'function') {
1700 cb = opts
1701 opts = {}
1702 }
1703
1704 if (typeof opts === 'string') opts = { encoding: opts }
1705 else if (!opts) opts = {}
1706
1707 if (!opts.flag) opts = { ...opts, flag: 'a' }
1708
1709 return writeFile(filepath, data, opts, cb)
1710}
1711
1712function appendFileSync(filepath, data, opts) {
1713 if (typeof opts === 'string') opts = { encoding: opts }
1714 else if (!opts) opts = {}
1715
1716 if (!opts.flag) opts = { ...opts, flag: 'a' }
1717
1718 return writeFileSync(filepath, data, opts)
1719}
1720
1721function watch(filepath, opts, cb) {
1722 if (typeof opts === 'function') {
1723 cb = opts
1724 opts = {}
1725 }
1726
1727 if (typeof opts === 'string') opts = { encoding: opts }
1728 else if (!opts) opts = {}
1729
1730 filepath = toNamespacedPath(filepath)
1731
1732 return new Watcher(filepath, opts, cb)
1733}
1734
1735class Stats {
1736 constructor(
1737 dev,
1738 mode,
1739 nlink,
1740 uid,
1741 gid,
1742 rdev,
1743 blksize,
1744 ino,
1745 size,
1746 blocks,
1747 atimeMs,
1748 mtimeMs,
1749 ctimeMs,
1750 birthtimeMs
1751 ) {
1752 this.dev = dev
1753 this.mode = mode
1754 this.nlink = nlink
1755 this.uid = uid
1756 this.gid = gid
1757 this.rdev = rdev
1758 this.blksize = blksize
1759 this.ino = ino
1760 this.size = size
1761 this.blocks = blocks
1762 this.atimeMs = atimeMs
1763 this.mtimeMs = mtimeMs
1764 this.ctimeMs = ctimeMs
1765 this.birthtimeMs = birthtimeMs
1766 this.atime = new Date(atimeMs)
1767 this.mtime = new Date(mtimeMs)
1768 this.ctime = new Date(ctimeMs)
1769 this.birthtime = new Date(birthtimeMs)
1770 }
1771
1772 isDirectory() {
1773 return (this.mode & constants.S_IFMT) === constants.S_IFDIR
1774 }
1775
1776 isFile() {
1777 return (this.mode & constants.S_IFMT) === constants.S_IFREG
1778 }
1779
1780 isBlockDevice() {
1781 return (this.mode & constants.S_IFMT) === constants.S_IFBLK
1782 }
1783
1784 isCharacterDevice() {
1785 return (this.mode & constants.S_IFMT) === constants.S_IFCHR
1786 }
1787
1788 isFIFO() {
1789 return (this.mode & constants.S_IFMT) === constants.S_IFIFO
1790 }
1791
1792 isSymbolicLink() {
1793 return (this.mode & constants.S_IFMT) === constants.S_IFLNK
1794 }
1795
1796 isSocket() {
1797 return (this.mode & constants.S_IFMT) === constants.S_IFSOCK
1798 }
1799}
1800
1801class Dir {
1802 constructor(path, handle, opts = {}) {
1803 const { encoding = 'utf8', bufferSize = 32 } = opts
1804
1805 this.path = path
1806
1807 this._encoding = encoding
1808 this._capacity = bufferSize
1809 this._buffer = new FIFO()
1810 this._ended = false
1811 this._handle = handle
1812 }
1813
1814 async read(cb) {
1815 if (this._buffer.length) return ok(this._buffer.shift(), cb)
1816 if (this._ended) return ok(null, cb)
1817
1818 const req = FileRequest.borrow()
1819
1820 let entries
1821 let err = null
1822 try {
1823 req.retain(binding.readdir(req.handle, this._handle, this._capacity))
1824
1825 await req
1826
1827 entries = binding.requestResultDirents(req.handle)
1828 } catch (e) {
1829 err = new FileError(e.message, {
1830 operation: 'readdir',
1831 code: e.code,
1832 path: this.path
1833 })
1834 } finally {
1835 req.return()
1836 }
1837
1838 if (err) return fail(err, cb)
1839
1840 if (entries.length === 0) {
1841 this._ended = true
1842
1843 return ok(null, cb)
1844 }
1845
1846 for (const entry of entries) {
1847 let name = Buffer.from(entry.name)
1848
1849 if (this._encoding !== 'buffer') name = name.toString(this._encoding)
1850
1851 this._buffer.push(new Dirent(this.path, name, entry.type))
1852 }
1853
1854 return ok(this._buffer.shift(), cb)
1855 }
1856
1857 readSync() {
1858 if (this._buffer.length) return this._buffer.shift()
1859 if (this._ended) return null
1860
1861 const req = FileRequest.borrow()
1862
1863 let entries
1864 try {
1865 req.retain(binding.readdirSync(req.handle, this._handle, this._capacity))
1866
1867 entries = binding.requestResultDirents(req.handle)
1868 } catch (e) {
1869 throw new FileError(e.message, {
1870 operation: 'readdir',
1871 code: e.code,
1872 path: this.path
1873 })
1874 } finally {
1875 req.return()
1876 }
1877
1878 if (entries.length === 0) {
1879 this._ended = true
1880
1881 return null
1882 }
1883
1884 for (const entry of entries) {
1885 let name = Buffer.from(entry.name)
1886
1887 if (this._encoding !== 'buffer') name = name.toString(this._encoding)
1888
1889 this._buffer.push(new Dirent(this.path, name, entry.type))
1890 }
1891
1892 return this._buffer.shift()
1893 }
1894
1895 async close(cb) {
1896 const req = FileRequest.borrow()
1897
1898 let err = null
1899 try {
1900 binding.closedir(req.handle, this._handle)
1901
1902 await req
1903 } catch (e) {
1904 err = new FileError(e.message, {
1905 operation: 'closedir',
1906 code: e.code,
1907 path: this.path
1908 })
1909 } finally {
1910 req.return()
1911 }
1912
1913 this._handle = null
1914
1915 return done(err, cb)
1916 }
1917
1918 closeSync() {
1919 const req = FileRequest.borrow()
1920
1921 try {
1922 binding.closedirSync(req.handle, this._handle)
1923 } catch (e) {
1924 throw new FileError(e.message, {
1925 operation: 'closedir',
1926 code: e.code,
1927 path: this.path
1928 })
1929 } finally {
1930 req.return()
1931 }
1932
1933 this._handle = null
1934 }
1935
1936 [Symbol.dispose]() {
1937 this.closeSync()
1938 }
1939
1940 async [Symbol.asyncDispose]() {
1941 await this.close()
1942 }
1943
1944 *[Symbol.iterator]() {
1945 while (true) {
1946 const entry = this.readSync()
1947 if (entry === null) break
1948 yield entry
1949 }
1950
1951 this.closeSync()
1952 }
1953
1954 async *[Symbol.asyncIterator]() {
1955 while (true) {
1956 const entry = await this.read()
1957 if (entry === null) break
1958 yield entry
1959 }
1960
1961 await this.close()
1962 }
1963}
1964
1965class Dirent {
1966 constructor(parentPath, name, type) {
1967 this.parentPath = parentPath
1968 this.name = name
1969 this.type = type
1970 }
1971
1972 isFile() {
1973 return this.type === constants.UV_DIRENT_FILE
1974 }
1975
1976 isDirectory() {
1977 return this.type === constants.UV_DIRENT_DIR
1978 }
1979
1980 isSymbolicLink() {
1981 return this.type === constants.UV_DIRENT_LINK
1982 }
1983
1984 isFIFO() {
1985 return this.type === constants.UV_DIRENT_FIFO
1986 }
1987
1988 isSocket() {
1989 return this.type === constants.UV_DIRENT_SOCKET
1990 }
1991
1992 isCharacterDevice() {
1993 return this.type === constants.UV_DIRENT_CHAR
1994 }
1995
1996 isBlockDevice() {
1997 return this.type === constants.UV_DIRENT_BLOCK
1998 }
1999}
2000
2001class FileReadStream extends Readable {
2002 constructor(path, opts = {}) {
2003 const { eagerOpen = true } = opts
2004
2005 super({ eagerOpen, ...opts })
2006
2007 this.path = path
2008 this.fd = typeof opts.fd === 'number' ? opts.fd : -1
2009 this.flags = opts.flags || 'r'
2010 this.mode = opts.mode || 0o666
2011
2012 this._offset = opts.start || 0
2013 this._missing = 0
2014
2015 if (opts.length) {
2016 this._missing = opts.length
2017 } else if (typeof opts.end === 'number') {
2018 this._missing = opts.end - this._offset + 1
2019 } else {
2020 this._missing = -1
2021 }
2022 }
2023
2024 async _open(cb) {
2025 let err
2026
2027 if (this.fd === -1) {
2028 err = null
2029 try {
2030 this.fd = await open(this.path, this.flags, this.mode)
2031 } catch (e) {
2032 err = e
2033 }
2034
2035 if (err) return cb(err)
2036 }
2037
2038 let st
2039 err = null
2040 try {
2041 st = await fstat(this.fd)
2042 } catch (e) {
2043 err = e
2044 }
2045
2046 if (err) return cb(err)
2047
2048 if (this._missing === -1) this._missing = st.size
2049
2050 if (st.size < this._offset) {
2051 this._offset = st.size
2052 this._missing = 0
2053 } else if (st.size < this._offset + this._missing) {
2054 this._missing = st.size - this._offset
2055 }
2056
2057 cb(null)
2058 }
2059
2060 async _read(size) {
2061 if (this._missing <= 0) return this.push(null)
2062
2063 const data = Buffer.allocUnsafe(Math.min(this._missing, size))
2064
2065 let len
2066 let err = null
2067 try {
2068 len = await read(this.fd, data, 0, data.byteLength, this._offset)
2069 } catch (e) {
2070 err = e
2071 }
2072
2073 if (err) return this.destroy(err)
2074
2075 if (len === 0) return this.push(null)
2076
2077 if (this._missing < len) len = this._missing
2078
2079 this._missing -= len
2080 this._offset += len
2081
2082 this.push(data.subarray(0, len))
2083 }
2084
2085 async _destroy(err, cb) {
2086 if (this.fd === -1) return cb(err)
2087
2088 try {
2089 await close(this.fd)
2090 } catch (e) {
2091 err = err || e
2092 }
2093
2094 cb(err)
2095 }
2096}
2097
2098class FileWriteStream extends Writable {
2099 constructor(path, opts = {}) {
2100 const { eagerOpen = true } = opts
2101
2102 super({ eagerOpen, ...opts })
2103
2104 this.path = path
2105 this.fd = typeof opts.fd === 'number' ? opts.fd : -1
2106 this.flags = opts.flags || 'w'
2107 this.mode = opts.mode || 0o666
2108 }
2109
2110 async _open(cb) {
2111 if (this.fd !== -1) return cb(null)
2112
2113 let err = null
2114 try {
2115 this.fd = await open(this.path, this.flags, this.mode)
2116 } catch (e) {
2117 err = e
2118 }
2119
2120 cb(err)
2121 }
2122
2123 async _writev(batch, cb) {
2124 let err = null
2125 try {
2126 await writev(
2127 this.fd,
2128 batch.map(({ chunk }) => chunk)
2129 )
2130 } catch (e) {
2131 err = e
2132 }
2133
2134 cb(err)
2135 }
2136
2137 async _destroy(err, cb) {
2138 if (this.fd === -1) return cb(err)
2139
2140 try {
2141 await close(this.fd)
2142 } catch (e) {
2143 err = err || e
2144 }
2145
2146 cb(err)
2147 }
2148}
2149
2150class Watcher extends EventEmitter {
2151 constructor(path, opts, onchange) {
2152 if (typeof opts === 'function') {
2153 onchange = opts
2154 opts = {}
2155 }
2156
2157 if (!opts) opts = {}
2158
2159 const { persistent = true, recursive = false, encoding = 'utf8' } = opts
2160
2161 super()
2162
2163 this._closed = false
2164 this._encoding = encoding
2165 this._handle = binding.watcherInit(path, recursive, this, this._onevent, this._onclose)
2166
2167 if (!persistent) this.unref()
2168
2169 if (onchange) this.on('change', onchange)
2170 }
2171
2172 close() {
2173 if (this._closed) return
2174 this._closed = true
2175
2176 binding.watcherClose(this._handle)
2177 }
2178
2179 ref() {
2180 if (this._handle) binding.watcherRef(this._handle)
2181 return this
2182 }
2183
2184 unref() {
2185 if (this._handle) binding.watcherUnref(this._handle)
2186 return this
2187 }
2188
2189 [Symbol.asyncIterator]() {
2190 const buffer = []
2191 let done = false
2192 let error = null
2193 let next = null
2194
2195 this.on('change', (eventType, filename) => {
2196 if (next) {
2197 next.resolve({ done: false, value: { eventType, filename } })
2198 next = null
2199 } else {
2200 buffer.push({ eventType, filename })
2201 }
2202 })
2203 .on('error', (err) => {
2204 done = true
2205 error = err
2206
2207 if (next) {
2208 next.reject(error)
2209 next = null
2210 }
2211 })
2212 .on('close', () => {
2213 done = true
2214
2215 if (next) {
2216 next.resolve({ done })
2217 next = null
2218 }
2219 })
2220
2221 return {
2222 next: () =>
2223 new Promise((resolve, reject) => {
2224 if (error) return reject(error)
2225
2226 if (buffer.length) return resolve({ done: false, value: buffer.shift() })
2227
2228 if (done) return resolve({ done })
2229
2230 next = { resolve, reject }
2231 })
2232 }
2233 }
2234
2235 _onevent(err, events, filename) {
2236 if (err) {
2237 this.close()
2238 this.emit('error', err)
2239 } else {
2240 const path =
2241 this._encoding === 'buffer'
2242 ? Buffer.from(filename)
2243 : Buffer.from(filename).toString(this._encoding)
2244
2245 if (events & binding.UV_RENAME) {
2246 this.emit('change', 'rename', path)
2247 }
2248
2249 if (events & binding.UV_CHANGE) {
2250 this.emit('change', 'change', path)
2251 }
2252 }
2253 }
2254
2255 _onclose() {
2256 this._handle = null
2257
2258 this.emit('close')
2259 }
2260}
2261
2262exports.access = access
2263exports.appendFile = appendFile
2264exports.chmod = chmod
2265// exports.chown = chown TODO
2266exports.close = close
2267exports.copyFile = copyFile
2268exports.cp = cp
2269exports.exists = exists
2270exports.fchmod = fchmod
2271// exports.fchown = fchown TODO
2272// exports.fdatasync = fdatasync TODO
2273exports.fstat = fstat
2274// exports.fsync = fsync TODO
2275exports.ftruncate = ftruncate
2276// exports.futimes = futimes TODO
2277// exports.lchmod = lchmod TODO
2278// exports.lchown = lchown TODO
2279// exports.lutimes = lutimes TODO
2280// exports.link = link TODO
2281exports.lstat = lstat
2282exports.mkdir = mkdir
2283// exports.mkdtemp = mkdtemp TODO
2284exports.open = open
2285exports.opendir = opendir
2286exports.read = read
2287exports.readFile = readFile
2288exports.readdir = readdir
2289exports.readlink = readlink
2290exports.readv = readv
2291exports.realpath = realpath
2292exports.rename = rename
2293exports.rm = rm
2294exports.rmdir = rmdir
2295exports.stat = stat
2296// exports.statfs = statfs TODO
2297exports.symlink = symlink
2298// exports.truncate = truncate TODO
2299exports.unlink = unlink
2300exports.utimes = utimes
2301exports.watch = watch
2302exports.write = write
2303exports.writeFile = writeFile
2304exports.writev = writev
2305
2306exports.accessSync = accessSync
2307exports.appendFileSync = appendFileSync
2308exports.chmodSync = chmodSync
2309// exports.chownSync = chownSync TODO
2310exports.closeSync = closeSync
2311exports.copyFileSync = copyFileSync
2312exports.existsSync = existsSync
2313exports.fchmodSync = fchmodSync
2314// exports.fchownSync = fchownSync TODO
2315// exports.fdatasyncSync = fdatasyncSync TODO
2316exports.fstatSync = fstatSync
2317// exports.fsyncSync = fsyncSync TODO
2318exports.ftruncateSync = ftruncateSync
2319// exports.futimesSync = futimesSync TODO
2320// exports.lchmodSync = lchmodSync TODO
2321// exports.lchownSync = lchownSync TODO
2322// exports.lutimesSync = lutimesSync TODO
2323// exports.linkSync = linkSync TODO
2324exports.lstatSync = lstatSync
2325exports.mkdirSync = mkdirSync
2326// exports.mkdtempSync = mkdtempSync TODO
2327exports.openSync = openSync
2328exports.opendirSync = opendirSync
2329exports.readFileSync = readFileSync
2330exports.readSync = readSync
2331exports.readdirSync = readdirSync
2332exports.readlinkSync = readlinkSync
2333exports.readvSync = readvSync
2334exports.realpathSync = realpathSync
2335exports.renameSync = renameSync
2336exports.rmSync = rmSync
2337exports.rmdirSync = rmdirSync
2338exports.statSync = statSync
2339// exports.statfsSync = statfsSync TODO
2340exports.symlinkSync = symlinkSync
2341// exports.truncateSync = truncateSync TODO
2342exports.unlinkSync = unlinkSync
2343exports.utimesSync = utimesSync
2344exports.writeFileSync = writeFileSync
2345exports.writeSync = writeSync
2346exports.writevSync = writevSync
2347
2348exports.promises = require('./promises')
2349
2350exports.Stats = Stats
2351exports.Dir = Dir
2352exports.Dirent = Dirent
2353exports.Watcher = Watcher
2354
2355exports.ReadStream = FileReadStream
2356
2357exports.createReadStream = function createReadStream(path, opts) {
2358 return new FileReadStream(path, opts)
2359}
2360
2361exports.WriteStream = FileWriteStream
2362
2363exports.createWriteStream = function createWriteStream(path, opts) {
2364 return new FileWriteStream(path, opts)
2365}
2366
2367function toNamespacedPath(filepath) {
2368 if (typeof filepath !== 'string') {
2369 if (isURL(filepath)) filepath = fileURLToPath(filepath)
2370 else filepath = filepath.toString()
2371 }
2372
2373 return path.toNamespacedPath(filepath)
2374}
2375
2376function toFlags(flags) {
2377 switch (flags) {
2378 case 'r':
2379 return constants.O_RDONLY
2380 case 'rs': // Fall through.
2381 case 'sr':
2382 return constants.O_RDONLY | constants.O_SYNC
2383 case 'r+':
2384 return constants.O_RDWR
2385 case 'rs+': // Fall through.
2386 case 'sr+':
2387 return constants.O_RDWR | constants.O_SYNC
2388
2389 case 'w':
2390 return constants.O_TRUNC | constants.O_CREAT | constants.O_WRONLY
2391 case 'wx': // Fall through.
2392 case 'xw':
2393 return constants.O_TRUNC | constants.O_CREAT | constants.O_WRONLY | constants.O_EXCL
2394
2395 case 'w+':
2396 return constants.O_TRUNC | constants.O_CREAT | constants.O_RDWR
2397 case 'wx+': // Fall through.
2398 case 'xw+':
2399 return constants.O_TRUNC | constants.O_CREAT | constants.O_RDWR | constants.O_EXCL
2400
2401 case 'a':
2402 return constants.O_APPEND | constants.O_CREAT | constants.O_WRONLY
2403 case 'ax': // Fall through.
2404 case 'xa':
2405 return constants.O_APPEND | constants.O_CREAT | constants.O_WRONLY | constants.O_EXCL
2406 case 'as': // Fall through.
2407 case 'sa':
2408 return constants.O_APPEND | constants.O_CREAT | constants.O_WRONLY | constants.O_SYNC
2409
2410 case 'a+':
2411 return constants.O_APPEND | constants.O_CREAT | constants.O_RDWR
2412 case 'ax+': // Fall through.
2413 case 'xa+':
2414 return constants.O_APPEND | constants.O_CREAT | constants.O_RDWR | constants.O_EXCL
2415 case 'as+': // Fall through.
2416 case 'sa+':
2417 return constants.O_APPEND | constants.O_CREAT | constants.O_RDWR | constants.O_SYNC
2418 default:
2419 return 0
2420 }
2421}
2422
2423function toMode(mode) {
2424 return parseInt(mode, 8)
2425}
node_modules/bare-fs/lib/constants.d.ts +49 -0
……@@ -0,0 +1,49 @@
1declare const constants: {
2 O_RDWR: number
3 O_RDONLY: number
4 O_WRONLY: number
5 O_CREAT: number
6 O_TRUNC: number
7 O_APPEND: number
8
9 F_OK: number
10 R_OK: number
11 W_OK: number
12 X_OK: number
13
14 S_IFMT: number
15 S_IFREG: number
16 S_IFDIR: number
17 S_IFCHR: number
18 S_IFLNK: number
19 S_IFBLK: number
20 S_IFIFO: number
21 S_IFSOCK: number
22
23 S_IRUSR: number
24 S_IWUSR: number
25 S_IXUSR: number
26 S_IRGRP: number
27 S_IWGRP: number
28 S_IXGRP: number
29 S_IROTH: number
30 S_IWOTH: number
31 S_IXOTH: number
32
33 UV_DIRENT_UNKNOWN: number
34 UV_DIRENT_FILE: number
35 UV_DIRENT_DIR: number
36 UV_DIRENT_LINK: number
37 UV_DIRENT_FIFO: number
38 UV_DIRENT_SOCKET: number
39 UV_DIRENT_CHAR: number
40 UV_DIRENT_BLOCK: number
41
42 COPYFILE_EXCL: number
43 COPYFILE_FICLONE: number
44 COPYFILE_FICLONE_FORCE: number
45 UV_FS_SYMLINK_DIR: number
46 UV_FS_SYMLINK_JUNCTION: number
47}
48
49export = constants
node_modules/bare-fs/lib/constants.js +49 -0
……@@ -0,0 +1,49 @@
1const binding = require('../binding')
2
3module.exports = {
4 O_RDWR: binding.O_RDWR,
5 O_RDONLY: binding.O_RDONLY,
6 O_WRONLY: binding.O_WRONLY,
7 O_CREAT: binding.O_CREAT,
8 O_TRUNC: binding.O_TRUNC,
9 O_APPEND: binding.O_APPEND,
10
11 F_OK: binding.F_OK || 0,
12 R_OK: binding.R_OK || 0,
13 W_OK: binding.W_OK || 0,
14 X_OK: binding.X_OK || 0,
15
16 S_IFMT: binding.S_IFMT,
17 S_IFREG: binding.S_IFREG,
18 S_IFDIR: binding.S_IFDIR,
19 S_IFCHR: binding.S_IFCHR,
20 S_IFLNK: binding.S_IFLNK,
21 S_IFBLK: binding.S_IFBLK || 0,
22 S_IFIFO: binding.S_IFIFO || 0,
23 S_IFSOCK: binding.S_IFSOCK || 0,
24
25 S_IRUSR: binding.S_IRUSR || 0,
26 S_IWUSR: binding.S_IWUSR || 0,
27 S_IXUSR: binding.S_IXUSR || 0,
28 S_IRGRP: binding.S_IRGRP || 0,
29 S_IWGRP: binding.S_IWGRP || 0,
30 S_IXGRP: binding.S_IXGRP || 0,
31 S_IROTH: binding.S_IROTH || 0,
32 S_IWOTH: binding.S_IWOTH || 0,
33 S_IXOTH: binding.S_IXOTH || 0,
34
35 UV_DIRENT_UNKNOWN: binding.UV_DIRENT_UNKNOWN,
36 UV_DIRENT_FILE: binding.UV_DIRENT_FILE,
37 UV_DIRENT_DIR: binding.UV_DIRENT_DIR,
38 UV_DIRENT_LINK: binding.UV_DIRENT_LINK,
39 UV_DIRENT_FIFO: binding.UV_DIRENT_FIFO,
40 UV_DIRENT_SOCKET: binding.UV_DIRENT_SOCKET,
41 UV_DIRENT_CHAR: binding.UV_DIRENT_CHAR,
42 UV_DIRENT_BLOCK: binding.UV_DIRENT_BLOCK,
43
44 COPYFILE_EXCL: binding.UV_FS_COPYFILE_EXCL,
45 COPYFILE_FICLONE: binding.UV_FS_COPYFILE_FICLONE,
46 COPYFILE_FICLONE_FORCE: binding.UV_FS_COPYFILE_FICLONE_FORCE,
47 UV_FS_SYMLINK_DIR: binding.UV_FS_SYMLINK_DIR,
48 UV_FS_SYMLINK_JUNCTION: binding.UV_FS_SYMLINK_JUNCTION
49}
node_modules/bare-fs/lib/errors.d.ts +11 -0
……@@ -0,0 +1,11 @@
1declare class FileError extends Error {
2 private constructor(msg: string)
3
4 readonly code: string
5 readonly operation?: string
6 readonly path?: string
7 readonly destination?: string
8 readonly fd?: number
9}
10
11export = FileError
node_modules/bare-fs/lib/errors.js +55 -0
……@@ -0,0 +1,55 @@
1const os = require('bare-os')
2
3module.exports = class FileError extends Error {
4 constructor(msg, opts = {}) {
5 const { code, operation = null, path = null, destination = null, fd = -1 } = opts
6
7 if (operation !== null) msg += describe(operation, opts)
8
9 super(`${code}: ${msg}`)
10
11 this.code = code
12
13 if (operation !== null) this.operation = operation
14 if (path !== null) this.path = path
15 if (destination !== null) this.destination = destination
16 if (fd !== -1) this.fd = fd
17 }
18
19 get name() {
20 return 'FileError'
21 }
22
23 // For Node.js compatibility
24 get errno() {
25 return os.constants.errnos[this.code]
26 }
27
28 // For Node.js compatibility
29 get syscall() {
30 return this.operation
31 }
32
33 // For Node.js compatibility
34 get dest() {
35 return this.destination
36 }
37}
38
39function describe(operation, opts) {
40 const { path = null, destination = null, fd = -1 } = opts
41
42 let result = `, ${operation}`
43
44 if (path !== null) {
45 result += ` ${JSON.stringify(path)}`
46
47 if (destination !== null) {
48 result += ` -> ${JSON.stringify(destination)}`
49 }
50 } else if (fd !== -1) {
51 result += ` ${fd}`
52 }
53
54 return result
55}
node_modules/bare-fs/package.json +71 -0
……@@ -0,0 +1,71 @@
1{
2 "name": "bare-fs",
3 "version": "4.5.6",
4 "description": "Native file system operations for Javascript",
5 "exports": {
6 "./package": "./package.json",
7 ".": {
8 "types": "./index.d.ts",
9 "default": "./index.js"
10 },
11 "./promises": {
12 "types": "./promises.d.ts",
13 "default": "./promises.js"
14 },
15 "./constants": {
16 "types": "./lib/constants.d.ts",
17 "default": "./lib/constants.js"
18 }
19 },
20 "files": [
21 "index.js",
22 "index.d.ts",
23 "promises.js",
24 "promises.d.ts",
25 "binding.c",
26 "binding.js",
27 "CMakeLists.txt",
28 "lib",
29 "prebuilds"
30 ],
31 "addon": true,
32 "scripts": {
33 "test": "prettier . --check && bare test.js"
34 },
35 "repository": {
36 "type": "git",
37 "url": "git+https://github.com/holepunchto/bare-fs.git"
38 },
39 "author": "Holepunch",
40 "license": "Apache-2.0",
41 "bugs": {
42 "url": "https://github.com/holepunchto/bare-fs/issues"
43 },
44 "homepage": "https://github.com/holepunchto/bare-fs#readme",
45 "engines": {
46 "bare": ">=1.16.0"
47 },
48 "dependencies": {
49 "bare-events": "^2.5.4",
50 "bare-path": "^3.0.0",
51 "bare-stream": "^2.6.4",
52 "bare-url": "^2.2.2",
53 "fast-fifo": "^1.3.2"
54 },
55 "devDependencies": {
56 "bare-buffer": "^3.0.2",
57 "bare-crypto": "^1.11.2",
58 "brittle": "^3.1.1",
59 "cmake-bare": "^1.1.7",
60 "prettier": "^3.4.1",
61 "prettier-config-holepunch": "^2.0.0"
62 },
63 "peerDependencies": {
64 "bare-buffer": "*"
65 },
66 "peerDependenciesMeta": {
67 "bare-buffer": {
68 "optional": true
69 }
70 }
71}
node_modules/bare-fs/prebuilds/android-arm/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/android-arm64/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/android-ia32/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/android-x64/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/darwin-arm64/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/darwin-x64/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/ios-arm64-simulator/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/ios-arm64/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/ios-x64-simulator/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/linux-arm64/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/linux-x64/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/win32-arm64/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/prebuilds/win32-x64/bare-fs.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-fs/promises.d.ts +282 -0
……@@ -0,0 +1,282 @@
1import EventEmitter, { EventMap } from 'bare-events'
2import Buffer, { BufferEncoding } from 'bare-buffer'
3import {
4 constants,
5 AppendFileOptions,
6 CpOptions,
7 Dir,
8 MkdirOptions,
9 OpendirOptions,
10 Path,
11 ReadFileOptions,
12 ReadStream,
13 ReadStreamOptions,
14 ReaddirOptions,
15 ReadlinkOptions,
16 RealpathOptions,
17 RmOptions,
18 Stats,
19 Watcher,
20 WatcherOptions,
21 WriteFileOptions,
22 WriteStream,
23 WriteStreamOptions
24} from '.'
25
26export { constants }
27
28interface FileHandleEvents extends EventMap {
29 close: []
30}
31
32interface FileHandle extends EventEmitter<FileHandleEvents>, AsyncDisposable {
33 close(): Promise<void>
34
35 read(
36 buffer: Buffer | ArrayBufferView,
37 offset?: number,
38 len?: number,
39 pos?: number
40 ): Promise<number>
41
42 readv(buffers: ArrayBufferView[], position?: number): Promise<number>
43
44 write(
45 data: Buffer | ArrayBufferView,
46 offset?: number,
47 len?: number,
48 pos?: number
49 ): Promise<number>
50
51 write(data: string, pos?: number, encoding?: BufferEncoding): Promise<number>
52
53 stat(): Promise<Stats>
54
55 chmod(mode: string | number): Promise<void>
56
57 createReadStream(opts?: ReadStreamOptions): ReadStream
58
59 createWriteStream(opts?: WriteStreamOptions): WriteStream
60}
61
62declare class FileHandle {
63 private constructor(fd: number)
64}
65
66export function open(
67 filepath: Path,
68 flags?: Flag | number,
69 mode?: string | number
70): Promise<FileHandle>
71
72export function access(filepath: Path, mode?: number): Promise<void>
73
74export function appendFile(
75 filepath: Path,
76 data: string | Buffer | ArrayBufferView,
77 opts?: AppendFileOptions
78): Promise<void>
79
80export function appendFile(
81 filepath: Path,
82 data: string | Buffer | ArrayBufferView,
83 encoding: BufferEncoding
84): Promise<void>
85
86export function chmod(filepath: Path, mode: string | number): Promise<void>
87
88export function copyFile(src: Path, dst: Path, mode?: number): Promise<void>
89
90export function cp(src: Path, dst: Path, opts?: CpOptions): Promise<void>
91
92export function lstat(filepath: Path): Promise<Stats>
93
94export function mkdir(filepath: Path, opts?: MkdirOptions): Promise<void>
95
96export function mkdir(filepath: Path, mode: number): Promise<void>
97
98export function opendir(
99 filepath: Path,
100 opts: OpendirOptions & { encoding?: BufferEncoding }
101): Promise<Dir<string>>
102
103export function opendir(
104 filepath: Path,
105 opts: OpendirOptions & { encoding: 'buffer' }
106): Promise<Dir<Buffer>>
107
108export function opendir(filepath: Path, opts: OpendirOptions): Promise<Dir>
109
110export function opendir(filepath: Path, encoding: BufferEncoding): Promise<Dir<string>>
111
112export function opendir(filepath: Path, encoding: 'buffer'): Promise<Dir<Buffer>>
113
114export function opendir(filepath: Path, encoding: BufferEncoding | 'buffer'): Promise<Dir>
115
116export function opendir(filepath: Path): Promise<Dir<string>>
117
118export function readFile(
119 filepath: Path,
120 opts: ReadFileOptions & { encoding: BufferEncoding }
121): Promise<string>
122
123export function readFile(
124 filepath: Path,
125 opts: ReadFileOptions & { encoding?: 'buffer' }
126): Promise<Buffer>
127
128export function readFile(filepath: Path, opts: ReadFileOptions): Promise<string | Buffer>
129
130export function readFile(filepath: Path, encoding: BufferEncoding): Promise<string>
131
132export function readFile(filepath: Path, encoding: 'buffer'): Promise<Buffer>
133
134export function readFile(
135 filepath: Path,
136 encoding?: BufferEncoding | 'buffer'
137): Promise<string | Buffer>
138
139export function readFile(filepath: Path): Promise<Buffer>
140
141export function readdir(
142 filepath: Path,
143 opts: ReaddirOptions & { encoding?: BufferEncoding }
144): Promise<Dir<string>[] | string[]>
145
146export function readdir(
147 filepath: Path,
148 opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes: true }
149): Promise<Dir<string>[]>
150
151export function readdir(
152 filepath: Path,
153 opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes?: false }
154): Promise<string[]>
155
156export function readdir(
157 filepath: Path,
158 opts: ReaddirOptions & { encoding: 'buffer' }
159): Promise<Dir<Buffer>[] | Buffer[]>
160
161export function readdir(
162 filepath: Path,
163 opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes: true }
164): Promise<Dir<Buffer>[]>
165
166export function readdir(
167 filepath: Path,
168 opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes?: false }
169): Promise<Buffer[]>
170
171export function readdir(
172 filepath: Path,
173 opts: ReaddirOptions & { withFileTypes: true }
174): Promise<Dir<string | Buffer>[]>
175
176export function readdir(
177 filepath: Path,
178 opts: ReaddirOptions & { withFileTypes?: false }
179): Promise<string[] | Buffer[]>
180
181export function readdir(filepath: Path, opts: ReaddirOptions): Promise<Dir[] | string[] | Buffer[]>
182
183export function readdir(filepath: Path, encoding: BufferEncoding): Promise<string[]>
184
185export function readdir(filepath: Path, encoding: 'buffer'): Promise<Buffer[]>
186
187export function readdir(
188 filepath: Path,
189 encoding: BufferEncoding | 'buffer'
190): Promise<string[] | Buffer[]>
191
192export function readdir(filepath: Path): Promise<string[]>
193
194export function readlink(
195 filepath: Path,
196 opts: ReadlinkOptions & { encoding?: BufferEncoding }
197): Promise<string>
198
199export function readlink(
200 filepath: Path,
201 opts: ReadlinkOptions & { encoding: 'buffer' }
202): Promise<Buffer>
203
204export function readlink(filepath: Path, opts: ReadlinkOptions): Promise<string | Buffer>
205
206export function readlink(filepath: Path, encoding: BufferEncoding): Promise<string>
207
208export function readlink(filepath: Path, encoding: 'buffer'): Promise<Buffer>
209
210export function readlink(
211 filepath: Path,
212 encoding: BufferEncoding | 'buffer'
213): Promise<string | Buffer>
214
215export function readlink(filepath: Path): Promise<string>
216
217export function realpath(
218 filepath: Path,
219 opts: RealpathOptions & { encoding?: BufferEncoding }
220): Promise<string>
221
222export function realpath(
223 filepath: Path,
224 opts: RealpathOptions & { encoding: 'buffer' }
225): Promise<Buffer>
226
227export function realpath(filepath: Path, opts: RealpathOptions): Promise<string | Buffer>
228
229export function realpath(filepath: Path, encoding: BufferEncoding): Promise<string>
230
231export function realpath(filepath: Path, encoding: 'buffer'): Promise<Buffer>
232
233export function realpath(
234 filepath: Path,
235 encoding: BufferEncoding | 'buffer'
236): Promise<string | Buffer>
237
238export function realpath(filepath: Path): Promise<string>
239
240export function rename(src: Path, dst: Path): Promise<void>
241
242export function rm(filepath: Path, opts?: RmOptions): Promise<void>
243
244export function rmdir(filepath: Path): Promise<void>
245
246export function stat(filepath: Path): Promise<Stats>
247
248export function symlink(target: Path, filepath: Path, type?: string | number): Promise<void>
249
250export function unlink(filepath: Path): Promise<void>
251
252export function watch(
253 filepath: Path,
254 opts: WatcherOptions & { encoding?: BufferEncoding }
255): Watcher<string>
256
257export function watch(
258 filepath: Path,
259 opts: WatcherOptions & { encoding: 'buffer' }
260): Watcher<Buffer>
261
262export function watch(filepath: Path, opts: WatcherOptions): Watcher
263
264export function watch(filepath: Path, encoding: BufferEncoding): Watcher<string>
265
266export function watch(filepath: Path, encoding: 'buffer'): Watcher<Buffer>
267
268export function watch(filepath: Path, encoding: BufferEncoding | 'buffer'): Watcher
269
270export function watch(filepath: Path): Watcher<string>
271
272export function writeFile(
273 filepath: Path,
274 data: string | Buffer | ArrayBufferView,
275 opts?: WriteFileOptions
276): Promise<void>
277
278export function writeFile(
279 filepath: Path,
280 data: string | Buffer | ArrayBufferView,
281 encoding: BufferEncoding
282): Promise<void>
node_modules/bare-fs/promises.js +90 -0
……@@ -0,0 +1,90 @@
1const EventEmitter = require('bare-events')
2const fs = require('.')
3
4class FileHandle extends EventEmitter {
5 constructor(fd) {
6 this.fd = fd
7 }
8
9 async close() {
10 await fs.close(fd)
11
12 this.fd = -1
13 this.emit('close')
14 }
15
16 async read(buffer, ...args) {
17 return {
18 bytesRead: await fs.read(this.fd, buffer, ...args),
19 buffer
20 }
21 }
22
23 async readv(buffers, ...args) {
24 return {
25 bytesRead: await fs.readv(this.fd, buffers, ...args),
26 buffers
27 }
28 }
29
30 async write(buffer, ...args) {
31 return {
32 bytesWritten: await fs.write(this.fd, buffer, ...args),
33 buffer
34 }
35 }
36
37 async writev(buffers, ...args) {
38 return {
39 bytesWritten: await fs.writev(this.fd, buffers, ...args),
40 buffers
41 }
42 }
43
44 async stat() {
45 return fs.fstat(this.fd)
46 }
47
48 async chmod(mode) {
49 await fs.fchmod(this.fd, mode)
50 }
51
52 createReadStream(opts) {
53 return fs.createReadStream(null, { ...opts, fd: this.fd })
54 }
55
56 createWriteStream(opts) {
57 return fs.createWriteStream(null, { ...opts, fd: this.fd })
58 }
59
60 async [Symbol.asyncDispose]() {
61 await this.close()
62 }
63}
64
65exports.open = async function open(filepath, flags, mode) {
66 return new FileHandle(await fs.open(filepath, flags, mode))
67}
68
69exports.access = fs.access
70exports.appendFile = fs.appendFile
71exports.chmod = fs.chmod
72exports.constants = fs.constants
73exports.copyFile = fs.copyFile
74exports.cp = fs.cp
75exports.lstat = fs.lstat
76exports.mkdir = fs.mkdir
77exports.opendir = fs.opendir
78exports.readFile = fs.readFile
79exports.readdir = fs.readdir
80exports.readlink = fs.readlink
81exports.realpath = fs.realpath
82exports.rename = fs.rename
83exports.rm = fs.rm
84exports.rmdir = fs.rmdir
85exports.stat = fs.stat
86exports.symlink = fs.symlink
87exports.unlink = fs.unlink
88exports.utimes = fs.utimes
89exports.watch = fs.watch
90exports.writeFile = fs.writeFile
node_modules/bare-inspect/CMakeLists.txt +13 -0
……@@ -0,0 +1,13 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4
5project(bare_inspect C)
6
7add_bare_module(bare_inspect)
8
9target_sources(
10 ${bare_inspect}
11 PRIVATE
12 binding.c
13)
node_modules/bare-inspect/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-inspect/README.md +19 -0
……@@ -0,0 +1,19 @@
1# bare-inspect
2
3Inspect objects as strings for debugging.
4
5```
6npm i bare-inspect
7```
8
9## Usage
10
11```js
12const inspect = require('bare-inspect')
13
14console.log(inspect(globalThis))
15```
16
17## License
18
19Apache-2.0
node_modules/bare-inspect/binding.c +111 -0
……@@ -0,0 +1,111 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4
5static js_value_t *
6bare_inspect_get_promise_state(js_env_t *env, js_callback_info_t *info) {
7 int err;
8
9 js_value_t *argv[1];
10 size_t argc = 1;
11
12 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
13 assert(err == 0);
14
15 assert(argc == 1);
16
17 js_promise_state_t state;
18 err = js_get_promise_state(env, argv[0], &state);
19 assert(err == 0);
20
21 js_value_t *result;
22 err = js_create_uint32(env, state, &result);
23 assert(err == 0);
24
25 return result;
26}
27
28static js_value_t *
29bare_inspect_get_promise_result(js_env_t *env, js_callback_info_t *info) {
30 int err;
31
32 js_value_t *argv[1];
33 size_t argc = 1;
34
35 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
36 assert(err == 0);
37
38 assert(argc == 1);
39
40 js_value_t *result;
41 err = js_get_promise_result(env, argv[0], &result);
42 assert(err == 0);
43
44 return result;
45}
46
47static js_value_t *
48bare_inspect_get_external(js_env_t *env, js_callback_info_t *info) {
49 int err;
50
51 size_t argc = 1;
52 js_value_t *argv[1];
53
54 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
55 assert(err == 0);
56
57 assert(argc == 1);
58
59 void *data;
60 err = js_get_value_external(env, argv[0], &data);
61 assert(err == 0);
62
63 js_value_t *result;
64 err = js_create_bigint_uint64(env, (uintptr_t) data, &result);
65 assert(err == 0);
66
67 return result;
68}
69
70static js_value_t *
71bare_inspect_get_own_non_index_property_names(js_env_t *env, js_callback_info_t *info) {
72 int err;
73
74 size_t argc = 1;
75 js_value_t *argv[1];
76
77 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
78 assert(err == 0);
79
80 assert(argc == 1);
81
82 js_value_t *result;
83 err = js_get_filtered_property_names(env, argv[0], js_key_own_only, js_property_only_enumerable, js_index_skip_indices, js_key_convert_to_string, &result);
84 assert(err == 0);
85
86 return result;
87}
88
89static js_value_t *
90bare_inspect_exports(js_env_t *env, js_value_t *exports) {
91 int err;
92
93#define V(name, fn) \
94 { \
95 js_value_t *val; \
96 err = js_create_function(env, name, -1, fn, NULL, &val); \
97 assert(err == 0); \
98 err = js_set_named_property(env, exports, name, val); \
99 assert(err == 0); \
100 }
101
102 V("getPromiseState", bare_inspect_get_promise_state)
103 V("getPromiseResult", bare_inspect_get_promise_result)
104 V("getExternal", bare_inspect_get_external)
105 V("getOwnNonIndexPropertyNames", bare_inspect_get_own_non_index_property_names)
106#undef V
107
108 return exports;
109}
110
111BARE_MODULE(bare_inspect, bare_inspect_exports)
node_modules/bare-inspect/binding.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require.addon()
node_modules/bare-inspect/index.d.ts +33 -0
……@@ -0,0 +1,33 @@
1interface InspectStylize {
2 (value: string, style: keyof typeof inspect.styles): string
3}
4
5interface InspectOptions {
6 colors?: boolean
7 depth?: number
8 breakLength?: number
9 stylize?: InspectStylize
10}
11
12declare function inspect(value: unknown, opts?: InspectOptions): string
13
14declare namespace inspect {
15 export const styles: {
16 bigint: string
17 boolean: string
18 date: string
19 module: string
20 name: string
21 null: string
22 number: string
23 regexp: string
24 special: string
25 string: string
26 symbol: string
27 undefined: string
28 }
29
30 export { type InspectOptions, type InspectStylize }
31}
32
33export = inspect
node_modules/bare-inspect/index.js +1063 -0
……@@ -0,0 +1,1063 @@
1const ansiEscapes = require('bare-ansi-escapes')
2const getType = require('bare-type')
3const binding = require('./binding')
4
5const PLAIN_KEY = /^[a-zA-Z_][a-zA-Z_0-9]*$/
6
7const defaultDepth = 2
8const defaultBreakLength = 80
9const defaultMaxArrayLength = 40
10
11module.exports = exports = function inspect(value, opts = {}) {
12 const {
13 colors = false,
14 depth = defaultDepth,
15 breakLength = defaultBreakLength,
16 stylize = defaultStylize(colors)
17 } = opts
18
19 const references = new InspectRefMap()
20
21 const tree = inspectValue(value, 0, {
22 colors,
23 depth,
24 breakLength,
25 stylize,
26 references
27 })
28
29 return tree.toString()
30}
31
32exports.styles = {
33 bigint: ansiEscapes.colorYellow,
34 boolean: ansiEscapes.colorYellow,
35 date: ansiEscapes.colorMagenta,
36 module: ansiEscapes.modifierUnderline,
37 name: ansiEscapes.modifierReset,
38 null: ansiEscapes.modifierBold,
39 number: ansiEscapes.colorYellow,
40 regexp: ansiEscapes.colorRed,
41 special: ansiEscapes.colorCyan,
42 string: ansiEscapes.colorGreen,
43 symbol: ansiEscapes.colorGreen,
44 undefined: ansiEscapes.colorBrightBlack
45}
46
47const styles = exports.styles
48
49function defaultStylize(colors) {
50 return function stylize(value, style) {
51 const color = colors && styles[style]
52
53 if (color) return color + value + ansiEscapes.modifierReset
54
55 return value
56 }
57}
58
59class InspectRefMap {
60 constructor() {
61 this.refs = new WeakMap()
62 this.ids = new WeakMap()
63 this.nextId = 1
64 }
65
66 has(object) {
67 return this.refs.has(object)
68 }
69
70 get(object) {
71 return this.refs.get(object) || null
72 }
73
74 set(object, ref) {
75 this.refs.set(object, ref)
76 }
77
78 id(object) {
79 let id = this.ids.get(object)
80 if (id) return id
81
82 id = this.nextId++
83 this.ids.set(object, id)
84
85 return id
86 }
87}
88
89class InspectNode {
90 constructor(depth, length, opts) {
91 const { breakLength = defaultBreakLength, breakAlways = false } = opts
92
93 this.depth = depth
94 this.length = length
95 this.breakLength = breakLength
96 this.breakAlways = breakAlways
97 }
98
99 pad(n, string) {
100 return string.padStart(n, ' ')
101 }
102
103 indent(n, string) {
104 return ' '.repeat(n) + string
105 }
106}
107
108class InspectRef extends InspectNode {
109 constructor(depth, opts) {
110 super(depth, '[circular *]'.length, opts)
111
112 this.refs = opts.references
113 this.count = 0
114 this.circular = false
115 this.color = opts.colors && styles.special
116 }
117
118 get id() {
119 return this.refs.id(this)
120 }
121
122 increment() {
123 return ++this.count
124 }
125
126 decrement() {
127 return --this.count
128 }
129
130 toString(opts = {}) {
131 const { offset = 0, pad = 0, indent = 0 } = opts
132
133 let value = this.pad(pad, '[circular *' + this.id + ']')
134
135 if (this.color) value = this.color + value + ansiEscapes.modifierReset
136
137 return offset ? value : this.indent(indent, value)
138 }
139}
140
141class InspectLeaf extends InspectNode {
142 constructor(value, color, depth, opts) {
143 const length = value.length
144
145 if (value.includes('\n')) {
146 value = value.replaceAll('\n', '\n' + ' '.repeat(depth))
147
148 opts = { ...opts, breakAlways: true }
149 }
150
151 super(depth, length, opts)
152
153 this.value = value
154 this.color = opts.colors && color
155 }
156
157 toString(opts = {}) {
158 const { offset = 0, pad = 0, indent = 0 } = opts
159
160 let value = this.pad(pad, this.value)
161
162 if (this.color) value = this.color + value + ansiEscapes.modifierReset
163
164 return offset ? value : this.indent(indent, value)
165 }
166}
167
168class InspectPair extends InspectNode {
169 constructor(delim, left, right, depth, opts) {
170 const length = left.length + delim.length + right.length
171
172 if (left.breakAlways || right.breakAlways) {
173 opts = { ...opts, breakAlways: true }
174 }
175
176 super(depth, length, opts)
177
178 this.delim = delim
179 this.left = left
180 this.right = right
181 }
182
183 toString(opts = {}) {
184 const { indent = 0 } = opts
185
186 return this.indent(
187 indent,
188 this.left +
189 this.delim +
190 this.right.toString({
191 indent,
192 offset: this.left.length + this.delim.length
193 })
194 )
195 }
196}
197
198class InspectSuspension extends InspectNode {
199 constructor(overflow, depth, opts) {
200 const label = `... ${overflow} more`
201
202 super(depth, label.length, opts)
203
204 this.label = label
205 }
206
207 toString(opts = {}) {
208 const { indent = 0 } = opts
209
210 return this.indent(indent, this.label)
211 }
212}
213
214class InspectSequence extends InspectNode {
215 constructor(header, footer, delim, values, ref, depth, opts) {
216 const { tabulate = false } = opts
217
218 const length =
219 (ref.circular ? '<ref *>'.length + 1 : 0) +
220 header.length +
221 values.reduce(
222 (length, value, i) =>
223 length + value.length + (i === 0 ? 0 : delim.length),
224 0
225 ) +
226 footer.length
227
228 if (values.some((value) => value.breakAlways)) {
229 opts = { ...opts, breakAlways: true }
230 }
231
232 super(depth, length, opts)
233
234 this.header = header
235 this.footer = footer
236 this.delim = delim
237 this.values = values
238 this.ref = ref
239 this.tabulate = tabulate
240 }
241
242 toString(opts = {}) {
243 const { offset = 0, indent = 0 } = opts
244
245 const split =
246 this.breakAlways ||
247 (this.values.length &&
248 (offset + this.length > this.breakLength ||
249 indent * 2 + this.length > this.breakLength))
250
251 let header = this.header
252
253 if (this.ref.circular) {
254 header = '<ref *' + this.ref.id + '> ' + header
255 }
256
257 if (this.values.length === 0) {
258 header = header.trimEnd()
259 }
260
261 if (offset === 0) {
262 header = this.indent(indent, header)
263 }
264
265 if (split) {
266 header = header.trimEnd() + '\n'
267 }
268
269 let string = header
270
271 let columns = 1
272 let pad = 0
273
274 if (this.tabulate) {
275 const widest = this.values.reduce(
276 (length, value) =>
277 value.breakAlways ? length : Math.max(length, value.length),
278 0
279 )
280
281 if (widest) {
282 columns = Math.max(
283 columns,
284 Math.floor(
285 (this.breakLength - indent * 2) / (widest + this.delim.length)
286 )
287 )
288
289 if (columns > 1) pad = widest
290 }
291 }
292
293 for (let i = 0, n = this.values.length, offset = 0; i < n; i++) {
294 const value = this.values[i]
295
296 if (split) {
297 let part
298
299 if (i % columns === 0 || value.breakAlways) {
300 part = value.toString({ indent: indent + 1, pad })
301 } else {
302 part = value.toString({ pad })
303 }
304
305 string += part
306
307 if (i < n - 1) {
308 if (i % columns === columns - 1 || this.values[i + 1].breakAlways) {
309 string += this.delim.trimEnd() + '\n'
310 } else {
311 string += this.delim
312 }
313 }
314 } else {
315 if (i > 0) string += this.delim
316
317 string += value.toString({ offset })
318
319 offset += value.length
320 }
321 }
322
323 let footer = this.footer
324
325 if (this.values.length === 0) {
326 footer = footer.trimStart()
327 }
328
329 if (split) {
330 string += '\n' + this.indent(indent, footer.trimStart())
331 } else {
332 string += footer
333 }
334
335 return string
336 }
337}
338
339function inspectValue(value, depth, opts) {
340 const type = getType(value)
341
342 if (type.isUndefined()) return inspectUndefined(depth, opts)
343 if (type.isNull()) return inspectNull(depth, opts)
344 if (type.isBoolean()) return inspectBoolean(value, depth, opts)
345 if (type.isNumber()) return inspectNumber(value, depth, opts)
346 if (type.isBigInt()) return inspectBigInt(value, depth, opts)
347 if (type.isString()) return inspectString(value, depth, opts)
348 if (type.isSymbol()) return inspectSymbol(value, depth, opts)
349 if (type.isObject()) return inspectObject(type, value, depth, opts)
350 if (type.isFunction()) return inspectFunction(type, value, depth, opts)
351 if (type.isExternal()) return inspectExternal(value, opts, opts)
352}
353
354function inspectUndefined(depth, opts) {
355 return new InspectLeaf('undefined', styles.undefined, depth, opts)
356}
357
358function inspectNull(depth, opts) {
359 return new InspectLeaf('null', styles.null, depth, opts)
360}
361
362function inspectBoolean(value, depth, opts) {
363 return new InspectLeaf(value.toString(), styles.boolean, depth, opts)
364}
365
366function inspectNumber(value, depth, opts) {
367 let string
368
369 if (Object.is(value, -0)) {
370 string = '-0'
371 } else {
372 string = value.toString(10)
373 }
374
375 return new InspectLeaf(string, styles.number, depth, opts)
376}
377
378function inspectBigInt(value, depth, opts) {
379 return new InspectLeaf(value.toString(10) + 'n', styles.bigint, depth, opts)
380}
381
382const STRING_ESCAPES =
383 /[\ud800-\udbff][\udc00-\udfff]|[\u0000-\u001f'\\\ud800-\udfff]/g
384
385function inspectString(value, depth, opts) {
386 // https://tc39.es/ecma262/multipage/structured-data.html#sec-quotejsonstring
387 const string = value.replace(STRING_ESCAPES, (match) => {
388 if (match.length === 2) return match
389
390 switch (match) {
391 case "'":
392 return "\\'"
393 case '\\':
394 return '\\\\'
395 case '\b':
396 return '\\b'
397 case '\t':
398 return '\\t'
399 case '\n':
400 return '\\n'
401 case '\f':
402 return '\\f'
403 case '\r':
404 return '\\r'
405 default:
406 return '\\u' + match.charCodeAt(0).toString(16).padStart(4, '0')
407 }
408 })
409
410 return new InspectLeaf("'" + string + "'", styles.string, depth, opts)
411}
412
413function inspectSymbol(value, depth, opts) {
414 return new InspectLeaf(value.toString(), styles.symbol, depth, opts)
415}
416
417function inspectKey(value, depth, opts) {
418 if (PLAIN_KEY.test(value)) {
419 return new InspectLeaf(value, null, depth, opts)
420 } else {
421 return inspectValue(value, depth, opts)
422 }
423}
424
425function inspectObject(type, object, depth, opts) {
426 const refs = opts.references
427
428 let ref = refs.get(object)
429 if (ref === null) {
430 ref = new InspectRef(depth, opts)
431 refs.set(object, ref)
432 } else if (ref.count) {
433 ref.circular = true
434 return ref
435 }
436
437 const maxDepth = typeof opts.depth === 'number' ? opts.depth : Infinity
438
439 if (maxDepth < depth) {
440 const constructor = object.constructor
441
442 return new InspectLeaf(
443 '[' +
444 (constructor && constructor.name ? constructor.name : 'Object') +
445 ']',
446 styles.special,
447 depth,
448 opts
449 )
450 }
451
452 const inspect =
453 object[Symbol.for('bare.inspect')] ||
454 object[Symbol.for('nodejs.util.inspect.custom')]
455
456 if (typeof inspect === 'function') {
457 const value = inspect.call(
458 object,
459 typeof opts.depth === 'number' ? opts.depth - depth : null,
460 {
461 colors: opts.colors,
462 breakLength: opts.breakLength,
463 stylize: opts.stylize
464 },
465 exports
466 )
467
468 if (typeof value === 'object' && value !== null) {
469 refs.set(value, ref)
470 }
471
472 if (typeof value !== 'string') {
473 return inspectValue(value, depth, opts)
474 }
475
476 return new InspectLeaf(value, null, depth, opts)
477 }
478
479 if (type.isArray()) return inspectArray(object, ref, depth, opts)
480 if (type.isDate()) return inspectDate(object, ref, depth, opts)
481 if (type.isRegExp()) return inspectRegExp(object, ref, depth, opts)
482 if (type.isError()) return inspectError(object, ref, depth, opts)
483 if (type.isPromise()) return inspectPromise(object, ref, depth, opts)
484 if (type.isMap()) return inspectMap(object, ref, depth, opts)
485 if (type.isSet()) return inspectSet(object, ref, depth, opts)
486 if (type.isWeakMap()) return inspectWeakMap(object, ref, depth, opts)
487 if (type.isWeakSet()) return inspectWeakSet(object, ref, depth, opts)
488 if (type.isWeakRef()) return inspectWeakRef(object, ref, depth, opts)
489 if (type.isArrayBuffer()) return inspectArrayBuffer(object, ref, depth, opts)
490 if (type.isSharedArrayBuffer())
491 return inspectSharedArrayBuffer(object, ref, depth, opts)
492 if (type.isTypedArray()) return inspectTypedArray(object, ref, depth, opts)
493 if (type.isDataView()) return inspectDataView(object, ref, depth, opts)
494
495 ref.increment()
496
497 const values = []
498
499 for (const key in object) {
500 if (key === 'constructor') continue
501
502 values.push(
503 new InspectPair(
504 ': ',
505 inspectKey(key, depth + 1, opts),
506 inspectValue(object[key], depth + 1, opts),
507 depth + 1,
508 opts
509 )
510 )
511 }
512
513 ref.decrement()
514
515 let header = '{ '
516
517 const tag = object[Symbol.toStringTag]
518
519 if (tag) header = '[' + tag + '] ' + header
520
521 if (object.constructor) {
522 const name = object.constructor.name
523
524 if (name && name !== 'Object') {
525 header = object.constructor.name + ' ' + header
526 }
527 }
528
529 return new InspectSequence(header, ' }', ', ', values, ref, depth, opts)
530}
531
532function inspectArray(array, ref, depth, opts) {
533 const { maxArrayLength = defaultMaxArrayLength } = opts
534
535 ref.increment()
536
537 const values = []
538
539 let remaining = Math.max(maxArrayLength, 0)
540
541 for (let i = 0, n = array.length; i < n; i++) {
542 if (remaining-- === 0) {
543 values.push(
544 new InspectSuspension(array.length - values.length, depth + 1, {
545 ...opts,
546 breakAlways: true
547 })
548 )
549
550 break
551 }
552
553 values.push(inspectValue(array[i], depth + 1, opts))
554 }
555
556 for (const key of binding.getOwnNonIndexPropertyNames(array)) {
557 values.push(
558 new InspectPair(
559 ': ',
560 inspectKey(key, depth + 1, opts),
561 inspectValue(array[key], depth + 1, opts),
562 depth + 1,
563 { ...opts, breakAlways: remaining < 0 }
564 )
565 )
566 }
567
568 ref.decrement()
569
570 let header = '[ '
571
572 if (array.constructor.name !== 'Array') {
573 header = array.constructor.name + '(' + array.length + ') ' + header
574 }
575
576 return new InspectSequence(header, ' ]', ', ', values, ref, depth, {
577 ...opts,
578 tabulate: true
579 })
580}
581
582function inspectDate(date, ref, depth, opts) {
583 return new InspectLeaf(date.toISOString(), styles.date, depth, opts)
584}
585
586function inspectRegExp(regExp, ref, depth, opts) {
587 return new InspectLeaf(regExp.toString(), styles.regexp, depth, opts)
588}
589
590function inspectError(error, ref, depth, opts) {
591 let header
592
593 if ('stack' in error) {
594 header = error.stack
595
596 if (depth > 0) {
597 header = header.replaceAll('\n', '\n' + ' '.repeat(depth))
598 }
599 } else {
600 header = error.toString()
601 }
602
603 const builtins = ['cause']
604
605 if (error.name === 'AggregateError') {
606 builtins.push('errors')
607 } else if (error.name === 'SuppressedError') {
608 builtins.push('error', 'suppressed')
609 }
610
611 const values = []
612
613 for (const key of builtins) {
614 if (key in error === false) continue
615
616 values.push(
617 new InspectPair(
618 ': ',
619 new InspectLeaf('[' + key + ']', null, depth + 1, opts),
620 inspectValue(error[key], depth + 1, opts),
621 depth + 1,
622 opts
623 )
624 )
625 }
626
627 for (const key in error) {
628 if (key === 'constructor' || builtins.includes(key)) continue
629
630 values.push(
631 new InspectPair(
632 ': ',
633 inspectKey(key, depth + 1, opts),
634 inspectValue(error[key], depth + 1, opts),
635 depth + 1,
636 opts
637 )
638 )
639 }
640
641 if (values.length === 0) return new InspectLeaf(header, null, depth, opts)
642
643 return new InspectSequence(
644 header + ' {',
645 ' }',
646 ', ',
647 values,
648 ref,
649 depth,
650 opts
651 )
652}
653
654function inspectPromise(promise, ref, depth, opts) {
655 ref.increment()
656
657 const state = binding.getPromiseState(promise)
658
659 const values = []
660
661 switch (state) {
662 case 0: // Pending
663 values.push(new InspectLeaf('<pending>', styles.special, depth, opts))
664 break
665
666 case 1: // Fulfilled
667 values.push(inspectValue(binding.getPromiseResult(promise), depth, opts))
668 break
669
670 case 2: // Rejected
671 values.push(
672 new InspectLeaf('<rejected>', styles.special, depth, opts),
673 inspectValue(binding.getPromiseResult(promise), depth, opts)
674 )
675 }
676
677 ref.decrement()
678
679 const header = promise.constructor.name + ' { '
680
681 return new InspectSequence(header, ' }', ' ', values, ref, depth, opts)
682}
683
684function inspectMap(map, ref, depth, opts) {
685 const {
686 maxArrayLength = defaultMaxArrayLength,
687 maxMapLength = maxArrayLength
688 } = opts
689
690 ref.increment()
691
692 const values = []
693
694 let remaining = maxMapLength
695
696 for (const entry of map) {
697 if (remaining-- === 0) {
698 values.push(
699 new InspectSuspension(map.size - values.length, depth + 1, {
700 ...opts,
701 breakAlways: true
702 })
703 )
704 break
705 }
706
707 values.push(
708 new InspectPair(
709 ' => ',
710 inspectValue(entry[0], depth + 1, opts),
711 inspectValue(entry[1], depth + 1, opts),
712 depth + 1,
713 opts
714 )
715 )
716 }
717
718 for (const key in map) {
719 if (key === 'constructor') continue
720
721 const value = inspectValue(map[key], depth + 1, opts)
722
723 values.push(
724 new InspectPair(
725 ': ',
726 inspectKey(key, depth + 1, opts),
727 value,
728 depth + 1,
729 { ...opts, breakAlways: remaining < 0 }
730 )
731 )
732 }
733
734 ref.decrement()
735
736 const header = map.constructor.name + '(' + map.size + ') { '
737
738 return new InspectSequence(header, ' }', ', ', values, ref, depth, {
739 ...opts,
740 tabulate: true
741 })
742}
743
744function inspectSet(set, ref, depth, opts) {
745 const {
746 maxArrayLength = defaultMaxArrayLength,
747 maxSetLength = maxArrayLength
748 } = opts
749
750 ref.increment()
751
752 const values = []
753
754 let remaining = maxSetLength
755
756 for (const entry of set) {
757 if (remaining-- === 0) {
758 values.push(
759 new InspectSuspension(set.size - values.length, depth + 1, {
760 ...opts,
761 breakAlways: true
762 })
763 )
764 break
765 }
766
767 values.push(inspectValue(entry, depth + 1, opts))
768 }
769
770 for (const key in set) {
771 if (key === 'constructor') continue
772
773 const value = inspectValue(set[key], depth + 1, opts)
774
775 values.push(
776 new InspectPair(
777 ': ',
778 inspectKey(key, depth + 1, opts),
779 value,
780 depth + 1,
781 { ...opts, breakAlways: remaining < 0 }
782 )
783 )
784 }
785
786 ref.decrement()
787
788 const header = set.constructor.name + '(' + set.size + ') { '
789
790 return new InspectSequence(header, ' }', ', ', values, ref, depth, {
791 ...opts,
792 tabulate: true
793 })
794}
795
796function inspectWeakMap(weakMap, ref, depth, opts) {
797 const header = weakMap.constructor.name + ' { '
798
799 return new InspectSequence(
800 header,
801 ' }',
802 ' ',
803 [new InspectLeaf('<items unknown>', styles.special, depth + 1, opts)],
804 ref,
805 depth,
806 opts
807 )
808}
809
810function inspectWeakSet(weakSet, ref, depth, opts) {
811 const header = weakSet.constructor.name + ' { '
812
813 return new InspectSequence(
814 header,
815 ' }',
816 ' ',
817 [new InspectLeaf('<items unknown>', styles.special, depth + 1, opts)],
818 ref,
819 depth,
820 opts
821 )
822}
823
824function inspectWeakRef(weakRef, ref, depth, opts) {
825 const target = weakRef.deref()
826
827 let value
828
829 if (target === undefined) {
830 value = new InspectLeaf('<cleared>', styles.special, depth + 1, opts)
831 } else {
832 value = inspectValue(target, depth + 1, opts)
833 }
834
835 const header = weakRef.constructor.name + ' { '
836
837 return new InspectSequence(header, ' }', ' ', [value], ref, depth, opts)
838}
839
840function inspectArrayBuffer(arrayBuffer, ref, depth, opts) {
841 ref.increment()
842
843 const values = []
844
845 for (const key of ['byteLength']) {
846 values.push(
847 new InspectPair(
848 ': ',
849 inspectKey(key, depth + 1, opts),
850 inspectValue(arrayBuffer[key], depth + 1, opts),
851 depth + 1,
852 opts
853 )
854 )
855 }
856
857 ref.decrement()
858
859 const header = arrayBuffer.constructor.name + ' { '
860
861 return new InspectSequence(header, ' }', ', ', values, ref, depth, opts)
862}
863
864function inspectSharedArrayBuffer(sharedArrayBuffer, ref, depth, opts) {
865 ref.increment()
866
867 const values = []
868
869 for (const key of ['byteLength']) {
870 values.push(
871 new InspectPair(
872 ': ',
873 inspectKey(key, depth + 1, opts),
874 inspectValue(sharedArrayBuffer[key], depth + 1, opts),
875 depth + 1,
876 opts
877 )
878 )
879 }
880
881 ref.decrement()
882
883 const header = sharedArrayBuffer.constructor.name + ' { '
884
885 return new InspectSequence(header, ' }', ', ', values, ref, depth, opts)
886}
887
888function inspectTypedArray(typedArray, ref, depth, opts) {
889 if (Buffer.isBuffer(typedArray)) {
890 return inspectBuffer(typedArray, ref, depth, opts)
891 }
892
893 const {
894 maxArrayLength = defaultMaxArrayLength,
895 maxTypedArrayLength = maxArrayLength
896 } = opts
897
898 ref.increment()
899
900 const values = []
901
902 let remaining = Math.max(maxTypedArrayLength, 0)
903
904 for (let i = 0, n = typedArray.length; i < n; i++) {
905 if (remaining-- === 0) {
906 values.push(
907 new InspectSuspension(typedArray.length - values.length, depth + 1, {
908 ...opts,
909 breakAlways: true
910 })
911 )
912
913 break
914 }
915
916 values.push(inspectValue(typedArray[i], depth + 1, opts))
917 }
918
919 for (const key of binding.getOwnNonIndexPropertyNames(typedArray)) {
920 values.push(
921 new InspectPair(
922 ': ',
923 inspectKey(key, depth + 1, opts),
924 inspectValue(typedArray[key], depth + 1, opts),
925 depth + 1,
926 { ...opts, breakAlways: remaining < 0 }
927 )
928 )
929 }
930
931 ref.decrement()
932
933 const header = typedArray.constructor.name + '(' + typedArray.length + ') [ '
934
935 return new InspectSequence(header, ' ]', ', ', values, ref, depth, {
936 ...opts,
937 tabulate: true
938 })
939}
940
941function inspectBuffer(buffer, ref, depth, opts) {
942 const {
943 maxArrayLength = defaultMaxArrayLength,
944 maxBufferLength = maxArrayLength
945 } = opts
946
947 ref.increment()
948
949 const values = []
950
951 let remaining = Math.max(maxBufferLength, 0)
952
953 for (let i = 0, n = buffer.byteLength; i < n; i++) {
954 if (remaining-- === 0) {
955 values.push(
956 new InspectSuspension(buffer.length - values.length, depth + 1, {
957 ...opts,
958 breakAlways: true
959 })
960 )
961
962 break
963 }
964
965 values.push(
966 new InspectLeaf(
967 buffer[i].toString(16).padStart(2, '0'),
968 null,
969 depth + 1,
970 opts
971 )
972 )
973 }
974
975 for (const key of binding.getOwnNonIndexPropertyNames(buffer)) {
976 values.push(
977 new InspectPair(
978 ': ',
979 inspectKey(key, depth + 1, opts),
980 inspectValue(buffer[key], depth + 1, opts),
981 depth + 1,
982 { ...opts, breakAlways: remaining < 0 }
983 )
984 )
985 }
986
987 ref.decrement()
988
989 return new InspectSequence('<Buffer ', '>', ' ', values, ref, depth, {
990 ...opts,
991 tabulate: true
992 })
993}
994
995function inspectDataView(dataView, ref, depth, opts) {
996 ref.increment()
997
998 const values = []
999
1000 for (const key of ['byteLength', 'byteOffset', 'buffer']) {
1001 values.push(
1002 new InspectPair(
1003 ': ',
1004 inspectKey(key, depth + 1, opts),
1005 inspectValue(dataView[key], depth + 1, opts),
1006 depth + 1,
1007 opts
1008 )
1009 )
1010 }
1011
1012 for (const key of binding.getOwnNonIndexPropertyNames(dataView)) {
1013 values.push(
1014 new InspectPair(
1015 ': ',
1016 inspectKey(key, depth + 1, opts),
1017 inspectValue(dataView[key], depth + 1, opts),
1018 depth + 1,
1019 opts
1020 )
1021 )
1022 }
1023
1024 ref.decrement()
1025
1026 const header = dataView.constructor.name + ' { '
1027
1028 return new InspectSequence(header, ' }', ', ', values, ref, depth, opts)
1029}
1030
1031function inspectFunction(type, fn, depth, opts) {
1032 if (fn.toString().startsWith('class')) return inspectClass(fn, depth, opts)
1033
1034 let tag = 'function'
1035
1036 if (type.isGeneratorFunction()) tag = 'generator ' + tag
1037 if (type.isAsyncFunction()) tag = 'async ' + tag
1038
1039 return new InspectLeaf(
1040 '[' + tag + ' ' + (fn.name ? fn.name : '(anonymous)') + ']',
1041 styles.special,
1042 depth,
1043 opts
1044 )
1045}
1046
1047function inspectClass(ctor, depth, opts) {
1048 return new InspectLeaf(
1049 '[class ' + (ctor.name ? ctor.name : '(anonymous)') + ']',
1050 styles.special,
1051 depth,
1052 opts
1053 )
1054}
1055
1056function inspectExternal(external, depth, opts) {
1057 return new InspectLeaf(
1058 '[external 0x' + binding.getExternal(external).toString(16) + ']',
1059 styles.special,
1060 depth,
1061 opts
1062 )
1063}
node_modules/bare-inspect/package.json +47 -0
……@@ -0,0 +1,47 @@
1{
2 "name": "bare-inspect",
3 "version": "3.1.4",
4 "description": "Inspect objects as strings for debugging",
5 "exports": {
6 ".": {
7 "types": "./index.d.ts",
8 "default": "./index.js"
9 },
10 "./package": "./package.json"
11 },
12 "files": [
13 "index.js",
14 "index.d.ts",
15 "binding.c",
16 "binding.js",
17 "CMakeLists.txt",
18 "prebuilds"
19 ],
20 "addon": true,
21 "scripts": {
22 "test": "prettier . --check && bare test.js"
23 },
24 "repository": {
25 "type": "git",
26 "url": "git+https://github.com/holepunchto/bare-inspect.git"
27 },
28 "author": "Holepunch",
29 "license": "Apache-2.0",
30 "bugs": {
31 "url": "https://github.com/holepunchto/bare-inspect/issues"
32 },
33 "homepage": "https://github.com/holepunchto/bare-inspect#readme",
34 "engines": {
35 "bare": ">=1.18.0"
36 },
37 "dependencies": {
38 "bare-ansi-escapes": "^2.1.0",
39 "bare-type": "^1.0.0"
40 },
41 "devDependencies": {
42 "brittle": "^3.3.2",
43 "cmake-bare": "^1.1.6",
44 "prettier": "^3.4.1",
45 "prettier-config-standard": "^7.0.0"
46 }
47}
node_modules/bare-inspect/prebuilds/android-arm/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/android-arm64/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/android-ia32/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/android-x64/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/darwin-arm64/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/darwin-x64/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/ios-arm64-simulator/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/ios-arm64/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/ios-x64-simulator/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/linux-arm64/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/linux-x64/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/win32-arm64/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-inspect/prebuilds/win32-x64/bare-inspect.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-module-resolve/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-module-resolve/README.md +352 -0
……@@ -0,0 +1,352 @@
1# bare-module-resolve
2
3Low-level module resolution algorithm for Bare. The algorithm is implemented as a generator function that yields either package manifests to be read or resolution candidates to be tested by the caller. As a convenience, the main export is a synchronous and asynchronous iterable that relies on package manifests being read by a callback. For asynchronous iteration, the callback may return promises which will be awaited before being passed to the generator.
4
5```
6npm i bare-module-resolve
7```
8
9## Usage
10
11For synchronous resolution:
12
13```js
14const resolve = require('bare-module-resolve')
15
16function readPackage(url) {
17 // Read and parse `url` if it exists, otherwise `null`
18}
19
20for (const resolution of resolve('./file.js', new URL('file:///directory/'), readPackage)) {
21 console.log(resolution)
22}
23```
24
25For asynchronous resolution:
26
27```js
28const resolve = require('bare-module-resolve')
29
30async function readPackage(url) {
31 // Read and parse `url` if it exists, otherwise `null`
32}
33
34for await (const resolution of resolve('./file.js', new URL('file:///directory/'), readPackage)) {
35 console.log(resolution)
36}
37```
38
39## API
40
41#### `const resolver = resolve(specifier, parentURL[, options][, readPackage])`
42
43Resolve `specifier` relative to `parentURL`, which must be a WHATWG `URL` instance. `readPackage` is called with a `URL` instance for every package manifest to be read and must either return the parsed JSON package manifest, if it exists, or `null`. If `readPackage` returns a promise, synchronous iteration is not supported.
44
45Options include:
46
47```js
48options = {
49 // A default "imports" map to apply to all specifiers. Follows the same
50 // syntax and rules as the "imports" property defined in `package.json`.
51 imports,
52 // A list of builtin module specifiers. If matched, the protocol of the
53 // resolved URL will be `builtinProtocol`.
54 builtins: [],
55 // The protocol to use for resolved builtin module specifiers.
56 builtinProtocol: 'builtin:',
57 // A list of module specifiers whose resolution should be deferred. If matched,
58 // the protocol of the resolved URL will be `deferredProtocol`.
59 defer: [],
60 // The protocol to use for resolved deferred module specifiers.
61 deferredProtocol: 'deferred:',
62 // The supported import conditions. "default" is always recognized.
63 conditions: [],
64 // An array reference which will contain the matched conditions when yielding
65 // resolutions.
66 matchedConditions: [],
67 // The supported engine versions.
68 engines: {},
69 // The file extensions to look for. Must be provided to support extensionless
70 // specifier resolution and directory support, such as resolving './foo' to
71 // './foo.js' or './foo/index.js'.
72 extensions: [],
73 // A map of preresolved imports with keys being serialized parent URLs and
74 // values being "imports" maps.
75 resolutions
76}
77```
78
79#### `for (const resolution of resolver)`
80
81Synchronously iterate the module resolution candidates. The resolved module is the first candidate that exists, either as a file on a file system, a resource at a URL, or something else entirely.
82
83#### `for await (const resolution of resolver)`
84
85Asynchronously iterate the module resolution candidates. If `readPackage` returns promises, these will be awaited. The same comments as `for (const resolution of resolver)` apply.
86
87### Algorithm
88
89The following generator functions implement the resolution algorithm, which has been adapted from the Node.js resolution algorithms for CommonJS and ES modules. Unlike Node.js, Bare uses the same resolution algorithm for both module formats. The yielded values have the following shape:
90
91**Package manifest**
92
93```js
94next.value = {
95 package: URL
96}
97```
98
99If the package manifest identified by `next.value.package` exists, `generator.next()` must be passed the parsed JSON value of the manifest. If it does not exist, pass `null` instead.
100
101**Resolution candidate**
102
103```js
104next.value = {
105 resolution: URL
106}
107```
108
109If the module identified by `next.value.resolution` exists, `generator.next()` may be passed `true` to signal that the resolution for the current set of conditions has been identified. If it does not exist, pass `false` instead.
110
111To drive the generator functions, a loop like the following can be used:
112
113```js
114const generator = resolve.module(specifier, parentURL)
115
116let next = generator.next()
117
118while (next.done !== true) {
119 const value = next.value
120
121 if (value.package) {
122 // Read and parse `value.package` if it exists, otherwise `null`
123 let info
124
125 next = generator.next(info)
126 } else {
127 const resolution = value.resolution
128
129 // `true` if `resolution` was the correct candidate, otherwise `false`
130 let resolved
131
132 next = generator.next(resolved)
133 }
134}
135```
136
137Options are the same as `resolve()` for all functions.
138
139> [!WARNING]
140> These functions are currently subject to change between minor releases. If using them directly, make sure to specify a tilde range (`~1.2.3`) when declaring the module dependency.
141
142#### `const generator = resolve.module(specifier, parentURL[, options])`
143
1441. If `specifier` [starts with a Windows drive letter](https://url.spec.whatwg.org/#start-with-a-windows-drive-letter):
145 1. Prepend `/` to `specifier`.
1462. If `options.resolutions` is set:
147 1. If `preresolved(specifier, options.resolutions, parentURL, options)` yields, return.
1483. If `url(specifier, parentURL, options)` yields, return.
1494. If `packageImports(specifier, parentURL, options)` yields, return.
1505. If `specifier` equals `.` or `..`, or if `specifier` starts with `/`, `\`, `./`, `.\`, `../`, or `..\`:
151 1. If `options.imports` is set:
152 1. If `packageImportsExports(specifier, options.imports, parentURL, true, options)` yields, return.
153 2. If `deferred(specifier, options)` yields, return.
154 3. If `file(specifier, parentURL, false, options)` resolves, return.
155 4. Return `directory(specifier, parentURL, options)`.
1566. Return `package(specifier, parentURL, options)`.
157
158#### `const generator = resolve.url(url, parentURL[, options])`
159
1601. If `url` is not a valid URL, return.
1612. If `options.imports` is set:
162 1. If `packageImportsExports(url.href, options.imports, parentURL, true, options)` yields, return.
1633. If `url.protocol` equals `options.deferredProtocol`:
164 1. Let `specifier` be `url.pathname`.
165 2. If `options.resolutions` is set:
166 1. Let `imports` be `options.resolutions[parentURL]`.
167 2. If `imports` is a non-`null` object:
168 1. Set `imports[specifier]` to `null`.
169 3. Return `module(specifier, parentURL, options)`.
1704. If `url.protocol` equals `node:`:
171 1. Let `specifier` be `url.pathname`.
172 2. If `specifier` equals `.` or `..`, or if `specifier` starts with `/`, `\`, `./`, `.\`, `../`, or `..\`, throw.
173 3. Return `package(specifier, parentURL, options)`.
1745. Yield `url`.
175
176#### `const generator = resolve.preresolved(specifier, resolutions, parentURL[, options])`
177
1781. Let `imports` be `resolutions[parentURL]`.
1792. If `imports` is a non-`null` object:
180 1. Return `packageImportsExports(specifier, imports, parentURL, true, options)`.
181
182#### `const generator = resolve.deferred(specifier[, options])`
183
1841. If `options.defer` includes `specifier`:
185 1. Yield `options.deferredProtocol` concatenated with `specifier` and return.
186
187#### `const generator = resolve.package(packageSpecifier, parentURL[, options])`
188
1891. If `packageSpecifier` is the empty string, throw.
1902. If `packageSpecifier` does not start with `@`:
191 1. Set `packageName` to the substring of `packageSpecifier` until the first `/` or the end of the string.
1923. Let `packageName` be `undefined`.
1934. Otherwise:
194 1. If `packageSpecifier` does not include `/`, throw.
195 2. Set `packageName` to the substring of `packageSpecifier` until the second `/` or the end of the string.
1965. If `packageName` starts with `.` or includes `\` or `%`, throw.
1976. If `builtinTarget(packageSpecifier, null, options.builtins, options)` yields, return.
1987. If `deferred(packageSpecifier, options)` yields, return.
1998. Let `packageSubpath` be `.` concatenated with the substring of `packageSpecifier` from the position at the length of `packageName`.
2009. If `packageSelf(packageName, packageSubpath, parentURL, options)` yields, return.
20110. For each value `packageURL` of `lookupPackageRoot(packageName, parentURL, options)`:
202 1. Let `info` be the result of yielding `packageURL`.
203 2. If `info` is not `null`:
204 1. If `info.engines` is set:
205 1. Call `validateEngines(packageURL, info.engines, options)`.
206 2. If `info.exports` is set:
207 1. Return `packageExports(packageURL, packageSubpath, info.exports, options)`.
208 3. If `packageSubpath` is `.`:
209 1. If `info.main` is a non-empty string:
210 1. Set `packageSubpath` to `info.main`.
211 2. Otherwise:
212 1. Return `file('index', packageURL, true, options)`.
213 4. If `file(packageSubpath, packageURL, false, options)` resolves, return.
214 5. Return `directory(packageSubpath, packageURL, options)`.
215
216#### `const generator = resolve.packageSelf(packageName, packageSubpath, parentURL[, options])`
217
2181. For each value `packageURL` of `lookupPackageScope(parentURL, options)`:
219 1. Let `info` be the result of yielding `packageURL`.
220 2. If `info` is not `null`:
221 1. If `info.name` does not equal `packageName`, return.
222 2. If `info.exports` is set:
223 1. Return `packageExports(packageURL, packageSubpath, info.exports, options)`.
224 3. If `packageSubpath` is `.`:
225 1. If `info.main` is a non-empty string:
226 1. Set `packageSubpath` to `info.main`.
227 2. Otherwise:
228 1. Return `file('index', packageURL, true, options)`.
229 4. If `file(packageSubpath, packageURL, false, options)` resolves, return.
230 5. Return `directory(packageSubpath, packageURL, options)`.
231
232#### `const generator = resolve.packageExports(packageURL, subpath, exports[, options])`
233
2341. If `subpath` is `.`:
235 1. Let `mainExport` be `undefined`.
236 2. If `exports` is a string or an array:
237 1. Set `mainExport` to `exports`.
238 3. If `exports` is a non-`null` object:
239 1. If some keys of `exports` start with `.`:
240 1. If `.` is a key of `exports`:
241 1. Set `mainExport` to `exports['.']`.
242 2. Otherwise:
243 1. Set `mainExport` to `exports`.
244 4. If `mainExport` is not `undefined`:
245 1. If `packageTarget(packageURL, mainExport, null, false, options)` yields, return.
2462. Otherwise, if `exports` is a non-`null` object:
247 1. If every key of `exports` starts with `.`:
248 1. If `packageImportsExports(subpath, exports, packageURL, false, options)` yields, return.
2493. Throw.
250
251#### `const generator = resolve.packageImports(specifier, parentURL[, options])`
252
2531. If `specifier` is `#` or starts with `#/`, throw.
2542. For each value `packageURL` of `lookupPackageScope(parentURL, options)`:
255 1. Let `info` be the result of yielding `packageURL`.
256 2. If `info` is not `null`:
257 1. If `info.imports` is set:
258 1. If `packageImportsExports(specifier, info.imports, packageURL, true, options)` yields, return.
259 2. If specifier starts with `#`, throw.
260 3. Return.
2613. If `options.imports` is set:
262 1. If `packageImportsExports(url.href, options.imports, parentURL, true, options)` yields, return.
263
264#### `const generator = resolve.packageImportsExports(matchKey, matchObject, packageURL, isImports[, options])`
265
2661. If `matchKey` is a key of `matchObject` and `matchKey` does not include `*`:
267 1. Let `target` be `matchObject[matchKey]`.
268 2. Return `packageTarget(packageURL, target, null, isImports, options)`.
2692. Let `expansionKeys` be the keys of `matchObject` that include `*` sorted by `patternKeyCompare`.
2703. For each value `expansionKey` of `expansionKeys`:
271 1. Let `patternBase` be the substring of `expansionKey` until the first `*`.
272 2. If `matchKey` starts with but isn't equal to `patternBase`:
273 1. Let `patternTrailer` be the substring of `expansionKey` from the position at the index after the first `*`.
274 2. If `patternTrailer` is the empty string, or if `matchKey` ends with `patternTrailer` and the length of `matchKey` is greater than or equal to the length of `expansionKey`:
275 1. Let `target` be `matchObject[expansionKey]`.
276 2. Let `patternMatch` be the substring of `matchKey` from the position at the length of `patternBase` until the length of `matchKey` minus the length of `patternTrailer`.
277 3. Return `packageTarget(packageURL, target, patternMatch, isImports, options)`.
278
279#### `const generator = resolve.packageTarget(packageURL, target, patternMatch, isImports[, options])`
280
2811. If `target` is a string:
282 1. If `target` does not start with `./` and `isImports` is `false`, throw.
283 2. If `patternMatch` is not `null`:
284 1. Replace every instance of `*` in `target` with `patternMatch`.
285 3. If `url(target, packageURL, options)` yields, return.
286 4. If `target` equals `.` or `..`, or if `target` starts with `/`, `./`, or `../`:
287 1. Yield the resolution of `target` relative to `packageURL` and return.
288 5. Return `package(target, packageURL, options)`.
2892. If `target` is an array:
290 1. For each value `targetValue` of `target`:
291 1. If `packageTarget(packageURL, targetValue, patternMatch, isImports, options)` yields, return.
2923. If `target` is a non-`null` object:
293 1. For each key `condition` of `target`:
294 1. If `condition` equals `default` or if `options.conditions` includes `condition`:
295 1. Let `targetValue` be `target[condition]`.
296 2. Return `packageTarget(packageURL, targetValue, patternMatch, isImports, options)`.
297
298#### `const generator = resolve.builtinTarget(packageSpecifier, packageVersion, target[, options])`
299
3001. If `target` is a string:
301 1. If `target` does not start with `@`:
302 1. Let `targetName` be the substring of `target` until the first `@` or the end of the string.
303 2. Let `targetVersion` be the substring of `target` from the character following the first `@` and to the end of string, or `null` if no such substring exists.
304 2. Otherwise:
305 1. Let `targetName` be the substring of `target` until the second `@` or the end of the string.
306 2. Let `targetVersion` be the substring of `target` from the character following the second `@` and to the end of string, or `null` if no such substring exists.
307 3. If `packageSpecifier` equals `targetName`:
308 1. If `packageVersion` is `null` and `targetVersion` is `null`:
309 1. Yield `options.builtinProtocol` concatenated with `packageSpecifier` and return.
310 2. Let `version` be `null`.
311 3. If `packageVersion` is `null`, let `version` be `targetVersion`.
312 4. Otherwise, if `targetVersion` is either `null` or equals `packageVersion`, let `version` be `packageVersion`
313 5. If `version` is not `null`:
314 1. Yield `options.builtinProtocol` concatenated with `packageSpecifier`, `@`, and `version` and return.
3152. If `target` is an array:
316 1. For each value `targetValue` of `target`:
317 1. If `builtinTarget(packageSpecifier, packageVersion, targetValue, options)` yields, return.
3183. If `target` is a non-`null` object:
319 1. For each key `condition` of `target`:
320 1. If `condition` equals `default` or if `options.conditions` includes `condition`:
321 1. Let `targetValue` be `target[condition]`.
322 2. Return `builtinTarget(packageSpecifier, packageVersion, targetValue, options)`.
323
324#### `const generator = resolve.file(filename, parentURL, isIndex[, options])`
325
3261. If `filename` equals `.` or `..`, or if `filename` ends with `/` or `\`, return.
3272. If `parentURL` is a `file:` URL and `filename` includes encoded `/` or `\`, throw.
3283. If `isIndex` is `false`:
329 1. Yield the resolution of `filename` relative to `parentURL`.
3304. For each value `ext` of `options.extensions`:
331 1. If `filename` ends with `ext`, continue.
332 2. Yield the resolution of `filename` concatenated with `ext` relative to `parentURL`.
333
334#### `const generator = resolve.directory(dirname, parentURL[, options])`
335
3361. Let `directoryURL` be `undefined`.
3372. If `dirname` ends with `/` or `\`:
338 1. Set `directoryURL` to the resolution of `dirname` relative to `parentURL`.
3393. Otherwise:
340 1. Set `directoryURL` to the resolution of `dirname` concatenated with `/` relative to `parentURL`.
3414. Let `info` be the result of yielding the resolution of `package.json` relative to `directoryURL`.
3425. If `info` is not `null`:
343 1. If `info.exports` is set:
344 1. Return `packageExports(directoryURL, '.', info.exports, options)`.
345 2. If `info.main` is a non-empty string:
346 1. If `file(info.main, directoryURL, false, options)` resolves, return.
347 2. Return `directory(info.main, directoryURL, options)`.
3486. Return `file('index', directoryURL, true, options)`.
349
350## License
351
352Apache-2.0
node_modules/bare-module-resolve/index.d.ts +147 -0
……@@ -0,0 +1,147 @@
1import URL from 'bare-url'
2
3type ConditionalSpecifier =
4 | string
5 | ConditionalSpecifier[]
6 | { [condition: string]: ConditionalSpecifier }
7
8type ImportsMap = { [specifier: string]: ConditionalSpecifier }
9
10type ExportsMap = ImportsMap
11
12type ResolutionsMap = { [href: string]: ImportsMap }
13
14type Builtins = ConditionalSpecifier[]
15
16type Conditions = string[] | Conditions[]
17
18type Engines = { [name: string]: string }
19
20type JSON = string | number | boolean | JSON[] | { [key: string]: JSON }
21
22interface ResolveOptions {
23 builtinProtocol?: string
24 builtins?: Builtins
25 conditions?: Conditions
26 defer?: string[]
27 deferredProtocol?: string
28 engines?: Engines
29 extensions?: string[]
30 imports?: ImportsMap
31 matchedConditions?: string[]
32 resolutions?: ResolutionsMap
33}
34
35declare function resolve(
36 specifier: string,
37 parentURL: URL,
38 readPackage?: (url: URL) => JSON | null
39): Iterable<URL>
40
41declare function resolve(
42 specifier: string,
43 parentURL: URL,
44 readPackage: (url: URL) => Promise<JSON | null>
45): AsyncIterable<URL>
46
47declare function resolve(
48 specifier: string,
49 parentURL: URL,
50 opts: ResolveOptions,
51 readPackage?: (url: URL) => JSON | null
52): Iterable<URL>
53
54declare function resolve(
55 specifier: string,
56 parentURL: URL,
57 opts: ResolveOptions,
58 readPackage: (url: URL) => Promise<JSON | null>
59): AsyncIterable<URL>
60
61declare namespace resolve {
62 export {
63 type ConditionalSpecifier,
64 type ImportsMap,
65 type ExportsMap,
66 type ResolutionsMap,
67 type Builtins,
68 type Conditions,
69 type Engines,
70 type ResolveOptions
71 }
72
73 export const constants: {
74 UNRESOLVED: number
75 YIELDED: number
76 RESOLVED: number
77 }
78
79 export type Resolver = Generator<
80 { package: URL } | { resolution: URL },
81 number,
82 void | boolean | JSON | null
83 >
84
85 export function module(specifier: string, parentURL: URL, opts?: ResolveOptions): Resolver
86
87 export function url(url: string, parentURL: URL, opts?: ResolveOptions): Resolver
88
89 export function preresolved(
90 specifier: string,
91 resolutions: ResolutionsMap,
92 parentURL: URL,
93 opts?: ResolveOptions
94 ): Resolver
95
96 export function package(packageSpecifier: string, parentURL: URL, opts?: ResolveOptions): Resolver
97
98 export function packageSelf(
99 packageName: string,
100 packageSubpath: string,
101 parentURL: URL,
102 opts?: ResolveOptions
103 ): Resolver
104
105 export function packageExports(
106 packageURL: URL,
107 subpath: string,
108 packageExports: ExportsMap,
109 opts?: ResolveOptions
110 ): Resolver
111
112 export function packageImports(specifier: string, parentURL: URL, opts?: ResolveOptions): Resolver
113
114 export function packageImportsExports(
115 matchKey: string,
116 matchObject: ImportsMap | ExportsMap,
117 packageURL: URL,
118 isImports: boolean,
119 opts?: ResolveOptions
120 ): Resolver
121
122 export function packageTarget(
123 packageURL: URL,
124 target: ConditionalSpecifier,
125 patternMatch: string,
126 isImports: boolean,
127 opts?: ResolveOptions
128 ): Resolver
129
130 export function builtinTarget(
131 packageSpecifier: string,
132 packageVersion: string,
133 target: ConditionalSpecifier,
134 opts?: ResolveOptions
135 ): Resolver
136
137 export function file(
138 filename: string,
139 parentURL: URL,
140 isIndex: boolean,
141 opts?: ResolveOptions
142 ): Resolver
143
144 export function directory(dirname: string, parentURL: URL, opts?: ResolveOptions): Resolver
145}
146
147export = resolve
node_modules/bare-module-resolve/index.js +796 -0
……@@ -0,0 +1,796 @@
1const { satisfies } = require('bare-semver')
2const errors = require('./lib/errors')
3
4module.exports = exports = function resolve(specifier, parentURL, opts, readPackage) {
5 if (typeof opts === 'function') {
6 readPackage = opts
7 opts = {}
8 } else if (typeof readPackage !== 'function') {
9 readPackage = defaultReadPackage
10 }
11
12 return {
13 *[Symbol.iterator]() {
14 const generator = exports.module(specifier, parentURL, opts)
15
16 let next = generator.next()
17
18 while (next.done !== true) {
19 const value = next.value
20
21 if (value.package) {
22 next = generator.next(readPackage(value.package))
23 } else {
24 next = generator.next(yield value.resolution)
25 }
26 }
27
28 return next.value
29 },
30
31 async *[Symbol.asyncIterator]() {
32 const generator = exports.module(specifier, parentURL, opts)
33
34 let next = generator.next()
35
36 while (next.done !== true) {
37 const value = next.value
38
39 if (value.package) {
40 next = generator.next(await readPackage(value.package))
41 } else {
42 next = generator.next(yield value.resolution)
43 }
44 }
45
46 return next.value
47 }
48 }
49}
50
51function defaultReadPackage() {
52 return null
53}
54
55// No resolution candidate was yielded
56const UNRESOLVED = 0x0
57// At least 1 resolution candidate was yielded
58const YIELDED = 0x1
59// At least 1 resolution candidate was yielded and resolved
60const RESOLVED = YIELDED | 0x2
61
62exports.constants = {
63 UNRESOLVED,
64 YIELDED,
65 RESOLVED
66}
67
68exports.module = function* (specifier, parentURL, opts = {}) {
69 const { resolutions = null, imports = null } = opts
70
71 if (exports.startsWithWindowsDriveLetter(specifier)) {
72 specifier = '/' + specifier
73 }
74
75 let status
76
77 if (resolutions) {
78 status = yield* exports.preresolved(specifier, resolutions, parentURL, opts)
79
80 if (status) return status
81 }
82
83 status = yield* exports.url(specifier, parentURL, opts)
84
85 if (status) return status
86
87 status = yield* exports.packageImports(specifier, parentURL, opts)
88
89 if (status) return status
90
91 if (
92 specifier === '.' ||
93 specifier === '..' ||
94 specifier[0] === '/' ||
95 specifier[0] === '\\' ||
96 specifier.startsWith('./') ||
97 specifier.startsWith('.\\') ||
98 specifier.startsWith('../') ||
99 specifier.startsWith('..\\')
100 ) {
101 if (imports) {
102 status = yield* exports.packageImportsExports(specifier, imports, parentURL, true, opts)
103
104 if (status) return status
105 }
106
107 status = yield* exports.deferred(specifier, opts)
108
109 if (status) return status
110
111 status = yield* exports.file(specifier, parentURL, false, opts)
112
113 if (status === RESOLVED) return status
114
115 return yield* exports.directory(specifier, parentURL, opts)
116 }
117
118 return yield* exports.package(specifier, parentURL, opts)
119}
120
121exports.url = function* (url, parentURL, opts = {}) {
122 const { imports = null, deferredProtocol = 'deferred:', resolutions = null } = opts
123
124 let resolution
125 try {
126 resolution = new URL(url)
127 } catch {
128 return UNRESOLVED
129 }
130
131 if (imports) {
132 const status = yield* exports.packageImportsExports(
133 resolution.href,
134 imports,
135 parentURL,
136 true,
137 opts
138 )
139
140 if (status) return status
141 }
142
143 if (resolution.protocol === deferredProtocol) {
144 const specifier = resolution.pathname
145
146 if (resolutions) {
147 const imports = resolutions[parentURL.href]
148
149 if (typeof imports === 'object' && imports !== null) {
150 opts = {
151 ...opts,
152 resolutions: { ...resolutions, [parentURL.href]: { ...imports, [specifier]: null } }
153 }
154 }
155 }
156
157 return yield* exports.module(specifier, parentURL, opts)
158 }
159
160 if (resolution.protocol === 'node:') {
161 const specifier = resolution.pathname
162
163 if (
164 specifier === '.' ||
165 specifier === '..' ||
166 specifier[0] === '/' ||
167 specifier.startsWith('./') ||
168 specifier.startsWith('../')
169 ) {
170 throw errors.INVALID_MODULE_SPECIFIER(`Module specifier '${url}' is not a valid package name`)
171 }
172
173 return yield* exports.package(specifier, parentURL, opts)
174 }
175
176 const resolved = yield { resolution }
177
178 return resolved ? RESOLVED : YIELDED
179}
180
181exports.preresolved = function* (specifier, resolutions, parentURL, opts = {}) {
182 const imports = resolutions[parentURL.href]
183
184 if (typeof imports === 'object' && imports !== null) {
185 return yield* exports.packageImportsExports(specifier, imports, parentURL, true, opts)
186 }
187
188 return UNRESOLVED
189}
190
191exports.deferred = function* (specifier, opts = {}) {
192 const { deferredProtocol = 'deferred:', defer = [] } = opts
193
194 if (defer.includes(specifier)) {
195 const resolved = yield { resolution: new URL(deferredProtocol + specifier) }
196
197 return resolved ? RESOLVED : YIELDED
198 }
199
200 return UNRESOLVED
201}
202
203exports.package = function* (packageSpecifier, parentURL, opts = {}) {
204 const { builtins = [] } = opts
205
206 if (packageSpecifier === '') {
207 throw errors.INVALID_MODULE_SPECIFIER(
208 `Module specifier '${packageSpecifier}' is not a valid package name`
209 )
210 }
211
212 let packageName
213
214 if (packageSpecifier[0] !== '@') {
215 packageName = packageSpecifier.split('/', 1).join()
216 } else {
217 if (!packageSpecifier.includes('/')) {
218 throw errors.INVALID_MODULE_SPECIFIER(
219 `Module specifier '${packageSpecifier}' is not a valid package name`
220 )
221 }
222
223 packageName = packageSpecifier.split('/', 2).join('/')
224 }
225
226 if (packageName[0] === '.' || packageName.includes('\\') || packageName.includes('%')) {
227 throw errors.INVALID_MODULE_SPECIFIER(
228 `Module specifier '${packageSpecifier}' is not a valid package name`
229 )
230 }
231
232 let status
233
234 status = yield* exports.builtinTarget(packageSpecifier, null, builtins, opts)
235
236 if (status) return status
237
238 status = yield* exports.deferred(packageSpecifier, opts)
239
240 if (status) return status
241
242 let packageSubpath = '.' + packageSpecifier.substring(packageName.length)
243
244 status = yield* exports.packageSelf(packageName, packageSubpath, parentURL, opts)
245
246 if (status) return status
247
248 parentURL = new URL(parentURL.href)
249
250 for (const packageURL of exports.lookupPackageRoot(packageName, parentURL)) {
251 const info = yield { package: packageURL }
252
253 if (info) {
254 if (info.engines) exports.validateEngines(packageURL, info.engines, opts)
255
256 if (info.exports) {
257 return yield* exports.packageExports(packageURL, packageSubpath, info.exports, opts)
258 }
259
260 if (packageSubpath === '.') {
261 if (typeof info.main === 'string' && info.main !== '') {
262 packageSubpath = info.main
263 } else {
264 return yield* exports.file('index', packageURL, true, opts)
265 }
266 }
267
268 status = yield* exports.file(packageSubpath, packageURL, false, opts)
269
270 if (status === RESOLVED) return status
271
272 return yield* exports.directory(packageSubpath, packageURL, opts)
273 }
274 }
275
276 return UNRESOLVED
277}
278
279exports.packageSelf = function* (packageName, packageSubpath, parentURL, opts = {}) {
280 for (const packageURL of exports.lookupPackageScope(parentURL, opts)) {
281 const info = yield { package: packageURL }
282
283 if (info) {
284 if (info.name !== packageName) return false
285
286 if (info.exports) {
287 return yield* exports.packageExports(packageURL, packageSubpath, info.exports, opts)
288 }
289
290 if (packageSubpath === '.') {
291 if (typeof info.main === 'string' && info.main !== '') {
292 packageSubpath = info.main
293 } else {
294 return yield* exports.file('index', packageURL, true, opts)
295 }
296 }
297
298 const status = yield* exports.file(packageSubpath, packageURL, false, opts)
299
300 if (status === RESOLVED) return status
301
302 return yield* exports.directory(packageSubpath, packageURL, opts)
303 }
304 }
305
306 return UNRESOLVED
307}
308
309exports.packageExports = function* (packageURL, subpath, packageExports, opts = {}) {
310 if (subpath === '.') {
311 let mainExport
312
313 if (typeof packageExports === 'string' || Array.isArray(packageExports)) {
314 mainExport = packageExports
315 } else if (typeof packageExports === 'object' && packageExports !== null) {
316 const keys = Object.keys(packageExports)
317
318 if (keys.some((key) => key.startsWith('.'))) {
319 if ('.' in packageExports) mainExport = packageExports['.']
320 } else {
321 mainExport = packageExports
322 }
323 }
324
325 if (mainExport) {
326 const status = yield* exports.packageTarget(packageURL, mainExport, null, false, opts)
327
328 if (status) return status
329 }
330 } else if (typeof packageExports === 'object' && packageExports !== null) {
331 const keys = Object.keys(packageExports)
332
333 if (keys.every((key) => key.startsWith('.'))) {
334 const status = yield* exports.packageImportsExports(
335 subpath,
336 packageExports,
337 packageURL,
338 false,
339 opts
340 )
341
342 if (status) return status
343 }
344 }
345
346 throw errors.PACKAGE_PATH_NOT_EXPORTED(
347 `Package subpath '${subpath}' is not defined by "exports" in '${packageURL}'`
348 )
349}
350
351exports.packageImports = function* (specifier, parentURL, opts = {}) {
352 const { imports = null } = opts
353
354 if (specifier === '#' || specifier.startsWith('#/')) {
355 throw errors.INVALID_MODULE_SPECIFIER(
356 `Module specifier '${specifier}' is not a valid internal imports specifier`
357 )
358 }
359
360 for (const packageURL of exports.lookupPackageScope(parentURL, opts)) {
361 const info = yield { package: packageURL }
362
363 if (info) {
364 if (info.imports) {
365 const status = yield* exports.packageImportsExports(
366 specifier,
367 info.imports,
368 packageURL,
369 true,
370 opts
371 )
372
373 if (status) return status
374 }
375
376 if (specifier.startsWith('#')) {
377 throw errors.PACKAGE_IMPORT_NOT_DEFINED(
378 `Package import specifier '${specifier}' is not defined by "imports" in '${packageURL}'`
379 )
380 }
381
382 break
383 }
384 }
385
386 if (imports) {
387 const status = yield* exports.packageImportsExports(specifier, imports, parentURL, true, opts)
388
389 if (status) return status
390 }
391
392 return UNRESOLVED
393}
394
395exports.packageImportsExports = function* (
396 matchKey,
397 matchObject,
398 packageURL,
399 isImports,
400 opts = {}
401) {
402 if (matchKey in matchObject && !matchKey.includes('*')) {
403 const target = matchObject[matchKey]
404
405 return yield* exports.packageTarget(packageURL, target, null, isImports, opts)
406 }
407
408 const expansionKeys = Object.keys(matchObject)
409 .filter((key) => key.includes('*'))
410 .sort(exports.patternKeyCompare)
411
412 for (const expansionKey of expansionKeys) {
413 const patternIndex = expansionKey.indexOf('*')
414 const patternBase = expansionKey.substring(0, patternIndex)
415
416 if (matchKey.startsWith(patternBase) && matchKey !== patternBase) {
417 const patternTrailer = expansionKey.substring(patternIndex + 1)
418
419 if (
420 patternTrailer === '' ||
421 (matchKey.endsWith(patternTrailer) && matchKey.length >= expansionKey.length)
422 ) {
423 const target = matchObject[expansionKey]
424
425 const patternMatch = matchKey.substring(
426 patternBase.length,
427 matchKey.length - patternTrailer.length
428 )
429
430 return yield* exports.packageTarget(packageURL, target, patternMatch, isImports, opts)
431 }
432 }
433 }
434
435 return UNRESOLVED
436}
437
438exports.validateEngines = function validateEngines(packageURL, packageEngines, opts = {}) {
439 const { engines = {} } = opts
440
441 for (const [engine, range] of Object.entries(packageEngines)) {
442 if (engine in engines) {
443 const version = engines[engine]
444
445 if (!satisfies(version, range)) {
446 throw errors.UNSUPPORTED_ENGINE(
447 `Package not compatible with engine '${engine}' ${version}, requires range '${range}' defined by "engines" in '${packageURL}'`
448 )
449 }
450 }
451 }
452}
453
454exports.patternKeyCompare = function patternKeyCompare(keyA, keyB) {
455 const patternIndexA = keyA.indexOf('*')
456 const patternIndexB = keyB.indexOf('*')
457 const baseLengthA = patternIndexA === -1 ? keyA.length : patternIndexA + 1
458 const baseLengthB = patternIndexB === -1 ? keyB.length : patternIndexB + 1
459 if (baseLengthA > baseLengthB) return -1
460 if (baseLengthB > baseLengthA) return 1
461 if (patternIndexA === -1) return 1
462 if (patternIndexB === -1) return -1
463 if (keyA.length > keyB.length) return -1
464 if (keyB.length > keyA.length) return 1
465 return 0
466}
467
468exports.packageTarget = function* (packageURL, target, patternMatch, isImports, opts = {}) {
469 const { conditions = [], matchedConditions = [] } = opts
470
471 if (typeof target === 'string') {
472 if (!target.startsWith('./') && !isImports) {
473 throw errors.INVALID_PACKAGE_TARGET(
474 `Invalid target '${target}' defined by "exports" in '${packageURL}'`
475 )
476 }
477
478 if (patternMatch !== null) {
479 target = target.replaceAll('*', patternMatch)
480 }
481
482 const status = yield* exports.url(target, packageURL, opts)
483
484 if (status) return status
485
486 if (
487 target === '.' ||
488 target === '..' ||
489 target[0] === '/' ||
490 target.startsWith('./') ||
491 target.startsWith('../')
492 ) {
493 const resolved = yield { resolution: new URL(target, packageURL) }
494
495 return resolved ? RESOLVED : YIELDED
496 }
497
498 return yield* exports.package(target, packageURL, opts)
499 }
500
501 if (Array.isArray(target)) {
502 for (const targetValue of target) {
503 const status = yield* exports.packageTarget(
504 packageURL,
505 targetValue,
506 patternMatch,
507 isImports,
508 opts
509 )
510
511 if (status) return status
512 }
513 } else if (typeof target === 'object' && target !== null) {
514 let status = UNRESOLVED
515
516 for (const [condition, targetValue, subset] of exports.conditionMatches(
517 target,
518 conditions,
519 opts
520 )) {
521 matchedConditions.push(condition)
522
523 status |= yield* exports.packageTarget(packageURL, targetValue, patternMatch, isImports, {
524 ...opts,
525 conditions: subset
526 })
527
528 matchedConditions.pop()
529 }
530
531 if (status) return status
532 }
533
534 return UNRESOLVED
535}
536
537exports.builtinTarget = function* (packageSpecifier, packageVersion, target, opts = {}) {
538 const { builtinProtocol = 'builtin:', conditions = [], matchedConditions = [] } = opts
539
540 if (typeof target === 'string') {
541 const targetParts = target.split('@')
542
543 let targetName
544 let targetVersion
545
546 if (target[0] !== '@') {
547 targetName = targetParts[0]
548 targetVersion = targetParts[1] || null
549 } else {
550 targetName = targetParts.slice(0, 2).join('@')
551 targetVersion = targetParts[2] || null
552 }
553
554 if (packageSpecifier === targetName) {
555 if (packageVersion === null && targetVersion === null) {
556 const resolved = yield {
557 resolution: new URL(builtinProtocol + packageSpecifier)
558 }
559
560 return resolved ? RESOLVED : YIELDED
561 }
562
563 let version = null
564
565 if (packageVersion === null) {
566 version = targetVersion
567 } else if (targetVersion === null || packageVersion === targetVersion) {
568 version = packageVersion
569 }
570
571 if (version !== null) {
572 const resolved = yield {
573 resolution: new URL(builtinProtocol + packageSpecifier + '@' + version)
574 }
575
576 return resolved ? RESOLVED : YIELDED
577 }
578 }
579 } else if (Array.isArray(target)) {
580 for (const targetValue of target) {
581 const status = yield* exports.builtinTarget(
582 packageSpecifier,
583 packageVersion,
584 targetValue,
585 opts
586 )
587
588 if (status) return status
589 }
590 } else if (typeof target === 'object' && target !== null) {
591 let status = UNRESOLVED
592
593 for (const [condition, targetValue, subset] of exports.conditionMatches(
594 target,
595 conditions,
596 opts
597 )) {
598 matchedConditions.push(condition)
599
600 status |= yield* exports.builtinTarget(packageSpecifier, packageVersion, targetValue, {
601 ...opts,
602 conditions: subset
603 })
604
605 matchedConditions.pop()
606 }
607
608 if (status) return status
609 }
610
611 return UNRESOLVED
612}
613
614exports.conditionMatches = function* conditionMatches(target, conditions, opts = {}) {
615 if (conditions.every((condition) => typeof condition === 'string')) {
616 const keys = Object.keys(target)
617
618 for (const condition of keys) {
619 if (condition === 'default' || conditions.includes(condition)) {
620 yield [condition, target[condition], conditions]
621
622 return true
623 }
624 }
625
626 return false
627 }
628
629 let yielded = false
630
631 for (const subset of conditions) {
632 if (yield* conditionMatches(target, subset, opts)) {
633 yielded = true
634 }
635 }
636
637 return yielded
638}
639
640exports.lookupPackageRoot = function* (packageName, parentURL) {
641 parentURL = new URL(parentURL.href)
642
643 do {
644 const packageURL = new URL('node_modules/' + packageName + '/', parentURL)
645
646 const info = yield new URL('package.json', packageURL)
647
648 if (info) return info
649
650 parentURL.pathname = parentURL.pathname.substring(0, parentURL.pathname.lastIndexOf('/'))
651
652 if (
653 parentURL.pathname.length === 3 &&
654 exports.isWindowsDriveLetter(parentURL.pathname.substring(1))
655 ) {
656 break
657 }
658 } while (parentURL.pathname !== '' && parentURL.pathname !== '/')
659
660 return null
661}
662
663exports.lookupPackageScope = function* lookupPackageScope(scopeURL, opts = {}) {
664 const { resolutions = null } = opts
665
666 if (resolutions) {
667 for (const { resolution } of exports.preresolved('#package', resolutions, scopeURL, opts)) {
668 if (resolution) return yield resolution
669 }
670 }
671
672 scopeURL = new URL(scopeURL.href)
673
674 do {
675 if (scopeURL.pathname.endsWith('/node_modules')) break
676
677 const info = yield new URL('package.json', scopeURL)
678
679 if (info) return info
680
681 scopeURL.pathname = scopeURL.pathname.substring(0, scopeURL.pathname.lastIndexOf('/'))
682
683 if (
684 scopeURL.pathname.length === 3 &&
685 exports.isWindowsDriveLetter(scopeURL.pathname.substring(1))
686 ) {
687 break
688 }
689 } while (scopeURL.pathname !== '' && scopeURL.pathname !== '/')
690
691 return null
692}
693
694exports.file = function* (filename, parentURL, isIndex, opts = {}) {
695 if (
696 filename === '.' ||
697 filename === '..' ||
698 filename[filename.length - 1] === '/' ||
699 filename[filename.length - 1] === '\\'
700 ) {
701 return UNRESOLVED
702 }
703
704 if (parentURL.protocol === 'file:' && /%2f|%5c/i.test(filename)) {
705 throw errors.INVALID_MODULE_SPECIFIER(`Module specifier '${filename}' is invalid`)
706 }
707
708 const { extensions = [] } = opts
709
710 let status = UNRESOLVED
711
712 if (!isIndex) {
713 if (yield { resolution: new URL(filename, parentURL) }) {
714 return RESOLVED
715 }
716
717 status = YIELDED
718 }
719
720 for (const ext of extensions) {
721 if (filename.endsWith(ext)) continue
722
723 if (yield { resolution: new URL(filename + ext, parentURL) }) {
724 return RESOLVED
725 }
726
727 status = YIELDED
728 }
729
730 return status
731}
732
733exports.directory = function* (dirname, parentURL, opts = {}) {
734 let directoryURL
735
736 if (dirname[dirname.length - 1] === '/' || dirname[dirname.length - 1] === '\\') {
737 directoryURL = new URL(dirname, parentURL)
738 } else {
739 directoryURL = new URL(dirname + '/', parentURL)
740 }
741
742 const info = yield { package: new URL('package.json', directoryURL) }
743
744 if (info) {
745 if (info.exports) {
746 return yield* exports.packageExports(directoryURL, '.', info.exports, opts)
747 }
748
749 if (typeof info.main === 'string' && info.main !== '') {
750 const status = yield* exports.file(info.main, directoryURL, false, opts)
751
752 if (status === RESOLVED) return status
753
754 return yield* exports.directory(info.main, directoryURL, opts)
755 }
756 }
757
758 return yield* exports.file('index', directoryURL, true, opts)
759}
760
761// https://infra.spec.whatwg.org/#ascii-upper-alpha
762function isASCIIUpperAlpha(c) {
763 return c >= 0x41 && c <= 0x5a
764}
765
766// https://infra.spec.whatwg.org/#ascii-lower-alpha
767function isASCIILowerAlpha(c) {
768 return c >= 0x61 && c <= 0x7a
769}
770
771// https://infra.spec.whatwg.org/#ascii-alpha
772function isASCIIAlpha(c) {
773 return isASCIIUpperAlpha(c) || isASCIILowerAlpha(c)
774}
775
776// https://url.spec.whatwg.org/#windows-drive-letter
777exports.isWindowsDriveLetter = function isWindowsDriveLetter(input) {
778 return (
779 input.length >= 2 &&
780 isASCIIAlpha(input.charCodeAt(0)) &&
781 (input.charCodeAt(1) === 0x3a || input.charCodeAt(1) === 0x7c)
782 )
783}
784
785// https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
786exports.startsWithWindowsDriveLetter = function startsWithWindowsDriveLetter(input) {
787 return (
788 input.length >= 2 &&
789 exports.isWindowsDriveLetter(input) &&
790 (input.length === 2 ||
791 input.charCodeAt(2) === 0x2f ||
792 input.charCodeAt(2) === 0x5c ||
793 input.charCodeAt(2) === 0x3f ||
794 input.charCodeAt(2) === 0x23)
795 )
796}
node_modules/bare-module-resolve/lib/errors.d.ts +11 -0
……@@ -0,0 +1,11 @@
1declare class ModuleResolveError extends Error {
2 readonly code: string
3
4 static INVALID_MODULE_SPECIFIER(msg: string): ModuleResolveError
5 static INVALID_PACKAGE_TARGET(msg: string): ModuleResolveError
6 static PACKAGE_PATH_NOT_EXPORTED(msg: string): ModuleResolveError
7 static PACKAGE_IMPORT_NOT_DEFINED(msg: string): ModuleResolveError
8 static UNSUPPORTED_ENGINE(msg: string): ModuleResolveError
9}
10
11export = ModuleResolveError
node_modules/bare-module-resolve/lib/errors.js +50 -0
……@@ -0,0 +1,50 @@
1module.exports = class ModuleResolveError extends Error {
2 constructor(msg, code, fn = ModuleResolveError) {
3 super(`${code}: ${msg}`)
4 this.code = code
5
6 if (Error.captureStackTrace) {
7 Error.captureStackTrace(this, fn)
8 }
9 }
10
11 get name() {
12 return 'ModuleResolveError'
13 }
14
15 static INVALID_MODULE_SPECIFIER(msg) {
16 return new ModuleResolveError(
17 msg,
18 'INVALID_MODULE_SPECIFIER',
19 ModuleResolveError.INVALID_MODULE_SPECIFIER
20 )
21 }
22
23 static INVALID_PACKAGE_TARGET(msg) {
24 return new ModuleResolveError(
25 msg,
26 'INVALID_PACKAGE_TARGET',
27 ModuleResolveError.INVALID_PACKAGE_TARGET
28 )
29 }
30
31 static PACKAGE_PATH_NOT_EXPORTED(msg) {
32 return new ModuleResolveError(
33 msg,
34 'PACKAGE_PATH_NOT_EXPORTED',
35 ModuleResolveError.PACKAGE_PATH_NOT_EXPORTED
36 )
37 }
38
39 static PACKAGE_IMPORT_NOT_DEFINED(msg) {
40 return new ModuleResolveError(
41 msg,
42 'PACKAGE_IMPORT_NOT_DEFINED',
43 ModuleResolveError.PACKAGE_IMPORT_NOT_DEFINED
44 )
45 }
46
47 static UNSUPPORTED_ENGINE(msg) {
48 return new ModuleResolveError(msg, 'UNSUPPORTED_ENGINE', ModuleResolveError.UNSUPPORTED_ENGINE)
49 }
50}
node_modules/bare-module-resolve/package.json +51 -0
……@@ -0,0 +1,51 @@
1{
2 "name": "bare-module-resolve",
3 "version": "1.12.1",
4 "description": "Low-level module resolution algorithm for Bare",
5 "exports": {
6 "./package": "./package.json",
7 ".": {
8 "types": "./index.d.ts",
9 "default": "./index.js"
10 },
11 "./errors": {
12 "types": "./lib/errors.d.ts",
13 "default": "./lib/errors.js"
14 }
15 },
16 "files": [
17 "index.js",
18 "index.d.ts",
19 "lib"
20 ],
21 "scripts": {
22 "test": "prettier . --check && bare test.js"
23 },
24 "repository": {
25 "type": "git",
26 "url": "git+https://github.com/holepunchto/bare-module-resolve.git"
27 },
28 "author": "Holepunch",
29 "license": "Apache-2.0",
30 "bugs": {
31 "url": "https://github.com/holepunchto/bare-module-resolve/issues"
32 },
33 "homepage": "https://github.com/holepunchto/bare-module-resolve#readme",
34 "dependencies": {
35 "bare-semver": "^1.0.0"
36 },
37 "devDependencies": {
38 "bare-url": "^2.1.3",
39 "brittle": "^3.2.1",
40 "prettier": "^3.3.3",
41 "prettier-config-holepunch": "^2.0.0"
42 },
43 "peerDependencies": {
44 "bare-url": "*"
45 },
46 "peerDependenciesMeta": {
47 "bare-url": {
48 "optional": true
49 }
50 }
51}
node_modules/bare-os/CMakeLists.txt +13 -0
……@@ -0,0 +1,13 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4
5project(bare_os C)
6
7add_bare_module(bare_os)
8
9target_sources(
10 ${bare_os}
11 PRIVATE
12 binding.c
13)
node_modules/bare-os/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-os/README.md +11 -0
……@@ -0,0 +1,11 @@
1# bare-os
2
3Operating system utilities for Javascript.
4
5```
6npm i bare-os
7```
8
9## License
10
11Apache-2.0
node_modules/bare-os/binding.c +1427 -0
……@@ -0,0 +1,1427 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4#include <stdlib.h>
5#include <utf.h>
6#include <uv.h>
7
8static uv_rwlock_t bare_os_env_lock;
9
10static uv_once_t bare_os_env_lock_guard = UV_ONCE_INIT;
11
12static void
13bare_os__on_env_lock_init(void) {
14 int err = uv_rwlock_init(&bare_os_env_lock);
15 assert(err == 0);
16}
17
18static js_value_t *
19bare_os_type(js_env_t *env, js_callback_info_t *info) {
20 int err;
21
22 uv_utsname_t buffer;
23 err = uv_os_uname(&buffer);
24 if (err < 0) {
25 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
26 assert(err == 0);
27
28 return NULL;
29 }
30
31 js_value_t *result;
32 err = js_create_string_utf8(env, (utf8_t *) buffer.sysname, -1, &result);
33 assert(err == 0);
34
35 return result;
36}
37
38static js_value_t *
39bare_os_version(js_env_t *env, js_callback_info_t *info) {
40 int err;
41
42 uv_utsname_t buffer;
43 err = uv_os_uname(&buffer);
44 if (err < 0) {
45 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
46 assert(err == 0);
47
48 return NULL;
49 }
50
51 js_value_t *result;
52 err = js_create_string_utf8(env, (utf8_t *) buffer.version, -1, &result);
53 assert(err == 0);
54
55 return result;
56}
57
58static js_value_t *
59bare_os_release(js_env_t *env, js_callback_info_t *info) {
60 int err;
61
62 uv_utsname_t buffer;
63 err = uv_os_uname(&buffer);
64 if (err < 0) {
65 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
66 assert(err == 0);
67
68 return NULL;
69 }
70
71 js_value_t *result;
72 err = js_create_string_utf8(env, (utf8_t *) buffer.release, -1, &result);
73 assert(err == 0);
74
75 return result;
76}
77
78static js_value_t *
79bare_os_machine(js_env_t *env, js_callback_info_t *info) {
80 int err;
81
82 uv_utsname_t buffer;
83 err = uv_os_uname(&buffer);
84 if (err < 0) {
85 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
86 assert(err == 0);
87
88 return NULL;
89 }
90
91 js_value_t *result;
92 err = js_create_string_utf8(env, (utf8_t *) buffer.machine, -1, &result);
93 assert(err == 0);
94
95 return result;
96}
97
98static js_value_t *
99bare_os_exec_path(js_env_t *env, js_callback_info_t *info) {
100 int err;
101
102 size_t len = 4096;
103 char exec_path[4096];
104
105 err = uv_exepath(exec_path, &len);
106 if (err < 0) {
107 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
108 assert(err == 0);
109
110 return NULL;
111 }
112
113 js_value_t *result;
114 err = js_create_string_utf8(env, (utf8_t *) exec_path, len, &result);
115 assert(err == 0);
116
117 return result;
118}
119
120static js_value_t *
121bare_os_pid(js_env_t *env, js_callback_info_t *info) {
122 int err;
123
124 js_value_t *result;
125 err = js_create_uint32(env, uv_os_getpid(), &result);
126 assert(err == 0);
127
128 return result;
129}
130
131static js_value_t *
132bare_os_ppid(js_env_t *env, js_callback_info_t *info) {
133 int err;
134
135 js_value_t *result;
136 err = js_create_uint32(env, uv_os_getppid(), &result);
137 assert(err == 0);
138
139 return result;
140}
141
142static js_value_t *
143bare_os_cwd(js_env_t *env, js_callback_info_t *info) {
144 int err;
145
146 size_t len = 4096;
147 char cwd[4096];
148
149 err = uv_cwd(cwd, &len);
150 if (err < 0) {
151 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
152 assert(err == 0);
153
154 return NULL;
155 }
156
157 js_value_t *result;
158 err = js_create_string_utf8(env, (utf8_t *) cwd, len, &result);
159 assert(err == 0);
160
161 return result;
162}
163
164static js_value_t *
165bare_os_chdir(js_env_t *env, js_callback_info_t *info) {
166 int err;
167
168 size_t argc = 1;
169 js_value_t *argv[1];
170
171 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
172 assert(err == 0);
173
174 assert(argc == 1);
175
176 utf8_t dir[4096];
177 err = js_get_value_string_utf8(env, argv[0], dir, 4096, NULL);
178 assert(err == 0);
179
180 err = uv_chdir((char *) dir);
181 if (err < 0) {
182 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
183 assert(err == 0);
184
185 return NULL;
186 }
187
188 return NULL;
189}
190
191static js_value_t *
192bare_os_tmpdir(js_env_t *env, js_callback_info_t *info) {
193 int err;
194
195 size_t len = 4096;
196 char tmpdir[4096];
197
198 err = uv_os_tmpdir(tmpdir, &len);
199 if (err < 0) {
200 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
201 assert(err == 0);
202
203 return NULL;
204 }
205
206 js_value_t *result;
207 err = js_create_string_utf8(env, (utf8_t *) tmpdir, len, &result);
208 assert(err == 0);
209
210 return result;
211}
212
213static js_value_t *
214bare_os_homedir(js_env_t *env, js_callback_info_t *info) {
215 int err;
216
217 size_t len = 4096;
218 char homedir[4096];
219
220 err = uv_os_homedir(homedir, &len);
221 if (err < 0) {
222 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
223 assert(err == 0);
224
225 return NULL;
226 }
227
228 js_value_t *result;
229 err = js_create_string_utf8(env, (utf8_t *) homedir, len, &result);
230 assert(err == 0);
231
232 return result;
233}
234
235static js_value_t *
236bare_os_hostname(js_env_t *env, js_callback_info_t *info) {
237 int err;
238
239 size_t len = UV_MAXHOSTNAMESIZE;
240 char hostname[UV_MAXHOSTNAMESIZE];
241
242 err = uv_os_gethostname(hostname, &len);
243 if (err < 0) {
244 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
245 assert(err == 0);
246
247 return NULL;
248 }
249
250 js_value_t *result;
251 err = js_create_string_utf8(env, (utf8_t *) hostname, len, &result);
252 assert(err == 0);
253
254 return result;
255}
256
257static js_value_t *
258bare_os_user_info(js_env_t *env, js_callback_info_t *info) {
259 int err;
260
261 uv_passwd_t pwd;
262 err = uv_os_get_passwd(&pwd);
263 if (err != 0) {
264 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
265 assert(err == 0);
266
267 return NULL;
268 }
269
270 js_value_t *result;
271 err = js_create_object(env, &result);
272 assert(err == 0);
273
274 js_value_t *uid;
275 err = js_create_int32(env, pwd.uid, &uid);
276 assert(err == 0);
277
278 err = js_set_named_property(env, result, "uid", uid);
279 assert(err == 0);
280
281 js_value_t *gid;
282 err = js_create_int32(env, pwd.gid, &gid);
283 assert(err == 0);
284
285 err = js_set_named_property(env, result, "gid", gid);
286 assert(err == 0);
287
288 js_value_t *username;
289 err = js_create_string_utf8(env, (utf8_t *) pwd.username, strlen(pwd.username), &username);
290 assert(err == 0);
291
292 err = js_set_named_property(env, result, "username", username);
293 assert(err == 0);
294
295 js_value_t *homedir;
296 err = js_create_string_utf8(env, (utf8_t *) pwd.homedir, strlen(pwd.homedir), &homedir);
297 assert(err == 0);
298
299 err = js_set_named_property(env, result, "homedir", homedir);
300 assert(err == 0);
301
302 js_value_t *shell;
303
304 if (pwd.shell == NULL) {
305 err = js_get_null(env, &shell);
306 assert(err == 0);
307 } else {
308 err = js_create_string_utf8(env, (utf8_t *) pwd.shell, -1, &shell);
309 assert(err == 0);
310 }
311
312 err = js_set_named_property(env, result, "shell", shell);
313 assert(err == 0);
314
315 uv_os_free_passwd(&pwd);
316
317 return result;
318}
319
320static int
321bare_os__population_count(uint32_t num) {
322 int result = 0;
323
324 while (num != 0) {
325 result++;
326 num &= num - 1;
327 }
328
329 return result;
330}
331
332static js_value_t *
333bare_os_network_interfaces(js_env_t *env, js_callback_info_t *info) {
334 int err;
335
336 uv_interface_address_t *addresses;
337 int len;
338 err = uv_interface_addresses(&addresses, &len);
339 if (err < 0) {
340 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
341 assert(err == 0);
342
343 return NULL;
344 }
345
346 js_value_t *result;
347 err = js_create_array_with_length(env, len, &result);
348 assert(err == 0);
349
350 for (size_t i = 0, n = len; i < n; i++) {
351 uv_interface_address_t address = addresses[i];
352
353 uint32_t family = address.address.address4.sin_family;
354
355 if (family != AF_INET && family != AF_INET6) {
356 continue;
357 }
358
359 js_value_t *item;
360 err = js_create_object(env, &item);
361 assert(err == 0);
362
363 js_value_t *val;
364
365 err = js_create_string_utf8(env, (utf8_t *) address.name, -1, &val);
366 assert(err == 0);
367
368 err = js_set_named_property(env, item, "name", val);
369 assert(err == 0);
370
371 char address_ip[INET6_ADDRSTRLEN];
372 char netmask_ip[INET6_ADDRSTRLEN];
373 char family_string[5];
374
375 char cidr[INET6_ADDRSTRLEN + 8];
376 uint32_t cidr_value = 0;
377
378 if (family == AF_INET) {
379 err = uv_ip4_name(&address.address.address4, address_ip, sizeof(address_ip));
380 assert(err == 0);
381
382 err = uv_ip4_name(&address.netmask.netmask4, netmask_ip, sizeof(netmask_ip));
383 assert(err == 0);
384
385 strcpy(family_string, "IPv4");
386
387 cidr_value = bare_os__population_count(address.netmask.netmask4.sin_addr.s_addr);
388 } else {
389 err = uv_ip6_name(&address.address.address6, address_ip, sizeof(address_ip));
390 assert(err == 0);
391
392 err = uv_ip6_name(&address.netmask.netmask6, netmask_ip, sizeof(netmask_ip));
393 assert(err == 0);
394
395 strcpy(family_string, "IPv6");
396
397 for (size_t i = 0; i < 16; i++) {
398 uint32_t count = bare_os__population_count(address.netmask.netmask6.sin6_addr.s6_addr[i]);
399
400 if (count == 0) break;
401
402 cidr_value += count;
403 }
404 }
405
406 err = js_create_string_utf8(env, (utf8_t *) address_ip, -1, &val);
407 assert(err == 0);
408
409 err = js_set_named_property(env, item, "address", val);
410 assert(err == 0);
411
412 err = js_create_string_utf8(env, (utf8_t *) netmask_ip, -1, &val);
413 assert(err == 0);
414
415 err = js_set_named_property(env, item, "netmask", val);
416 assert(err == 0);
417
418 err = js_create_string_utf8(env, (utf8_t *) family_string, -1, &val);
419 assert(err == 0);
420
421 err = js_set_named_property(env, item, "family", val);
422 assert(err == 0);
423
424 err = snprintf(cidr, sizeof(cidr), "%s/%d", address_ip, cidr_value);
425 assert(err > 0);
426
427 err = js_create_string_utf8(env, (utf8_t *) cidr, -1, &val);
428 assert(err == 0);
429
430 err = js_set_named_property(env, item, "cidr", val);
431 assert(err == 0);
432
433 char mac[18];
434 err = snprintf(
435 mac,
436 sizeof(mac),
437 "%02x:%02x:%02x:%02x:%02x:%02x",
438 (unsigned char) address.phys_addr[0],
439 (unsigned char) address.phys_addr[1],
440 (unsigned char) address.phys_addr[2],
441 (unsigned char) address.phys_addr[3],
442 (unsigned char) address.phys_addr[4],
443 (unsigned char) address.phys_addr[5]
444 );
445 assert(err > 0);
446
447 err = js_create_string_utf8(env, (utf8_t *) mac, -1, &val);
448 assert(err == 0);
449
450 err = js_set_named_property(env, item, "mac", val);
451 assert(err == 0);
452
453 err = js_get_boolean(env, address.is_internal == 1, &val);
454 assert(err == 0);
455
456 err = js_set_named_property(env, item, "internal", val);
457 assert(err == 0);
458
459 if (family == AF_INET6) {
460 err = js_create_uint32(env, address.address.address6.sin6_scope_id, &val);
461 assert(err == 0);
462
463 err = js_set_named_property(env, item, "scopeid", val);
464 assert(err == 0);
465 }
466
467 err = js_set_element(env, result, i, item);
468 assert(err == 0);
469 }
470
471 uv_free_interface_addresses(addresses, len);
472
473 return result;
474}
475
476static js_value_t *
477bare_os_kill(js_env_t *env, js_callback_info_t *info) {
478 int err;
479
480 size_t argc = 2;
481 js_value_t *argv[2];
482
483 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
484 assert(err == 0);
485
486 assert(argc == 2);
487
488 uint32_t pid;
489 err = js_get_value_uint32(env, argv[0], &pid);
490 assert(err == 0);
491
492 uint32_t signum;
493 err = js_get_value_uint32(env, argv[1], &signum);
494 assert(err == 0);
495
496 err = uv_kill(pid, signum);
497 if (err < 0) {
498 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
499 assert(err == 0);
500
501 return NULL;
502 }
503
504 return NULL;
505}
506
507static js_value_t *
508bare_os_available_parallelism(js_env_t *env, js_callback_info_t *info) {
509 int err;
510
511 js_value_t *result;
512 err = js_create_int64(env, uv_available_parallelism(), &result);
513 assert(err == 0);
514
515 return result;
516}
517
518static js_value_t *
519bare_os_cpu_usage(js_env_t *env, js_callback_info_t *info) {
520 int err;
521
522 uv_rusage_t usage;
523 err = uv_getrusage(&usage);
524 assert(err == 0);
525
526 js_value_t *result;
527 err = js_create_object(env, &result);
528 assert(err == 0);
529
530#define V(name, property) \
531 { \
532 uv_timeval_t time = usage.ru_##property; \
533\
534 js_value_t *value; \
535 err = js_create_int64(env, time.tv_sec * 1e6 + time.tv_usec, &value); \
536 assert(err == 0); \
537\
538 err = js_set_named_property(env, result, name, value); \
539 assert(err == 0); \
540 }
541
542 V("user", utime)
543 V("system", stime)
544#undef V
545
546 return result;
547}
548
549static js_value_t *
550bare_os_cpu_usage_thread(js_env_t *env, js_callback_info_t *info) {
551 int err;
552
553 uv_rusage_t usage;
554 err = uv_getrusage_thread(&usage);
555 assert(err == 0);
556
557 js_value_t *result;
558 err = js_create_object(env, &result);
559 assert(err == 0);
560
561#define V(name, property) \
562 { \
563 uv_timeval_t time = usage.ru_##property; \
564\
565 js_value_t *value; \
566 err = js_create_int64(env, time.tv_sec * 1e6 + time.tv_usec, &value); \
567 assert(err == 0); \
568\
569 err = js_set_named_property(env, result, name, value); \
570 assert(err == 0); \
571 }
572
573 V("user", utime)
574 V("system", stime)
575#undef V
576
577 return result;
578}
579
580static js_value_t *
581bare_os_resource_usage(js_env_t *env, js_callback_info_t *info) {
582 int err;
583
584 uv_rusage_t usage;
585 err = uv_getrusage(&usage);
586 assert(err == 0);
587
588 js_value_t *result;
589 err = js_create_object(env, &result);
590 assert(err == 0);
591
592#define V(name, property) \
593 { \
594 uv_timeval_t time = usage.ru_##property; \
595\
596 js_value_t *value; \
597 err = js_create_int64(env, time.tv_sec * 1e6 + time.tv_usec, &value); \
598 assert(err == 0); \
599\
600 err = js_set_named_property(env, result, name, value); \
601 assert(err == 0); \
602 }
603
604 V("userCPUTime", utime)
605 V("systemCPUTime", stime)
606#undef V
607
608#define V(name, property) \
609 { \
610 js_value_t *value; \
611 err = js_create_int64(env, usage.ru_##property, &value); \
612 assert(err == 0); \
613\
614 err = js_set_named_property(env, result, name, value); \
615 assert(err == 0); \
616 }
617
618 V("maxRSS", maxrss)
619 V("sharedMemorySize", ixrss)
620 V("unsharedDataSize", idrss)
621 V("unsharedStackSize", isrss)
622 V("minorPageFault", minflt)
623 V("majorPageFault", majflt)
624 V("swappedOut", nswap)
625 V("fsRead", inblock)
626 V("fsWrite", oublock)
627 V("ipcSent", msgsnd)
628 V("ipcReceived", msgrcv)
629 V("signalsCount", nsignals)
630 V("voluntaryContextSwitches", nvcsw)
631 V("involuntaryContextSwitches", nivcsw)
632#undef V
633
634 return result;
635}
636
637static js_value_t *
638bare_os_memory_usage(js_env_t *env, js_callback_info_t *info) {
639 int err;
640
641 js_heap_statistics_t stats = {
642 .version = 1,
643
644 // Since 0
645 .total_heap_size = -1,
646 .used_heap_size = -1,
647
648 // Since 1
649 .external_memory = -1,
650 };
651
652 err = js_get_heap_statistics(env, &stats);
653 assert(err == 0);
654
655 js_value_t *result;
656 err = js_create_object(env, &result);
657 assert(err == 0);
658
659 size_t rss;
660 err = uv_resident_set_memory(&rss);
661 assert(err == 0);
662
663 js_value_t *value;
664 err = js_create_int64(env, rss, &value);
665 assert(err == 0);
666
667 err = js_set_named_property(env, result, "rss", value);
668 assert(err == 0);
669
670#define V(name, property) \
671 { \
672 if (stats.property != (size_t) -1) { \
673 js_value_t *value; \
674 err = js_create_int64(env, stats.property, &value); \
675 assert(err == 0); \
676\
677 err = js_set_named_property(env, result, name, value); \
678 assert(err == 0); \
679 } \
680 }
681
682 V("heapTotal", total_heap_size)
683 V("heapUsed", used_heap_size)
684 V("external", external_memory)
685#undef V
686
687 return result;
688}
689
690static js_value_t *
691bare_os_freemem(js_env_t *env, js_callback_info_t *info) {
692 int err;
693
694 js_value_t *result;
695 err = js_create_int64(env, uv_get_free_memory(), &result);
696 assert(err == 0);
697
698 return result;
699}
700
701static js_value_t *
702bare_os_totalmem(js_env_t *env, js_callback_info_t *info) {
703 int err;
704
705 js_value_t *result;
706 err = js_create_int64(env, uv_get_total_memory(), &result);
707 assert(err == 0);
708
709 return result;
710}
711
712static js_value_t *
713bare_os_available_memory(js_env_t *env, js_callback_info_t *info) {
714 int err;
715
716 js_value_t *result;
717 err = js_create_int64(env, uv_get_available_memory(), &result);
718 assert(err == 0);
719
720 return result;
721}
722
723static js_value_t *
724bare_os_constrained_memory(js_env_t *env, js_callback_info_t *info) {
725 int err;
726
727 js_value_t *result;
728 err = js_create_int64(env, uv_get_constrained_memory(), &result);
729 assert(err == 0);
730
731 return result;
732}
733
734static js_value_t *
735bare_os_uptime(js_env_t *env, js_callback_info_t *info) {
736 int err;
737
738 double uptime;
739 err = uv_uptime(&uptime);
740 assert(err == 0);
741
742 js_value_t *result;
743 err = js_create_double(env, uptime, &result);
744 assert(err == 0);
745
746 return result;
747}
748
749static js_value_t *
750bare_os_loadavg(js_env_t *env, js_callback_info_t *info) {
751 int err;
752
753 double *data;
754
755 js_value_t *arraybuffer;
756 err = js_create_arraybuffer(env, sizeof(double) * 3, (void **) &data, &arraybuffer);
757 assert(err == 0);
758
759 js_value_t *result;
760 err = js_create_typedarray(env, js_float64array, 3, arraybuffer, 0, &result);
761 assert(err == 0);
762
763 uv_loadavg(data);
764
765 return result;
766}
767
768static js_value_t *
769bare_os_cpus(js_env_t *env, js_callback_info_t *info) {
770 int err;
771
772 uv_cpu_info_t *cpus;
773 int len;
774 err = uv_cpu_info(&cpus, &len);
775 if (err < 0) {
776 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
777 assert(err == 0);
778
779 return NULL;
780 }
781
782 js_value_t *result;
783 err = js_create_array_with_length(env, len, &result);
784 assert(err == 0);
785
786 for (uint32_t i = 0, n = len; i < n; i++) {
787 uv_cpu_info_t cpu = cpus[i];
788
789 js_value_t *item;
790 err = js_create_object(env, &item);
791 assert(err == 0);
792
793 err = js_set_element(env, result, i, item);
794 assert(err == 0);
795
796#define V(name, type, ...) \
797 { \
798 js_value_t *val; \
799 err = type(env, ##__VA_ARGS__, &val); \
800 assert(err == 0); \
801 err = js_set_named_property(env, item, name, val); \
802 assert(err == 0); \
803 }
804
805 V("model", js_create_string_utf8, (const utf8_t *) cpu.model, -1)
806 V("speed", js_create_double, cpu.speed)
807 V("times", js_create_object)
808#undef V
809
810 js_value_t *times;
811 err = js_get_named_property(env, item, "times", &times);
812 assert(err == 0);
813
814#define V(name) \
815 { \
816 js_value_t *val; \
817 err = js_create_int64(env, cpu.cpu_times.name, &val); \
818 assert(err == 0); \
819 err = js_set_named_property(env, times, #name, val); \
820 assert(err == 0); \
821 }
822
823 V(user)
824 V(nice)
825 V(sys)
826 V(idle)
827 V(irq)
828#undef V
829 }
830
831 uv_free_cpu_info(cpus, len);
832
833 return result;
834}
835
836static js_value_t *
837bare_os_get_process_title(js_env_t *env, js_callback_info_t *info) {
838 int err;
839
840 char title[256];
841 err = uv_get_process_title(title, 256);
842 if (err < 0) {
843 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
844 assert(err == 0);
845
846 return NULL;
847 }
848
849 js_value_t *result;
850 err = js_create_string_utf8(env, (utf8_t *) title, -1, &result);
851 assert(err == 0);
852
853 return result;
854}
855
856static js_value_t *
857bare_os_set_process_title(js_env_t *env, js_callback_info_t *info) {
858 int err;
859
860 size_t argc = 1;
861 js_value_t *argv[1];
862
863 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
864 assert(err == 0);
865
866 assert(argc == 1);
867
868 utf8_t data[256];
869 err = js_get_value_string_utf8(env, argv[0], data, 256, NULL);
870 assert(err == 0);
871
872 err = uv_set_process_title((char *) data);
873 assert(err == 0);
874
875 return NULL;
876}
877
878static js_value_t *
879bare_os_get_priority(js_env_t *env, js_callback_info_t *info) {
880 int err;
881
882 size_t argc = 1;
883 js_value_t *argv[1];
884
885 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
886 assert(err == 0);
887
888 assert(argc == 1);
889
890 uv_pid_t pid;
891 err = js_get_value_int32(env, argv[0], &pid);
892 assert(err == 0);
893
894 int priority;
895 err = uv_os_getpriority(pid, &priority);
896 if (err < 0) {
897 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
898 assert(err == 0);
899
900 return NULL;
901 }
902
903 js_value_t *result;
904 err = js_create_int32(env, priority, &result);
905 assert(err == 0);
906
907 return result;
908}
909
910static js_value_t *
911bare_os_set_priority(js_env_t *env, js_callback_info_t *info) {
912 int err;
913
914 size_t argc = 2;
915 js_value_t *argv[2];
916
917 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
918 assert(err == 0);
919
920 assert(argc == 2);
921
922 uv_pid_t pid;
923 err = js_get_value_int32(env, argv[0], &pid);
924 assert(err == 0);
925
926 int priority;
927 err = js_get_value_int32(env, argv[1], &priority);
928 assert(err == 0);
929
930 err = uv_os_setpriority(pid, priority);
931 if (err < 0) {
932 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
933 assert(err == 0);
934
935 return NULL;
936 }
937
938 return NULL;
939}
940
941static js_value_t *
942bare_os_get_env_keys(js_env_t *env, js_callback_info_t *info) {
943 int err;
944
945 uv_env_item_t *items;
946 int len;
947
948 uv_rwlock_rdlock(&bare_os_env_lock);
949
950 err = uv_os_environ(&items, &len);
951
952 uv_rwlock_rdunlock(&bare_os_env_lock);
953
954 if (err < 0) {
955 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
956 assert(err == 0);
957
958 return NULL;
959 }
960
961 js_value_t *result;
962 err = js_create_array_with_length(env, len, &result);
963 assert(err == 0);
964
965 for (int i = 0; i < len; i++) {
966 uv_env_item_t *item = &items[i];
967
968 js_value_t *val;
969 err = js_create_string_utf8(env, (utf8_t *) item->name, -1, &val);
970 assert(err == 0);
971
972 err = js_set_element(env, result, i, val);
973 assert(err == 0);
974 }
975
976 uv_os_free_environ(items, len);
977
978 return result;
979}
980
981static js_value_t *
982bare_os_get_env(js_env_t *env, js_callback_info_t *info) {
983 int err;
984
985 size_t argc = 1;
986 js_value_t *argv[1];
987
988 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
989 assert(err == 0);
990
991 assert(argc == 1);
992
993 size_t name_len;
994 err = js_get_value_string_utf8(env, argv[0], NULL, 0, &name_len);
995 assert(err == 0);
996
997 name_len += 1 /* NULL */;
998
999 utf8_t *name = malloc(name_len);
1000 err = js_get_value_string_utf8(env, argv[0], name, name_len, &name_len);
1001 assert(err == 0);
1002
1003 uv_rwlock_rdlock(&bare_os_env_lock);
1004
1005 size_t value_len = 256;
1006 char *value = malloc(value_len);
1007 err = uv_os_getenv((char *) name, value, &value_len);
1008
1009 js_value_t *result;
1010
1011 if (err == UV_ENOENT) {
1012 err = js_get_undefined(env, &result);
1013 assert(err == 0);
1014 } else {
1015 if (err == UV_ENOBUFS) {
1016 value = realloc(value, value_len);
1017
1018 err = uv_os_getenv((char *) name, value, &value_len);
1019 assert(err == 0);
1020 } else if (err < 0) {
1021 uv_rwlock_rdunlock(&bare_os_env_lock);
1022
1023 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1024 assert(err == 0);
1025
1026 free(name);
1027 return NULL;
1028 }
1029
1030 err = js_create_string_utf8(env, (utf8_t *) value, value_len, &result);
1031 assert(err == 0);
1032 }
1033
1034 uv_rwlock_rdunlock(&bare_os_env_lock);
1035
1036 free(name);
1037 free(value);
1038
1039 return result;
1040}
1041
1042static js_value_t *
1043bare_os_has_env(js_env_t *env, js_callback_info_t *info) {
1044 int err;
1045
1046 size_t argc = 1;
1047 js_value_t *argv[1];
1048
1049 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1050 assert(err == 0);
1051
1052 assert(argc == 1);
1053
1054 size_t name_len;
1055 err = js_get_value_string_utf8(env, argv[0], NULL, 0, &name_len);
1056 assert(err == 0);
1057
1058 utf8_t *name = malloc(++name_len);
1059 err = js_get_value_string_utf8(env, argv[0], name, name_len, &name_len);
1060 assert(err == 0);
1061
1062 uv_rwlock_rdlock(&bare_os_env_lock);
1063
1064 size_t value_len = 1;
1065 char value[1];
1066 err = uv_os_getenv((char *) name, value, &value_len);
1067
1068 uv_rwlock_rdunlock(&bare_os_env_lock);
1069
1070 if (err != 0 && err != UV_ENOENT && err != UV_ENOBUFS) {
1071 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1072 assert(err == 0);
1073
1074 free(name);
1075 return NULL;
1076 }
1077
1078 free(name);
1079
1080 js_value_t *result;
1081 err = js_get_boolean(env, err != UV_ENOENT, &result);
1082 assert(err == 0);
1083
1084 return result;
1085}
1086
1087static js_value_t *
1088bare_os_set_env(js_env_t *env, js_callback_info_t *info) {
1089 int err;
1090
1091 size_t argc = 2;
1092 js_value_t *argv[2];
1093
1094 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1095 assert(err == 0);
1096
1097 assert(argc == 2);
1098
1099 size_t name_len;
1100 err = js_get_value_string_utf8(env, argv[0], NULL, 0, &name_len);
1101 assert(err == 0);
1102
1103 utf8_t *name = malloc(++name_len);
1104 err = js_get_value_string_utf8(env, argv[0], name, name_len, &name_len);
1105 assert(err == 0);
1106
1107 size_t value_len;
1108 err = js_get_value_string_utf8(env, argv[1], NULL, 0, &value_len);
1109 assert(err == 0);
1110
1111 utf8_t *value = malloc(++value_len);
1112 err = js_get_value_string_utf8(env, argv[1], value, value_len, &value_len);
1113 assert(err == 0);
1114
1115 uv_rwlock_wrlock(&bare_os_env_lock);
1116
1117 err = uv_os_setenv((char *) name, (char *) value);
1118
1119 uv_rwlock_wrunlock(&bare_os_env_lock);
1120
1121 if (err < 0) {
1122 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1123 assert(err == 0);
1124
1125 free(name);
1126 free(value);
1127 return NULL;
1128 }
1129
1130 free(name);
1131 free(value);
1132
1133 return NULL;
1134}
1135
1136static js_value_t *
1137bare_os_unset_env(js_env_t *env, js_callback_info_t *info) {
1138 int err;
1139
1140 size_t argc = 1;
1141 js_value_t *argv[1];
1142
1143 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1144 assert(err == 0);
1145
1146 assert(argc == 1);
1147
1148 size_t name_len;
1149 err = js_get_value_string_utf8(env, argv[0], NULL, 0, &name_len);
1150 assert(err == 0);
1151
1152 utf8_t *name = malloc(++name_len);
1153 err = js_get_value_string_utf8(env, argv[0], name, name_len, &name_len);
1154 assert(err == 0);
1155
1156 uv_rwlock_wrlock(&bare_os_env_lock);
1157
1158 err = uv_os_unsetenv((char *) name);
1159
1160 uv_rwlock_wrunlock(&bare_os_env_lock);
1161
1162 if (err < 0) {
1163 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1164 assert(err == 0);
1165
1166 free(name);
1167 return NULL;
1168 }
1169
1170 free(name);
1171
1172 return NULL;
1173}
1174
1175static js_value_t *
1176bare_os_exports(js_env_t *env, js_value_t *exports) {
1177 uv_once(&bare_os_env_lock_guard, bare_os__on_env_lock_init);
1178
1179 int err;
1180
1181#define V(name, str) \
1182 { \
1183 js_value_t *val; \
1184 err = js_create_string_utf8(env, (utf8_t *) str, -1, &val); \
1185 assert(err == 0); \
1186 err = js_set_named_property(env, exports, name, val); \
1187 assert(err == 0); \
1188 }
1189
1190 V("platform", BARE_PLATFORM)
1191 V("arch", BARE_ARCH)
1192#undef V
1193
1194#define V(name, fn) \
1195 { \
1196 js_value_t *val; \
1197 err = js_create_function(env, name, -1, fn, NULL, &val); \
1198 assert(err == 0); \
1199 err = js_set_named_property(env, exports, name, val); \
1200 assert(err == 0); \
1201 }
1202
1203 V("type", bare_os_type)
1204 V("version", bare_os_version)
1205 V("release", bare_os_release)
1206 V("machine", bare_os_machine)
1207 V("execPath", bare_os_exec_path)
1208 V("pid", bare_os_pid)
1209 V("ppid", bare_os_ppid)
1210 V("cwd", bare_os_cwd)
1211 V("chdir", bare_os_chdir)
1212 V("tmpdir", bare_os_tmpdir)
1213 V("homedir", bare_os_homedir)
1214 V("hostname", bare_os_hostname)
1215 V("kill", bare_os_kill)
1216 V("availableParallelism", bare_os_available_parallelism)
1217 V("cpuUsage", bare_os_cpu_usage)
1218 V("threadCpuUsage", bare_os_cpu_usage_thread)
1219 V("resourceUsage", bare_os_resource_usage)
1220 V("memoryUsage", bare_os_memory_usage)
1221 V("freemem", bare_os_freemem)
1222 V("totalmem", bare_os_totalmem)
1223 V("availableMemory", bare_os_available_memory)
1224 V("constrainedMemory", bare_os_constrained_memory)
1225 V("uptime", bare_os_uptime)
1226 V("loadavg", bare_os_loadavg)
1227 V("cpus", bare_os_cpus)
1228 V("getProcessTitle", bare_os_get_process_title)
1229 V("setProcessTitle", bare_os_set_process_title)
1230 V("getPriority", bare_os_get_priority)
1231 V("setPriority", bare_os_set_priority)
1232 V("getEnvKeys", bare_os_get_env_keys)
1233 V("getEnv", bare_os_get_env)
1234 V("hasEnv", bare_os_get_env)
1235 V("setEnv", bare_os_set_env)
1236 V("unsetEnv", bare_os_unset_env)
1237 V("userInfo", bare_os_user_info)
1238 V("networkInterfaces", bare_os_network_interfaces)
1239#undef V
1240
1241 const union {
1242 uint8_t u8[2];
1243 uint16_t u16;
1244 } byte_order = {{1, 0}};
1245
1246 js_value_t *is_little_endian;
1247 err = js_get_boolean(env, byte_order.u16 == 1, &is_little_endian);
1248 assert(err == 0);
1249
1250 err = js_set_named_property(env, exports, "isLittleEndian", is_little_endian);
1251 assert(err == 0);
1252
1253 js_value_t *signals;
1254 err = js_create_object(env, &signals);
1255 assert(err == 0);
1256
1257 err = js_set_named_property(env, exports, "signals", signals);
1258 assert(err == 0);
1259
1260#define V(name) \
1261 { \
1262 js_value_t *val; \
1263 err = js_create_uint32(env, name, &val); \
1264 assert(err == 0); \
1265 err = js_set_named_property(env, signals, #name, val); \
1266 assert(err == 0); \
1267 }
1268
1269#ifdef SIGHUP
1270 V(SIGHUP);
1271#endif
1272#ifdef SIGINT
1273 V(SIGINT);
1274#endif
1275#ifdef SIGQUIT
1276 V(SIGQUIT);
1277#endif
1278#ifdef SIGILL
1279 V(SIGILL);
1280#endif
1281#ifdef SIGTRAP
1282 V(SIGTRAP);
1283#endif
1284#ifdef SIGABRT
1285 V(SIGABRT);
1286#endif
1287#ifdef SIGIOT
1288 V(SIGIOT);
1289#endif
1290#ifdef SIGBUS
1291 V(SIGBUS);
1292#endif
1293#ifdef SIGFPE
1294 V(SIGFPE);
1295#endif
1296#ifdef SIGKILL
1297 V(SIGKILL);
1298#endif
1299#ifdef SIGUSR1
1300 V(SIGUSR1);
1301#endif
1302#ifdef SIGSEGV
1303 V(SIGSEGV);
1304#endif
1305#ifdef SIGUSR2
1306 V(SIGUSR2);
1307#endif
1308#ifdef SIGPIPE
1309 V(SIGPIPE);
1310#endif
1311#ifdef SIGALRM
1312 V(SIGALRM);
1313#endif
1314#ifdef SIGTERM
1315 V(SIGTERM);
1316#endif
1317#ifdef SIGCHLD
1318 V(SIGCHLD);
1319#endif
1320#ifdef SIGSTKFLT
1321 V(SIGSTKFLT);
1322#endif
1323#ifdef SIGCONT
1324 V(SIGCONT);
1325#endif
1326#ifdef SIGSTOP
1327 V(SIGSTOP);
1328#endif
1329#ifdef SIGTSTP
1330 V(SIGTSTP);
1331#endif
1332#ifdef SIGBREAK
1333 V(SIGBREAK);
1334#endif
1335#ifdef SIGTTIN
1336 V(SIGTTIN);
1337#endif
1338#ifdef SIGTTOU
1339 V(SIGTTOU);
1340#endif
1341#ifdef SIGURG
1342 V(SIGURG);
1343#endif
1344#ifdef SIGXCPU
1345 V(SIGXCPU);
1346#endif
1347#ifdef SIGXFSZ
1348 V(SIGXFSZ);
1349#endif
1350#ifdef SIGVTALRM
1351 V(SIGVTALRM);
1352#endif
1353#ifdef SIGPROF
1354 V(SIGPROF);
1355#endif
1356#ifdef SIGWINCH
1357 V(SIGWINCH);
1358#endif
1359#ifdef SIGIO
1360 V(SIGIO);
1361#endif
1362#ifdef SIGPOLL
1363 V(SIGPOLL);
1364#endif
1365#ifdef SIGLOST
1366 V(SIGLOST);
1367#endif
1368#ifdef SIGPWR
1369 V(SIGPWR);
1370#endif
1371#ifdef SIGINFO
1372 V(SIGINFO);
1373#endif
1374#ifdef SIGSYS
1375 V(SIGSYS);
1376#endif
1377#ifdef SIGUNUSED
1378 V(SIGUNUSED);
1379#endif
1380#undef V
1381
1382 js_value_t *errnos;
1383 err = js_create_object(env, &errnos);
1384 assert(err == 0);
1385
1386 err = js_set_named_property(env, exports, "errnos", errnos);
1387 assert(err == 0);
1388
1389#define V(name, msg) \
1390 { \
1391 js_value_t *val; \
1392 err = js_create_int32(env, UV_##name, &val); \
1393 assert(err == 0); \
1394 err = js_set_named_property(env, errnos, #name, val); \
1395 assert(err == 0); \
1396 }
1397
1398 UV_ERRNO_MAP(V);
1399#undef V
1400
1401 js_value_t *priority;
1402 err = js_create_object(env, &priority);
1403 assert(err == 0);
1404
1405 err = js_set_named_property(env, exports, "priority", priority);
1406 assert(err == 0);
1407
1408#define V(name) \
1409 { \
1410 js_value_t *val; \
1411 err = js_create_int32(env, UV_##name, &val); \
1412 assert(err == 0); \
1413 err = js_set_named_property(env, priority, #name, val); \
1414 assert(err == 0); \
1415 }
1416
1417 V(PRIORITY_LOW);
1418 V(PRIORITY_BELOW_NORMAL);
1419 V(PRIORITY_NORMAL);
1420 V(PRIORITY_ABOVE_NORMAL);
1421 V(PRIORITY_HIGH);
1422 V(PRIORITY_HIGHEST);
1423
1424 return exports;
1425}
1426
1427BARE_MODULE(bare_os, bare_os_exports)
node_modules/bare-os/binding.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require.addon()
node_modules/bare-os/index.d.ts +143 -0
……@@ -0,0 +1,143 @@
1export const constants: {
2 signals: Record<string, number>
3 errnos: Record<string, number>
4 priority: Record<string, number>
5}
6
7export const EOL: '\r\n' | '\n'
8
9export const devNull: '\\\\.\\nul' | '/dev/null'
10
11export function platform(): 'android' | 'darwin' | 'ios' | 'linux' | 'win32'
12
13export function arch(): 'arm' | 'arm64' | 'ia32' | 'x64'
14
15export function type(): string
16
17export function version(): string
18
19export function release(): string
20
21export function machine(): string
22
23export function execPath(): string
24
25export function pid(): number
26
27export function ppid(): number
28
29export function cwd(): string
30
31export function chdir(dir: string): string
32
33export function tmpdir(): string
34
35export function homedir(): string
36
37export function hostname(): string
38
39export interface NetworkInterface {
40 address: string
41 netmask: string
42 family: 'IPv4' | 'IPv6'
43 cidr: string
44 mac: string
45 internal: boolean
46 scopeid?: number
47}
48
49export function networkInterfaces(): Record<string, NetworkInterface[]>
50
51export function kill(pid: number, signal?: string | number): void
52
53export interface UserInfo {
54 uid: number
55 gid: number
56 username: string
57 homedir: string
58 shell: string | null
59}
60
61export function userInfo(): UserInfo
62
63export function endianness(): 'LE' | 'BE'
64
65export function availableParallelism(): number
66
67export interface CpuUsage {
68 user: number
69 system: number
70}
71
72export function cpuUsage(previous?: CpuUsage): CpuUsage
73
74export function threadCpuUsage(previous?: CpuUsage): CpuUsage
75
76export function resourceUsage(): {
77 userCPUTime: number
78 systemCPUTime: number
79 maxRSS: number
80 sharedMemorySize: number
81 unsharedDataSize: number
82 unsharedStackSize: number
83 minorPageFault: number
84 majorPageFault: number
85 swappedOut: number
86 fsRead: number
87 fsWrite: number
88 ipcSent: number
89 ipcReceived: number
90 signalsCount: number
91 voluntaryContextSwitches: number
92 involuntaryContextSwitches: number
93}
94
95export function memoryUsage(): {
96 rss: number
97 heapTotal: number
98 heapUsed: number
99 external: number
100}
101
102export function freemem(): number
103
104export function totalmem(): number
105
106export function availableMemory(): number
107
108export function constrainedMemory(): number
109
110export function uptime(): number
111
112export function loadavg(): ArrayLike<number>
113
114export function cpus(): {
115 model: string
116 speed: number
117 times: {
118 user: number
119 nice: number
120 sys: number
121 idle: number
122 irq: number
123 }
124}[]
125
126export function getProcessTitle(): string
127
128export function setProcessTitle(title: unknown): void
129
130export function getPriority(pid?: number): number
131
132export function setPriority(priority: number): void
133export function setPriority(pid: number, priority: number): void
134
135export function getEnvKeys(): string[]
136
137export function getEnv(name: string): string | undefined
138
139export function hasEnv(name: string): boolean
140
141export function setEnv(name: string, value: string): void
142
143export function unsetEnv(name: string): void
node_modules/bare-os/index.js +129 -0
……@@ -0,0 +1,129 @@
1const binding = require('./binding')
2const errors = require('./lib/errors')
3const constants = require('./lib/constants')
4
5exports.constants = constants
6
7exports.EOL = binding.platform === 'win32' ? '\r\n' : '\n'
8
9exports.devNull = binding.platform === 'win32' ? '\\\\.\\nul' : '/dev/null'
10
11exports.platform = function platform() {
12 return binding.platform
13}
14
15exports.arch = function arch() {
16 return binding.arch
17}
18
19exports.type = binding.type
20exports.version = binding.version
21exports.release = binding.release
22exports.machine = binding.machine
23exports.execPath = binding.execPath
24exports.pid = binding.pid
25exports.ppid = binding.ppid
26exports.cwd = binding.cwd
27exports.chdir = binding.chdir
28exports.tmpdir = binding.tmpdir
29exports.homedir = binding.homedir
30exports.hostname = binding.hostname
31exports.userInfo = binding.userInfo
32
33exports.networkInterfaces = function networkInterfaces() {
34 const result = {}
35
36 for (const entry of binding.networkInterfaces()) {
37 const { name, ...properties } = entry
38
39 if (result[name]) result[name].push(properties)
40 else result[name] = [properties]
41 }
42
43 return result
44}
45
46exports.kill = function kill(pid, signal = constants.signals.SIGTERM) {
47 if (typeof signal === 'string') {
48 if (signal in constants.signals === false) {
49 throw errors.UNKNOWN_SIGNAL('Unknown signal: ' + signal)
50 }
51
52 signal = constants.signals[signal]
53 }
54
55 binding.kill(pid, signal)
56}
57
58exports.endianness = function endianness() {
59 return binding.isLittleEndian ? 'LE' : 'BE'
60}
61
62exports.availableParallelism = binding.availableParallelism
63
64exports.cpuUsage = function cpuUsage(previous) {
65 const current = binding.cpuUsage()
66
67 if (previous) {
68 return {
69 user: current.user - previous.user,
70 system: current.system - previous.system
71 }
72 }
73
74 return current
75}
76
77exports.threadCpuUsage = function threadCpuUsage(previous) {
78 const current = binding.threadCpuUsage()
79
80 if (previous) {
81 return {
82 user: current.user - previous.user,
83 system: current.system - previous.system
84 }
85 }
86
87 return current
88}
89
90exports.resourceUsage = binding.resourceUsage
91exports.memoryUsage = binding.memoryUsage
92exports.freemem = binding.freemem
93exports.totalmem = binding.totalmem
94exports.availableMemory = binding.availableMemory
95exports.constrainedMemory = binding.constrainedMemory
96exports.uptime = binding.uptime
97exports.loadavg = binding.loadavg
98exports.cpus = binding.cpus
99
100exports.getProcessTitle = binding.getProcessTitle
101
102exports.setProcessTitle = function setProcessTitle(title) {
103 if (typeof title !== 'string') title = title.toString()
104
105 if (title.length >= 256) {
106 throw errors.TITLE_OVERFLOW('Process title is too long')
107 }
108
109 binding.setProcessTitle(title)
110}
111
112exports.getPriority = function getPriority(pid = 0) {
113 return binding.getPriority(pid)
114}
115
116exports.setPriority = function setPriority(pid, priority) {
117 if (priority === undefined) {
118 priority = pid
119 pid = 0
120 }
121
122 binding.setPriority(pid, priority)
123}
124
125exports.getEnvKeys = binding.getEnvKeys
126exports.getEnv = binding.getEnv
127exports.hasEnv = binding.hasEnv
128exports.setEnv = binding.setEnv
129exports.unsetEnv = binding.unsetEnv
node_modules/bare-os/lib/constants.js +7 -0
……@@ -0,0 +1,7 @@
1const binding = require('../binding')
2
3module.exports = {
4 signals: binding.signals,
5 errnos: binding.errnos,
6 priority: binding.priority
7}
node_modules/bare-os/lib/errors.js +22 -0
……@@ -0,0 +1,22 @@
1module.exports = class OSError extends Error {
2 constructor(msg, code, fn = OSError) {
3 super(`${code}: ${msg}`)
4 this.code = code
5
6 if (Error.captureStackTrace) {
7 Error.captureStackTrace(this, fn)
8 }
9 }
10
11 get name() {
12 return 'OSError'
13 }
14
15 static UNKNOWN_SIGNAL(msg) {
16 return new OSError(msg, 'UNKNOWN_SIGNAL', OSError.UNKNOWN_SIGNAL)
17 }
18
19 static TITLE_OVERFLOW(msg) {
20 return new OSError(msg, 'TITLE_OVERFLOW', OSError.TITLE_OVERFLOW)
21 }
22}
node_modules/bare-os/package.json +46 -0
……@@ -0,0 +1,46 @@
1{
2 "name": "bare-os",
3 "version": "3.8.0",
4 "description": "Operating system utilities for Javascript",
5 "exports": {
6 ".": {
7 "types": "./index.d.ts",
8 "default": "./index.js"
9 },
10 "./package": "./package.json",
11 "./constants": "./lib/constants.js",
12 "./errors": "./lib/errors.js"
13 },
14 "files": [
15 "index.js",
16 "index.d.ts",
17 "binding.c",
18 "binding.js",
19 "CMakeLists.txt",
20 "lib",
21 "prebuilds"
22 ],
23 "addon": true,
24 "scripts": {
25 "test": "prettier . --check && bare test.js"
26 },
27 "repository": {
28 "type": "git",
29 "url": "git+https://github.com/holepunchto/bare-os.git"
30 },
31 "author": "Holepunch",
32 "license": "Apache-2.0",
33 "bugs": {
34 "url": "https://github.com/holepunchto/bare-os/issues"
35 },
36 "homepage": "https://github.com/holepunchto/bare-os#readme",
37 "engines": {
38 "bare": ">=1.14.0"
39 },
40 "devDependencies": {
41 "brittle": "^3.1.1",
42 "cmake-bare": "^1.1.6",
43 "prettier": "^3.4.2",
44 "prettier-config-holepunch": "^2.0.0"
45 }
46}
node_modules/bare-os/prebuilds/android-arm/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/android-arm64/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/android-ia32/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/android-x64/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/darwin-arm64/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/darwin-x64/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/ios-arm64-simulator/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/ios-arm64/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/ios-x64-simulator/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/linux-arm64/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/linux-x64/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/win32-arm64/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-os/prebuilds/win32-x64/bare-os.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-path/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-path/NOTICE +28 -0
……@@ -0,0 +1,28 @@
1Copyright 2023 Holepunch Inc
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14
15---
16
17Copyright Joyent, Inc. and other Node contributors.
18
19Permission is hereby granted, free of charge, to any person obtaining a
20copy of this software and associated documentation files (the
21"Software"), to deal in the Software without restriction, including
22without limitation the rights to use, copy, modify, merge, publish,
23distribute, sublicense, and/or sell copies of the Software, and to permit
24persons to whom the Software is furnished to do so, subject to the
25following conditions:
26
27The above copyright notice and this permission notice shall be included
28in all copies or substantial portions of the Software.
node_modules/bare-path/README.md +19 -0
……@@ -0,0 +1,19 @@
1# bare-path
2
3Path manipulation library for JavaScript.
4
5```
6npm i bare-path
7```
8
9## Usage
10
11``` js
12const path = require('bare-path')
13
14path.join('foo', 'bar') // foo/bar on posix, foo\bar on windows
15```
16
17## License
18
19Apache-2.0
node_modules/bare-path/index.js +11 -0
……@@ -0,0 +1,11 @@
1/* global Bare */
2
3// This export SHOULD NOT be shortened in any way as having the full
4// `module.exports = require(...)` statement is crucial for synthesizing
5// ESM exports.
6
7if (Bare.platform === 'win32') {
8 module.exports = require('./lib/win32')
9} else {
10 module.exports = require('./lib/posix')
11}
node_modules/bare-path/lib/constants.js +11 -0
……@@ -0,0 +1,11 @@
1module.exports = {
2 CHAR_UPPERCASE_A: 0x41,
3 CHAR_LOWERCASE_A: 0x61,
4 CHAR_UPPERCASE_Z: 0x5a,
5 CHAR_LOWERCASE_Z: 0x7a,
6 CHAR_DOT: 0x2e,
7 CHAR_FORWARD_SLASH: 0x2f,
8 CHAR_BACKWARD_SLASH: 0x5c,
9 CHAR_COLON: 0x3a,
10 CHAR_QUESTION_MARK: 0x3f
11}
node_modules/bare-path/lib/posix.js +242 -0
……@@ -0,0 +1,242 @@
1const os = require('bare-os')
2
3const { normalizeString } = require('./shared')
4const {
5 CHAR_DOT,
6 CHAR_FORWARD_SLASH
7} = require('./constants')
8
9function isPosixPathSeparator (code) {
10 return code === CHAR_FORWARD_SLASH
11}
12
13exports.win32 = require('./win32')
14exports.posix = exports
15
16exports.sep = '/'
17exports.delimiter = ':'
18
19exports.resolve = function resolve (...args) {
20 let resolvedPath = ''
21 let resolvedAbsolute = false
22
23 for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
24 const path = i >= 0 ? args[i] : os.cwd()
25
26 if (path.length === 0) {
27 continue
28 }
29
30 resolvedPath = `${path}/${resolvedPath}`
31 resolvedAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH
32 }
33
34 resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/', isPosixPathSeparator)
35
36 if (resolvedAbsolute) {
37 return `/${resolvedPath}`
38 }
39
40 return resolvedPath.length > 0 ? resolvedPath : '.'
41}
42
43exports.normalize = function normalize (path) {
44 if (path.length === 0) return '.'
45
46 const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH
47 const trailingSeparator = path.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH
48
49 path = normalizeString(path, !isAbsolute, '/', isPosixPathSeparator)
50
51 if (path.length === 0) {
52 if (isAbsolute) return '/'
53 return trailingSeparator ? './' : '.'
54 }
55
56 if (trailingSeparator) path += '/'
57
58 return isAbsolute ? `/${path}` : path
59}
60
61exports.isAbsolute = function isAbsolute (path) {
62 return path.length > 0 && path.charCodeAt(0) === CHAR_FORWARD_SLASH
63}
64
65exports.join = function join (...args) {
66 if (args.length === 0) return '.'
67 let joined
68 for (let i = 0; i < args.length; ++i) {
69 const arg = args[i]
70 if (arg.length > 0) {
71 if (joined === undefined) joined = arg
72 else joined += `/${arg}`
73 }
74 }
75 if (joined === undefined) return '.'
76 return exports.normalize(joined)
77}
78
79exports.relative = function relative (from, to) {
80 if (from === to) return ''
81
82 from = exports.resolve(from)
83 to = exports.resolve(to)
84
85 if (from === to) return ''
86
87 const fromStart = 1
88 const fromEnd = from.length
89 const fromLen = fromEnd - fromStart
90 const toStart = 1
91 const toLen = to.length - toStart
92
93 const length = (fromLen < toLen ? fromLen : toLen)
94 let lastCommonSep = -1
95 let i = 0
96 for (; i < length; i++) {
97 const fromCode = from.charCodeAt(fromStart + i)
98 if (fromCode !== to.charCodeAt(toStart + i)) {
99 break
100 } else if (fromCode === CHAR_FORWARD_SLASH) {
101 lastCommonSep = i
102 }
103 }
104 if (i === length) {
105 if (toLen > length) {
106 if (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) {
107 return to.substring(toStart + i + 1)
108 }
109 if (i === 0) {
110 return to.substring(toStart + i)
111 }
112 } else if (fromLen > length) {
113 if (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) {
114 lastCommonSep = i
115 } else if (i === 0) {
116 lastCommonSep = 0
117 }
118 }
119 }
120
121 let out = ''
122 for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
123 if (i === fromEnd || from.charCodeAt(i) === CHAR_FORWARD_SLASH) {
124 out += out.length === 0 ? '..' : '/..'
125 }
126 }
127
128 return `${out}${to.substring(toStart + lastCommonSep)}`
129}
130
131exports.toNamespacedPath = function toNamespacedPath (path) {
132 return path
133}
134
135exports.dirname = function dirname (path) {
136 if (path.length === 0) return '.'
137 const hasRoot = path.charCodeAt(0) === CHAR_FORWARD_SLASH
138 let end = -1
139 let matchedSlash = true
140 for (let i = path.length - 1; i >= 1; --i) {
141 if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) {
142 if (!matchedSlash) {
143 end = i
144 break
145 }
146 } else {
147 matchedSlash = false
148 }
149 }
150
151 if (end === -1) return hasRoot ? '/' : '.'
152 if (hasRoot && end === 1) return '//'
153 return path.substring(0, end)
154}
155
156exports.basename = function basename (path, suffix) {
157 let start = 0
158 let end = -1
159 let matchedSlash = true
160
161 if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) {
162 if (suffix === path) { return '' }
163 let extIdx = suffix.length - 1
164 let firstNonSlashEnd = -1
165 for (let i = path.length - 1; i >= 0; --i) {
166 const code = path.charCodeAt(i)
167 if (code === CHAR_FORWARD_SLASH) {
168 if (!matchedSlash) {
169 start = i + 1
170 break
171 }
172 } else {
173 if (firstNonSlashEnd === -1) {
174 matchedSlash = false
175 firstNonSlashEnd = i + 1
176 }
177 if (extIdx >= 0) {
178 if (code === suffix.charCodeAt(extIdx)) {
179 if (--extIdx === -1) {
180 end = i
181 }
182 } else {
183 extIdx = -1
184 end = firstNonSlashEnd
185 }
186 }
187 }
188 }
189
190 if (start === end) end = firstNonSlashEnd
191 else if (end === -1) end = path.length
192 return path.substring(start, end)
193 }
194
195 for (let i = path.length - 1; i >= 0; --i) {
196 if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) {
197 if (!matchedSlash) {
198 start = i + 1
199 break
200 }
201 } else if (end === -1) {
202 matchedSlash = false
203 end = i + 1
204 }
205 }
206
207 if (end === -1) return ''
208 return path.substring(start, end)
209}
210
211exports.extname = function extname (path) {
212 let startDot = -1
213 let startPart = 0
214 let end = -1
215 let matchedSlash = true
216 let preDotState = 0
217 for (let i = path.length - 1; i >= 0; --i) {
218 const code = path.charCodeAt(i)
219 if (code === CHAR_FORWARD_SLASH) {
220 if (!matchedSlash) {
221 startPart = i + 1
222 break
223 }
224 continue
225 }
226 if (end === -1) {
227 matchedSlash = false
228 end = i + 1
229 }
230 if (code === CHAR_DOT) {
231 if (startDot === -1) startDot = i
232 else if (preDotState !== 1) preDotState = 1
233 } else if (startDot !== -1) {
234 preDotState = -1
235 }
236 }
237
238 if (startDot === -1 || end === -1 || preDotState === 0 || (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) {
239 return ''
240 }
241 return path.substring(startDot, end)
242}
node_modules/bare-path/lib/shared.js +67 -0
……@@ -0,0 +1,67 @@
1const {
2 CHAR_DOT,
3 CHAR_FORWARD_SLASH
4} = require('./constants')
5
6exports.normalizeString = function normalizeString (path, allowAboveRoot, separator, isPathSeparator) {
7 let res = ''
8 let lastSegmentLength = 0
9 let lastSlash = -1
10 let dots = 0
11 let code = 0
12 for (let i = 0; i <= path.length; ++i) {
13 if (i < path.length) {
14 code = path.charCodeAt(i)
15 } else if (isPathSeparator(code)) {
16 break
17 } else {
18 code = CHAR_FORWARD_SLASH
19 }
20
21 if (isPathSeparator(code)) {
22 if (lastSlash === i - 1 || dots === 1) ;
23 else if (dots === 2) {
24 if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== CHAR_DOT || res.charCodeAt(res.length - 2) !== CHAR_DOT) {
25 if (res.length > 2) {
26 const lastSlashIndex = res.lastIndexOf(separator)
27 if (lastSlashIndex === -1) {
28 res = ''
29 lastSegmentLength = 0
30 } else {
31 res = res.substring(0, lastSlashIndex)
32 lastSegmentLength =
33 res.length - 1 - res.lastIndexOf(separator)
34 }
35 lastSlash = i
36 dots = 0
37 continue
38 } else if (res.length !== 0) {
39 res = ''
40 lastSegmentLength = 0
41 lastSlash = i
42 dots = 0
43 continue
44 }
45 }
46 if (allowAboveRoot) {
47 res += res.length > 0 ? `${separator}..` : '..'
48 lastSegmentLength = 2
49 }
50 } else {
51 if (res.length > 0) {
52 res += `${separator}${path.substring(lastSlash + 1, i)}`
53 } else {
54 res = path.substring(lastSlash + 1, i)
55 }
56 lastSegmentLength = i - lastSlash - 1
57 }
58 lastSlash = i
59 dots = 0
60 } else if (code === CHAR_DOT && dots !== -1) {
61 ++dots
62 } else {
63 dots = -1
64 }
65 }
66 return res
67}
node_modules/bare-path/lib/win32.js +513 -0
……@@ -0,0 +1,513 @@
1const os = require('bare-os')
2
3const { normalizeString } = require('./shared')
4const {
5 CHAR_UPPERCASE_A,
6 CHAR_LOWERCASE_A,
7 CHAR_UPPERCASE_Z,
8 CHAR_LOWERCASE_Z,
9 CHAR_DOT,
10 CHAR_FORWARD_SLASH,
11 CHAR_BACKWARD_SLASH,
12 CHAR_COLON,
13 CHAR_QUESTION_MARK
14} = require('./constants')
15
16function isWindowsPathSeparator (code) {
17 return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH
18}
19
20function isWindowsDeviceRoot (code) {
21 return (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) ||
22 (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)
23}
24
25exports.posix = require('./posix')
26exports.win32 = exports
27
28exports.sep = '\\'
29exports.delimiter = ';'
30
31exports.resolve = function resolve (...args) {
32 let resolvedDevice = ''
33 let resolvedTail = ''
34 let resolvedAbsolute = false
35
36 for (let i = args.length - 1; i >= -1; i--) {
37 let path
38 if (i >= 0) {
39 path = args[i]
40
41 if (path.length === 0) continue
42 } else if (resolvedDevice.length === 0) {
43 path = os.cwd()
44 } else {
45 path = os.getEnv(`=${resolvedDevice}`) || os.cwd()
46
47 if (path === undefined || (path.substring(0, 2).toLowerCase() !== resolvedDevice.toLowerCase() && path.charCodeAt(2) === CHAR_BACKWARD_SLASH)) {
48 path = `${resolvedDevice}\\`
49 }
50 }
51
52 const len = path.length
53 let rootEnd = 0
54 let device = ''
55 let isAbsolute = false
56 const code = path.charCodeAt(0)
57
58 if (len === 1) {
59 if (isWindowsPathSeparator(code)) {
60 rootEnd = 1
61 isAbsolute = true
62 }
63 } else if (isWindowsPathSeparator(code)) {
64 isAbsolute = true
65
66 if (isWindowsPathSeparator(path.charCodeAt(1))) {
67 let j = 2
68 let last = j
69 while (j < len && !isWindowsPathSeparator(path.charCodeAt(j))) {
70 j++
71 }
72 if (j < len && j !== last) {
73 const firstPart = path.substring(last, j)
74 last = j
75 while (j < len && isWindowsPathSeparator(path.charCodeAt(j))) {
76 j++
77 }
78 if (j < len && j !== last) {
79 last = j
80 while (j < len && !isWindowsPathSeparator(path.charCodeAt(j))) {
81 j++
82 }
83 if (j === len || j !== last) {
84 device = `\\\\${firstPart}\\${path.substring(last, j)}`
85 rootEnd = j
86 }
87 }
88 }
89 } else {
90 rootEnd = 1
91 }
92 } else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {
93 device = path.substring(0, 2)
94 rootEnd = 2
95 if (len > 2 && isWindowsPathSeparator(path.charCodeAt(2))) {
96 isAbsolute = true
97 rootEnd = 3
98 }
99 }
100
101 if (device.length > 0) {
102 if (resolvedDevice.length > 0) {
103 if (device.toLowerCase() !== resolvedDevice.toLowerCase()) { continue }
104 } else {
105 resolvedDevice = device
106 }
107 }
108
109 if (resolvedAbsolute) {
110 if (resolvedDevice.length > 0) { break }
111 } else {
112 resolvedTail = `${path.substring(rootEnd)}\\${resolvedTail}`
113 resolvedAbsolute = isAbsolute
114 if (isAbsolute && resolvedDevice.length > 0) {
115 break
116 }
117 }
118 }
119
120 resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\', isWindowsPathSeparator)
121
122 return resolvedAbsolute ? `${resolvedDevice}\\${resolvedTail}` : `${resolvedDevice}${resolvedTail}` || '.'
123}
124
125exports.normalize = function normalize (path) {
126 const len = path.length
127 if (len === 0) return '.'
128 let rootEnd = 0
129 let device
130 let isAbsolute = false
131 const code = path.charCodeAt(0)
132
133 if (len === 1) {
134 return code === CHAR_FORWARD_SLASH ? '\\' : path
135 }
136
137 if (isWindowsPathSeparator(code)) {
138 isAbsolute = true
139
140 if (isWindowsPathSeparator(path.charCodeAt(1))) {
141 let j = 2
142 let last = j
143 while (j < len && !isWindowsPathSeparator(path.charCodeAt(j))) {
144 j++
145 }
146 if (j < len && j !== last) {
147 const firstPart = path.substring(last, j)
148 last = j
149 while (j < len && isWindowsPathSeparator(path.charCodeAt(j))) {
150 j++
151 }
152 if (j < len && j !== last) {
153 last = j
154 while (j < len && !isWindowsPathSeparator(path.charCodeAt(j))) {
155 j++
156 }
157 if (j === len) {
158 return `\\\\${firstPart}\\${path.substring(last)}\\`
159 }
160 if (j !== last) {
161 device = `\\\\${firstPart}\\${path.substring(last, j)}`
162 rootEnd = j
163 }
164 }
165 }
166 } else {
167 rootEnd = 1
168 }
169 } else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {
170 device = path.substring(0, 2)
171 rootEnd = 2
172 if (len > 2 && isWindowsPathSeparator(path.charCodeAt(2))) {
173 isAbsolute = true
174 rootEnd = 3
175 }
176 }
177
178 let tail = rootEnd < len ? normalizeString(path.substring(rootEnd), !isAbsolute, '\\', isWindowsPathSeparator) : ''
179 if (tail.length === 0 && !isAbsolute) {
180 tail = '.'
181 }
182 if (tail.length > 0 && isWindowsPathSeparator(path.charCodeAt(len - 1))) {
183 tail += '\\'
184 }
185 if (device === undefined) {
186 return isAbsolute ? `\\${tail}` : tail
187 }
188 return isAbsolute ? `${device}\\${tail}` : `${device}${tail}`
189}
190
191exports.isAbsolute = function isAbsolute (path) {
192 const len = path.length
193 if (len === 0) return false
194
195 const code = path.charCodeAt(0)
196
197 return isWindowsPathSeparator(code) || (len > 2 && isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON && isWindowsPathSeparator(path.charCodeAt(2)))
198}
199
200exports.join = function join (...args) {
201 if (args.length === 0) return '.'
202
203 let joined
204 let firstPart
205 for (let i = 0; i < args.length; ++i) {
206 const arg = args[i]
207 if (arg.length > 0) {
208 if (joined === undefined) joined = firstPart = arg
209 else joined += `\\${arg}`
210 }
211 }
212
213 if (joined === undefined) return '.'
214
215 let needsReplace = true
216 let slashCount = 0
217 if (isWindowsPathSeparator(firstPart.charCodeAt(0))) {
218 ++slashCount
219 const firstLen = firstPart.length
220 if (firstLen > 1 && isWindowsPathSeparator(firstPart.charCodeAt(1))) {
221 ++slashCount
222 if (firstLen > 2) {
223 if (isWindowsPathSeparator(firstPart.charCodeAt(2))) {
224 ++slashCount
225 } else {
226 needsReplace = false
227 }
228 }
229 }
230 }
231 if (needsReplace) {
232 while (slashCount < joined.length && isWindowsPathSeparator(joined.charCodeAt(slashCount))) {
233 slashCount++
234 }
235
236 if (slashCount >= 2) {
237 joined = `\\${joined.substring(slashCount)}`
238 }
239 }
240
241 return exports.normalize(joined)
242}
243
244exports.relative = function relative (from, to) {
245 if (from === to) return ''
246
247 const fromOrig = exports.resolve(from)
248 const toOrig = exports.resolve(to)
249
250 if (fromOrig === toOrig) return ''
251
252 from = fromOrig.toLowerCase()
253 to = toOrig.toLowerCase()
254
255 if (from === to) return ''
256
257 let fromStart = 0
258 while (fromStart < from.length && from.charCodeAt(fromStart) === CHAR_BACKWARD_SLASH) {
259 fromStart++
260 }
261 let fromEnd = from.length
262 while (fromEnd - 1 > fromStart && from.charCodeAt(fromEnd - 1) === CHAR_BACKWARD_SLASH) {
263 fromEnd--
264 }
265 const fromLen = fromEnd - fromStart
266
267 let toStart = 0
268 while (toStart < to.length && to.charCodeAt(toStart) === CHAR_BACKWARD_SLASH) {
269 toStart++
270 }
271 let toEnd = to.length
272 while (toEnd - 1 > toStart && to.charCodeAt(toEnd - 1) === CHAR_BACKWARD_SLASH) {
273 toEnd--
274 }
275 const toLen = toEnd - toStart
276
277 const length = fromLen < toLen ? fromLen : toLen
278 let lastCommonSep = -1
279 let i = 0
280 for (; i < length; i++) {
281 const fromCode = from.charCodeAt(fromStart + i)
282 if (fromCode !== to.charCodeAt(toStart + i)) {
283 break
284 } else if (fromCode === CHAR_BACKWARD_SLASH) {
285 lastCommonSep = i
286 }
287 }
288
289 if (i !== length) {
290 if (lastCommonSep === -1) return toOrig
291 } else {
292 if (toLen > length) {
293 if (to.charCodeAt(toStart + i) === CHAR_BACKWARD_SLASH) {
294 return toOrig.substring(toStart + i + 1)
295 }
296 if (i === 2) {
297 return toOrig.substring(toStart + i)
298 }
299 }
300 if (fromLen > length) {
301 if (from.charCodeAt(fromStart + i) === CHAR_BACKWARD_SLASH) {
302 lastCommonSep = i
303 } else if (i === 2) {
304 lastCommonSep = 3
305 }
306 }
307 if (lastCommonSep === -1) lastCommonSep = 0
308 }
309
310 let out = ''
311 for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
312 if (i === fromEnd || from.charCodeAt(i) === CHAR_BACKWARD_SLASH) {
313 out += out.length === 0 ? '..' : '\\..'
314 }
315 }
316
317 toStart += lastCommonSep
318
319 if (out.length > 0) {
320 return `${out}${toOrig.substring(toStart, toEnd)}`
321 }
322 if (toOrig.charCodeAt(toStart) === CHAR_BACKWARD_SLASH) {
323 ++toStart
324 }
325 return toOrig.substring(toStart, toEnd)
326}
327
328exports.toNamespacedPath = function toNamespacedPath (path) {
329 if (path.length === 0) return path
330
331 const resolvedPath = exports.resolve(path)
332
333 if (resolvedPath.length <= 2) return path
334
335 if (resolvedPath.charCodeAt(0) === CHAR_BACKWARD_SLASH) {
336 if (resolvedPath.charCodeAt(1) === CHAR_BACKWARD_SLASH) {
337 const code = resolvedPath.charCodeAt(2)
338 if (code !== CHAR_QUESTION_MARK && code !== CHAR_DOT) {
339 return `\\\\?\\UNC\\${resolvedPath.substring(2)}`
340 }
341 }
342 } else if (
343 isWindowsDeviceRoot(resolvedPath.charCodeAt(0)) &&
344 resolvedPath.charCodeAt(1) === CHAR_COLON &&
345 resolvedPath.charCodeAt(2) === CHAR_BACKWARD_SLASH
346 ) {
347 return `\\\\?\\${resolvedPath}`
348 }
349
350 return path
351}
352
353exports.dirname = function dirname (path) {
354 const len = path.length
355 if (len === 0) return '.'
356 let rootEnd = -1
357 let offset = 0
358 const code = path.charCodeAt(0)
359
360 if (len === 1) {
361 return isWindowsPathSeparator(code) ? path : '.'
362 }
363
364 if (isWindowsPathSeparator(code)) {
365 rootEnd = offset = 1
366
367 if (isWindowsPathSeparator(path.charCodeAt(1))) {
368 let j = 2
369 let last = j
370 while (j < len && !isWindowsPathSeparator(path.charCodeAt(j))) {
371 j++
372 }
373 if (j < len && j !== last) {
374 last = j
375 while (j < len && isWindowsPathSeparator(path.charCodeAt(j))) {
376 j++
377 }
378 if (j < len && j !== last) {
379 last = j
380 while (j < len && !isWindowsPathSeparator(path.charCodeAt(j))) {
381 j++
382 }
383 if (j === len) {
384 return path
385 }
386 if (j !== last) {
387 rootEnd = offset = j + 1
388 }
389 }
390 }
391 }
392 } else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {
393 rootEnd = len > 2 && isWindowsPathSeparator(path.charCodeAt(2)) ? 3 : 2
394 offset = rootEnd
395 }
396
397 let end = -1
398 let matchedSlash = true
399 for (let i = len - 1; i >= offset; --i) {
400 if (isWindowsPathSeparator(path.charCodeAt(i))) {
401 if (!matchedSlash) {
402 end = i
403 break
404 }
405 } else {
406 matchedSlash = false
407 }
408 }
409
410 if (end === -1) {
411 if (rootEnd === -1) return '.'
412
413 end = rootEnd
414 }
415 return path.substring(0, end)
416}
417
418exports.basename = function basename (path, suffix) {
419 let start = 0
420 let end = -1
421 let matchedSlash = true
422
423 if (path.length >= 2 && isWindowsDeviceRoot(path.charCodeAt(0)) && path.charCodeAt(1) === CHAR_COLON) {
424 start = 2
425 }
426
427 if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) {
428 if (suffix === path) return ''
429 let extIdx = suffix.length - 1
430 let firstNonSlashEnd = -1
431 for (let i = path.length - 1; i >= start; --i) {
432 const code = path.charCodeAt(i)
433 if (isWindowsPathSeparator(code)) {
434 if (!matchedSlash) {
435 start = i + 1
436 break
437 }
438 } else {
439 if (firstNonSlashEnd === -1) {
440 matchedSlash = false
441 firstNonSlashEnd = i + 1
442 }
443 if (extIdx >= 0) {
444 if (code === suffix.charCodeAt(extIdx)) {
445 if (--extIdx === -1) {
446 end = i
447 }
448 } else {
449 extIdx = -1
450 end = firstNonSlashEnd
451 }
452 }
453 }
454 }
455
456 if (start === end) end = firstNonSlashEnd
457 else if (end === -1) end = path.length
458 return path.substring(start, end)
459 }
460 for (let i = path.length - 1; i >= start; --i) {
461 if (isWindowsPathSeparator(path.charCodeAt(i))) {
462 if (!matchedSlash) {
463 start = i + 1
464 break
465 }
466 } else if (end === -1) {
467 matchedSlash = false
468 end = i + 1
469 }
470 }
471
472 if (end === -1) return ''
473 return path.substring(start, end)
474}
475
476exports.extname = function extname (path) {
477 let start = 0
478 let startDot = -1
479 let startPart = 0
480 let end = -1
481 let matchedSlash = true
482 let preDotState = 0
483
484 if (path.length >= 2 && path.charCodeAt(1) === CHAR_COLON && isWindowsDeviceRoot(path.charCodeAt(0))) {
485 start = startPart = 2
486 }
487
488 for (let i = path.length - 1; i >= start; --i) {
489 const code = path.charCodeAt(i)
490 if (isWindowsPathSeparator(code)) {
491 if (!matchedSlash) {
492 startPart = i + 1
493 break
494 }
495 continue
496 }
497 if (end === -1) {
498 matchedSlash = false
499 end = i + 1
500 }
501 if (code === CHAR_DOT) {
502 if (startDot === -1) startDot = i
503 else if (preDotState !== 1) preDotState = 1
504 } else if (startDot !== -1) {
505 preDotState = -1
506 }
507 }
508
509 if (startDot === -1 || end === -1 || preDotState === 0 || (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) {
510 return ''
511 }
512 return path.substring(startDot, end)
513}
node_modules/bare-path/package.json +36 -0
……@@ -0,0 +1,36 @@
1{
2 "name": "bare-path",
3 "version": "3.0.0",
4 "description": "Path manipulation library for JavaScript",
5 "exports": {
6 ".": "./index.js",
7 "./package": "./package.json",
8 "./posix": "./lib/posix.js",
9 "./win32": "./lib/win32.js"
10 },
11 "files": [
12 "index.js",
13 "lib",
14 "NOTICE"
15 ],
16 "scripts": {
17 "test": "standard && bare test.js"
18 },
19 "repository": {
20 "type": "git",
21 "url": "git+https://github.com/holepunchto/bare-path.git"
22 },
23 "author": "Holepunch",
24 "license": "Apache-2.0",
25 "bugs": {
26 "url": "https://github.com/holepunchto/bare-path/issues"
27 },
28 "homepage": "https://github.com/holepunchto/bare-path#readme",
29 "dependencies": {
30 "bare-os": "^3.0.1"
31 },
32 "devDependencies": {
33 "brittle": "^3.3.2",
34 "standard": "^17.0.0"
35 }
36}
node_modules/bare-semver/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-semver/README.md +19 -0
……@@ -0,0 +1,19 @@
1# bare-semver
2
3Minimal semantic versioning library for Bare.
4
5```
6npm i bare-semver
7```
8
9## Usage
10
11```js
12const { Version } = require('bare-semver')
13
14Version.parse('1.2.3')
15```
16
17## License
18
19Apache-2.0
node_modules/bare-semver/index.d.ts +61 -0
……@@ -0,0 +1,61 @@
1export const constants: { EQ: 1; LT: 2; LTE: 3; GT: 4; GTE: 5 }
2
3declare class SemVerError extends Error {
4 static INVALID_VERSION(msg: string, fn?: Function): SemVerError
5
6 static INVALID_RANGE(msg: string, fn?: Function): SemVerError
7}
8
9export { SemVerError as errors }
10
11export function satisfies(version: Version, range: Range): boolean
12
13export class Version {
14 constructor(
15 major: number,
16 minor: number,
17 patch: number,
18 opts?: { prerelease?: string[]; build?: string[] }
19 )
20
21 major: number
22 minor: number
23 patch: number
24 prerealease: string[]
25 build: string[]
26
27 compare(version: Version): boolean
28
29 toString(): string
30}
31
32export namespace Version {
33 export function parse(input: string): Version
34
35 export function compare(a: Version, b: Version): number
36}
37
38export class Comparator {
39 constructor(operator: number, version: Version)
40
41 operator: number
42 version: Version
43
44 test(version: Version): boolean
45
46 toString(): string
47}
48
49export class Range {
50 constructor(comparators?: Comparator[][])
51
52 comparators: Comparator[][]
53
54 test(version: Version): boolean
55
56 toString(): string
57}
58
59export namespace Range {
60 export function parse(input: string): Range
61}
node_modules/bare-semver/index.js +13 -0
……@@ -0,0 +1,13 @@
1exports.constants = require('./lib/constants')
2exports.errors = require('./lib/errors')
3
4const Version = (exports.Version = require('./lib/version'))
5const Range = (exports.Range = require('./lib/range'))
6exports.Comparator = require('./lib/comparator')
7
8exports.satisfies = function satisfies(version, range) {
9 if (typeof version === 'string') version = Version.parse(version)
10 if (typeof range === 'string') range = Range.parse(range)
11
12 return range.test(version)
13}
node_modules/bare-semver/lib/comparator.js +37 -0
……@@ -0,0 +1,37 @@
1const constants = require('./constants')
2
3const symbols = {
4 [constants.EQ]: '=',
5 [constants.LT]: '<',
6 [constants.LTE]: '<=',
7 [constants.GT]: '>',
8 [constants.GTE]: '>='
9}
10
11module.exports = class Comparator {
12 constructor(operator, version) {
13 this.operator = operator
14 this.version = version
15 }
16
17 test(version) {
18 const result = version.compare(this.version)
19
20 switch (this.operator) {
21 case constants.LT:
22 return result < 0
23 case constants.LTE:
24 return result <= 0
25 case constants.GT:
26 return result > 0
27 case constants.GTE:
28 return result >= 0
29 default:
30 return result === 0
31 }
32 }
33
34 toString() {
35 return symbols[this.operator] + this.version
36 }
37}
node_modules/bare-semver/lib/constants.js +7 -0
……@@ -0,0 +1,7 @@
1module.exports = {
2 EQ: 1,
3 LT: 2,
4 LTE: 3,
5 GT: 4,
6 GTE: 5
7}
node_modules/bare-semver/lib/errors.js +22 -0
……@@ -0,0 +1,22 @@
1module.exports = class SemVerError extends Error {
2 constructor(msg, code, fn = SemVerError) {
3 super(`${code}: ${msg}`)
4 this.code = code
5
6 if (Error.captureStackTrace) {
7 Error.captureStackTrace(this, fn)
8 }
9 }
10
11 get name() {
12 return 'SemVerError'
13 }
14
15 static INVALID_VERSION(msg, fn = SemVerError.INVALID_VERSION) {
16 return new SemVerError(msg, 'INVALID_VERSION', fn)
17 }
18
19 static INVALID_RANGE(msg, fn = SemVerError.INVALID_RANGE) {
20 return new SemVerError(msg, 'INVALID_RANGE', fn)
21 }
22}
node_modules/bare-semver/lib/range.js +121 -0
……@@ -0,0 +1,121 @@
1const constants = require('./constants')
2const errors = require('./errors')
3const Version = require('./version')
4const Comparator = require('./comparator')
5
6class Range {
7 constructor(comparators = []) {
8 this.comparators = comparators
9 }
10
11 test(version) {
12 for (const set of this.comparators) {
13 let matches = true
14
15 for (const comparator of set) {
16 if (comparator.test(version)) continue
17 matches = false
18 break
19 }
20
21 if (matches) return true
22 }
23
24 return false
25 }
26
27 toString() {
28 let result = ''
29 let first = true
30
31 for (const set of this.comparators) {
32 if (first) first = false
33 else result += ' || '
34
35 result += set.join(' ')
36 }
37
38 return result
39 }
40}
41
42module.exports = exports = Range
43
44exports.parse = function parse(input, state = { position: 0, partial: false }) {
45 let i = state.position
46 let c
47
48 const unexpected = (expected) => {
49 let msg
50
51 if (i >= input.length) {
52 msg = `Unexpected end of input in '${input}'`
53 } else {
54 msg = `Unexpected token '${input[i]}' in '${input}' at position ${i}`
55 }
56
57 if (expected) msg += `, ${expected}`
58
59 throw errors.INVALID_VERSION(msg, unexpected)
60 }
61
62 const comparators = []
63
64 while (i < input.length) {
65 const set = []
66
67 while (i < input.length) {
68 c = input[i]
69
70 let operator = constants.EQ
71
72 if (c === '<') {
73 operator = constants.LT
74 c = input[++i]
75
76 if (c === '=') {
77 operator = constants.LTE
78 c = input[++i]
79 }
80 } else if (c === '>') {
81 operator = constants.GT
82 c = input[++i]
83
84 if (c === '=') {
85 operator = constants.GTE
86 c = input[++i]
87 }
88 } else if (c === '=') {
89 c = input[++i]
90 }
91
92 const state = { position: i, partial: true, range: true }
93
94 set.push(new Comparator(operator, Version.parse(input, state)))
95
96 c = input[(i = state.position)]
97
98 while (c === ' ') c = input[++i]
99
100 if (c === '|' && input[i + 1] === '|') {
101 c = input[(i += 2)]
102
103 while (c === ' ') c = input[++i]
104
105 break
106 }
107
108 if (c && c !== '<' && c !== '>') unexpected("expected '||', '<', or '>'")
109 }
110
111 if (set.length) comparators.push(set)
112 }
113
114 if (i < input.length && state.partial === false) {
115 unexpected('expected end of input')
116 }
117
118 state.position = i
119
120 return new Range(comparators)
121}
node_modules/bare-semver/lib/version.js +208 -0
……@@ -0,0 +1,208 @@
1const errors = require('./errors')
2
3class Version {
4 constructor(major, minor, patch, opts = {}) {
5 const { prerelease = [], build = [] } = opts
6
7 this.major = major
8 this.minor = minor
9 this.patch = patch
10 this.prerelease = prerelease
11 this.build = build
12 }
13
14 compare(version) {
15 return exports.compare(this, version)
16 }
17
18 toString() {
19 let result = `${this.major}.${this.minor}.${this.patch}`
20
21 if (this.prerelease.length) {
22 result += '-' + this.prerelease.join('.')
23 }
24
25 if (this.build.length) {
26 result += '+' + this.build.join('.')
27 }
28
29 return result
30 }
31}
32
33module.exports = exports = Version
34
35exports.parse = function parse(
36 input,
37 state = { position: 0, partial: false, range: false }
38) {
39 let i = state.position
40 let c
41
42 const unexpected = (expected) => {
43 let msg
44
45 if (i >= input.length) {
46 msg = `Unexpected end of input in '${input}'`
47 } else {
48 msg = `Unexpected token '${input[i]}' in '${input}' at position ${i}`
49 }
50
51 if (expected) msg += `, ${expected}`
52
53 throw errors.INVALID_VERSION(msg, unexpected)
54 }
55
56 const components = [0, 0, 0]
57
58 let k = 0
59
60 while (k < 3) {
61 c = input[i]
62
63 if (k > 0) {
64 if (c === '.') c = input[++i]
65 else if (state.range) break
66 else unexpected("expected '.'")
67 }
68
69 if (c === '0') {
70 i++
71 k++
72 } else if (c >= '1' && c <= '9') {
73 let j = 0
74 do c = input[i + ++j]
75 while (c >= '0' && c <= '9')
76
77 components[k++] = parseInt(input.substring(i, i + j))
78
79 i += j
80 } else unexpected('expected /[0-9]/')
81 }
82
83 const prerelease = []
84
85 if (k === 3 && input[i] === '-') {
86 i++
87
88 while (true) {
89 c = input[i]
90
91 let tag = ''
92 let j = 0
93
94 while (c >= '0' && c <= '9') c = input[i + ++j]
95
96 let isNumeric = false
97
98 if (j) {
99 tag += input.substring(i, i + j)
100
101 c = input[(i += j)]
102
103 isNumeric = tag[0] !== '0' || tag.length === 1
104 }
105
106 j = 0
107
108 while (
109 (c >= '0' && c <= '9') ||
110 (c >= 'a' && c <= 'z') ||
111 (c >= 'A' && c <= 'Z') ||
112 c === '-'
113 )
114 c = input[i + ++j]
115
116 if (j) {
117 tag += input.substring(i, i + j)
118
119 c = input[(i += j)]
120 } else if (!isNumeric) unexpected('expected /[a-zA-Z-]/')
121
122 prerelease.push(tag)
123
124 if (c === '.') c = input[++i]
125 else break
126 }
127 }
128
129 const build = []
130
131 if (k === 3 && input[i] === '+') {
132 i++
133
134 while (true) {
135 c = input[i]
136
137 let tag = ''
138 let j = 0
139
140 while (
141 (c >= '0' && c <= '9') ||
142 (c >= 'a' && c <= 'z') ||
143 (c >= 'A' && c <= 'Z') ||
144 c === '-'
145 )
146 c = input[i + ++j]
147
148 if (j) {
149 tag += input.substring(i, i + j)
150
151 c = input[(i += j)]
152 } else unexpected('expected /[0-9a-zA-Z-]/')
153
154 build.push(tag)
155
156 if (c === '.') c = input[++i]
157 else break
158 }
159 }
160
161 if (i < input.length && state.partial === false) {
162 unexpected('expected end of input')
163 }
164
165 state.position = i
166
167 return new Version(...components, { prerelease, build })
168}
169
170const integer = /^[0-9]+$/
171
172exports.compare = function compare(a, b) {
173 if (a.major > b.major) return 1
174 if (a.major < b.major) return -1
175
176 if (a.minor > b.minor) return 1
177 if (a.minor < b.minor) return -1
178
179 if (a.patch > b.patch) return 1
180 if (a.patch < b.patch) return -1
181
182 if (a.prerelease.length === 0) return b.prerelease.length === 0 ? 0 : 1
183 if (b.prerelease.length === 0) return -1
184
185 let i = 0
186 do {
187 let x = a.prerelease[i]
188 let y = b.prerelease[i]
189
190 if (x === undefined) return y === undefined ? 0 : -1
191 if (y === undefined) return 1
192
193 if (x === y) continue
194
195 const xInt = integer.test(x)
196 const yInt = integer.test(y)
197
198 if (xInt && yInt) {
199 x = +x
200 y = +y
201 } else {
202 if (xInt) return -1
203 if (yInt) return 1
204 }
205
206 return x > y ? 1 : -1
207 } while (++i)
208}
node_modules/bare-semver/package.json +40 -0
……@@ -0,0 +1,40 @@
1{
2 "name": "bare-semver",
3 "version": "1.0.2",
4 "description": "Minimal semantic versioning library for Bare",
5 "exports": {
6 ".": {
7 "types": "./index.d.ts",
8 "default": "./index.js"
9 },
10 "./package": "./package.json",
11 "./constants": "./lib/constants.js",
12 "./errors": "./lib/errors.js",
13 "./version": "./lib/version.js",
14 "./range": "./lib/range.js",
15 "./comparator": "./lib/comparator.js"
16 },
17 "files": [
18 "index.js",
19 "index.d.ts",
20 "lib"
21 ],
22 "scripts": {
23 "test": "prettier . --check && bare test.js"
24 },
25 "repository": {
26 "type": "git",
27 "url": "git+https://github.com/holepunchto/bare-semver.git"
28 },
29 "author": "Holepunch",
30 "license": "Apache-2.0",
31 "bugs": {
32 "url": "https://github.com/holepunchto/bare-semver/issues"
33 },
34 "homepage": "https://github.com/holepunchto/bare-semver#readme",
35 "devDependencies": {
36 "brittle": "^3.2.1",
37 "prettier": "^3.4.2",
38 "prettier-config-standard": "^7.0.0"
39 }
40}
node_modules/bare-stream/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-stream/README.md +15 -0
……@@ -0,0 +1,15 @@
1# bare-stream
2
3Streaming data for JavaScript.
4
5```
6npm i bare-stream
7```
8
9## API
10
11See <https://github.com/mafintosh/streamx>.
12
13## License
14
15Apache-2.0
node_modules/bare-stream/global.js +12 -0
……@@ -0,0 +1,12 @@
1const stream = require('./web')
2
3global.ReadableStream = stream.ReadableStream
4global.ReadableStreamDefaultController = stream.ReadableStreamDefaultController
5global.ReadableStreamDefaultReader = stream.ReadableStreamDefaultReader
6
7global.CountQueuingStrategy = stream.CountQueuingStrategy
8global.ByteLengthQueuingStrategy = stream.ByteLengthQueuingStrategy
9
10global.WritableStream = stream.WritableStream
11global.WritableStreamDefaultController = stream.WritableStreamDefaultController
12global.WritableStreamDefaultReader = stream.WritableStreamDefaultReader
node_modules/bare-stream/index.d.ts +188 -0
……@@ -0,0 +1,188 @@
1import EventEmitter, { EventMap } from 'bare-events'
2import Buffer, { BufferEncoding } from 'bare-buffer'
3
4type StreamEncoding = BufferEncoding | 'buffer'
5
6interface StreamCallback {
7 (err: Error | null): void
8}
9
10interface StreamEvents extends EventMap {
11 close: []
12 error: [err: Error]
13}
14
15interface StreamOptions<S extends Stream = Stream> {
16 eagerOpen?: boolean
17 signal?: AbortSignal
18 open?(this: S, cb: StreamCallback): void
19 predestroy?(this: S): void
20 destroy?(this: S, err: Error | null, cb: StreamCallback): void
21}
22
23interface Stream<M extends StreamEvents = StreamEvents> extends EventEmitter<M> {
24 _open(cb: StreamCallback): void
25 _predestroy(): void
26 _destroy(err: Error | null, cb: StreamCallback): void
27
28 readonly readable: boolean
29 readonly writable: boolean
30 readonly destroyed: boolean
31 readonly destroying: boolean
32
33 destroy(err?: Error | null): void
34}
35
36declare class Stream {}
37
38interface ReadableEvents extends StreamEvents {
39 data: [data: unknown]
40 end: []
41 readable: []
42 piping: [dest: Writable]
43}
44
45interface ReadableOptions<S extends Readable = Readable> extends StreamOptions<S> {
46 encoding?: BufferEncoding
47 highWaterMark?: number
48 read?(this: S, size: number): void
49}
50
51interface Readable<M extends ReadableEvents = ReadableEvents>
52 extends Stream<M>, AsyncIterable<unknown> {
53 _read(size: number): void
54
55 push(data: unknown | null, encoding?: BufferEncoding): boolean
56 unshift(data: unknown | null, encoding?: BufferEncoding): boolean
57 read(): unknown | null
58
59 resume(): this
60 pause(): this
61
62 pipe<S extends Writable>(dest: S, cb?: StreamCallback): S
63
64 setEncoding(encoding: BufferEncoding): void
65}
66
67declare class Readable<M extends ReadableEvents = ReadableEvents> extends Stream<M> {
68 constructor(opts?: ReadableOptions)
69
70 static from(data: unknown | unknown[] | AsyncIterable<unknown>, opts?: ReadableOptions): Readable
71
72 static isBackpressured(rs: Readable): boolean
73
74 static isPaused(rs: Readable): boolean
75}
76
77interface WritableEvents extends StreamEvents {
78 drain: []
79 finish: []
80 pipe: [src: Readable]
81}
82
83interface WritableOptions<S extends Writable = Writable> extends StreamOptions<S> {
84 write?(this: S, data: unknown, encoding: StreamEncoding, cb: StreamCallback): void
85 writev?(this: S, batch: { chunk: unknown; encoding: StreamEncoding }[], cb: StreamCallback): void
86 final?(this: S, cb: StreamCallback): void
87}
88
89interface Writable<M extends WritableEvents = WritableEvents> extends Stream<M> {
90 _write(data: unknown, encoding: StreamEncoding, cb: StreamCallback): void
91 _writev(batch: { chunk: unknown; encoding: StreamEncoding }[], cb: StreamCallback): void
92 _final(cb: StreamCallback): void
93
94 readonly destroyed: boolean
95
96 write(data: unknown, encoding?: BufferEncoding, cb?: StreamCallback): boolean
97 write(data: unknown, cb?: StreamCallback): boolean
98
99 end(cb?: StreamCallback): this
100 end(data: unknown, encoding?: BufferEncoding, cb?: StreamCallback): this
101 end(data: unknown, cb?: StreamCallback): this
102
103 cork(): void
104 uncork(): void
105}
106
107declare class Writable<M extends WritableEvents = WritableEvents> extends Stream<M> {
108 constructor(opts?: WritableOptions)
109
110 static isBackpressured(ws: Writable): boolean
111
112 static drained(ws: Writable): Promise<boolean>
113}
114
115interface DuplexEvents extends ReadableEvents, WritableEvents {}
116
117interface DuplexOptions<S extends Duplex = Duplex> extends ReadableOptions<S>, WritableOptions<S> {}
118
119interface Duplex<M extends DuplexEvents = DuplexEvents> extends Readable<M>, Writable<M> {}
120
121declare class Duplex<M extends DuplexEvents = DuplexEvents> extends Stream<M> {
122 constructor(opts?: DuplexOptions)
123}
124
125interface TransformEvents extends DuplexEvents {}
126
127interface TransformOptions<S extends Transform = Transform> extends DuplexOptions<S> {
128 transform?(this: S, data: unknown, encoding: StreamEncoding, cb: StreamCallback): void
129 flush?(this: S, cb: StreamCallback): void
130}
131
132interface Transform<M extends TransformEvents = TransformEvents> extends Duplex<M> {
133 _transform(data: unknown, encoding: StreamEncoding, cb: StreamCallback): void
134 _flush(cb: StreamCallback): void
135}
136
137declare class Transform<M extends TransformEvents = TransformEvents> extends Duplex<M> {
138 constructor(opts?: TransformOptions)
139}
140
141type Pipeline<S extends Writable> = [src: Readable, ...transforms: Duplex[], dest: S]
142
143declare namespace Stream {
144 export {
145 Stream,
146 StreamEvents,
147 StreamOptions,
148 Readable,
149 ReadableEvents,
150 ReadableOptions,
151 Writable,
152 WritableEvents,
153 WritableOptions,
154 Duplex,
155 DuplexEvents,
156 DuplexOptions,
157 Transform,
158 TransformEvents,
159 TransformOptions,
160 Transform as PassThrough
161 }
162
163 export function pipeline<S extends Writable>(streams: Pipeline<S>, cb?: StreamCallback): S
164
165 export function pipeline<S extends Writable>(...args: Pipeline<S>): S
166
167 export function pipeline<S extends Writable>(...args: [...Pipeline<S>, cb: StreamCallback]): S
168
169 export function finished(
170 stream: Stream,
171 opts: { cleanup?: boolean },
172 cb: StreamCallback
173 ): () => void
174
175 export function finished(stream: Stream, cb: StreamCallback): () => void
176
177 export function isStream(stream: unknown): stream is Stream
178
179 export function isEnded(stream: Stream): boolean
180
181 export function isFinished(stream: Stream): boolean
182
183 export function isDisturbed(stream: Stream): boolean
184
185 export function getStreamError(stream: Stream, opts?: { all?: boolean }): Error | null
186}
187
188export = Stream
node_modules/bare-stream/index.js +351 -0
……@@ -0,0 +1,351 @@
1const stream = require('streamx')
2
3const defaultEncoding = 'utf8'
4
5module.exports = exports = stream.Stream
6
7exports.pipeline = stream.pipeline
8
9exports.isStream = stream.isStream
10exports.isEnding = stream.isEnding
11exports.isEnded = stream.isEnded
12exports.isFinishing = stream.isFinishing
13exports.isFinished = stream.isFinished
14exports.isDisturbed = stream.isDisturbed
15
16exports.getStreamError = stream.getStreamError
17
18exports.Stream = exports
19
20exports.Readable = class Readable extends stream.Readable {
21 constructor(opts = {}) {
22 super({
23 ...opts,
24 byteLength: null,
25 byteLengthReadable: null,
26 map: null,
27 mapReadable: null
28 })
29
30 if (this._construct) this._open = this._construct
31
32 if (this._read !== stream.Readable.prototype._read) {
33 this._read = read.bind(this, this._read)
34 }
35
36 if (this._destroy !== stream.Stream.prototype._destroy) {
37 this._destroy = destroy.bind(this, this._destroy)
38 }
39 }
40
41 push(chunk, encoding) {
42 if (typeof chunk === 'string') {
43 chunk = Buffer.from(chunk, encoding || defaultEncoding)
44 }
45
46 return super.push(chunk)
47 }
48
49 unshift(chunk, encoding) {
50 if (typeof chunk === 'string') {
51 chunk = Buffer.from(chunk, encoding || defaultEncoding)
52 }
53
54 super.unshift(chunk)
55 }
56}
57
58exports.Writable = class Writable extends stream.Writable {
59 constructor(opts = {}) {
60 super({
61 ...opts,
62 byteLength: null,
63 byteLengthWritable,
64 map: null,
65 mapWritable: null
66 })
67
68 if (this._construct) this._open = this._construct
69
70 if (this._write !== stream.Writable.prototype._write) {
71 this._write = write.bind(this, this._write)
72 }
73
74 if (this._destroy !== stream.Stream.prototype._destroy) {
75 this._destroy = destroy.bind(this, this._destroy)
76 }
77 }
78
79 write(chunk, encoding, cb) {
80 if (typeof encoding === 'function') {
81 cb = encoding
82 encoding = null
83 }
84
85 if (typeof chunk === 'string') {
86 encoding = encoding || defaultEncoding
87 chunk = Buffer.from(chunk, encoding)
88 } else {
89 encoding = 'buffer'
90 }
91
92 const result = super.write({ chunk, encoding })
93
94 if (cb) stream.Writable.drained(this).then(() => cb(null), cb)
95
96 return result
97 }
98
99 end(chunk, encoding, cb) {
100 if (typeof chunk === 'function') {
101 cb = chunk
102 chunk = null
103 } else if (typeof encoding === 'function') {
104 cb = encoding
105 encoding = null
106 }
107
108 if (typeof chunk === 'string') {
109 encoding = encoding || defaultEncoding
110 chunk = Buffer.from(chunk, encoding || defaultEncoding)
111 } else {
112 encoding = 'buffer'
113 }
114
115 const result =
116 chunk !== undefined && chunk !== null ? super.end({ chunk, encoding }) : super.end()
117
118 if (cb) this.once('finish', () => cb(null))
119
120 return result
121 }
122}
123
124exports.Duplex = class Duplex extends stream.Duplex {
125 constructor(opts = {}) {
126 super({
127 ...opts,
128 byteLength: null,
129 byteLengthReadable: null,
130 byteLengthWritable,
131 map: null,
132 mapReadable: null,
133 mapWritable: null
134 })
135
136 if (this._construct) this._open = this._construct
137
138 if (this._read !== stream.Readable.prototype._read) {
139 this._read = read.bind(this, this._read)
140 }
141
142 if (this._write !== stream.Duplex.prototype._write) {
143 this._write = write.bind(this, this._write)
144 }
145
146 if (this._destroy !== stream.Stream.prototype._destroy) {
147 this._destroy = destroy.bind(this, this._destroy)
148 }
149 }
150
151 push(chunk, encoding) {
152 if (typeof chunk === 'string') {
153 chunk = Buffer.from(chunk, encoding || defaultEncoding)
154 }
155
156 return super.push(chunk)
157 }
158
159 unshift(chunk, encoding) {
160 if (typeof chunk === 'string') {
161 chunk = Buffer.from(chunk, encoding || defaultEncoding)
162 }
163
164 super.unshift(chunk)
165 }
166
167 write(chunk, encoding, cb) {
168 if (typeof encoding === 'function') {
169 cb = encoding
170 encoding = null
171 }
172
173 if (typeof chunk === 'string') {
174 encoding = encoding || defaultEncoding
175 chunk = Buffer.from(chunk, encoding)
176 } else {
177 encoding = 'buffer'
178 }
179
180 const result = super.write({ chunk, encoding })
181
182 if (cb) stream.Writable.drained(this).then(() => cb(null), cb)
183
184 return result
185 }
186
187 end(chunk, encoding, cb) {
188 if (typeof chunk === 'function') {
189 cb = chunk
190 chunk = null
191 } else if (typeof encoding === 'function') {
192 cb = encoding
193 encoding = null
194 }
195
196 if (typeof chunk === 'string') {
197 encoding = encoding || defaultEncoding
198 chunk = Buffer.from(chunk, encoding)
199 } else {
200 encoding = 'buffer'
201 }
202
203 const result =
204 chunk !== undefined && chunk !== null ? super.end({ chunk, encoding }) : super.end()
205
206 if (cb) this.once('finish', () => cb(null))
207
208 return result
209 }
210}
211
212exports.Transform = class Transform extends stream.Transform {
213 constructor(opts = {}) {
214 super({
215 ...opts,
216 byteLength: null,
217 byteLengthReadable: null,
218 byteLengthWritable,
219 map: null,
220 mapReadable: null,
221 mapWritable: null
222 })
223
224 if (this._transform !== stream.Transform.prototype._transform) {
225 this._transform = transform.bind(this, this._transform)
226 } else {
227 this._transform = passthrough
228 }
229 }
230
231 push(chunk, encoding) {
232 if (typeof chunk === 'string') {
233 chunk = Buffer.from(chunk, encoding || defaultEncoding)
234 }
235
236 return super.push(chunk)
237 }
238
239 unshift(chunk, encoding) {
240 if (typeof chunk === 'string') {
241 chunk = Buffer.from(chunk, encoding || defaultEncoding)
242 }
243
244 super.unshift(chunk)
245 }
246
247 write(chunk, encoding, cb) {
248 if (typeof encoding === 'function') {
249 cb = encoding
250 encoding = null
251 }
252
253 if (typeof chunk === 'string') {
254 encoding = encoding || defaultEncoding
255 chunk = Buffer.from(chunk, encoding)
256 } else {
257 encoding = 'buffer'
258 }
259
260 const result = super.write({ chunk, encoding })
261
262 if (cb) stream.Writable.drained(this).then(() => cb(null), cb)
263
264 return result
265 }
266
267 end(chunk, encoding, cb) {
268 if (typeof chunk === 'function') {
269 cb = chunk
270 chunk = null
271 } else if (typeof encoding === 'function') {
272 cb = encoding
273 encoding = null
274 }
275
276 if (typeof chunk === 'string') {
277 encoding = encoding || defaultEncoding
278 chunk = Buffer.from(chunk, encoding)
279 } else {
280 encoding = 'buffer'
281 }
282
283 const result =
284 chunk !== undefined && chunk !== null ? super.end({ chunk, encoding }) : super.end()
285
286 if (cb) this.once('finish', () => cb(null))
287
288 return result
289 }
290}
291
292exports.PassThrough = class PassThrough extends exports.Transform {}
293
294exports.finished = function finished(stream, opts, cb) {
295 if (typeof opts === 'function') {
296 cb = opts
297 opts = {}
298 }
299
300 if (!opts) opts = {}
301
302 const { cleanup = false } = opts
303
304 const done = () => {
305 cb(exports.getStreamError(stream, { all: true }))
306
307 if (cleanup) detach()
308 }
309
310 const detach = () => {
311 stream.off('close', done)
312 stream.off('error', noop)
313 }
314
315 if (stream.destroyed) {
316 done()
317 } else {
318 stream.on('close', done)
319 stream.on('error', noop)
320 }
321
322 return detach
323}
324
325function read(read, cb) {
326 read.call(this, 65536)
327
328 cb(null)
329}
330
331function write(write, data, cb) {
332 write.call(this, data.chunk, data.encoding, cb)
333}
334
335function transform(transform, data, cb) {
336 transform.call(this, data.chunk, data.encoding, cb)
337}
338
339function destroy(destroy, cb) {
340 destroy.call(this, exports.getStreamError(this), cb)
341}
342
343function passthrough(data, cb) {
344 cb(null, data.chunk)
345}
346
347function byteLengthWritable(data) {
348 return data.chunk.byteLength
349}
350
351function noop() {}
node_modules/bare-stream/package.json +62 -0
……@@ -0,0 +1,62 @@
1{
2 "name": "bare-stream",
3 "version": "2.10.0",
4 "description": "Streaming data for JavaScript",
5 "exports": {
6 ".": {
7 "types": "./index.d.ts",
8 "default": "./index.js"
9 },
10 "./package": "./package.json",
11 "./promises": "./promises.js",
12 "./web": {
13 "types": "./web.d.ts",
14 "default": "./web.js"
15 },
16 "./global": "./global.js"
17 },
18 "files": [
19 "index.js",
20 "index.d.ts",
21 "promises.js",
22 "web.js",
23 "web.d.ts",
24 "global.js"
25 ],
26 "scripts": {
27 "test": "prettier . --check && bare test.js"
28 },
29 "repository": {
30 "type": "git",
31 "url": "git+https://github.com/holepunchto/bare-stream.git"
32 },
33 "author": "Holepunch",
34 "license": "Apache-2.0",
35 "bugs": {
36 "url": "https://github.com/holepunchto/bare-stream/issues"
37 },
38 "homepage": "https://github.com/holepunchto/bare-stream#readme",
39 "dependencies": {
40 "streamx": "^2.25.0",
41 "teex": "^1.0.1"
42 },
43 "devDependencies": {
44 "bare-buffer": "^3.0.0",
45 "bare-events": "^2.5.4",
46 "brittle": "^3.5.2",
47 "prettier": "^3.3.3",
48 "prettier-config-holepunch": "^2.0.0"
49 },
50 "peerDependencies": {
51 "bare-buffer": "*",
52 "bare-events": "*"
53 },
54 "peerDependenciesMeta": {
55 "bare-buffer": {
56 "optional": true
57 },
58 "bare-events": {
59 "optional": true
60 }
61 }
62}
node_modules/bare-stream/promises.js +3 -0
……@@ -0,0 +1,3 @@
1const stream = require('streamx')
2
3exports.pipeline = stream.pipelinePromise
node_modules/bare-stream/web.d.ts +119 -0
……@@ -0,0 +1,119 @@
1export interface ReadableStreamDefaultReader {
2 readonly closed: Promise<void>
3
4 read(): Promise<{ value: unknown; done: boolean }>
5 releaseLock(): void
6 cancel(reason?: unknown): Promise<void>
7}
8
9export class ReadableStreamDefaultReader {
10 constructor(stream: ReadableStream)
11}
12
13export interface ReadableStreamDefaultController {
14 readonly desiredSize: number
15
16 enqueue(data: unknown): void
17 close(): void
18 error(error?: unknown): void
19}
20
21export class ReadableStreamDefaultController {
22 constructor(stream: ReadableStream)
23}
24
25export interface UnderlyingSource<S extends ReadableStream = ReadableStream> {
26 start?(this: S, controller: ReadableStreamDefaultController): void
27 pull?(this: S, controller: ReadableStreamDefaultController): void
28 cancel?(this: S, reason?: unknown): void
29}
30
31export interface CustomQueuingStrategy {
32 highWaterMark?: number
33 size?: (chunk: unknown) => number
34}
35
36export interface ReadableStream extends AsyncIterable<unknown> {
37 readonly locked: boolean
38
39 getReader(): ReadableStreamDefaultReader
40 cancel(reason?: unknown): Promise<void>
41 tee(): [ReadableStream, ReadableStream]
42 pipeTo(destination: WritableStream): Promise<void>
43}
44
45export class ReadableStream {
46 constructor(underlyingSource?: UnderlyingSource, queuingStrategy?: CustomQueuingStrategy)
47
48 static from(iterable: unknown | unknown[] | AsyncIterable<unknown>): ReadableStream
49}
50
51export interface QueuingStrategyOptions {
52 highWaterMark?: number
53}
54
55interface QueuingStrategy {
56 readonly highWaterMark: number
57
58 size(chunk: unknown): number
59}
60
61declare class QueuingStrategy {
62 constructor(opts?: QueuingStrategyOptions)
63}
64
65export { type QueuingStrategy }
66
67export class CountQueuingStrategy extends QueuingStrategy {}
68
69export class ByteLengthQueuingStrategy extends QueuingStrategy {}
70
71export function isReadableStream(value: unknown): value is ReadableStream
72
73export function isReadableStreamErrored(stream: ReadableStream): boolean
74
75export function isReadableStreamDisturbed(stream: ReadableStream): boolean
76
77export interface WritableStreamDefaultWriter {
78 readonly desiredSize: number
79 readonly closed: Promise<void>
80 readonly ready: Promise<void>
81
82 write(chunk: unknown): Promise<void>
83 releaseLock(): void
84 close(): Promise<void>
85 abort(reason?: unknown): Promise<void>
86}
87
88export class WritableStreamDefaultWriter {
89 constructor(stream: WritableStream)
90}
91
92export interface WritableStreamDefaultController {
93 error(err?: unknown): void
94}
95
96export class WritableStreamDefaultController {
97 constructor(stream: WritableStream)
98}
99
100export interface UnderlyingSink<S extends WritableStream = WritableStream> {
101 start?(this: S, controller: WritableStreamDefaultController): void
102 write?(this: S, chunk: unknown, controller: WritableStreamDefaultController): void
103 close?(this: S): void
104 abort?(this: S, reason?: unknown): void
105}
106
107export interface WritableStream extends AsyncIterable<unknown> {
108 readonly locked: boolean
109
110 getWriter(): WritableStreamDefaultWriter
111 abort(reason?: unknown): Promise<void>
112 close(): Promise<void>
113}
114
115export class WritableStream {
116 constructor(underlyingSink?: UnderlyingSink, queuingStrategy?: CustomQueuingStrategy)
117}
118
119export function isWritableStream(value: unknown): value is WritableStream
node_modules/bare-stream/web.js +488 -0
……@@ -0,0 +1,488 @@
1const { Readable, Writable, getStreamError, isStreamx, isDisturbed } = require('streamx')
2const tee = require('teex')
3
4const readableKind = Symbol.for('bare.stream.readable.kind')
5const writableKind = Symbol.for('bare.stream.writable.kind')
6
7// https://streams.spec.whatwg.org/#readablestreamdefaultreader
8exports.ReadableStreamDefaultReader = class ReadableStreamDefaultReader {
9 constructor(stream) {
10 this._stream = stream
11 this._stream._stream.once('close', onclose).once('error', onerror)
12
13 const closed = Promise.withResolvers()
14
15 // Avoid unhandled exceptions
16 closed.promise.catch(noop)
17
18 this._closed = closed
19
20 function onclose() {
21 closed.resolve()
22 }
23
24 function onerror(err) {
25 closed.reject(err)
26 }
27 }
28
29 get closed() {
30 return this._closed.promise
31 }
32
33 read() {
34 const stream = this._stream._stream
35
36 return new Promise((resolve, reject) => {
37 const err = getStreamError(stream)
38
39 if (err) return reject(err)
40
41 if (stream.destroyed) {
42 return resolve({ value: undefined, done: true })
43 }
44
45 const value = stream.read()
46
47 if (value !== null) {
48 return resolve({ value, done: false })
49 }
50
51 stream.once('readable', onreadable).once('close', onclose).once('error', onerror)
52
53 function onreadable() {
54 const value = stream.read()
55
56 ondone(null, value === null ? { value: undefined, done: true } : { value, done: false })
57 }
58
59 function onclose() {
60 ondone(null, { value: undefined, done: true })
61 }
62
63 function onerror(err) {
64 ondone(err, null)
65 }
66
67 function ondone(err, value) {
68 stream.off('readable', onreadable).off('close', onclose).off('error', onerror)
69
70 if (err) reject(err)
71 else resolve(value)
72 }
73 })
74 }
75
76 releaseLock() {
77 this._closed.reject(new TypeError('Reader was released'))
78 this._stream._releaseLock()
79 this._stream = null
80 }
81
82 cancel(reason = new TypeError('Stream was cancelled')) {
83 const stream = this._stream._stream
84
85 if (stream.destroyed) return Promise.resolve()
86
87 return new Promise((resolve) =>
88 stream.once('close', resolve).once('error', noop).destroy(reason)
89 )
90 }
91}
92
93// https://streams.spec.whatwg.org/#readablestreamdefaultcontroller
94exports.ReadableStreamDefaultController = class ReadableStreamDefaultController {
95 constructor(stream) {
96 this._stream = stream
97 }
98
99 get desiredSize() {
100 const stream = this._stream._stream
101
102 return stream._readableState.highWaterMark - stream._readableState.buffered
103 }
104
105 enqueue(data) {
106 this._stream._stream.push(data)
107 }
108
109 close() {
110 this._stream._stream.push(null)
111 }
112
113 error(err) {
114 this._stream._stream.destroy(err)
115 }
116}
117
118// https://streams.spec.whatwg.org/#readablestream
119class ReadableStream {
120 static get [readableKind]() {
121 return 0 // Compatibility version
122 }
123
124 static from(iterable) {
125 return new ReadableStream(Readable.from(iterable))
126 }
127
128 constructor(underlyingSource = {}, queuingStrategy) {
129 if (isStreamx(underlyingSource)) {
130 this._stream = underlyingSource
131 } else {
132 if (queuingStrategy === undefined) {
133 queuingStrategy = new exports.CountQueuingStrategy()
134 }
135
136 const { start, pull, cancel } = underlyingSource
137 const { highWaterMark = 1, size = defaultSize } = queuingStrategy
138
139 this._stream = new Readable({ highWaterMark, byteLength: size })
140
141 const controller = new exports.ReadableStreamDefaultController(this)
142
143 if (start) {
144 this._stream._open = this._open.bind(this, start.call(this, controller))
145 }
146
147 if (pull) {
148 this._stream._read = this._read.bind(this, pull.bind(this, controller))
149 }
150
151 if (cancel) {
152 this._stream.once('error', cancel)
153 }
154 }
155
156 this._reader = null
157 }
158
159 get [readableKind]() {
160 return ReadableStream[readableKind]
161 }
162
163 get locked() {
164 return this._reader !== null
165 }
166
167 getReader() {
168 if (this.locked) throw new TypeError('Stream is locked')
169
170 this._reader = new exports.ReadableStreamDefaultReader(this)
171
172 return this._reader
173 }
174
175 cancel(reason = new TypeError('Stream was cancelled')) {
176 const stream = this._stream
177
178 if (stream.destroyed) return Promise.resolve()
179
180 if (this.locked) return Promise.reject(new TypeError('Stream is locked'))
181
182 return new Promise((resolve) =>
183 stream.once('close', resolve).once('error', noop).destroy(reason)
184 )
185 }
186
187 tee() {
188 const [a, b] = tee(this._stream)
189
190 return [new ReadableStream(a), new ReadableStream(b)]
191 }
192
193 pipeTo(destination) {
194 return new Promise((resolve, reject) =>
195 this._stream.pipe(destination._stream, (err) => {
196 err ? reject(err) : resolve()
197 })
198 )
199 }
200
201 [Symbol.asyncIterator]() {
202 return this._stream[Symbol.asyncIterator]()
203 }
204
205 _releaseLock() {
206 this._reader = null
207 }
208
209 async _open(starting, cb) {
210 try {
211 await starting
212
213 cb(null)
214 } catch (err) {
215 cb(err)
216 }
217 }
218
219 async _read(pull, cb) {
220 try {
221 await pull()
222
223 cb(null)
224 } catch (err) {
225 cb(err)
226 }
227 }
228}
229
230function defaultSize() {
231 return 1
232}
233
234exports.ReadableStream = ReadableStream
235
236// https://streams.spec.whatwg.org/#countqueuingstrategy
237exports.CountQueuingStrategy = class CountQueuingStrategy {
238 constructor(opts = {}) {
239 const { highWaterMark = 1 } = opts
240
241 this.highWaterMark = highWaterMark
242 }
243
244 size(chunk) {
245 return 1
246 }
247}
248
249// https://streams.spec.whatwg.org/#bytelengthqueuingstrategy
250exports.ByteLengthQueuingStrategy = class ByteLengthQueuingStrategy {
251 constructor(opts = {}) {
252 const { highWaterMark = 16384 } = opts
253
254 this.highWaterMark = highWaterMark
255 }
256
257 size(chunk) {
258 return chunk.byteLength
259 }
260}
261
262exports.isReadableStream = function isReadableStream(value) {
263 if (value instanceof ReadableStream) return true
264
265 return (
266 typeof value === 'object' &&
267 value !== null &&
268 value[readableKind] === ReadableStream[readableKind]
269 )
270}
271
272// https://streams.spec.whatwg.org/#readablestream-errored
273exports.isReadableStreamErrored = function isReadableStreamErrored(stream) {
274 return getStreamError(stream._stream) !== null
275}
276
277// https://streams.spec.whatwg.org/#is-readable-stream-disturbed
278exports.isReadableStreamDisturbed = function isReadableStreamDisturbed(stream) {
279 return isDisturbed(stream._stream)
280}
281
282// https://streams.spec.whatwg.org/#writablestreamdefaultwriter
283exports.WritableStreamDefaultWriter = class WritableStreamDefaultWriter {
284 constructor(stream) {
285 this._stream = stream
286 this._stream._stream.once('close', onclose).once('error', onerror)
287
288 const closed = Promise.withResolvers()
289
290 // Avoid unhandled exceptions
291 closed.promise.catch(noop)
292
293 this._closed = closed
294
295 function onclose() {
296 closed.resolve()
297 }
298
299 function onerror(err) {
300 closed.reject(err)
301 }
302 }
303
304 get desiredSize() {
305 const stream = this._stream._stream
306
307 return stream._writableState.highWaterMark - stream._writableState.buffered
308 }
309
310 get closed() {
311 return this._closed.promise
312 }
313
314 get ready() {
315 const stream = this._stream._stream
316
317 if (getStreamError(stream)) return Promise.reject()
318
319 return Writable.drained(stream).then()
320 }
321
322 async write(chunk) {
323 const stream = this._stream._stream
324
325 const err = getStreamError(stream)
326
327 if (err) return Promise.reject(err)
328
329 stream.write(chunk)
330
331 await Writable.drained(stream)
332 }
333
334 releaseLock() {
335 this._closed.reject(new TypeError('Writer was released'))
336 this._stream._releaseLock()
337 this._stream = null
338 }
339
340 close() {
341 const stream = this._stream._stream
342
343 if (stream.destroyed) return Promise.resolve()
344
345 return new Promise((resolve) => stream.once('close', resolve).end())
346 }
347
348 abort(reason = new TypeError('Stream was aborted')) {
349 const stream = this._stream._stream
350
351 if (stream.destroyed) return Promise.resolve()
352
353 return new Promise((resolve) => stream.once('close', resolve).destroy(reason))
354 }
355}
356
357// https://streams.spec.whatwg.org/#writablestreamdefaultcontroller
358exports.WritableStreamDefaultController = class WritableStreamDefaultController {
359 constructor(stream) {
360 this._stream = stream
361 }
362
363 error(err) {
364 this._stream._stream.destroy(err)
365 }
366}
367
368// https://streams.spec.whatwg.org/#writablestream
369class WritableStream {
370 static get [writableKind]() {
371 return 0 // Compatibility version
372 }
373
374 constructor(underlyingSink = {}, queuingStrategy = {}) {
375 if (isStreamx(underlyingSink)) {
376 this._stream = underlyingSink
377 } else {
378 if (queuingStrategy === undefined) {
379 queuingStrategy = new exports.CountQueuingStrategy()
380 }
381
382 const { start, write, close, abort } = underlyingSink
383 const { highWaterMark = 1, size = defaultSize } = queuingStrategy
384
385 this._stream = new Writable({ highWaterMark, byteLength: size })
386
387 this._controller = new exports.WritableStreamDefaultController(this)
388
389 if (start) {
390 this._stream._open = this._open.bind(this, start.call(this, this._controller))
391 }
392
393 if (write) {
394 this._stream._write = this._write.bind(this, write)
395 }
396
397 if (close) {
398 this._stream._destroy = this._destroy.bind(this, close.call(this))
399 }
400
401 if (abort) {
402 this._stream.once('error', abort)
403 }
404 }
405
406 this._writer = null
407 }
408
409 get [writableKind]() {
410 return WritableStream[writableKind]
411 }
412
413 get locked() {
414 return this._writer !== null
415 }
416
417 getWriter() {
418 if (this.locked) throw new TypeError('Stream is locked')
419
420 this._writer = new exports.WritableStreamDefaultWriter(this)
421
422 return this._writer
423 }
424
425 abort(reason = new TypeError('Stream was aborted')) {
426 if (this._stream.destroyed) return Promise.resolve()
427
428 if (this.locked) return Promise.reject(new TypeError('Stream is locked'))
429
430 return new Promise((resolve) => this._stream.once('close', resolve).destroy(reason))
431 }
432
433 close() {
434 if (this._stream.destroyed) return Promise.resolve()
435
436 if (this.locked) return Promise.reject(new TypeError('Stream is locked'))
437
438 return new Promise((resolve) => this._stream.once('close', resolve).end())
439 }
440
441 _releaseLock() {
442 this._writer = null
443 }
444
445 async _open(starting, cb) {
446 try {
447 await starting
448
449 cb(null)
450 } catch (err) {
451 cb(err)
452 }
453 }
454
455 async _write(write, data, cb) {
456 try {
457 await write(data, this._controller)
458
459 cb(null)
460 } catch (err) {
461 cb(err)
462 }
463 }
464
465 async _destroy(closing, cb) {
466 try {
467 await closing
468
469 cb(null)
470 } catch (err) {
471 cb(err)
472 }
473 }
474}
475
476exports.WritableStream = WritableStream
477
478exports.isWritableStream = function isWritableStream(value) {
479 if (value instanceof WritableStream) return true
480
481 return (
482 typeof value === 'object' &&
483 value !== null &&
484 value[writableKind] === WritableStream[writableKind]
485 )
486}
487
488function noop() {}
node_modules/bare-type/CMakeLists.txt +13 -0
……@@ -0,0 +1,13 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4
5project(bare_type C)
6
7add_bare_module(bare_type)
8
9target_sources(
10 ${bare_type}
11 PRIVATE
12 binding.c
13)
node_modules/bare-type/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-type/README.md +21 -0
……@@ -0,0 +1,21 @@
1# bare-type
2
3Cross-realm type predicates for Bare.
4
5```
6npm i bare-type
7```
8
9## Usage
10
11```js
12const type = require('bare-type')
13
14if (type(123).isNumber()) {
15 console.log(123, 'is a number')
16}
17```
18
19## License
20
21Apache-2.0
node_modules/bare-type/binding.c +315 -0
……@@ -0,0 +1,315 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4#include <stdint.h>
5#include <utf.h>
6
7typedef enum {
8 // Base types
9 bare_type_undefined = js_undefined,
10 bare_type_null = js_null,
11 bare_type_boolean = js_boolean,
12 bare_type_number = js_number,
13 bare_type_string = js_string,
14 bare_type_symbol = js_symbol,
15 bare_type_object = js_object,
16 bare_type_function = js_function,
17 bare_type_external = js_external,
18 bare_type_bigint = js_bigint,
19
20 // Number types
21 bare_type_int32 = 1 << 8,
22 bare_type_uint32 = 1 << 9,
23
24 // Object types
25 bare_type_array = 1 << 8,
26 bare_type_arguments = 2 << 8,
27 bare_type_date = 3 << 8,
28 bare_type_regexp = 4 << 8,
29 bare_type_error = 5 << 8,
30 bare_type_promise = 6 << 8,
31 bare_type_proxy = 7 << 8,
32 bare_type_generator = 8 << 8,
33 bare_type_map = 9 << 8,
34 bare_type_set = 10 << 8,
35 bare_type_weak_map = 11 << 8,
36 bare_type_weak_set = 12 << 8,
37 bare_type_weak_ref = 13 << 8,
38 bare_type_arraybuffer = 14 << 8,
39 bare_type_sharedarraybuffer = 15 << 8,
40 bare_type_typedarray = 16 << 8,
41 bare_type_dataview = 17 << 8,
42 bare_type_module_namespace = 18 << 8,
43
44 // TypedArray types
45 bare_type_int8array = 1 << 16,
46 bare_type_uint8array = 2 << 16,
47 bare_type_uint8clampedarray = 3 << 16,
48 bare_type_int16array = 4 << 16,
49 bare_type_uint16array = 5 << 16,
50 bare_type_int32array = 6 << 16,
51 bare_type_uint32array = 7 << 16,
52 bare_type_float16array = 12 << 16,
53 bare_type_float32array = 8 << 16,
54 bare_type_float64array = 9 << 16,
55 bare_type_bigint64array = 10 << 16,
56 bare_type_biguint64array = 11 << 16,
57
58 // Function types
59 bare_type_async_function = 1 << 8,
60 bare_type_generator_function = 1 << 9,
61} bare_type_t;
62
63static js_value_t *
64bare_type(js_env_t *env, js_callback_info_t *info) {
65 int err;
66
67 size_t argc = 1;
68 js_value_t *argv[1];
69
70 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
71 assert(err == 0);
72
73 assert(argc == 1);
74
75 js_value_t *value = argv[0];
76
77 uint32_t type;
78 err = js_typeof(env, value, (js_value_type_t *) &type);
79 assert(err == 0);
80
81 switch (type) {
82 case bare_type_number: {
83#define V(t) \
84 bool is_##t; \
85 err = js_is_##t(env, value, &is_##t); \
86 assert(err == 0); \
87 if (is_##t) type |= bare_type_##t;
88
89 V(int32)
90 V(uint32)
91#undef V
92
93 break;
94 }
95
96 case bare_type_object: {
97#define V(t) \
98 bool is_##t; \
99 err = js_is_##t(env, value, &is_##t); \
100 assert(err == 0); \
101 if (is_##t) { \
102 type |= bare_type_##t; \
103 break; \
104 }
105
106 V(array)
107 V(arguments)
108 V(date)
109 V(regexp)
110 V(error)
111 V(promise)
112 V(proxy)
113 V(generator)
114 V(map)
115 V(set)
116 V(weak_map)
117 V(weak_set)
118 V(weak_ref)
119 V(arraybuffer)
120 V(sharedarraybuffer)
121 V(typedarray)
122 V(dataview)
123 V(module_namespace)
124#undef V
125
126 break;
127 }
128
129 case bare_type_function: {
130#define V(t) \
131 bool is_##t; \
132 err = js_is_##t(env, value, &is_##t); \
133 assert(err == 0); \
134 if (is_##t) type |= bare_type_##t;
135
136 V(async_function)
137 V(generator_function)
138#undef V
139
140 break;
141 }
142 }
143
144 switch (type) {
145 case bare_type_object | bare_type_typedarray: {
146#define V(t) \
147 bool is_##t; \
148 err = js_is_##t(env, value, &is_##t); \
149 assert(err == 0); \
150 if (is_##t) { \
151 type |= bare_type_##t; \
152 break; \
153 }
154
155 V(int8array)
156 V(uint8array)
157 V(uint8clampedarray)
158 V(int16array)
159 V(uint16array)
160 V(int32array)
161 V(uint32array)
162 V(float16array)
163 V(float32array)
164 V(float64array)
165 V(bigint64array)
166 V(biguint64array)
167#undef V
168
169 break;
170 }
171 }
172
173 js_value_t *result;
174 err = js_create_uint32(env, type, &result);
175 assert(err == 0);
176
177 return result;
178}
179
180static js_value_t *
181bare_type_add_tag(js_env_t *env, js_callback_info_t *info) {
182 int err;
183
184 size_t argc = 2;
185 js_value_t *argv[2];
186
187 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
188 assert(err == 0);
189
190 assert(argc == 2);
191
192 js_type_tag_t *tag;
193 err = js_get_typedarray_info(env, argv[1], NULL, (void **) &tag, NULL, NULL, NULL);
194 assert(err == 0);
195
196 js_add_type_tag(env, argv[0], tag);
197
198 return NULL;
199}
200
201static js_value_t *
202bare_type_check_tag(js_env_t *env, js_callback_info_t *info) {
203 int err;
204
205 size_t argc = 2;
206 js_value_t *argv[2];
207
208 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
209 assert(err == 0);
210
211 assert(argc == 2);
212
213 js_type_tag_t *tag;
214 err = js_get_typedarray_info(env, argv[1], NULL, (void **) &tag, NULL, NULL, NULL);
215 assert(err == 0);
216
217 bool matches;
218 err = js_check_type_tag(env, argv[0], tag, &matches);
219 assert(err == 0);
220
221 js_value_t *result;
222 err = js_get_boolean(env, matches, &result);
223 assert(err == 0);
224
225 return result;
226}
227
228static js_value_t *
229bare_type_exports(js_env_t *env, js_value_t *exports) {
230 int err;
231
232#define V(name, fn) \
233 { \
234 js_value_t *val; \
235 err = js_create_function(env, name, -1, fn, NULL, &val); \
236 assert(err == 0); \
237 err = js_set_named_property(env, exports, name, val); \
238 assert(err == 0); \
239 }
240
241 V("type", bare_type)
242 V("addTag", bare_type_add_tag)
243 V("checkTag", bare_type_check_tag)
244#undef V
245
246 js_value_t *constants;
247 err = js_create_object(env, &constants);
248 assert(err == 0);
249
250 err = js_set_named_property(env, exports, "constants", constants);
251 assert(err == 0);
252
253#define V(name, n) \
254 { \
255 js_value_t *val; \
256 err = js_create_uint32(env, n, &val); \
257 assert(err == 0); \
258 err = js_set_named_property(env, constants, name, val); \
259 assert(err == 0); \
260 }
261
262 V("UNDEFINED", bare_type_undefined)
263 V("NULL", bare_type_null)
264 V("BOOLEAN", bare_type_boolean)
265 V("NUMBER", bare_type_number)
266 V("STRING", bare_type_string)
267 V("SYMBOL", bare_type_symbol)
268 V("OBJECT", bare_type_object)
269 V("FUNCTION", bare_type_function)
270 V("EXTERNAL", bare_type_external)
271 V("BIGINT", bare_type_bigint)
272
273 V("INT32", bare_type_int32)
274 V("UINT32", bare_type_uint32)
275
276 V("ARRAY", bare_type_array)
277 V("ARGUMENTS", bare_type_arguments)
278 V("DATE", bare_type_date)
279 V("REGEXP", bare_type_regexp)
280 V("ERROR", bare_type_error)
281 V("PROMISE", bare_type_promise)
282 V("PROXY", bare_type_proxy)
283 V("GENERATOR", bare_type_generator)
284 V("MAP", bare_type_map)
285 V("SET", bare_type_set)
286 V("WEAK_MAP", bare_type_weak_map)
287 V("WEAK_SET", bare_type_weak_set)
288 V("WEAK_REF", bare_type_weak_ref)
289 V("ARRAYBUFFER", bare_type_arraybuffer)
290 V("SHAREDARRAYBUFFER", bare_type_sharedarraybuffer)
291 V("TYPEDARRAY", bare_type_typedarray)
292 V("DATAVIEW", bare_type_dataview)
293 V("MODULE_NAMESPACE", bare_type_module_namespace)
294
295 V("INT8ARRAY", bare_type_int8array)
296 V("UINT8ARRAY", bare_type_uint8array)
297 V("UINT8CLAMPEDARRAY", bare_type_uint8clampedarray)
298 V("INT16ARRAY", bare_type_int16array)
299 V("UINT16ARRAY", bare_type_uint16array)
300 V("INT32ARRAY", bare_type_int32array)
301 V("UINT32ARRAY", bare_type_uint32array)
302 V("FLOAT16ARRAY", bare_type_float16array)
303 V("FLOAT32ARRAY", bare_type_float32array)
304 V("FLOAT64ARRAY", bare_type_float64array)
305 V("BIGINT64ARRAY", bare_type_bigint64array)
306 V("BIGUINT64ARRAY", bare_type_biguint64array)
307
308 V("ASYNC_FUNCTION", bare_type_async_function)
309 V("GENERATOR_FUNCTION", bare_type_generator_function)
310#undef V
311
312 return exports;
313}
314
315BARE_MODULE(bare_type, bare_type_exports)
node_modules/bare-type/binding.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require.addon()
node_modules/bare-type/index.d.ts +62 -0
……@@ -0,0 +1,62 @@
1interface Type {
2 isUndefined(): boolean
3 isNull(): boolean
4 isBoolean(): boolean
5 isNumber(): boolean
6 isInt32(): boolean
7 isUint32(): boolean
8 isString(): boolean
9 isSymbol(): boolean
10 isObject(): boolean
11 isArray(): boolean
12 isArguments(): boolean
13 isDate(): boolean
14 isRegExp(): boolean
15 isError(): boolean
16 isPromise(): boolean
17 isProxy(): boolean
18 isGenerator(): boolean
19 isMap(): boolean
20 isSet(): boolean
21 isWeakMap(): boolean
22 isWeakSet(): boolean
23 isWeakRef(): boolean
24 isArrayBuffer(): boolean
25 isSharedArrayBuffer(): boolean
26 isTypedArray(): boolean
27 isInt8Array(): boolean
28 isUint8Array(): boolean
29 isUint8ClampedArray(): boolean
30 isInt16Array(): boolean
31 isUint16Array(): boolean
32 isInt32Array(): boolean
33 isUint32Array(): boolean
34 isFloat16Array(): boolean
35 isFloat32Array(): boolean
36 isFloat64Array(): boolean
37 isBigInt64Array(): boolean
38 isBigUint64Array(): boolean
39 isDataView(): boolean
40 isModuleNamespace(): boolean
41 isFunction(): boolean
42 isAsyncFunction(): boolean
43 isGeneratorFunction(): boolean
44 isExternal(): boolean
45 isBigInt(): boolean
46}
47
48declare class Type {
49 constructor(type: number)
50}
51
52declare function type(value: unknown): Type
53
54declare namespace type {
55 export function createTag(...components: number[]): Uint32Array
56
57 export function addTag(object: object, tag: Uint32Array): void
58
59 export function checkTag(object: object, tag: Uint32Array): boolean
60}
61
62export = type
node_modules/bare-type/index.js +228 -0
……@@ -0,0 +1,228 @@
1const binding = require('./binding')
2
3const t = binding.constants
4
5class Type {
6 constructor(type) {
7 this._type = type
8 }
9
10 isUndefined() {
11 return this._type === t.UNDEFINED
12 }
13
14 isNull() {
15 return this._type === t.NULL
16 }
17
18 isBoolean() {
19 return this._type === t.BOOLEAN
20 }
21
22 isNumber() {
23 return (this._type & 0xff) === t.NUMBER
24 }
25
26 isInt32() {
27 return (this._type & (0xff | t.INT32)) === (t.NUMBER | t.INT32)
28 }
29
30 isUint32() {
31 return (this._type & (0xff | t.UINT32)) === (t.NUMBER | t.UINT32)
32 }
33
34 isString() {
35 return this._type === t.STRING
36 }
37
38 isSymbol() {
39 return this._type === t.SYMBOL
40 }
41
42 isObject() {
43 return (this._type & 0xff) === t.OBJECT
44 }
45
46 isArray() {
47 return this._type === (t.OBJECT | t.ARRAY)
48 }
49
50 isArguments() {
51 return this._type === (t.OBJECT | t.ARGUMENTS)
52 }
53
54 isDate() {
55 return this._type === (t.OBJECT | t.DATE)
56 }
57
58 isRegExp() {
59 return this._type === (t.OBJECT | t.REGEXP)
60 }
61
62 isError() {
63 return this._type === (t.OBJECT | t.ERROR)
64 }
65
66 isPromise() {
67 return this._type === (t.OBJECT | t.PROMISE)
68 }
69
70 isProxy() {
71 return this._type === (t.OBJECT | t.PROXY)
72 }
73
74 isGenerator() {
75 return this._type === (t.OBJECT | t.GENERATOR)
76 }
77
78 isMap() {
79 return this._type === (t.OBJECT | t.MAP)
80 }
81
82 isSet() {
83 return this._type === (t.OBJECT | t.SET)
84 }
85
86 isWeakMap() {
87 return this._type === (t.OBJECT | t.WEAK_MAP)
88 }
89
90 isWeakSet() {
91 return this._type === (t.OBJECT | t.WEAK_SET)
92 }
93
94 isWeakRef() {
95 return this._type === (t.OBJECT | t.WEAK_REF)
96 }
97
98 isArrayBuffer() {
99 return this._type === (t.OBJECT | t.ARRAYBUFFER)
100 }
101
102 isSharedArrayBuffer() {
103 return this._type === (t.OBJECT | t.SHAREDARRAYBUFFER)
104 }
105
106 isTypedArray() {
107 return (this._type & 0xffff) === (t.OBJECT | t.TYPEDARRAY)
108 }
109
110 isInt8Array() {
111 return this._type === (t.OBJECT | t.TYPEDARRAY | t.INT8ARRAY)
112 }
113
114 isUint8Array() {
115 return this._type === (t.OBJECT | t.TYPEDARRAY | t.UINT8ARRAY)
116 }
117
118 isUint8ClampedArray() {
119 return this._type === (t.OBJECT | t.TYPEDARRAY | t.UINT8CLAMPEDARRAY)
120 }
121
122 isInt16Array() {
123 return this._type === (t.OBJECT | t.TYPEDARRAY | t.INT16ARRAY)
124 }
125
126 isUint16Array() {
127 return this._type === (t.OBJECT | t.TYPEDARRAY | t.UINT16ARRAY)
128 }
129
130 isInt32Array() {
131 return this._type === (t.OBJECT | t.TYPEDARRAY | t.INT32ARRAY)
132 }
133
134 isUint32Array() {
135 return this._type === (t.OBJECT | t.TYPEDARRAY | t.UINT32ARRAY)
136 }
137
138 isFloat16Array() {
139 return this._type === (t.OBJECT | t.TYPEDARRAY | t.FLOAT16ARRAY)
140 }
141
142 isFloat32Array() {
143 return this._type === (t.OBJECT | t.TYPEDARRAY | t.FLOAT32ARRAY)
144 }
145
146 isFloat64Array() {
147 return this._type === (t.OBJECT | t.TYPEDARRAY | t.FLOAT64ARRAY)
148 }
149
150 isBigInt64Array() {
151 return this._type === (t.OBJECT | t.TYPEDARRAY | t.BIGINT64ARRAY)
152 }
153
154 isBigUint64Array() {
155 return this._type === (t.OBJECT | t.TYPEDARRAY | t.BIGUINT64ARRAY)
156 }
157
158 isDataView() {
159 return this._type === (t.OBJECT | t.DATAVIEW)
160 }
161
162 isModuleNamespace() {
163 return this._type === (t.OBJECT | t.MODULE_NAMESPACE)
164 }
165
166 isFunction() {
167 return (this._type & 0xff) === t.FUNCTION
168 }
169
170 isAsyncFunction() {
171 return (
172 (this._type & (0xff | t.ASYNC_FUNCTION)) ===
173 (t.FUNCTION | t.ASYNC_FUNCTION)
174 )
175 }
176
177 isGeneratorFunction() {
178 return (
179 (this._type & (0xff | t.GENERATOR_FUNCTION)) ===
180 (t.FUNCTION | t.GENERATOR_FUNCTION)
181 )
182 }
183
184 isExternal() {
185 return this._type === t.EXTERNAL
186 }
187
188 isBigInt() {
189 return this._type === t.BIGINT
190 }
191}
192
193module.exports = exports = function type(value) {
194 switch (typeof value) {
195 case 'undefined':
196 return new Type(t.UNDEFINED)
197 case 'boolean':
198 return new Type(t.BOOLEAN)
199 case 'number':
200 return new Type(
201 Number.isSafeInteger(value) ? binding.type(value) : t.NUMBER
202 )
203 case 'string':
204 return new Type(t.STRING)
205 case 'symbol':
206 return new Type(t.SYMBOL)
207 case 'object':
208 return new Type(value === null ? t.NULL : binding.type(value))
209 case 'function':
210 return new Type(binding.type(value))
211 case 'bigint':
212 return new Type(t.BIGINT)
213 }
214}
215
216exports.createTag = function createTag(...components) {
217 const tag = new Uint32Array(4)
218 for (let i = 0; i < 4; i++) tag[i] = components[i] || 0
219 return tag
220}
221
222exports.addTag = function addTag(object, tag) {
223 binding.addTag(object, tag)
224}
225
226exports.checkTag = function checkTag(object, tag) {
227 return binding.checkTag(object, tag)
228}
node_modules/bare-type/package.json +43 -0
……@@ -0,0 +1,43 @@
1{
2 "name": "bare-type",
3 "version": "1.1.0",
4 "description": "Cross-realm type predicates for Bare",
5 "exports": {
6 ".": {
7 "types": "./index.d.ts",
8 "default": "./index.js"
9 },
10 "./package": "./package.json"
11 },
12 "files": [
13 "index.js",
14 "index.d.ts",
15 "binding.c",
16 "binding.js",
17 "CMakeLists.txt",
18 "prebuilds"
19 ],
20 "addon": true,
21 "scripts": {
22 "test": "prettier . --check && bare test.js"
23 },
24 "repository": {
25 "type": "git",
26 "url": "git+https://github.com/holepunchto/bare-type.git"
27 },
28 "author": "Holepunch",
29 "license": "Apache-2.0",
30 "bugs": {
31 "url": "https://github.com/holepunchto/bare-type/issues"
32 },
33 "homepage": "https://github.com/holepunchto/bare-type#readme",
34 "engines": {
35 "bare": ">=1.2.0"
36 },
37 "devDependencies": {
38 "brittle": "^3.4.0",
39 "cmake-bare": "^1.1.6",
40 "prettier": "^3.4.1",
41 "prettier-config-standard": "^7.0.0"
42 }
43}
node_modules/bare-type/prebuilds/android-arm/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/android-arm64/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/android-ia32/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/android-x64/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/darwin-arm64/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/darwin-x64/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/ios-arm64-simulator/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/ios-arm64/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/ios-x64-simulator/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/linux-arm64/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/linux-x64/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/win32-arm64/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-type/prebuilds/win32-x64/bare-type.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/CMakeLists.txt +27 -0
……@@ -0,0 +1,27 @@
1cmake_minimum_required(VERSION 4.0)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5
6project(bare_url C)
7
8fetch_package("github:holepunchto/libutf#6b1a36f")
9fetch_package("github:holepunchto/liburl#03f1488")
10
11add_bare_module(bare_url)
12
13target_sources(
14 ${bare_url}
15 PRIVATE
16 binding.c
17)
18
19target_link_libraries(
20 ${bare_url}
21 PRIVATE
22 $<TARGET_OBJECTS:utf>
23 $<TARGET_OBJECTS:url>
24 PUBLIC
25 utf
26 url
27)
node_modules/bare-url/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/bare-url/README.md +19 -0
……@@ -0,0 +1,19 @@
1# bare-url
2
3WHATWG URL implementation for JavaScript.
4
5```
6npm i bare-url
7```
8
9## Usage
10
11```js
12const url = require('bare-url')
13
14const p = url.fileURLToPath('file:///foo') // --> /foo
15```
16
17## License
18
19Apache-2.0
node_modules/bare-url/binding.c +188 -0
……@@ -0,0 +1,188 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4#include <stddef.h>
5#include <stdlib.h>
6#include <string.h>
7#include <url.h>
8#include <utf.h>
9#include <utf/string.h>
10
11static js_type_tag_t bare_url__tag = {0x6f1fd92f476698b0, 0x93b59c349143ee50};
12
13static js_value_t *
14bare_url_parse (js_env_t *env, js_callback_info_t *info) {
15 int err;
16
17 size_t argc = 4;
18 js_value_t *argv[4];
19
20 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
21 assert(err == 0);
22
23 assert(argc == 4);
24
25 bool should_throw;
26 err = js_get_value_bool(env, argv[3], &should_throw);
27 assert(err == 0);
28
29 bool has_base;
30 err = js_is_string(env, argv[1], &has_base);
31 assert(err == 0);
32
33 url_t base;
34 url_init(&base);
35
36 if (has_base) {
37 size_t len;
38 err = js_get_value_string_utf8(env, argv[1], NULL, 0, &len);
39 assert(err == 0);
40
41 utf8_t *input = malloc(len);
42 err = js_get_value_string_utf8(env, argv[1], input, len, NULL);
43 assert(err == 0);
44
45 err = url_parse(&base, input, len, NULL);
46
47 free(input);
48
49 if (err < 0) {
50 url_destroy(&base);
51
52 if (should_throw) js_throw_error(env, NULL, "Invalid base URL");
53
54 return NULL;
55 }
56 }
57
58 size_t len;
59 err = js_get_value_string_utf8(env, argv[0], NULL, 0, &len);
60 assert(err == 0);
61
62 utf8_t *input = malloc(len);
63 err = js_get_value_string_utf8(env, argv[0], input, len, NULL);
64 assert(err == 0);
65
66 js_value_t *handle;
67
68 url_t url;
69 url_init(&url);
70
71 err = url_parse(&url, input, len, has_base ? &base : NULL);
72
73 free(input);
74
75 if (err < 0) {
76 url_destroy(&base);
77 url_destroy(&url);
78
79 if (should_throw) js_throw_error(env, NULL, "Invalid URL");
80
81 return NULL;
82 }
83
84 js_value_t *href;
85 err = js_create_string_utf8(env, url.href.data, url.href.len, &href);
86 assert(err == 0);
87
88 uint32_t *components;
89 err = js_get_typedarray_info(env, argv[2], NULL, (void **) &components, NULL, NULL, NULL);
90 assert(err == 0);
91
92 memcpy(components, &url.components, sizeof(url.components));
93
94 url_destroy(&base);
95 url_destroy(&url);
96
97 return href;
98}
99
100static js_value_t *
101bare_url_can_parse (js_env_t *env, js_callback_info_t *info) {
102 int err;
103
104 size_t argc = 2;
105 js_value_t *argv[2];
106
107 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
108 assert(err == 0);
109
110 assert(argc == 2);
111
112 bool has_base;
113 err = js_is_string(env, argv[1], &has_base);
114 assert(err == 0);
115
116 url_t base;
117 url_init(&base);
118
119 if (has_base) {
120 size_t len;
121 err = js_get_value_string_utf8(env, argv[1], NULL, 0, &len);
122 assert(err == 0);
123
124 utf8_t *input = malloc(len);
125 err = js_get_value_string_utf8(env, argv[1], input, len, NULL);
126 assert(err == 0);
127
128 err = url_parse(&base, input, len, NULL);
129
130 free(input);
131
132 if (err < 0) {
133 url_destroy(&base);
134
135 js_value_t *result;
136 err = js_get_boolean(env, false, &result);
137 assert(err == 0);
138
139 return result;
140 }
141 }
142
143 size_t len;
144 err = js_get_value_string_utf8(env, argv[0], NULL, 0, &len);
145 assert(err == 0);
146
147 utf8_t *input = malloc(len);
148 err = js_get_value_string_utf8(env, argv[0], input, len, NULL);
149 assert(err == 0);
150
151 url_t url;
152 url_init(&url);
153
154 err = url_parse(&url, input, len, has_base ? &base : NULL);
155
156 free(input);
157
158 url_destroy(&base);
159 url_destroy(&url);
160
161 js_value_t *result;
162 err = js_get_boolean(env, err == 0, &result);
163 assert(err == 0);
164
165 return result;
166}
167
168static js_value_t *
169bare_url_exports (js_env_t *env, js_value_t *exports) {
170 int err;
171
172#define V(name, fn) \
173 { \
174 js_value_t *val; \
175 err = js_create_function(env, name, -1, fn, NULL, &val); \
176 assert(err == 0); \
177 err = js_set_named_property(env, exports, name, val); \
178 assert(err == 0); \
179 }
180
181 V("parse", bare_url_parse)
182 V("canParse", bare_url_can_parse)
183#undef V
184
185 return exports;
186}
187
188BARE_MODULE(bare_url, bare_url_exports)
node_modules/bare-url/binding.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require.addon()
node_modules/bare-url/global.d.ts +12 -0
……@@ -0,0 +1,12 @@
1import * as url from '.'
2
3type URLConstructor = typeof url.URL
4type URLSearchParamsConstructor = typeof url.URLSearchParams
5
6declare global {
7 type URL = url.URL
8 type URLSearchParams = url.URLSearchParams
9
10 const URL: URLConstructor
11 const URLSearchParams: URLSearchParamsConstructor
12}
node_modules/bare-url/global.js +2 -0
……@@ -0,0 +1,2 @@
1global.URL = require('.')
2global.URLSearchParams = require('./lib/url-search-params')
node_modules/bare-url/index.d.ts +41 -0
……@@ -0,0 +1,41 @@
1import URLError from './lib/errors'
2import URLSearchParams from './lib/url-search-params'
3
4interface URL {
5 href: string
6 protocol: string
7 username: string
8 password: string
9 host: string
10 hostname: string
11 port: string
12 pathname: string
13 search: string
14 searchParams: URLSearchParams
15 hash: string
16
17 toString(): string
18 toJSON(): string
19}
20
21declare class URL {
22 constructor(input: string, base?: string | URL)
23}
24
25declare namespace URL {
26 export function isURL(value: unknown): value is URL
27
28 export function isURLSearchParams(value: unknown): value is URLSearchParams
29
30 export function parse(input: string, base?: string | URL): URL | null
31
32 export function canParse(input: string, base?: string | URL): boolean
33
34 export function fileURLToPath(url: URL | string): string
35
36 export function pathToFileURL(pathname: string): URL
37
38 export { URL, type URLError, URLError as errors, URLSearchParams }
39}
40
41export = URL
node_modules/bare-url/index.js +407 -0
……@@ -0,0 +1,407 @@
1const path = require('bare-path')
2const binding = require('./binding')
3const errors = require('./lib/errors')
4const URLSearchParams = require('./lib/url-search-params')
5
6const kind = Symbol.for('bare.url.kind')
7
8const isWindows = Bare.platform === 'win32'
9
10class URL {
11 static get [kind]() {
12 return 0 // Compatibility version
13 }
14
15 constructor(input, base, opts = {}) {
16 if (arguments.length === 0) throw errors.INVALID_URL()
17
18 input = String(input)
19
20 if (base !== undefined) base = String(base)
21
22 this._components = new Uint32Array(8)
23
24 this._parse(input, base, opts.throw !== false)
25
26 if (this._href) this._params = new URLSearchParams(this.search, this)
27 }
28
29 get [kind]() {
30 return URL[kind]
31 }
32
33 // https://url.spec.whatwg.org/#dom-url-href
34
35 get href() {
36 return this._href
37 }
38
39 set href(value) {
40 this._update(value)
41
42 this._params._parse(this.search)
43 }
44
45 // https://url.spec.whatwg.org/#dom-url-protocol
46
47 get protocol() {
48 return this._slice(0, this._components[0]) + ':'
49 }
50
51 set protocol(value) {
52 this._update(this._replace(value.replace(/:+$/, ''), 0, this._components[0]))
53 }
54
55 // https://url.spec.whatwg.org/#dom-url-username
56
57 get username() {
58 return this._slice(this._components[0] + 3 /* :// */, this._components[1])
59 }
60
61 set username(value) {
62 if (cannotHaveCredentialsOrPort(this)) {
63 return
64 }
65
66 if (this.username === '') value += '@'
67
68 this._update(this._replace(value, this._components[0] + 3 /* :// */, this._components[1]))
69 }
70
71 // https://url.spec.whatwg.org/#dom-url-password
72
73 get password() {
74 return this._href.slice(this._components[1] + 1 /* : */, this._components[2] - 1 /* @ */)
75 }
76
77 set password(value) {
78 if (cannotHaveCredentialsOrPort(this)) {
79 return
80 }
81
82 let start = this._components[1] + 1 /* : */
83 let end = this._components[2] - 1 /* @ */
84
85 if (this.password === '') {
86 value = ':' + value
87 start--
88 }
89
90 if (this.username === '') {
91 value += '@'
92 end++
93 }
94
95 this._update(this._replace(value, start, end))
96 }
97
98 // https://url.spec.whatwg.org/#dom-url-host
99
100 get host() {
101 return this._slice(this._components[2], this._components[5])
102 }
103
104 set host(value) {
105 if (hasOpaquePath(this)) {
106 return
107 }
108
109 this._update(
110 this._replace(value, this._components[2], this._components[value.includes(':') ? 5 : 3])
111 )
112 }
113
114 // https://url.spec.whatwg.org/#dom-url-hostname
115
116 get hostname() {
117 return this._slice(this._components[2], this._components[3])
118 }
119
120 set hostname(value) {
121 if (hasOpaquePath(this)) {
122 return
123 }
124
125 this._update(this._replace(value, this._components[2], this._components[3]))
126 }
127
128 // https://url.spec.whatwg.org/#dom-url-port
129
130 get port() {
131 return this._slice(this._components[3] + 1 /* : */, this._components[5])
132 }
133
134 set port(value) {
135 if (cannotHaveCredentialsOrPort(this)) {
136 return
137 }
138
139 let start = this._components[3] + 1 /* : */
140
141 if (this.port === '') {
142 value = ':' + value
143 start--
144 }
145
146 this._update(this._replace(value, start, this._components[5]))
147 }
148
149 // https://url.spec.whatwg.org/#dom-url-pathname
150
151 get pathname() {
152 return this._slice(this._components[5], this._components[6] - 1 /* ? */)
153 }
154
155 set pathname(value) {
156 if (hasOpaquePath(this)) {
157 return
158 }
159
160 if (value[0] !== '/' && value[0] !== '\\') {
161 value = '/' + value
162 }
163
164 this._update(this._replace(value, this._components[5], this._components[6] - 1 /* ? */))
165 }
166
167 // https://url.spec.whatwg.org/#dom-url-search
168
169 get search() {
170 return this._slice(this._components[6] - 1 /* ? */, this._components[7] - 1 /* # */)
171 }
172
173 set search(value) {
174 if (value && value[0] !== '?') value = '?' + value
175
176 this._update(
177 this._replace(value, this._components[6] - 1 /* ? */, this._components[7] - 1 /* # */)
178 )
179
180 this._params._parse(this.search)
181 }
182
183 // https://url.spec.whatwg.org/#dom-url-searchparams
184
185 get searchParams() {
186 return this._params
187 }
188
189 // https://url.spec.whatwg.org/#dom-url-hash
190
191 get hash() {
192 return this._slice(this._components[7] - 1 /* # */)
193 }
194
195 set hash(value) {
196 if (value && value[0] !== '#') value = '#' + value
197
198 this._update(this._replace(value, this._components[7] - 1 /* # */))
199 }
200
201 toString() {
202 return this._href
203 }
204
205 toJSON() {
206 return this._href
207 }
208
209 [Symbol.for('bare.inspect')]() {
210 return {
211 __proto__: { constructor: URL },
212
213 href: this.href,
214 protocol: this.protocol,
215 username: this.username,
216 password: this.password,
217 host: this.host,
218 hostname: this.hostname,
219 port: this.port,
220 pathname: this.pathname,
221 search: this.search,
222 searchParams: this.searchParams,
223 hash: this.hash
224 }
225 }
226
227 _slice(start, end = this._href.length) {
228 return this._href.slice(start, end)
229 }
230
231 _replace(replacement, start, end = this._href.length) {
232 return this._slice(0, start) + replacement + this._slice(end)
233 }
234
235 _parse(input, base, shouldThrow) {
236 try {
237 this._href = binding.parse(
238 String(input),
239 base ? String(base) : null,
240 this._components,
241 shouldThrow
242 )
243 } catch (err) {
244 if (err instanceof TypeError) throw err
245
246 throw errors.INVALID_URL(`Invalid URL '${input}'`, input)
247 }
248 }
249
250 _update(input) {
251 try {
252 this._parse(input, null, true)
253 } catch (err) {
254 if (err instanceof TypeError) throw err
255 }
256 }
257}
258
259module.exports = exports = URL
260
261// https://url.spec.whatwg.org/#url-opaque-path
262function hasOpaquePath(url) {
263 return url.pathname[0] !== '/'
264}
265
266// https://url.spec.whatwg.org/#cannot-have-a-username-password-port
267function cannotHaveCredentialsOrPort(url) {
268 return url.hostname === '' || url.protocol === 'file:'
269}
270
271exports.URL = URL
272exports.URLSearchParams = URLSearchParams
273
274exports.errors = errors
275
276exports.isURL = function isURL(value) {
277 if (value instanceof URL) return true
278
279 return typeof value === 'object' && value !== null && value[kind] === URL[kind]
280}
281
282exports.isURLSearchParams = URLSearchParams.isURLSearchParams
283
284// https://url.spec.whatwg.org/#dom-url-parse
285exports.parse = function parse(input, base) {
286 const url = new URL(input, base, { throw: false })
287 return url._href ? url : null
288}
289
290// https://url.spec.whatwg.org/#dom-url-canparse
291exports.canParse = function canParse(input, base) {
292 return binding.canParse(String(input), base ? String(base) : null)
293}
294
295exports.fileURLToPath = function fileURLToPath(url) {
296 if (typeof url === 'string') {
297 url = new URL(url)
298 }
299
300 if (url.protocol !== 'file:') {
301 throw errors.INVALID_URL_SCHEME('The URL must use the file: protocol')
302 }
303
304 if (isWindows) {
305 if (/%2f|%5c/i.test(url.pathname)) {
306 throw errors.INVALID_FILE_URL_PATH(
307 'The file: URL path must not include encoded \\ or / characters'
308 )
309 }
310 } else {
311 if (url.hostname) {
312 throw errors.INVALID_FILE_URL_HOST("The file: URL host must be 'localhost' or empty")
313 }
314
315 if (/%2f/i.test(url.pathname)) {
316 throw errors.INVALID_FILE_URL_PATH('The file: URL path must not include encoded / characters')
317 }
318 }
319
320 const pathname = path.normalize(decodeURIComponent(url.pathname))
321
322 if (isWindows) {
323 if (url.hostname) return '\\\\' + url.hostname + pathname
324
325 const letter = pathname.charCodeAt(1) | 0x20
326
327 if (letter < 0x61 /* a */ || letter > 0x7a /* z */ || pathname.charCodeAt(2) !== 0x3a /* : */) {
328 throw errors.INVALID_FILE_URL_PATH('The file: URL path must be absolute')
329 }
330
331 return pathname.slice(1)
332 }
333
334 return pathname
335}
336
337exports.pathToFileURL = function pathToFileURL(pathname) {
338 let resolved = path.resolve(pathname)
339
340 if (pathname[pathname.length - 1] === '/') {
341 resolved += '/'
342 } else if (isWindows && pathname[pathname.length - 1] === '\\') {
343 resolved += '\\'
344 }
345
346 resolved = resolved
347 .replaceAll('%', '%25') // Must be first
348 .replaceAll('#', '%23')
349 .replaceAll('?', '%3f')
350 .replaceAll('\n', '%0a')
351 .replaceAll('\r', '%0d')
352 .replaceAll('\t', '%09')
353
354 if (!isWindows) {
355 resolved = resolved.replaceAll('\\', '%5c')
356 }
357
358 return new URL('file:' + resolved)
359}
360
361exports.format = function format(parts) {
362 const { protocol, auth, host, hostname, port, pathname, search, query, hash, slashes } = parts
363
364 let result = ''
365
366 if (typeof protocol === 'string') {
367 result += protocol
368
369 if (protocol[protocol.length - 1] !== ':') {
370 result += ':'
371 }
372
373 if (slashes === true || /https?|ftp|gopher|file/.test(protocol)) {
374 result += '//'
375 }
376 }
377
378 if (typeof auth === 'string') {
379 if (host || hostname) result += auth + '@'
380 }
381
382 if (typeof host === 'string') result += host
383 else {
384 result += hostname
385
386 if (port) result += ':' + port
387 }
388
389 if (typeof pathname === 'string' && pathname !== '') {
390 if (pathname[0] !== '/') result += '/'
391 result += pathname
392 }
393
394 if (typeof search === 'string') {
395 if (search[0] !== '?') result += '?'
396 result += search
397 } else if (typeof query === 'object' && query !== null) {
398 result += '?' + new URLSearchParams(query)
399 }
400
401 if (typeof hash === 'string') {
402 if (hash[0] !== '#') result += '#'
403 result += hash
404 }
405
406 return result
407}
node_modules/bare-url/lib/errors.d.ts +10 -0
……@@ -0,0 +1,10 @@
1interface URLError extends Error {
2 readonly code: string
3 readonly input?: string
4}
5
6declare class URLError extends Error {
7 private constructor()
8}
9
10export = URLError
node_modules/bare-url/lib/errors.js +33 -0
……@@ -0,0 +1,33 @@
1module.exports = class URLError extends Error {
2 constructor(msg, fn = URLError, code = fn.name) {
3 super(`${code}: ${msg}`)
4
5 this.code = code
6
7 if (Error.captureStackTrace) Error.captureStackTrace(this, fn)
8 }
9
10 get name() {
11 return 'URLError'
12 }
13
14 static INVALID_URL(msg, input) {
15 const err = new URLError(msg, URLError.INVALID_URL)
16
17 err.input = input
18
19 return err
20 }
21
22 static INVALID_URL_SCHEME(msg = 'Invalid URL') {
23 return new URLError(msg, URLError.INVALID_URL_SCHEME)
24 }
25
26 static INVALID_FILE_URL_HOST(msg = 'Invalid file: URL host') {
27 return new URLError(msg, URLError.INVALID_FILE_URL_HOST)
28 }
29
30 static INVALID_FILE_URL_PATH(msg = 'Invalid file: URL path') {
31 return new URLError(msg, URLError.INVALID_FILE_URL_PATH)
32 }
33}
node_modules/bare-url/lib/url-search-params.d.ts +23 -0
……@@ -0,0 +1,23 @@
1interface URLSearchParams extends Iterable<[name: string, value: string]> {
2 readonly size: number
3
4 append(name: string, value: string): void
5 delete(name: string, value?: string): void
6 get(name: string): string | undefined
7 getAll(name: string): string[]
8 has(name: string, value?: string): boolean
9 set(name: string, value: string): void
10
11 toString(): string
12 toJSON(): string
13}
14
15declare class URLSearchParams {
16 constructor(init: string | Record<string, string> | Iterable<[string, string]>)
17}
18
19declare namespace URLSearchParams {
20 export function isURLSearchParams(value: unknown): value is URLSearchParams
21}
22
23export = URLSearchParams
node_modules/bare-url/lib/url-search-params.js +192 -0
……@@ -0,0 +1,192 @@
1const kind = Symbol.for('bare.url.search-params.kind')
2
3class URLSearchParams {
4 static _urls = new WeakMap()
5
6 static get [kind]() {
7 return 0 // Compatibility version
8 }
9
10 // https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams
11 constructor(init, url = null) {
12 this._params = new Map()
13
14 if (url) URLSearchParams._urls.set(this, url)
15
16 if (typeof init === 'string') {
17 this._parse(init)
18 } else if (init) {
19 for (const [name, value] of typeof init[Symbol.iterator] === 'function'
20 ? init
21 : Object.entries(init)) {
22 this.append(name, value)
23 }
24 }
25 }
26
27 get [kind]() {
28 return URLSearchParams[kind]
29 }
30
31 // https://url.spec.whatwg.org/#dom-urlsearchparams-size
32 get size() {
33 return this._params.length
34 }
35
36 // https://url.spec.whatwg.org/#dom-urlsearchparams-append
37 append(name, value = null) {
38 if (value === null) return
39
40 let list = this._params.get(name)
41
42 if (list === undefined) {
43 list = []
44 this._params.set(name, list)
45 }
46
47 list.push(value)
48
49 this._update()
50 }
51
52 // https://url.spec.whatwg.org/#dom-urlsearchparams-delete
53 delete(name, value = null) {
54 if (value === null) this._params.delete(name)
55 else {
56 let list = this._params.get(name)
57
58 if (list === undefined) return
59
60 list = list.filter((found) => found !== value)
61
62 if (list.length === 0) this._params.delete(name)
63 else this._params.set(name, list)
64 }
65
66 this._update()
67 }
68
69 // https://url.spec.whatwg.org/#dom-urlsearchparams-get
70 get(name) {
71 const list = this._params.get(name)
72
73 if (list === undefined) return null
74
75 return list[0]
76 }
77
78 // https://url.spec.whatwg.org/#dom-urlsearchparams-getall
79 getAll(name) {
80 const list = this._params.get(name)
81
82 if (list === undefined) return []
83
84 return Array.from(list)
85 }
86
87 // https://url.spec.whatwg.org/#dom-urlsearchparams-has
88 has(name, value = null) {
89 const list = this._params.get(name)
90
91 if (list === undefined) return false
92
93 if (value === null) return true
94
95 return list.includes(value)
96 }
97
98 // https://url.spec.whatwg.org/#dom-urlsearchparams-set
99 set(name, value = null) {
100 if (value === null) this._params.delete(name)
101 else this._params.set(name, [value])
102
103 this._update()
104 }
105
106 toString() {
107 return this._serialize()
108 }
109
110 toJSON() {
111 return [...this]
112 }
113
114 *[Symbol.iterator]() {
115 for (const [name, values] of this._params) {
116 for (const value of values) yield [name, value]
117 }
118 }
119
120 [Symbol.for('bare.inspect')]() {
121 const object = {
122 __proto__: { constructor: URLSearchParams }
123 }
124
125 for (const [name, values] of this._params) {
126 if (values.length === 1) object[name] = values[0]
127 else object[name] = values
128 }
129
130 return object
131 }
132
133 // https://url.spec.whatwg.org/#concept-urlsearchparams-update
134 _update() {
135 const url = URLSearchParams._urls.get(this)
136
137 if (url === undefined) return
138
139 url.search = this._serialize()
140 }
141
142 // https://url.spec.whatwg.org/#concept-urlencoded-parser
143 _parse(input) {
144 if (input[0] === '?') input = input.substring(1)
145
146 this._params = new Map()
147
148 for (const sequence of input.split('&')) {
149 if (sequence.length === 0) continue
150
151 let i = sequence.indexOf('=')
152 if (i === -1) i = sequence.length
153
154 const name = decodeURIComponent(sequence.substring(0, i))
155 const value = decodeURIComponent(sequence.substring(i + 1, sequence.length))
156
157 let list = this._params.get(name)
158
159 if (list === undefined) {
160 list = []
161 this._params.set(name, list)
162 }
163
164 list.push(value)
165 }
166 }
167
168 // https://url.spec.whatwg.org/#concept-urlencoded-serializer
169 _serialize() {
170 let output = ''
171
172 for (let [name, values] of this._params) {
173 name = encodeURIComponent(name)
174
175 for (const value of values) {
176 if (output) output += '&'
177
178 output += name + '=' + encodeURIComponent(value)
179 }
180 }
181
182 return output
183 }
184}
185
186module.exports = exports = URLSearchParams
187
188exports.isURLSearchParams = function isURLSearchParams(value) {
189 if (value instanceof URLSearchParams) return true
190
191 return typeof value === 'object' && value !== null && value[kind] === URLSearchParams[kind]
192}
node_modules/bare-url/package.json +51 -0
……@@ -0,0 +1,51 @@
1{
2 "name": "bare-url",
3 "version": "2.4.0",
4 "description": "WHATWG URL implementation for JavaScript",
5 "exports": {
6 "./package": "./package.json",
7 ".": {
8 "types": "./index.d.ts",
9 "default": "./index.js"
10 },
11 "./global": {
12 "types": "./global.d.ts",
13 "default": "./global.js"
14 }
15 },
16 "files": [
17 "index.js",
18 "index.d.ts",
19 "global.js",
20 "global.d.ts",
21 "binding.c",
22 "binding.js",
23 "CMakeLists.txt",
24 "lib",
25 "prebuilds"
26 ],
27 "addon": true,
28 "scripts": {
29 "test": "prettier . --check && bare test.js"
30 },
31 "repository": {
32 "type": "git",
33 "url": "git+https://github.com/holepunchto/bare-url.git"
34 },
35 "author": "Holepunch",
36 "license": "Apache-2.0",
37 "bugs": {
38 "url": "https://github.com/holepunchto/bare-url/issues"
39 },
40 "homepage": "https://github.com/holepunchto/bare-url",
41 "dependencies": {
42 "bare-path": "^3.0.0"
43 },
44 "devDependencies": {
45 "brittle": "^3.3.2",
46 "cmake-bare": "^1.1.6",
47 "cmake-fetch": "^1.0.0",
48 "prettier": "^3.3.3",
49 "prettier-config-holepunch": "^2.0.0"
50 }
51}
node_modules/bare-url/prebuilds/android-arm/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/android-arm64/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/android-ia32/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/android-x64/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/darwin-arm64/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/darwin-x64/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/ios-arm64-simulator/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/ios-arm64/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/ios-x64-simulator/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/linux-arm64/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/linux-x64/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/win32-arm64/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/bare-url/prebuilds/win32-x64/bare-url.bare +0 -0
(no content changes — binary or rename)
node_modules/big-sparse-array/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - master
6 pull_request:
7 branches:
8 - master
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v2
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v2
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/big-sparse-array/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2020 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/big-sparse-array/README.md +43 -0
……@@ -0,0 +1,43 @@
1# big-sparse-array
2
3A sparse array optimised for low memory whilst still being fast.
4
5```
6npm install big-sparse-array
7```
8
9Uses a shallow tree structure with a branching factor of 4096
10to index a series of small arrays that try to compress as much as possible
11to reduce the memory overhead needed.
12
13Similar to a Map, except it is faster, but might use a bit more memory, ymmv.
14
15## Usage
16
17``` js
18const BigSparseArray = require('big-sparse-array')
19
20const b = new BigSparseArray()
21
22b.set(42422242525, true)
23b.get(42422242525) // returns true
24b.get(111111111) // returns undefined
25```
26
27## API
28
29#### `const b = new BigSparseArray()`
30
31Make a new sparse array.
32
33#### `b.set(index, value)`
34
35Insert a new value at an index. `index` must be a integer.
36
37#### `value = b.get(index)`
38
39Get a value out. Returns `undefined` if the value could not be found.
40
41## License
42
43MIT
node_modules/big-sparse-array/index.js +124 -0
……@@ -0,0 +1,124 @@
1const FACTOR = new Uint16Array(8)
2
3function factor4096 (i, n) {
4 while (n > 0) {
5 const f = i & 4095
6 FACTOR[--n] = f
7 i = (i - f) / 4096
8 }
9 return FACTOR
10}
11
12module.exports = class BigSparseArray {
13 constructor () {
14 this.tiny = new TinyArray()
15 this.maxLength = 4096
16 this.factor = 1
17 }
18
19 set (index, val) {
20 if (val !== undefined) {
21 while (index >= this.maxLength) {
22 this.maxLength *= 4096
23 this.factor++
24 if (!this.tiny.isEmptyish()) {
25 const t = new TinyArray()
26 t.set(0, this.tiny)
27 this.tiny = t
28 }
29 }
30 }
31
32 const f = factor4096(index, this.factor)
33 const last = this.factor - 1
34
35 let tiny = this.tiny
36 for (let i = 0; i < last; i++) {
37 const next = tiny.get(f[i])
38 if (next === undefined) {
39 if (val === undefined) return
40 tiny = tiny.set(f[i], new TinyArray())
41 } else {
42 tiny = next
43 }
44 }
45
46 return tiny.set(f[last], val)
47 }
48
49 get (index) {
50 if (index >= this.maxLength) return
51
52 const f = factor4096(index, this.factor)
53 const last = this.factor - 1
54
55 let tiny = this.tiny
56 for (let i = 0; i < last; i++) {
57 tiny = tiny.get(f[i])
58 if (tiny === undefined) return
59 }
60
61 return tiny.get(f[last])
62 }
63}
64
65class TinyArray {
66 constructor () {
67 this.s = 0
68 this.b = new Array(1)
69 this.f = new Uint16Array(1)
70 }
71
72 isEmptyish () {
73 return this.b.length === 1 && this.b[0] === undefined
74 }
75
76 get (i) {
77 if (this.s === 12) return this.b[i]
78 const f = i >>> this.s
79 const r = i & (this.b.length - 1)
80 return this.f[r] === f ? this.b[r] : undefined
81 }
82
83 set (i, v) {
84 while (this.s !== 12) {
85 const f = i >>> this.s
86 const r = i & (this.b.length - 1)
87 const o = this.b[r]
88
89 if (o === undefined || f === this.f[r]) {
90 this.b[r] = v
91 this.f[r] = f
92 return v
93 }
94
95 this.grow()
96 }
97
98 this.b[i] = v
99 return v
100 }
101
102 grow () {
103 const os = this.s
104 const ob = this.b
105 const of = this.f
106
107 this.s += 4
108 this.b = new Array(this.b.length << 4)
109 this.f = this.s === 12 ? null : new Uint8Array(this.b.length)
110
111 const m = this.b.length - 1
112
113 for (let or = 0; or < ob.length; or++) {
114 if (ob[or] === undefined) continue
115
116 const i = of[or] << os | or
117 const f = i >>> this.s
118 const r = i & m
119
120 this.b[r] = ob[or]
121 if (this.s !== 12) this.f[r] = f
122 }
123 }
124}
node_modules/big-sparse-array/package.json +24 -0
……@@ -0,0 +1,24 @@
1{
2 "name": "big-sparse-array",
3 "version": "1.0.3",
4 "description": "A sparse array optimised for low memory whilst still being fast",
5 "main": "index.js",
6 "dependencies": {},
7 "devDependencies": {
8 "brittle": "^3.1.1",
9 "standard": "^16.0.3"
10 },
11 "scripts": {
12 "test": "standard && brittle test.js"
13 },
14 "repository": {
15 "type": "git",
16 "url": "https://github.com/mafintosh/big-sparse-array.git"
17 },
18 "author": "Mathias Buus (@mafintosh)",
19 "license": "MIT",
20 "bugs": {
21 "url": "https://github.com/mafintosh/big-sparse-array/issues"
22 },
23 "homepage": "https://github.com/mafintosh/big-sparse-array"
24}
node_modules/big-sparse-array/test.js +41 -0
……@@ -0,0 +1,41 @@
1const test = require('brittle')
2const BigSparseArray = require('./')
3
4test('basic', function (t) {
5 const b = new BigSparseArray()
6
7 b.set(42, true)
8 t.is(b.get(42), true)
9
10 b.set(42, 42)
11 t.is(b.get(42), 42)
12
13 b.set(42424242424242, 'big')
14 t.is(b.get(42424242424242), 'big')
15 t.is(b.get(42424242424243), undefined)
16 t.is(b.get(42), 42)
17})
18
19test('grow', function (t) {
20 const b = new BigSparseArray()
21
22 for (let i = 0; i < 10000; i++) {
23 b.set(i, i)
24 }
25
26 let missing = 10000
27
28 for (let i = 0; i < 10000; i++) {
29 if (b.get(i) === i) missing--
30 }
31
32 t.is(missing, 0)
33})
34
35test('bounds', function (t) {
36 const b = new BigSparseArray()
37
38 b.set(0, true)
39
40 t.is(b.get(4096), undefined)
41})
node_modules/binary-stream-equals/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - master
6 pull_request:
7 branches:
8 - master
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v2
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v2
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/binary-stream-equals/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2022 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/binary-stream-equals/README.md +22 -0
……@@ -0,0 +1,22 @@
1# binary-stream-equals
2
3Check if two binary streams have the same content
4
5```
6npm install binary-stream-equals
7```
8
9(Only works with [streamx](https://github.com/streamxorg/streamx) and the latest versions of Node's readable-stream)
10
11## Usage
12
13``` js
14const streamEquals = require('binary-stream-equals')
15
16// Note that streamEquals consumes and destroys the streams when done
17const eq = await streamEquals(binaryStreamA, binaryStreamB)
18```
19
20## License
21
22MIT
node_modules/binary-stream-equals/index.js +101 -0
……@@ -0,0 +1,101 @@
1const b4a = require('b4a')
2
3module.exports = function (a, b) {
4 return new Promise((resolve, reject) => binaryEquals(a, b, resolve, reject))
5}
6
7function binaryEquals (a, b, resolve, reject) {
8 let aBuf = null
9 let aEnded = false
10
11 let bBuf = null
12 let bEnded = false
13
14 let closed = 0
15 let done = false
16 let error = null
17 let equals = false
18
19 a.on('readable', tick)
20 a.on('end', onend)
21 a.on('error', onerror)
22 a.on('close', onclose)
23
24 b.on('readable', tick)
25 b.on('end', onend)
26 b.on('error', onerror)
27 b.on('close', onclose)
28
29 function onerror (err) {
30 error = err
31 a.destroy()
32 b.destroy()
33 }
34
35 function onclose () {
36 if (++closed !== 2) return
37 if (error !== null && done === false) reject(error)
38 else resolve(equals)
39 }
40
41 function ondone (eq) {
42 if (done) return
43 done = true
44
45 equals = eq
46
47 a.destroy()
48 b.destroy()
49 }
50
51 function onend () {
52 if (this === a) aEnded = true
53 else bEnded = true
54 tick()
55 }
56
57 function tick () {
58 while (done === false) {
59 if (aBuf === null) aBuf = a.read()
60 if (bBuf === null) bBuf = b.read()
61
62 if (aBuf === null && bBuf === null && aEnded && bEnded) {
63 ondone(true)
64 return
65 }
66
67 if (aBuf !== null && (bBuf === null && bEnded)) {
68 ondone(false)
69 return
70 }
71
72 if (bBuf !== null && (aBuf === null && aEnded)) {
73 ondone(false)
74 return
75 }
76
77 if (aBuf === null || bBuf === null) return // read pending
78
79 if (aBuf.byteLength === bBuf.byteLength) {
80 if (b4a.equals(aBuf, bBuf)) {
81 aBuf = bBuf = null
82 continue
83 }
84
85 ondone(false)
86 return
87 }
88
89 const min = Math.min(aBuf.byteLength, bBuf.byteLength)
90
91 if (b4a.equals(aBuf.subarray(0, min), bBuf.subarray(0, min))) {
92 aBuf = aBuf.byteLength === min ? null : aBuf.subarray(min)
93 bBuf = bBuf.byteLength === min ? null : bBuf.subarray(min)
94 continue
95 }
96
97 ondone(false)
98 return
99 }
100 }
101}
node_modules/binary-stream-equals/package.json +27 -0
……@@ -0,0 +1,27 @@
1{
2 "name": "binary-stream-equals",
3 "version": "1.0.0",
4 "description": "Check if two binary streams have the same content",
5 "main": "index.js",
6 "dependencies": {
7 "b4a": "^1.3.1"
8 },
9 "devDependencies": {
10 "brittle": "^2.2.7",
11 "standard": "^16.0.4",
12 "streamx": "^2.12.4"
13 },
14 "scripts": {
15 "test": "standard && brittle test.js"
16 },
17 "repository": {
18 "type": "git",
19 "url": "https://github.com/mafintosh/binary-stream-equals.git"
20 },
21 "author": "Mathias Buus (@mafintosh)",
22 "license": "MIT",
23 "bugs": {
24 "url": "https://github.com/mafintosh/binary-stream-equals/issues"
25 },
26 "homepage": "https://github.com/mafintosh/binary-stream-equals"
27}
node_modules/binary-stream-equals/test.js +164 -0
……@@ -0,0 +1,164 @@
1const test = require('brittle')
2const { Readable } = require('streamx')
3const streamEquals = require('./')
4
5test('two exactly equal streams', async function (t) {
6 const a = Readable.from([
7 Buffer.from('abe'),
8 Buffer.from('fest'),
9 Buffer.from('er'),
10 Buffer.from('sjov')
11 ])
12
13 const b = Readable.from([
14 Buffer.from('abe'),
15 Buffer.from('fest'),
16 Buffer.from('er'),
17 Buffer.from('sjov')
18 ])
19
20 const eq = await streamEquals(a, b)
21
22 t.is(eq, true)
23})
24
25test('two exactly unequal streams', async function (t) {
26 const a = Readable.from([
27 Buffer.from('abe'),
28 Buffer.from('fest'),
29 Buffer.from('er'),
30 Buffer.from('sjov')
31 ])
32
33 const b = Readable.from([
34 Buffer.from('abe'),
35 Buffer.from('fest'),
36 Buffer.from('er'),
37 Buffer.from('sjow')
38 ])
39
40 const eq = await streamEquals(a, b)
41
42 t.is(eq, false)
43})
44
45test('first block is different', async function (t) {
46 const a = Readable.from([
47 Buffer.from('abe'),
48 Buffer.from('fest'),
49 Buffer.from('er'),
50 Buffer.from('sjov')
51 ])
52
53 const b = Readable.from([
54 Buffer.from('xbe'),
55 Buffer.from('fest'),
56 Buffer.from('er'),
57 Buffer.from('sjov')
58 ])
59
60 const eq = await streamEquals(a, b)
61
62 t.is(eq, false)
63})
64
65test('two equal streams', async function (t) {
66 const a = Readable.from([
67 Buffer.from('abe'),
68 Buffer.from('fest'),
69 Buffer.from('er'),
70 Buffer.from('sjov')
71 ])
72
73 const b = Readable.from([
74 Buffer.from('abef'),
75 Buffer.from('es'),
76 Buffer.from('t'),
77 Buffer.from('e'),
78 Buffer.from('rsjov')
79 ])
80
81 const eq = await streamEquals(a, b)
82
83 t.is(eq, true)
84})
85
86test('two unequal streams', async function (t) {
87 const a = Readable.from([
88 Buffer.from('abe'),
89 Buffer.from('fest'),
90 Buffer.from('er'),
91 Buffer.from('sjov')
92 ])
93
94 const b = Readable.from([
95 Buffer.from('abef'),
96 Buffer.from('es'),
97 Buffer.from('t'),
98 Buffer.from('e'),
99 Buffer.from('rsjow')
100 ])
101
102 const eq = await streamEquals(a, b)
103
104 t.is(eq, false)
105})
106
107test('one stream shorter than the other', async function (t) {
108 const a = Readable.from([
109 Buffer.from('abe'),
110 Buffer.from('fest'),
111 Buffer.from('er'),
112 Buffer.from('sjov')
113 ])
114
115 const b = Readable.from([
116 Buffer.from('abe'),
117 Buffer.from('fest'),
118 Buffer.from('er')
119 ])
120
121 const eq = await streamEquals(a, b)
122
123 t.is(eq, false)
124})
125
126test('second stream is stream shorter than the other', async function (t) {
127 const a = Readable.from([
128 Buffer.from('abe'),
129 Buffer.from('fest'),
130 Buffer.from('er')
131 ])
132
133 const b = Readable.from([
134 Buffer.from('abe'),
135 Buffer.from('fest'),
136 Buffer.from('er'),
137 Buffer.from('sjov')
138 ])
139
140 const eq = await streamEquals(a, b)
141
142 t.is(eq, false)
143})
144
145test('one fails', async function (t) {
146 const a = Readable.from([
147 Buffer.from('abe'),
148 Buffer.from('fest'),
149 Buffer.from('er'),
150 Buffer.from('sjov')
151 ])
152
153 const b = Readable.from([
154 Buffer.from('abef'),
155 Buffer.from('es'),
156 Buffer.from('t'),
157 Buffer.from('e'),
158 Buffer.from('rsjov')
159 ])
160
161 b.destroy(new Error('stop'))
162
163 t.exception(streamEquals(a, b))
164})
node_modules/codecs/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - master
6 pull_request:
7 branches:
8 - master
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v2
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v2
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/codecs/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2016 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/codecs/README.md +56 -0
……@@ -0,0 +1,56 @@
1# codecs
2
3Create an binary encoder/decoder for Node's build in types like, json, utf-8, hex.
4
5```
6npm install codecs
7```
8
9Useful to support value encodings similar to leveldb's.
10
11## Usage
12
13``` js
14const codecs = require('codecs')
15const json = codecs('json')
16
17console.log(json.encode({ hello: 'world' })) // Buffer.from('{"hello":"world"}')
18console.log(json.decode(new Buffer('{"hello":"world"}'))) // { hello: 'world' }
19```
20
21## API
22
23#### `const codec = codecs(type, [fallback])`
24
25Create a new codec.
26
27Supported types are
28
29* utf8
30* json
31* [ndjson](http://ndjson.org/)
32* binary
33* hex
34* ascii
35* base64
36* ucs2
37* ucs-2
38* utf16le
39* utf-16le
40* binary
41
42If an unknown type is passed-in, the `fallback` is used if given, else `binary`.
43If you want to use a custom codec you can pass in an object containing a an `encode` and `decode` method and that will be returned.
44If you pass a [compact encoder](https://github.com/compact-encoding/compact-encoding), then it will be converted into a codec for you and returned.
45
46#### `const buf = codec.encode(value)`
47
48Encode a value to a buffer.
49
50#### `const value = codec.decode(buf)`
51
52Decode a buffer to a value.
53
54## License
55
56MIT
node_modules/codecs/index.js +96 -0
……@@ -0,0 +1,96 @@
1const b4a = require('b4a')
2
3module.exports = codecs
4
5codecs.ascii = createString('ascii')
6codecs.utf8 = createString('utf-8')
7codecs.hex = createString('hex')
8codecs.base64 = createString('base64')
9codecs.ucs2 = createString('ucs2')
10codecs.utf16le = createString('utf16le')
11codecs.ndjson = createJSON(true)
12codecs.json = createJSON(false)
13codecs.binary = {
14 name: 'binary',
15 encode: function encodeBinary (obj) {
16 return typeof obj === 'string'
17 ? b4a.from(obj, 'utf-8')
18 : b4a.toBuffer(obj)
19 },
20 decode: function decodeBinary (buf) {
21 return b4a.toBuffer(buf)
22 }
23}
24
25function isCompactEncoding (c) {
26 return !!(c.encode && c.decode && c.preencode)
27}
28
29function fromCompactEncoding (c) {
30 return {
31 name: 'compact-encoding',
32 encode: function encodeWithCompact (value) {
33 const state = { start: 0, end: 0, buffer: null, cache: null }
34 c.preencode(state, value)
35 state.buffer = b4a.allocUnsafe(state.end)
36 c.encode(state, value)
37 return state.buffer
38 },
39 decode: function decodeWithCompact (buffer) {
40 return c.decode({ start: 0, end: buffer.byteLength, buffer, cache: null })
41 }
42 }
43}
44
45function codecs (fmt, fallback) {
46 if (typeof fmt === 'object' && fmt) {
47 return isCompactEncoding(fmt) ? fromCompactEncoding(fmt) : fmt
48 }
49
50 switch (fmt) {
51 case 'ndjson': return codecs.ndjson
52 case 'json': return codecs.json
53 case 'ascii': return codecs.ascii
54 case 'utf-8':
55 case 'utf8': return codecs.utf8
56 case 'hex': return codecs.hex
57 case 'base64': return codecs.base64
58 case 'ucs-2':
59 case 'ucs2': return codecs.ucs2
60 case 'utf16-le':
61 case 'utf16le': return codecs.utf16le
62 }
63
64 return fallback !== undefined ? fallback : codecs.binary
65}
66
67function createJSON (newline) {
68 return {
69 name: newline ? 'ndjson' : 'json',
70 encode: newline ? encodeNDJSON : encodeJSON,
71 decode: function decodeJSON (buf) {
72 return JSON.parse(b4a.toString(buf))
73 }
74 }
75
76 function encodeJSON (val) {
77 return b4a.from(JSON.stringify(val))
78 }
79
80 function encodeNDJSON (val) {
81 return b4a.from(JSON.stringify(val) + '\n')
82 }
83}
84
85function createString (type) {
86 return {
87 name: type,
88 encode: function encodeString (val) {
89 if (typeof val !== 'string') val = val.toString()
90 return b4a.from(val, type)
91 },
92 decode: function decodeString (buf) {
93 return b4a.toString(buf, type)
94 }
95 }
96}
node_modules/codecs/package.json +27 -0
……@@ -0,0 +1,27 @@
1{
2 "name": "codecs",
3 "version": "3.1.0",
4 "description": "Create an binary encoder/decoder for json, utf-8 or custom types",
5 "main": "index.js",
6 "dependencies": {
7 "b4a": "^1.6.3"
8 },
9 "devDependencies": {
10 "brittle": "^3.2.1",
11 "compact-encoding": "^2.11.0",
12 "standard": "^17.0.0"
13 },
14 "scripts": {
15 "test": "standard && brittle test.js"
16 },
17 "repository": {
18 "type": "git",
19 "url": "https://github.com/mafintosh/codecs.git"
20 },
21 "author": "Mathias Buus (@mafintosh)",
22 "license": "MIT",
23 "bugs": {
24 "url": "https://github.com/mafintosh/codecs/issues"
25 },
26 "homepage": "https://github.com/mafintosh/codecs"
27}
node_modules/codecs/test.js +75 -0
……@@ -0,0 +1,75 @@
1const test = require('brittle')
2const c = require('compact-encoding')
3const codecs = require('./')
4
5test('json', function (t) {
6 const enc = codecs('json')
7 t.alike(enc.name, 'json')
8 t.alike(enc.encode({}), Buffer.from('{}'))
9 t.alike(enc.decode(Buffer.from('{}')), {})
10})
11
12test('utf-8', function (t) {
13 const enc = codecs('utf-8')
14 t.alike(enc.name, 'utf-8')
15 t.alike(enc.encode('hello world'), Buffer.from('hello world'))
16 t.alike(enc.decode(Buffer.from('hello world')), 'hello world')
17})
18
19test('hex', function (t) {
20 const enc = codecs('hex')
21 t.alike(enc.name, 'hex')
22 t.alike(enc.encode('abcd'), Buffer.from([0xab, 0xcd]))
23 t.alike(enc.decode(Buffer.from([0xab, 0xcd])), 'abcd')
24})
25
26test('binary', function (t) {
27 const enc = codecs()
28 t.alike(enc.name, 'binary')
29 const input = Buffer.from('hello world')
30 t.alike(enc.encode('hello world'), input)
31 t.alike(enc.encode(input), input)
32 t.alike(enc.decode(input), input)
33 const uint8 = new Uint8Array(input.buffer, input.byteOffset, input.byteLength)
34 t.ok(Buffer.isBuffer(enc.encode(uint8)))
35 t.alike(enc.encode(uint8).compare(input), 0)
36 t.ok(Buffer.isBuffer(enc.decode(uint8)))
37 t.alike(enc.decode(uint8).compare(input), 0)
38})
39
40test('custom', function (t) {
41 const enc = codecs({
42 name: 'custom',
43 encode: function () {
44 return Buffer.from('lol')
45 },
46 decode: function () {
47 return 42
48 }
49 })
50
51 t.alike(enc.name, 'custom')
52 t.alike(enc.encode('hello'), Buffer.from('lol'))
53 t.alike(enc.encode(42), Buffer.from('lol'))
54 t.alike(enc.decode(Buffer.from('lol')), 42)
55})
56
57test('uint8arrays in binary', function (t) {
58 const enc = codecs('binary')
59 const buf = enc.encode(new Uint8Array([1, 2, 3]))
60 t.alike(buf, Buffer.from([1, 2, 3]))
61})
62
63test('custom fallback', function (t) {
64 t.alike(codecs('baseless', null), null)
65 const custom = { decode: function () {}, encode: function () {} }
66 t.alike(codecs('baseless', custom), custom)
67})
68
69test('compact encoding', function (t) {
70 const uint = codecs(c.uint)
71 t.alike(uint.encode(4), Buffer.from([4]))
72 t.alike(uint.encode(1000), Buffer.from([253, 232, 3]))
73 t.alike(uint.decode(Buffer.from([4])), 4)
74 t.alike(uint.decode(Buffer.from([253, 232, 3])), 1000)
75})
node_modules/compact-encoding/.gitattributes +1 -0
……@@ -0,0 +1 @@
1* text=auto eol=lf
node_modules/compact-encoding/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - main
6 pull_request:
7 branches:
8 - main
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v2
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v2
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/compact-encoding/.prettierrc +1 -0
……@@ -0,0 +1 @@
1prettier-config-holepunch
node_modules/compact-encoding/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/compact-encoding/NOTICE +13 -0
……@@ -0,0 +1,13 @@
1Copyright 2023 Holepunch Inc
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
node_modules/compact-encoding/README.md +165 -0
……@@ -0,0 +1,165 @@
1# compact-encoding
2
3A series of compact encoding schemes for building small and fast parsers and serializers
4
5```
6npm install compact-encoding
7```
8
9## Usage
10
11```js
12const cenc = require('compact-encoding')
13
14const state = cenc.state()
15
16// use preencode to figure out how big a buffer is needed
17cenc.uint.preencode(state, 42)
18cenc.string.preencode(state, 'hi')
19
20console.log(state) // { start: 0, end: 4, buffer: null }
21
22state.buffer = Buffer.allocUnsafe(state.end)
23
24// then use encode to actually encode it to the buffer
25cenc.uint.encode(state, 42)
26cenc.string.encode(state, 'hi')
27
28// to decode it simply use decode instead
29
30state.start = 0
31cenc.uint.decode(state) // 42
32cenc.string.decode(state) // 'hi'
33```
34
35## Encoder API
36
37#### `state`
38
39Should be an object that looks like this `{ start, end, buffer }`.
40
41You can also get a blank state object using `cenc.state()`.
42
43- `start` is the byte offset to start encoding/decoding at.
44- `end` is the byte offset indicating the end of the buffer.
45- `buffer` should be either a Node.js Buffer or Uint8Array.
46
47#### `enc.preencode(state, val)`
48
49Does a fast preencode dry-run that only sets state.end.
50Use this to figure out how big of a buffer you need.
51
52#### `enc.encode(state, val)`
53
54Encodes `val` into `state.buffer` at position `state.start`.
55Updates `state.start` to point after the encoded value when done.
56
57#### `val = enc.decode(state)`
58
59Decodes a value from `state.buffer` as position `state.start`.
60Updates `state.start` to point after the decoded value when done in the buffer.
61
62## Helpers
63
64If you are just encoding to a buffer or decoding from one you can use the `encode` and `decode` helpers
65to reduce your boilerplate
66
67```js
68const buf = cenc.encode(cenc.bool, true)
69const bool = cenc.decode(cenc.bool, buf)
70```
71
72## Bundled encodings
73
74The following encodings are bundled as they are primitives that can be used
75to build others on top. Feel free to PR more that are missing.
76
77- `cenc.raw` - Pass through encodes a buffer, i.e. a basic copy.
78- `cenc.uint` - Encodes a uint using the smallest fixed size encoding with a prefix to signal which one. Useful for uints that can be a wide range of values.
79- `cenc.uint8` - Encodes a fixed size uint8.
80- `cenc.uint16` - Encodes a fixed size uint16. Useful for things like ports.
81- `cenc.uint24` - Encodes a fixed size uint24. Useful for message framing.
82- `cenc.uint32` - Encodes a fixed size uint32. Useful for very large message framing.
83- `cenc.uint40` - Encodes a fixed size uint40.
84- `cenc.uint48` - Encodes a fixed size uint48.
85- `cenc.uint56` - Encodes a fixed size uint56.
86- `cenc.uint64` - Encodes a fixed size uint64.
87- `cenc.int` - Encodes an int using `cenc.uint` with ZigZag encoding.
88- `cenc.int8` - Encodes a fixed size int8 using `cenc.uint8` with ZigZag encoding.
89- `cenc.int16` - Encodes a fixed size int16 using `cenc.uint16` with ZigZag encoding.
90- `cenc.int24` - Encodes a fixed size int24 using `cenc.uint24` with ZigZag encoding.
91- `cenc.int32` - Encodes a fixed size int32 using `cenc.uint32` with ZigZag encoding.
92- `cenc.int40` - Encodes a fixed size int40 using `cenc.uint40` with ZigZag encoding.
93- `cenc.int48` - Encodes a fixed size int48 using `cenc.uint48` with ZigZag encoding.
94- `cenc.int56` - Encodes a fixed size int56 using `cenc.uint56` with ZigZag encoding.
95- `cenc.int64` - Encodes a fixed size int64 using `cenc.uint64` with ZigZag encoding.
96- `cenc.biguint64` - Encodes a fixed size biguint64.
97- `cenc.bigint64` - Encodes a fixed size bigint64 using `cenc.biguint64` with ZigZag encoding.
98- `cenc.biguint` - Encodes a biguint with its word count uint prefixed.
99- `cenc.bigint` - Encodes a bigint using `cenc.biguint` with ZigZag encoding.
100- `cenc.float32` - Encodes a fixed size float32.
101- `cenc.float64` - Encodes a fixed size float64.
102- `cenc.buffer` - Encodes a buffer with its length uint prefixed. When decoding an empty buffer, `null` is returned.
103- `cenc.raw.buffer` - Encodes a buffer without a length prefixed.
104- `cenc.arraybuffer` - Encodes an arraybuffer with its length uint prefixed.
105- `cenc.raw.arraybuffer` - Encodes an arraybuffer without a length prefixed.
106- `cenc.uint8array` - Encodes a uint8array with its element length uint prefixed.
107- `cenc.raw.uint8array` - Encodes a uint8array without a length prefixed.
108- `cenc.uint16array` - Encodes a uint16array with its element length uint prefixed.
109- `cenc.raw.uint16array` - Encodes a uint16array without a length prefixed.
110- `cenc.uint32array` - Encodes a uint32array with its element length uint prefixed.
111- `cenc.raw.uint32array` - Encodes a uint32array without a length prefixed.
112- `cenc.int8array` - Encodes a int8array with its element length uint prefixed.
113- `cenc.raw.int8array` - Encodes a int8array without a length prefixed.
114- `cenc.int16array` - Encodes a int16array with its element length uint prefixed.
115- `cenc.raw.int16array` - Encodes a int16array without a length prefixed.
116- `cenc.int32array` - Encodes a int32array with its element length uint prefixed.
117- `cenc.raw.int32array` - Encodes a int32array without a length prefixed.
118- `cenc.biguint64array` - Encodes a biguint64array with its element length uint prefixed.
119- `cenc.raw.biguint64array` - Encodes a biguint64array without a length prefixed.
120- `cenc.bigint64array` - Encodes a bigint64array with its element length uint prefixed.
121- `cenc.raw.bigint64array` - Encodes a bigint64array without a length prefixed.
122- `cenc.float32array` - Encodes a float32array with its element length uint prefixed.
123- `cenc.raw.float32array` - Encodes a float32array without a length prefixed.
124- `cenc.float64array` - Encodes a float64array with its element length uint prefixed.
125- `cenc.raw.float64array` - Encodes a float64array without a length prefixed.
126- `cenc.bool` - Encodes a boolean as 1 or 0.
127- `cenc.string`, `cenc.utf8` - Encodes a utf-8 string, similar to buffer.
128- `cenc.raw.string`, `cenc.raw.utf8` - Encodes a utf-8 string without a length prefixed.
129- `cenc.string.fixed(n)`, `cenc.utf8.fixed(n)` - Encodes a fixed sized utf-8 string.
130- `cenc.ascii` - Encodes an ascii string.
131- `cenc.raw.ascii` - Encodes an ascii string without a length prefixed.
132- `cenc.ascii.fixed(n)` - Encodes a fixed size ascii string.
133- `cenc.hex` - Encodes a hex string.
134- `cenc.raw.hex` - Encodes a hex string without a length prefixed.
135- `cenc.hex.fixed(n)` - Encodes a fixed size hex string.
136- `cenc.base64` - Encodes a base64 string.
137- `cenc.raw.base64` - Encodes a base64 string without a length prefixed.
138- `cenc.base64.fixed(n)` - Encodes a fixed size base64 string.
139- `cenc.utf16le`, `cenc.ucs2` - Encodes a utf16le string.
140- `cenc.raw.utf16le`, `cenc.raw.ucs2` - Encodes a utf16le string without a length prefixed.
141- `cenc.utf16le.fixed(n)`, `cenc.ucs2.fixed(n)` - Encodes a fixed size utf16le string.
142- `cenc.fixed32` - Encodes a fixed 32 byte buffer.
143- `cenc.fixed64` - Encodes a fixed 64 byte buffer.
144- `cenc.fixed(n)` - Makes a fixed sized encoder.
145- `cenc.date(d)` - Encodes a date object.
146- `cenc.array(enc)` - Makes an array encoder from another encoder. Arrays are uint prefixed with their length.
147- `cenc.raw.array(enc)` - Makes an array encoder from another encoder, without a length prefixed.
148- `cenc.json` - Encodes a JSON value as utf-8.
149- `cenc.raw.json` - Encodes a JSON value as utf-8 without a length prefixed.
150- `cenc.ndjson` - Encodes a JSON value as newline delimited utf-8.
151- `cenc.raw.ndjson` - Encodes a JSON value as newline delimited utf-8 without a length prefixed.
152- `cenc.any` - Encodes any JSON representable value into a self described buffer. Like JSON + buffer, but using compact types. Useful for schemaless codecs.
153- `cenc.port` - Encodes a port number for network addresses.
154- `cenc.ipv4` - Encodes an IPv4 network address.
155- `cenc.ipv4Address` Encodes an IPv4 network address and a port number.
156- `cenc.ipv6` - Encodes an IPv6 network address.
157- `cenc.ipv6Address` Encodes an IPv6 network address and a port number.
158- `cenc.ip` - Encodes a dual IPv4/6 network address.
159- `cenc.ipAddress` Encodes a dual IPv4/6 network address and a port number.
160- `cenc.from(enc)` - Makes a compact encoder from a [codec](https://github.com/mafintosh/codecs) or [abstract-encoding](https://github.com/mafintosh/abstract-encoding).
161- `cenc.none` - Helper for when you want to just express nothing
162
163## License
164
165Apache 2.0
node_modules/compact-encoding/endian.js +4 -0
……@@ -0,0 +1,4 @@
1const LE = (exports.LE =
2 new Uint8Array(new Uint16Array([0xff]).buffer)[0] === 0xff)
3
4exports.BE = !LE
node_modules/compact-encoding/index.js +1053 -0
……@@ -0,0 +1,1053 @@
1const b4a = require('b4a')
2
3const { BE } = require('./endian')
4
5exports.state = function (start = 0, end = 0, buffer = null) {
6 return { start, end, buffer }
7}
8
9const raw = (exports.raw = require('./raw'))
10
11const uint = (exports.uint = {
12 preencode(state, n) {
13 state.end += n <= 0xfc ? 1 : n <= 0xffff ? 3 : n <= 0xffffffff ? 5 : 9
14 },
15 encode(state, n) {
16 if (n <= 0xfc) uint8.encode(state, n)
17 else if (n <= 0xffff) {
18 state.buffer[state.start++] = 0xfd
19 uint16.encode(state, n)
20 } else if (n <= 0xffffffff) {
21 state.buffer[state.start++] = 0xfe
22 uint32.encode(state, n)
23 } else {
24 state.buffer[state.start++] = 0xff
25 uint64.encode(state, n)
26 }
27 },
28 decode(state) {
29 const a = uint8.decode(state)
30 if (a <= 0xfc) return a
31 if (a === 0xfd) return uint16.decode(state)
32 if (a === 0xfe) return uint32.decode(state)
33 return uint64.decode(state)
34 }
35})
36
37const uint8 = (exports.uint8 = {
38 preencode(state, n) {
39 state.end += 1
40 },
41 encode(state, n) {
42 validateUint(n)
43 state.buffer[state.start++] = n
44 },
45 decode(state) {
46 if (state.start >= state.end) throw new Error('Out of bounds')
47 return state.buffer[state.start++]
48 }
49})
50
51const uint16 = (exports.uint16 = {
52 preencode(state, n) {
53 state.end += 2
54 },
55 encode(state, n) {
56 validateUint(n)
57 state.buffer[state.start++] = n
58 state.buffer[state.start++] = n >>> 8
59 },
60 decode(state) {
61 if (state.end - state.start < 2) throw new Error('Out of bounds')
62 return state.buffer[state.start++] + state.buffer[state.start++] * 0x100
63 }
64})
65
66const uint24 = (exports.uint24 = {
67 preencode(state, n) {
68 state.end += 3
69 },
70 encode(state, n) {
71 validateUint(n)
72 state.buffer[state.start++] = n
73 state.buffer[state.start++] = n >>> 8
74 state.buffer[state.start++] = n >>> 16
75 },
76 decode(state) {
77 if (state.end - state.start < 3) throw new Error('Out of bounds')
78 return (
79 state.buffer[state.start++] +
80 state.buffer[state.start++] * 0x100 +
81 state.buffer[state.start++] * 0x10000
82 )
83 }
84})
85
86const uint32 = (exports.uint32 = {
87 preencode(state, n) {
88 state.end += 4
89 },
90 encode(state, n) {
91 validateUint(n)
92 state.buffer[state.start++] = n
93 state.buffer[state.start++] = n >>> 8
94 state.buffer[state.start++] = n >>> 16
95 state.buffer[state.start++] = n >>> 24
96 },
97 decode(state) {
98 if (state.end - state.start < 4) throw new Error('Out of bounds')
99 return (
100 state.buffer[state.start++] +
101 state.buffer[state.start++] * 0x100 +
102 state.buffer[state.start++] * 0x10000 +
103 state.buffer[state.start++] * 0x1000000
104 )
105 }
106})
107
108const uint40 = (exports.uint40 = {
109 preencode(state, n) {
110 state.end += 5
111 },
112 encode(state, n) {
113 validateUint(n)
114 const r = Math.floor(n / 0x100)
115 uint8.encode(state, n)
116 uint32.encode(state, r)
117 },
118 decode(state) {
119 if (state.end - state.start < 5) throw new Error('Out of bounds')
120 return uint8.decode(state) + 0x100 * uint32.decode(state)
121 }
122})
123
124const uint48 = (exports.uint48 = {
125 preencode(state, n) {
126 state.end += 6
127 },
128 encode(state, n) {
129 validateUint(n)
130 const r = Math.floor(n / 0x10000)
131 uint16.encode(state, n)
132 uint32.encode(state, r)
133 },
134 decode(state) {
135 if (state.end - state.start < 6) throw new Error('Out of bounds')
136 return uint16.decode(state) + 0x10000 * uint32.decode(state)
137 }
138})
139
140const uint56 = (exports.uint56 = {
141 preencode(state, n) {
142 state.end += 7
143 },
144 encode(state, n) {
145 validateUint(n)
146 const r = Math.floor(n / 0x1000000)
147 uint24.encode(state, n)
148 uint32.encode(state, r)
149 },
150 decode(state) {
151 if (state.end - state.start < 7) throw new Error('Out of bounds')
152 return uint24.decode(state) + 0x1000000 * uint32.decode(state)
153 }
154})
155
156const uint64 = (exports.uint64 = {
157 preencode(state, n) {
158 state.end += 8
159 },
160 encode(state, n) {
161 validateUint(n)
162 const r = Math.floor(n / 0x100000000)
163 uint32.encode(state, n)
164 uint32.encode(state, r)
165 },
166 decode(state) {
167 if (state.end - state.start < 8) throw new Error('Out of bounds')
168 return uint32.decode(state) + 0x100000000 * uint32.decode(state)
169 }
170})
171
172const int = (exports.int = zigZagInt(uint))
173exports.int8 = zigZagInt(uint8)
174exports.int16 = zigZagInt(uint16)
175exports.int24 = zigZagInt(uint24)
176exports.int32 = zigZagInt(uint32)
177exports.int40 = zigZagInt(uint40)
178exports.int48 = zigZagInt(uint48)
179exports.int56 = zigZagInt(uint56)
180exports.int64 = zigZagInt(uint64)
181
182const biguint64 = (exports.biguint64 = {
183 preencode(state, n) {
184 state.end += 8
185 },
186 encode(state, n) {
187 const view = new DataView(
188 state.buffer.buffer,
189 state.start + state.buffer.byteOffset,
190 8
191 )
192 view.setBigUint64(0, n, true) // little endian
193 state.start += 8
194 },
195 decode(state) {
196 if (state.end - state.start < 8) throw new Error('Out of bounds')
197 const view = new DataView(
198 state.buffer.buffer,
199 state.start + state.buffer.byteOffset,
200 8
201 )
202 const n = view.getBigUint64(0, true) // little endian
203 state.start += 8
204 return n
205 }
206})
207
208exports.bigint64 = zigZagBigInt(biguint64)
209
210const biguint = (exports.biguint = {
211 preencode(state, n) {
212 let len = 0
213 for (let m = n; m; m = m >> 64n) len++
214 uint.preencode(state, len)
215 state.end += 8 * len
216 },
217 encode(state, n) {
218 let len = 0
219 for (let m = n; m; m = m >> 64n) len++
220 uint.encode(state, len)
221 const view = new DataView(
222 state.buffer.buffer,
223 state.start + state.buffer.byteOffset,
224 8 * len
225 )
226 for (let m = n, i = 0; m; m = m >> 64n, i += 8) {
227 view.setBigUint64(i, BigInt.asUintN(64, m), true) // little endian
228 }
229 state.start += 8 * len
230 },
231 decode(state) {
232 const len = uint.decode(state)
233 if (state.end - state.start < 8 * len) throw new Error('Out of bounds')
234 const view = new DataView(
235 state.buffer.buffer,
236 state.start + state.buffer.byteOffset,
237 8 * len
238 )
239 let n = 0n
240 for (let i = len - 1; i >= 0; i--)
241 n = (n << 64n) + view.getBigUint64(i * 8, true) // little endian
242 state.start += 8 * len
243 return n
244 }
245})
246
247exports.bigint = zigZagBigInt(biguint)
248
249exports.lexint = require('./lexint')
250
251exports.float32 = {
252 preencode(state, n) {
253 state.end += 4
254 },
255 encode(state, n) {
256 const view = new DataView(
257 state.buffer.buffer,
258 state.start + state.buffer.byteOffset,
259 4
260 )
261 view.setFloat32(0, n, true) // little endian
262 state.start += 4
263 },
264 decode(state) {
265 if (state.end - state.start < 4) throw new Error('Out of bounds')
266 const view = new DataView(
267 state.buffer.buffer,
268 state.start + state.buffer.byteOffset,
269 4
270 )
271 const float = view.getFloat32(0, true) // little endian
272 state.start += 4
273 return float
274 }
275}
276
277exports.float64 = {
278 preencode(state, n) {
279 state.end += 8
280 },
281 encode(state, n) {
282 const view = new DataView(
283 state.buffer.buffer,
284 state.start + state.buffer.byteOffset,
285 8
286 )
287 view.setFloat64(0, n, true) // little endian
288 state.start += 8
289 },
290 decode(state) {
291 if (state.end - state.start < 8) throw new Error('Out of bounds')
292 const view = new DataView(
293 state.buffer.buffer,
294 state.start + state.buffer.byteOffset,
295 8
296 )
297 const float = view.getFloat64(0, true) // little endian
298 state.start += 8
299 return float
300 }
301}
302
303const buffer = (exports.buffer = {
304 preencode(state, b) {
305 if (b) uint8array.preencode(state, b)
306 else state.end++
307 },
308 encode(state, b) {
309 if (b) uint8array.encode(state, b)
310 else state.buffer[state.start++] = 0
311 },
312 decode(state) {
313 const len = uint.decode(state)
314 if (len === 0) return null
315 if (state.end - state.start < len) throw new Error('Out of bounds')
316 return state.buffer.subarray(state.start, (state.start += len))
317 }
318})
319
320exports.binary = {
321 ...buffer,
322 preencode(state, b) {
323 if (typeof b === 'string') utf8.preencode(state, b)
324 else buffer.preencode(state, b)
325 },
326 encode(state, b) {
327 if (typeof b === 'string') utf8.encode(state, b)
328 else buffer.encode(state, b)
329 }
330}
331
332exports.arraybuffer = {
333 preencode(state, b) {
334 uint.preencode(state, b.byteLength)
335 state.end += b.byteLength
336 },
337 encode(state, b) {
338 uint.encode(state, b.byteLength)
339
340 const view = new Uint8Array(b)
341
342 state.buffer.set(view, state.start)
343 state.start += b.byteLength
344 },
345 decode(state) {
346 const len = uint.decode(state)
347
348 const b = new ArrayBuffer(len)
349 const view = new Uint8Array(b)
350
351 view.set(state.buffer.subarray(state.start, (state.start += len)))
352
353 return b
354 }
355}
356
357function typedarray(TypedArray, swap) {
358 const n = TypedArray.BYTES_PER_ELEMENT
359
360 return {
361 preencode(state, b) {
362 uint.preencode(state, b.length)
363 state.end += b.byteLength
364 },
365 encode(state, b) {
366 uint.encode(state, b.length)
367
368 const view = new Uint8Array(b.buffer, b.byteOffset, b.byteLength)
369
370 if (BE && swap) swap(view)
371
372 state.buffer.set(view, state.start)
373 state.start += b.byteLength
374 },
375 decode(state) {
376 const len = uint.decode(state)
377
378 let b = state.buffer.subarray(state.start, (state.start += len * n))
379 if (b.byteLength !== len * n) throw new Error('Out of bounds')
380 if (b.byteOffset % n !== 0) b = new Uint8Array(b)
381
382 if (BE && swap) swap(b)
383
384 return new TypedArray(b.buffer, b.byteOffset, b.byteLength / n)
385 }
386 }
387}
388
389const uint8array = (exports.uint8array = typedarray(Uint8Array))
390exports.uint16array = typedarray(Uint16Array, b4a.swap16)
391exports.uint32array = typedarray(Uint32Array, b4a.swap32)
392
393exports.int8array = typedarray(Int8Array)
394exports.int16array = typedarray(Int16Array, b4a.swap16)
395exports.int32array = typedarray(Int32Array, b4a.swap32)
396
397exports.biguint64array = typedarray(BigUint64Array, b4a.swap64)
398exports.bigint64array = typedarray(BigInt64Array, b4a.swap64)
399
400exports.float32array = typedarray(Float32Array, b4a.swap32)
401exports.float64array = typedarray(Float64Array, b4a.swap64)
402
403function string(encoding) {
404 return {
405 preencode(state, s) {
406 const len = b4a.byteLength(s, encoding)
407 uint.preencode(state, len)
408 state.end += len
409 },
410 encode(state, s) {
411 const len = b4a.byteLength(s, encoding)
412 uint.encode(state, len)
413 b4a.write(state.buffer, s, state.start, encoding)
414 state.start += len
415 },
416 decode(state) {
417 const len = uint.decode(state)
418 if (state.end - state.start < len) throw new Error('Out of bounds')
419 return b4a.toString(
420 state.buffer,
421 encoding,
422 state.start,
423 (state.start += len)
424 )
425 },
426 fixed(n) {
427 return {
428 preencode(state) {
429 state.end += n
430 },
431 encode(state, s) {
432 b4a.write(state.buffer, s, state.start, n, encoding)
433 state.start += n
434 },
435 decode(state) {
436 if (state.end - state.start < n) throw new Error('Out of bounds')
437 return b4a.toString(
438 state.buffer,
439 encoding,
440 state.start,
441 (state.start += n)
442 )
443 }
444 }
445 }
446 }
447}
448
449const utf8 = (exports.string = exports.utf8 = string('utf-8'))
450exports.ascii = string('ascii')
451exports.hex = string('hex')
452exports.base64 = string('base64')
453exports.ucs2 = exports.utf16le = string('utf16le')
454
455exports.bool = {
456 preencode(state, b) {
457 state.end++
458 },
459 encode(state, b) {
460 state.buffer[state.start++] = b ? 1 : 0
461 },
462 decode(state) {
463 if (state.start >= state.end) throw Error('Out of bounds')
464 return state.buffer[state.start++] === 1
465 }
466}
467
468const fixed = (exports.fixed = function fixed(n) {
469 return {
470 preencode(state, s) {
471 if (s.byteLength !== n) throw new Error('Incorrect buffer size')
472 state.end += n
473 },
474 encode(state, s) {
475 state.buffer.set(s, state.start)
476 state.start += n
477 },
478 decode(state) {
479 if (state.end - state.start < n) throw new Error('Out of bounds')
480 return state.buffer.subarray(state.start, (state.start += n))
481 }
482 }
483})
484
485exports.fixed32 = fixed(32)
486exports.fixed64 = fixed(64)
487
488exports.array = function array(enc) {
489 return {
490 preencode(state, list) {
491 uint.preencode(state, list.length)
492 for (let i = 0; i < list.length; i++) enc.preencode(state, list[i])
493 },
494 encode(state, list) {
495 uint.encode(state, list.length)
496 for (let i = 0; i < list.length; i++) enc.encode(state, list[i])
497 },
498 decode(state) {
499 const len = uint.decode(state)
500 if (len > 0x100000) throw new Error('Array is too big')
501 const arr = new Array(len)
502 for (let i = 0; i < len; i++) arr[i] = enc.decode(state)
503 return arr
504 }
505 }
506}
507
508exports.frame = function frame(enc) {
509 const dummy = exports.state()
510
511 return {
512 preencode(state, m) {
513 const end = state.end
514 enc.preencode(state, m)
515 uint.preencode(state, state.end - end)
516 },
517 encode(state, m) {
518 dummy.end = 0
519 enc.preencode(dummy, m)
520 uint.encode(state, dummy.end)
521 enc.encode(state, m)
522 },
523 decode(state) {
524 const end = state.end
525 const len = uint.decode(state)
526 state.end = state.start + len
527 const m = enc.decode(state)
528 state.start = state.end
529 state.end = end
530 return m
531 }
532 }
533}
534
535exports.date = {
536 preencode(state, d) {
537 int.preencode(state, d.getTime())
538 },
539 encode(state, d) {
540 int.encode(state, d.getTime())
541 },
542 decode(state, d) {
543 return new Date(int.decode(state))
544 }
545}
546
547exports.json = {
548 preencode(state, v) {
549 utf8.preencode(state, JSON.stringify(v))
550 },
551 encode(state, v) {
552 utf8.encode(state, JSON.stringify(v))
553 },
554 decode(state) {
555 return JSON.parse(utf8.decode(state))
556 }
557}
558
559exports.ndjson = {
560 preencode(state, v) {
561 utf8.preencode(state, JSON.stringify(v) + '\n')
562 },
563 encode(state, v) {
564 utf8.encode(state, JSON.stringify(v) + '\n')
565 },
566 decode(state) {
567 return JSON.parse(utf8.decode(state))
568 }
569}
570
571// simple helper for when you want to just express nothing
572exports.none = {
573 preencode(state, n) {
574 // do nothing
575 },
576 encode(state, n) {
577 // do nothing
578 },
579 decode(state) {
580 return null
581 }
582}
583
584// "any" encoders here for helping just structure any object without schematising it
585
586const anyArray = {
587 preencode(state, arr) {
588 uint.preencode(state, arr.length)
589 for (let i = 0; i < arr.length; i++) {
590 any.preencode(state, arr[i])
591 }
592 },
593 encode(state, arr) {
594 uint.encode(state, arr.length)
595 for (let i = 0; i < arr.length; i++) {
596 any.encode(state, arr[i])
597 }
598 },
599 decode(state) {
600 const arr = []
601 let len = uint.decode(state)
602 while (len-- > 0) {
603 arr.push(any.decode(state))
604 }
605 return arr
606 }
607}
608
609const anyObject = {
610 preencode(state, o) {
611 const keys = Object.keys(o)
612 uint.preencode(state, keys.length)
613 for (const key of keys) {
614 utf8.preencode(state, key)
615 any.preencode(state, o[key])
616 }
617 },
618 encode(state, o) {
619 const keys = Object.keys(o)
620 uint.encode(state, keys.length)
621 for (const key of keys) {
622 utf8.encode(state, key)
623 any.encode(state, o[key])
624 }
625 },
626 decode(state) {
627 let len = uint.decode(state)
628 const o = {}
629 while (len-- > 0) {
630 const key = utf8.decode(state)
631 o[key] = any.decode(state)
632 }
633 return o
634 }
635}
636
637const anyTypes = [
638 exports.none,
639 exports.bool,
640 exports.string,
641 exports.buffer,
642 exports.uint,
643 exports.int,
644 exports.float64,
645 anyArray,
646 anyObject,
647 exports.date
648]
649
650const any = (exports.any = {
651 preencode(state, o) {
652 const t = getType(o)
653 uint.preencode(state, t)
654 anyTypes[t].preencode(state, o)
655 },
656 encode(state, o) {
657 const t = getType(o)
658 uint.encode(state, t)
659 anyTypes[t].encode(state, o)
660 },
661 decode(state) {
662 const t = uint.decode(state)
663 if (t >= anyTypes.length) throw new Error('Unknown type: ' + t)
664 return anyTypes[t].decode(state)
665 }
666})
667
668const port = (exports.port = {
669 preencode(state, p) {
670 if (!p) throw new Error('Port must be >0 and <65536')
671 uint16.preencode(state, p)
672 },
673 encode(state, p) {
674 if (!p) throw new Error('Port must be >0 and <65536')
675 uint16.encode(state, p)
676 },
677 decode(state) {
678 const p = uint16.decode(state)
679 if (!p) throw new Error('Port must be >0 and <65536')
680 return p
681 }
682})
683
684const address = (host, family) => {
685 return {
686 preencode(state, m) {
687 host.preencode(state, m.host)
688 port.preencode(state, m.port)
689 },
690 encode(state, m) {
691 host.encode(state, m.host)
692 port.encode(state, m.port)
693 },
694 decode(state) {
695 return {
696 host: host.decode(state),
697 family,
698 port: port.decode(state)
699 }
700 }
701 }
702}
703
704const ipv4 = (exports.ipv4 = {
705 preencode(state) {
706 state.end += 4
707 },
708 encode(state, string) {
709 const start = state.start
710 const end = start + 4
711
712 let i = 0
713
714 while (i < string.length) {
715 let n = 0
716 let c
717
718 while (
719 i < string.length &&
720 (c = string.charCodeAt(i++)) !== /* . */ 0x2e
721 ) {
722 n = n * 10 + (c - /* 0 */ 0x30)
723 }
724
725 state.buffer[state.start++] = n
726 }
727
728 state.start = end
729 },
730 decode(state) {
731 if (state.end - state.start < 4) throw new Error('Out of bounds')
732 return (
733 state.buffer[state.start++] +
734 '.' +
735 state.buffer[state.start++] +
736 '.' +
737 state.buffer[state.start++] +
738 '.' +
739 state.buffer[state.start++]
740 )
741 }
742})
743
744exports.ipv4Address = address(ipv4, 4)
745
746const ipv6 = (exports.ipv6 = {
747 preencode(state) {
748 state.end += 16
749 },
750 encode(state, string) {
751 const start = state.start
752 const end = start + 16
753
754 let i = 0
755 let split = null
756
757 while (i < string.length) {
758 let n = 0
759 let c
760
761 while (
762 i < string.length &&
763 (c = string.charCodeAt(i++)) !== /* : */ 0x3a
764 ) {
765 if (c >= 0x30 && c <= 0x39) n = n * 0x10 + (c - /* 0 */ 0x30)
766 else if (c >= 0x41 && c <= 0x46) n = n * 0x10 + (c - /* A */ 0x41 + 10)
767 else if (c >= 0x61 && c <= 0x66) n = n * 0x10 + (c - /* a */ 0x61 + 10)
768 }
769
770 state.buffer[state.start++] = n >>> 8
771 state.buffer[state.start++] = n
772
773 if (i < string.length && string.charCodeAt(i) === /* : */ 0x3a) {
774 i++
775 split = state.start
776 }
777 }
778
779 if (split !== null) {
780 const offset = end - state.start
781 state.buffer
782 .copyWithin(split + offset, split)
783 .fill(0, split, split + offset)
784 }
785
786 state.start = end
787 },
788 decode(state) {
789 if (state.end - state.start < 16) throw new Error('Out of bounds')
790 return (
791 (
792 state.buffer[state.start++] * 256 +
793 state.buffer[state.start++]
794 ).toString(16) +
795 ':' +
796 (
797 state.buffer[state.start++] * 256 +
798 state.buffer[state.start++]
799 ).toString(16) +
800 ':' +
801 (
802 state.buffer[state.start++] * 256 +
803 state.buffer[state.start++]
804 ).toString(16) +
805 ':' +
806 (
807 state.buffer[state.start++] * 256 +
808 state.buffer[state.start++]
809 ).toString(16) +
810 ':' +
811 (
812 state.buffer[state.start++] * 256 +
813 state.buffer[state.start++]
814 ).toString(16) +
815 ':' +
816 (
817 state.buffer[state.start++] * 256 +
818 state.buffer[state.start++]
819 ).toString(16) +
820 ':' +
821 (
822 state.buffer[state.start++] * 256 +
823 state.buffer[state.start++]
824 ).toString(16) +
825 ':' +
826 (
827 state.buffer[state.start++] * 256 +
828 state.buffer[state.start++]
829 ).toString(16)
830 )
831 }
832})
833
834exports.ipv6Address = address(ipv6, 6)
835
836const ip = (exports.ip = {
837 preencode(state, string) {
838 const family = string.includes(':') ? 6 : 4
839 uint8.preencode(state, family)
840 if (family === 4) ipv4.preencode(state)
841 else ipv6.preencode(state)
842 },
843 encode(state, string) {
844 const family = string.includes(':') ? 6 : 4
845 uint8.encode(state, family)
846 if (family === 4) ipv4.encode(state, string)
847 else ipv6.encode(state, string)
848 },
849 decode(state) {
850 const family = uint8.decode(state)
851 if (family === 4) return ipv4.decode(state)
852 else return ipv6.decode(state)
853 }
854})
855
856exports.ipAddress = {
857 preencode(state, m) {
858 ip.preencode(state, m.host)
859 port.preencode(state, m.port)
860 },
861 encode(state, m) {
862 ip.encode(state, m.host)
863 port.encode(state, m.port)
864 },
865 decode(state) {
866 const family = uint8.decode(state)
867 return {
868 host: family === 4 ? ipv4.decode(state) : ipv6.decode(state),
869 family,
870 port: port.decode(state)
871 }
872 }
873}
874
875const record = (exports.record = function (keyEncoding, valueEncoding) {
876 return {
877 preencode(state, v) {
878 const keys = Object.keys(v)
879 uint.preencode(state, keys.length)
880 for (const k of keys) {
881 keyEncoding.preencode(state, k)
882 valueEncoding.preencode(state, v[k])
883 }
884 },
885 encode(state, v) {
886 const keys = Object.keys(v)
887 uint.encode(state, keys.length)
888 for (const k of keys) {
889 keyEncoding.encode(state, k)
890 valueEncoding.encode(state, v[k])
891 }
892 },
893 decode(state) {
894 const out = Object.create(null)
895 const keys = uint.decode(state)
896 for (let i = 0; i < keys; i++) {
897 out[keyEncoding.decode(state)] = valueEncoding.decode(state)
898 }
899 return out
900 }
901 }
902})
903
904exports.stringRecord = record(utf8, utf8)
905
906function getType(o) {
907 if (o === null || o === undefined) return 0
908 if (typeof o === 'boolean') return 1
909 if (typeof o === 'string') return 2
910 if (b4a.isBuffer(o)) return 3
911 if (typeof o === 'number') {
912 if (Number.isInteger(o)) return o >= 0 ? 4 : 5
913 return 6
914 }
915 if (Array.isArray(o)) return 7
916 if (o instanceof Date) return 9
917 if (typeof o === 'object') return 8
918
919 throw new Error('Unsupported type for ' + o)
920}
921
922exports.from = function from(enc) {
923 if (typeof enc === 'string') return fromNamed(enc)
924 if (enc.preencode) return enc
925 if (enc.encodingLength) return fromAbstractEncoder(enc)
926 return fromCodec(enc)
927}
928
929function fromNamed(enc) {
930 switch (enc) {
931 case 'ascii':
932 return raw.ascii
933 case 'utf-8':
934 case 'utf8':
935 return raw.utf8
936 case 'hex':
937 return raw.hex
938 case 'base64':
939 return raw.base64
940 case 'utf16-le':
941 case 'utf16le':
942 case 'ucs-2':
943 case 'ucs2':
944 return raw.ucs2
945 case 'ndjson':
946 return raw.ndjson
947 case 'json':
948 return raw.json
949 case 'binary':
950 default:
951 return raw.binary
952 }
953}
954
955function fromCodec(enc) {
956 let tmpM = null
957 let tmpBuf = null
958
959 return {
960 preencode(state, m) {
961 tmpM = m
962 tmpBuf = enc.encode(m)
963 state.end += tmpBuf.byteLength
964 },
965 encode(state, m) {
966 raw.encode(state, m === tmpM ? tmpBuf : enc.encode(m))
967 tmpM = tmpBuf = null
968 },
969 decode(state) {
970 return enc.decode(raw.decode(state))
971 }
972 }
973}
974
975function fromAbstractEncoder(enc) {
976 return {
977 preencode(state, m) {
978 state.end += enc.encodingLength(m)
979 },
980 encode(state, m) {
981 enc.encode(m, state.buffer, state.start)
982 state.start += enc.encode.bytes
983 },
984 decode(state) {
985 const m = enc.decode(state.buffer, state.start, state.end)
986 state.start += enc.decode.bytes
987 return m
988 }
989 }
990}
991
992exports.encode = function encode(enc, m) {
993 const state = exports.state()
994 enc.preencode(state, m)
995 state.buffer = b4a.allocUnsafe(state.end)
996 enc.encode(state, m)
997 return state.buffer
998}
999
1000exports.decode = function decode(enc, buffer) {
1001 return enc.decode(exports.state(0, buffer.byteLength, buffer))
1002}
1003
1004function zigZagInt(enc) {
1005 return {
1006 preencode(state, n) {
1007 enc.preencode(state, zigZagEncodeInt(n))
1008 },
1009 encode(state, n) {
1010 enc.encode(state, zigZagEncodeInt(n))
1011 },
1012 decode(state) {
1013 return zigZagDecodeInt(enc.decode(state))
1014 }
1015 }
1016}
1017
1018function zigZagDecodeInt(n) {
1019 return n === 0 ? n : (n & 1) === 0 ? n / 2 : -(n + 1) / 2
1020}
1021
1022function zigZagEncodeInt(n) {
1023 // 0, -1, 1, -2, 2, ...
1024 return n < 0 ? 2 * -n - 1 : n === 0 ? 0 : 2 * n
1025}
1026
1027function zigZagBigInt(enc) {
1028 return {
1029 preencode(state, n) {
1030 enc.preencode(state, zigZagEncodeBigInt(n))
1031 },
1032 encode(state, n) {
1033 enc.encode(state, zigZagEncodeBigInt(n))
1034 },
1035 decode(state) {
1036 return zigZagDecodeBigInt(enc.decode(state))
1037 }
1038 }
1039}
1040
1041function zigZagDecodeBigInt(n) {
1042 return n === 0n ? n : (n & 1n) === 0n ? n / 2n : -(n + 1n) / 2n
1043}
1044
1045function zigZagEncodeBigInt(n) {
1046 // 0, -1, 1, -2, 2, ...
1047 return n < 0n ? 2n * -n - 1n : n === 0n ? 0n : 2n * n
1048}
1049
1050function validateUint(n) {
1051 if (n >= 0 === false /* Handles NaN as well */)
1052 throw new Error('uint must be positive')
1053}
node_modules/compact-encoding/lexint.js +117 -0
……@@ -0,0 +1,117 @@
1module.exports = {
2 preencode,
3 encode,
4 decode
5}
6
7function preencode(state, num) {
8 if (num < 251) {
9 state.end++
10 } else if (num < 256) {
11 state.end += 2
12 } else if (num < 0x10000) {
13 state.end += 3
14 } else if (num < 0x1000000) {
15 state.end += 4
16 } else if (num < 0x100000000) {
17 state.end += 5
18 } else {
19 state.end++
20 const exp = Math.floor(Math.log(num) / Math.log(2)) - 32
21 preencode(state, exp)
22 state.end += 6
23 }
24}
25
26function encode(state, num) {
27 const max = 251
28 const x = num - max
29
30 if (num < max) {
31 state.buffer[state.start++] = num
32 } else if (num < 256) {
33 state.buffer[state.start++] = max
34 state.buffer[state.start++] = x
35 } else if (num < 0x10000) {
36 state.buffer[state.start++] = max + 1
37 state.buffer[state.start++] = (x >> 8) & 0xff
38 state.buffer[state.start++] = x & 0xff
39 } else if (num < 0x1000000) {
40 state.buffer[state.start++] = max + 2
41 state.buffer[state.start++] = x >> 16
42 state.buffer[state.start++] = (x >> 8) & 0xff
43 state.buffer[state.start++] = x & 0xff
44 } else if (num < 0x100000000) {
45 state.buffer[state.start++] = max + 3
46 state.buffer[state.start++] = x >> 24
47 state.buffer[state.start++] = (x >> 16) & 0xff
48 state.buffer[state.start++] = (x >> 8) & 0xff
49 state.buffer[state.start++] = x & 0xff
50 } else {
51 // need to use Math here as bitwise ops are 32 bit
52 const exp = Math.floor(Math.log(x) / Math.log(2)) - 32
53 state.buffer[state.start++] = 0xff
54
55 encode(state, exp)
56 const rem = x / Math.pow(2, exp - 11)
57
58 for (let i = 5; i >= 0; i--) {
59 state.buffer[state.start++] = (rem / Math.pow(2, 8 * i)) & 0xff
60 }
61 }
62}
63
64function decode(state) {
65 const max = 251
66
67 if (state.end - state.start < 1) throw new Error('Out of bounds')
68
69 const flag = state.buffer[state.start++]
70
71 if (flag < max) return flag
72
73 if (state.end - state.start < flag - max + 1) {
74 throw new Error('Out of bounds.')
75 }
76
77 if (flag < 252) {
78 return state.buffer[state.start++] + max
79 }
80
81 if (flag < 253) {
82 return (
83 (state.buffer[state.start++] << 8) + state.buffer[state.start++] + max
84 )
85 }
86
87 if (flag < 254) {
88 return (
89 (state.buffer[state.start++] << 16) +
90 (state.buffer[state.start++] << 8) +
91 state.buffer[state.start++] +
92 max
93 )
94 }
95
96 // << 24 result may be interpreted as negative
97 if (flag < 255) {
98 return (
99 state.buffer[state.start++] * 0x1000000 +
100 (state.buffer[state.start++] << 16) +
101 (state.buffer[state.start++] << 8) +
102 state.buffer[state.start++] +
103 max
104 )
105 }
106
107 const exp = decode(state)
108
109 if (state.end - state.start < 6) throw new Error('Out of bounds')
110
111 let rem = 0
112 for (let i = 5; i >= 0; i--) {
113 rem += state.buffer[state.start++] * Math.pow(2, 8 * i)
114 }
115
116 return rem * Math.pow(2, exp - 11) + max
117}
node_modules/compact-encoding/package.json +28 -0
……@@ -0,0 +1,28 @@
1{
2 "name": "compact-encoding",
3 "version": "2.19.1",
4 "description": "A series of compact encoding schemes for building small and fast parsers and serializers",
5 "main": "index.js",
6 "dependencies": {
7 "b4a": "^1.3.0"
8 },
9 "devDependencies": {
10 "brittle": "^3.0.0",
11 "prettier": "^3.6.2",
12 "prettier-config-holepunch": "^1.0.0"
13 },
14 "scripts": {
15 "format": "prettier . --write",
16 "test": "prettier . --check && brittle test.js"
17 },
18 "repository": {
19 "type": "git",
20 "url": "https://github.com/holepunchto/compact-encoding.git"
21 },
22 "author": "Mathias Buus (@mafintosh)",
23 "license": "Apache-2.0",
24 "bugs": {
25 "url": "https://github.com/holepunchto/compact-encoding/issues"
26 },
27 "homepage": "https://github.com/holepunchto/compact-encoding"
28}
node_modules/compact-encoding/raw.js +173 -0
……@@ -0,0 +1,173 @@
1const b4a = require('b4a')
2
3const { BE } = require('./endian')
4
5exports = module.exports = {
6 preencode(state, b) {
7 state.end += b.byteLength
8 },
9 encode(state, b) {
10 state.buffer.set(b, state.start)
11 state.start += b.byteLength
12 },
13 decode(state) {
14 const b = state.buffer.subarray(state.start, state.end)
15 state.start = state.end
16 return b
17 }
18}
19
20const buffer = (exports.buffer = {
21 preencode(state, b) {
22 if (b) uint8array.preencode(state, b)
23 else state.end++
24 },
25 encode(state, b) {
26 if (b) uint8array.encode(state, b)
27 else state.buffer[state.start++] = 0
28 },
29 decode(state) {
30 const b = state.buffer.subarray(state.start)
31 if (b.byteLength === 0) return null
32 state.start = state.end
33 return b
34 }
35})
36
37exports.binary = {
38 ...buffer,
39 preencode(state, b) {
40 if (typeof b === 'string') utf8.preencode(state, b)
41 else buffer.preencode(state, b)
42 },
43 encode(state, b) {
44 if (typeof b === 'string') utf8.encode(state, b)
45 else buffer.encode(state, b)
46 }
47}
48
49exports.arraybuffer = {
50 preencode(state, b) {
51 state.end += b.byteLength
52 },
53 encode(state, b) {
54 const view = new Uint8Array(b)
55
56 state.buffer.set(view, state.start)
57 state.start += b.byteLength
58 },
59 decode(state) {
60 const b = new ArrayBuffer(state.end - state.start)
61 const view = new Uint8Array(b)
62
63 view.set(state.buffer.subarray(state.start))
64
65 state.start = state.end
66
67 return b
68 }
69}
70
71function typedarray(TypedArray, swap) {
72 const n = TypedArray.BYTES_PER_ELEMENT
73
74 return {
75 preencode(state, b) {
76 state.end += b.byteLength
77 },
78 encode(state, b) {
79 const view = new Uint8Array(b.buffer, b.byteOffset, b.byteLength)
80
81 if (BE && swap) swap(view)
82
83 state.buffer.set(view, state.start)
84 state.start += b.byteLength
85 },
86 decode(state) {
87 let b = state.buffer.subarray(state.start)
88 if (b.byteOffset % n !== 0) b = new Uint8Array(b)
89
90 if (BE && swap) swap(b)
91
92 state.start = state.end
93
94 return new TypedArray(b.buffer, b.byteOffset, b.byteLength / n)
95 }
96 }
97}
98
99const uint8array = (exports.uint8array = typedarray(Uint8Array))
100exports.uint16array = typedarray(Uint16Array, b4a.swap16)
101exports.uint32array = typedarray(Uint32Array, b4a.swap32)
102
103exports.int8array = typedarray(Int8Array)
104exports.int16array = typedarray(Int16Array, b4a.swap16)
105exports.int32array = typedarray(Int32Array, b4a.swap32)
106
107exports.biguint64array = typedarray(BigUint64Array, b4a.swap64)
108exports.bigint64array = typedarray(BigInt64Array, b4a.swap64)
109
110exports.float32array = typedarray(Float32Array, b4a.swap32)
111exports.float64array = typedarray(Float64Array, b4a.swap64)
112
113function string(encoding) {
114 return {
115 preencode(state, s) {
116 state.end += b4a.byteLength(s, encoding)
117 },
118 encode(state, s) {
119 state.start += b4a.write(state.buffer, s, state.start, encoding)
120 },
121 decode(state) {
122 const s = b4a.toString(state.buffer, encoding, state.start)
123 state.start = state.end
124 return s
125 }
126 }
127}
128
129const utf8 = (exports.string = exports.utf8 = string('utf-8'))
130exports.ascii = string('ascii')
131exports.hex = string('hex')
132exports.base64 = string('base64')
133exports.ucs2 = exports.utf16le = string('utf16le')
134
135exports.array = function array(enc) {
136 return {
137 preencode(state, list) {
138 for (const value of list) enc.preencode(state, value)
139 },
140 encode(state, list) {
141 for (const value of list) enc.encode(state, value)
142 },
143 decode(state) {
144 const arr = []
145 while (state.start < state.end) arr.push(enc.decode(state))
146 return arr
147 }
148 }
149}
150
151exports.json = {
152 preencode(state, v) {
153 utf8.preencode(state, JSON.stringify(v))
154 },
155 encode(state, v) {
156 utf8.encode(state, JSON.stringify(v))
157 },
158 decode(state) {
159 return JSON.parse(utf8.decode(state))
160 }
161}
162
163exports.ndjson = {
164 preencode(state, v) {
165 utf8.preencode(state, JSON.stringify(v) + '\n')
166 },
167 encode(state, v) {
168 utf8.encode(state, JSON.stringify(v) + '\n')
169 },
170 decode(state) {
171 return JSON.parse(utf8.decode(state))
172 }
173}
node_modules/compact-encoding/test.js +1184 -0
……@@ -0,0 +1,1184 @@
1const enc = require('./')
2const test = require('brittle')
3const b4a = require('b4a')
4
5test('uint', function (t) {
6 const state = enc.state()
7
8 enc.uint.preencode(state, 42)
9 t.alike(state, enc.state(0, 1))
10 enc.uint.preencode(state, 4200)
11 t.alike(state, enc.state(0, 4))
12 enc.uint.preencode(state, Number.MAX_SAFE_INTEGER)
13 t.alike(state, enc.state(0, 13))
14
15 state.buffer = b4a.alloc(state.end)
16 enc.uint.encode(state, 42)
17 t.alike(
18 state,
19 enc.state(1, 13, b4a.from([42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))
20 )
21 enc.uint.encode(state, 4200)
22 t.alike(
23 state,
24 enc.state(4, 13, b4a.from([42, 0xfd, 104, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0]))
25 )
26 enc.uint.encode(state, Number.MAX_SAFE_INTEGER)
27 t.alike(
28 state,
29 enc.state(
30 13,
31 13,
32 b4a.from([42, 0xfd, 104, 16, 0xff, 255, 255, 255, 255, 255, 255, 31, 0])
33 )
34 )
35
36 state.start = 0
37 t.is(enc.uint.decode(state), 42)
38 t.is(enc.uint.decode(state), 4200)
39 t.is(enc.uint.decode(state), Number.MAX_SAFE_INTEGER)
40 t.is(state.start, state.end)
41
42 t.exception(() => enc.uint.decode(state))
43})
44
45test('int', function (t) {
46 const state = enc.state()
47
48 enc.int.preencode(state, 42)
49 t.alike(state, enc.state(0, 1))
50 enc.int.preencode(state, -4200)
51 t.alike(state, enc.state(0, 4))
52
53 state.buffer = b4a.alloc(state.end)
54 enc.int.encode(state, 42)
55 t.alike(state, enc.state(1, 4, b4a.from([84, 0, 0, 0])))
56 enc.int.encode(state, -4200)
57 t.alike(state, enc.state(4, 4, b4a.from([84, 0xfd, 207, 32])))
58
59 state.start = 0
60 t.is(enc.int.decode(state), 42)
61 t.is(enc.int.decode(state), -4200)
62 t.is(state.start, state.end)
63
64 t.exception(() => enc.int.decode(state))
65})
66
67test('float64', function (t) {
68 const state = enc.state()
69
70 enc.float64.preencode(state, 162.2377294)
71 t.alike(state, enc.state(0, 8))
72
73 state.buffer = b4a.alloc(state.end)
74 t.alike(state, enc.state(0, 8, b4a.from([0, 0, 0, 0, 0, 0, 0, 0])))
75 enc.float64.encode(state, 162.2377294)
76 t.alike(
77 state,
78 enc.state(8, 8, b4a.from([0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40]))
79 )
80
81 state.start = 0
82 t.is(enc.float64.decode(state), 162.2377294)
83 t.is(state.start, state.end)
84
85 t.exception(() => enc.float64.decode(state))
86
87 // alignement
88 state.start = 0
89 state.end = 0
90 state.buffer = null
91
92 enc.int.preencode(state, 0)
93 enc.float64.preencode(state, 162.2377294)
94 t.alike(state, enc.state(0, 9))
95
96 state.buffer = b4a.alloc(state.end)
97 t.alike(state, enc.state(0, 9, b4a.from([0, 0, 0, 0, 0, 0, 0, 0, 0])))
98 enc.int.encode(state, 0)
99 enc.float64.encode(state, 162.2377294)
100 t.alike(
101 state,
102 enc.state(
103 9,
104 9,
105 b4a.from([0, 0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40])
106 )
107 )
108
109 state.start = 0
110 t.is(enc.int.decode(state), 0)
111 t.is(enc.float64.decode(state), 162.2377294)
112 t.is(state.start, state.end)
113
114 // subarray
115 const buf = b4a.alloc(10)
116 state.start = 0
117 state.buffer = buf.subarray(1)
118 t.alike(state, enc.state(0, 9, b4a.from([0, 0, 0, 0, 0, 0, 0, 0, 0])))
119 enc.int.encode(state, 0)
120 enc.float64.encode(state, 162.2377294)
121 t.alike(
122 state,
123 enc.state(
124 9,
125 9,
126 b4a.from([0, 0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40])
127 )
128 )
129 t.alike(buf, b4a.from([0, 0, 0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40]))
130
131 state.start = 0
132 t.is(enc.int.decode(state), 0)
133 t.is(enc.float64.decode(state), 162.2377294)
134 t.is(state.start, state.end)
135
136 // 0
137 state.start = 0
138 state.end = 0
139 state.buffer = null
140
141 enc.float64.preencode(state, 162.2377294)
142 state.buffer = b4a.alloc(state.end)
143 enc.float64.encode(state, 0)
144 t.alike(state, enc.state(8, 8, b4a.from([0, 0, 0, 0, 0, 0, 0, 0])))
145
146 state.start = 0
147 t.is(enc.float64.decode(state), 0)
148 t.is(state.start, state.end)
149
150 // Infinity
151 state.start = 0
152 state.end = 0
153 state.buffer = null
154
155 enc.float64.preencode(state, Infinity)
156 state.buffer = b4a.alloc(state.end)
157 enc.float64.encode(state, Infinity)
158 t.alike(state, enc.state(8, 8, b4a.from([0, 0, 0, 0, 0, 0, 0xf0, 0x7f])))
159
160 state.start = 0
161 t.is(enc.float64.decode(state), Infinity)
162 t.is(state.start, state.end)
163
164 // Edge cases
165 state.start = 0
166 state.end = 0
167 state.buffer = null
168
169 enc.float64.preencode(state, 0.1 + 0.2)
170 state.buffer = b4a.alloc(state.end)
171 enc.float64.encode(state, 0.1 + 0.2)
172 t.alike(
173 state,
174 enc.state(8, 8, b4a.from([0x34, 0x33, 0x33, 0x33, 0x33, 0x33, 0xd3, 0x3f]))
175 )
176
177 state.start = 0
178 t.is(enc.float64.decode(state), 0.1 + 0.2)
179 t.is(state.start, state.end)
180})
181
182test('biguint64', function (t) {
183 const state = enc.state()
184
185 const n = 0x0102030405060708n
186
187 enc.biguint64.preencode(state, n)
188 t.alike(state, enc.state(0, 8))
189
190 state.buffer = b4a.alloc(state.end)
191 enc.biguint64.encode(state, n)
192 t.alike(
193 state,
194 enc.state(8, 8, b4a.from([0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1]))
195 )
196
197 state.start = 0
198 t.is(enc.biguint64.decode(state), n)
199 t.is(state.start, state.end)
200
201 t.exception(() => enc.biguint64.decode(state))
202})
203
204test('bigint64', function (t) {
205 const state = enc.state()
206
207 const n = -0x0102030405060708n
208
209 enc.bigint64.preencode(state, n)
210 t.alike(state, enc.state(0, 8))
211
212 state.buffer = b4a.alloc(state.end)
213 enc.bigint64.encode(state, n)
214 t.alike(
215 state,
216 enc.state(8, 8, b4a.from([0xf, 0xe, 0xc, 0xa, 0x8, 0x6, 0x4, 0x2]))
217 )
218
219 state.start = 0
220 t.is(enc.bigint64.decode(state), n)
221 t.is(state.start, state.end)
222
223 t.exception(() => enc.bigint64.decode(state))
224})
225
226test('biguint', function (t) {
227 const state = enc.state()
228
229 const n = 0x0102030405060708090a0b0cn
230
231 enc.biguint.preencode(state, n)
232 t.alike(state, enc.state(0, 17))
233
234 state.buffer = b4a.alloc(state.end)
235 enc.biguint.encode(state, n)
236 t.alike(
237 state,
238 enc.state(
239 17,
240 17,
241 b4a.from([
242 2, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0,
243 0x0, 0x0
244 ])
245 )
246 )
247
248 state.start = 0
249 t.is(enc.biguint.decode(state), n)
250 t.is(state.start, state.end)
251
252 t.exception(() => enc.biguint.decode(state))
253})
254
255test('bigint', function (t) {
256 const state = enc.state()
257
258 const n = -0x0102030405060708090a0b0cn
259
260 enc.bigint.preencode(state, n)
261 t.alike(state, enc.state(0, 17))
262
263 state.buffer = b4a.alloc(state.end)
264 enc.bigint.encode(state, n)
265 t.alike(
266 state,
267 enc.state(
268 17,
269 17,
270 b4a.from([
271 2, 0x17, 0x16, 0x14, 0x12, 0x10, 0xe, 0xc, 0xa, 0x8, 0x6, 0x4, 0x2, 0x0,
272 0x0, 0x0, 0x0
273 ])
274 )
275 )
276
277 state.start = 0
278 t.is(enc.bigint.decode(state), n)
279 t.is(state.start, state.end)
280
281 t.exception(() => enc.bigint.decode(state))
282})
283
284test('buffer', function (t) {
285 const state = enc.state()
286
287 enc.buffer.preencode(state, b4a.from('hi'))
288 t.alike(state, enc.state(0, 3))
289 enc.buffer.preencode(state, b4a.from('hello'))
290 t.alike(state, enc.state(0, 9))
291 enc.buffer.preencode(state, null)
292 t.alike(state, enc.state(0, 10))
293
294 state.buffer = b4a.alloc(state.end)
295 enc.buffer.encode(state, b4a.from('hi'))
296 t.alike(
297 state,
298 enc.state(3, 10, b4a.from('\x02hi\x00\x00\x00\x00\x00\x00\x00'))
299 )
300 enc.buffer.encode(state, b4a.from('hello'))
301 t.alike(state, enc.state(9, 10, b4a.from('\x02hi\x05hello\x00')))
302 enc.buffer.encode(state, null)
303 t.alike(state, enc.state(10, 10, b4a.from('\x02hi\x05hello\x00')))
304
305 state.start = 0
306 t.alike(enc.buffer.decode(state), b4a.from('hi'))
307 t.alike(enc.buffer.decode(state), b4a.from('hello'))
308 t.is(enc.buffer.decode(state), null)
309 t.is(state.start, state.end)
310
311 t.exception(() => enc.buffer.decode(state))
312})
313
314test('arraybuffer', function (t) {
315 const state = enc.state()
316
317 const b1 = new ArrayBuffer(4)
318 b4a.from(b1).fill('a')
319
320 const b2 = new ArrayBuffer(8)
321 b4a.from(b2).fill('b')
322
323 enc.arraybuffer.preencode(state, b1)
324 t.alike(state, enc.state(0, 5))
325 enc.arraybuffer.preencode(state, b2)
326 t.alike(state, enc.state(0, 14))
327
328 state.buffer = b4a.alloc(state.end)
329 enc.arraybuffer.encode(state, b1)
330 t.alike(
331 state,
332 enc.state(5, 14, b4a.from('\x04aaaa\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
333 )
334 enc.arraybuffer.encode(state, b2)
335 t.alike(state, enc.state(14, 14, b4a.from('\x04aaaa\x08bbbbbbbb')))
336
337 state.start = 0
338 t.alike(enc.arraybuffer.decode(state), b1)
339 t.alike(enc.arraybuffer.decode(state), b2)
340 t.is(state.start, state.end)
341
342 t.exception(() => enc.arraybuffer.decode(state))
343})
344
345test('raw', function (t) {
346 const state = enc.state()
347
348 enc.raw.preencode(state, b4a.from('hi'))
349 t.alike(state, enc.state(0, 2))
350
351 state.buffer = b4a.alloc(state.end)
352 enc.raw.encode(state, b4a.from('hi'))
353 t.alike(state, enc.state(2, 2, b4a.from('hi')))
354
355 state.start = 0
356 t.alike(enc.raw.decode(state), b4a.from('hi'))
357 t.is(state.start, state.end)
358})
359
360test('raw uint8array', function (t) {
361 const state = enc.state()
362
363 enc.raw.uint8array.preencode(state, Uint8Array.of(1, 2))
364 t.alike(state, enc.state(0, 2))
365 enc.raw.uint8array.preencode(state, Uint8Array.of(3, 4))
366 t.alike(state, enc.state(0, 4))
367
368 state.buffer = b4a.alloc(state.end)
369 enc.raw.uint8array.encode(state, Uint8Array.of(1, 2))
370 t.alike(state, enc.state(2, 4, b4a.from([1, 2, 0, 0])))
371 enc.raw.uint8array.encode(state, Uint8Array.of(3, 4))
372 t.alike(state, enc.state(4, 4, b4a.from([1, 2, 3, 4])))
373
374 state.start = 0
375 t.alike(enc.raw.uint8array.decode(state), Uint8Array.of(1, 2, 3, 4))
376 t.alike(enc.raw.uint8array.decode(state), Uint8Array.of())
377})
378
379test('uint16array', function (t) {
380 const state = enc.state()
381
382 enc.uint16array.preencode(state, new Uint16Array([1, 2, 3]))
383 t.alike(state, enc.state(0, 7))
384
385 state.buffer = b4a.alloc(state.end)
386 enc.uint16array.encode(state, new Uint16Array([1, 2, 3]))
387 t.alike(state, enc.state(7, 7, b4a.from([3, 1, 0, 2, 0, 3, 0])))
388
389 state.start = 0
390 t.alike(enc.uint16array.decode(state), new Uint16Array([1, 2, 3]))
391 t.is(state.start, state.end)
392
393 t.exception(() => enc.uint16array.decode(state))
394})
395
396test('uint32array', function (t) {
397 const state = enc.state()
398
399 enc.uint32array.preencode(state, new Uint32Array([1]))
400 t.alike(state, enc.state(0, 5))
401 enc.uint32array.preencode(state, new Uint32Array([42, 43]))
402 t.alike(state, enc.state(0, 14))
403
404 state.buffer = b4a.alloc(state.end)
405 enc.uint32array.encode(state, new Uint32Array([1]))
406 t.alike(
407 state,
408 enc.state(5, 14, b4a.from([1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))
409 )
410 enc.uint32array.encode(state, new Uint32Array([42, 43]))
411 t.alike(
412 state,
413 enc.state(14, 14, b4a.from([1, 1, 0, 0, 0, 2, 42, 0, 0, 0, 43, 0, 0, 0]))
414 )
415
416 state.start = 0
417 t.alike(enc.uint32array.decode(state), new Uint32Array([1]))
418 t.alike(enc.uint32array.decode(state), new Uint32Array([42, 43]))
419 t.is(state.start, state.end)
420
421 t.exception(() => enc.uint32array.decode(state))
422})
423
424test('int16array', function (t) {
425 const state = enc.state()
426
427 enc.int16array.preencode(state, new Int16Array([1, -2, 3]))
428 t.alike(state, enc.state(0, 7))
429
430 state.buffer = b4a.alloc(state.end)
431 enc.int16array.encode(state, new Int16Array([1, -2, 3]))
432 t.alike(state, enc.state(7, 7, b4a.from([3, 1, 0, 0xfe, 0xff, 3, 0])))
433
434 state.start = 0
435 t.alike(enc.int16array.decode(state), new Int16Array([1, -2, 3]))
436 t.is(state.start, state.end)
437
438 t.exception(() => enc.int16array.decode(state))
439})
440
441test('int32array', function (t) {
442 const state = enc.state()
443
444 enc.int32array.preencode(state, new Int32Array([1, -2, 3]))
445 t.alike(state, enc.state(0, 13))
446
447 state.buffer = b4a.alloc(state.end)
448 enc.int32array.encode(state, new Int32Array([1, -2, 3]))
449 t.alike(
450 state,
451 enc.state(
452 13,
453 13,
454 b4a.from([3, 1, 0, 0, 0, 0xfe, 0xff, 0xff, 0xff, 3, 0, 0, 0])
455 )
456 )
457
458 state.start = 0
459 t.alike(enc.int32array.decode(state), new Int32Array([1, -2, 3]))
460 t.is(state.start, state.end)
461
462 t.exception(() => enc.int32array.decode(state))
463})
464
465test('biguint64array', function (t) {
466 const state = enc.state()
467
468 const arr = new BigUint64Array([0x01020304n, 0x05060708n, 0x090a0b0cn])
469
470 enc.biguint64array.preencode(state, arr)
471 t.alike(state, enc.state(0, 25))
472
473 state.buffer = b4a.alloc(state.end)
474 enc.biguint64array.encode(state, arr)
475 t.alike(
476 state,
477 enc.state(
478 25,
479 25,
480 b4a.from([
481 3, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x8, 0x7, 0x6, 0x5, 0x0, 0x0,
482 0x0, 0x0, 0xc, 0xb, 0xa, 0x9, 0x0, 0x0, 0x0, 0x0
483 ])
484 )
485 )
486
487 state.start = 0
488 t.alike(enc.biguint64array.decode(state), arr)
489 t.is(state.start, state.end)
490
491 t.exception(() => enc.biguint64array.decode(state))
492})
493
494test('bigint64array', function (t) {
495 const state = enc.state()
496
497 const arr = new BigInt64Array([-0x01020304n, 0x05060708n, -0x090a0b0cn])
498
499 enc.bigint64array.preencode(state, arr)
500 t.alike(state, enc.state(0, 25))
501
502 state.buffer = b4a.alloc(state.end)
503 enc.bigint64array.encode(state, arr)
504 t.alike(
505 state,
506 enc.state(
507 25,
508 25,
509 b4a.from([
510 3, 0xfc, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x8, 0x7, 0x6, 0x5,
511 0x0, 0x0, 0x0, 0x0, 0xf4, 0xf4, 0xf5, 0xf6, 0xff, 0xff, 0xff, 0xff
512 ])
513 )
514 )
515
516 state.start = 0
517 t.alike(enc.bigint64array.decode(state), arr)
518 t.is(state.start, state.end)
519
520 t.exception(() => enc.bigint64array.decode(state))
521})
522
523test('float32array', function (t) {
524 const state = enc.state()
525
526 enc.float32array.preencode(state, new Float32Array([1.1, -2.2, 3.3]))
527 t.alike(state, enc.state(0, 13))
528
529 state.buffer = b4a.alloc(state.end)
530 enc.float32array.encode(state, new Float32Array([1.1, -2.2, 3.3]))
531 t.alike(
532 state,
533 enc.state(
534 13,
535 13,
536 b4a.from([
537 3, 0xcd, 0xcc, 0x8c, 0x3f, 0xcd, 0xcc, 0x0c, 0xc0, 0x33, 0x33, 0x53,
538 0x40
539 ])
540 )
541 )
542
543 state.start = 0
544 t.alike(enc.float32array.decode(state), new Float32Array([1.1, -2.2, 3.3]))
545 t.is(state.start, state.end)
546
547 t.exception(() => enc.float32array.decode(state))
548})
549
550test('float64array', function (t) {
551 const state = enc.state()
552
553 enc.float64array.preencode(state, new Float64Array([1.1, -2.2, 3.3]))
554 t.alike(state, enc.state(0, 25))
555
556 state.buffer = b4a.alloc(state.end)
557 enc.float64array.encode(state, new Float64Array([1.1, -2.2, 3.3]))
558 t.alike(
559 state,
560 enc.state(
561 25,
562 25,
563 b4a.from([
564 3, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xf1, 0x3f, 0x9a, 0x99, 0x99,
565 0x99, 0x99, 0x99, 0x01, 0xc0, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0a,
566 0x40
567 ])
568 )
569 )
570
571 state.start = 0
572 t.alike(enc.float64array.decode(state), new Float64Array([1.1, -2.2, 3.3]))
573 t.is(state.start, state.end)
574
575 t.exception(() => enc.float64array.decode(state))
576})
577
578test('string', function (t) {
579 const state = enc.state()
580
581 enc.string.preencode(state, '🌾')
582 t.alike(state, enc.state(0, 5))
583 enc.string.preencode(state, 'høsten er fin')
584 t.alike(state, enc.state(0, 20))
585
586 state.buffer = b4a.alloc(state.end)
587 enc.string.encode(state, '🌾')
588 t.alike(
589 state,
590 enc.state(
591 5,
592 20,
593 b4a.from(
594 '\x04🌾\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
595 )
596 )
597 )
598 enc.string.encode(state, 'høsten er fin')
599 t.alike(state, enc.state(20, 20, b4a.from('\x04🌾\x0ehøsten er fin')))
600
601 state.start = 0
602 t.is(enc.string.decode(state), '🌾')
603 t.is(enc.string.decode(state), 'høsten er fin')
604 t.is(state.start, state.end)
605
606 t.exception(() => enc.string.decode(state))
607})
608
609test('raw string', function (t) {
610 const state = enc.state()
611
612 enc.raw.string.preencode(state, 'hello')
613 t.alike(state, enc.state(0, 5))
614 enc.raw.string.preencode(state, ' world')
615 t.alike(state, enc.state(0, 11))
616
617 state.buffer = b4a.alloc(state.end)
618 enc.raw.string.encode(state, 'hello')
619 enc.raw.string.encode(state, ' world')
620 t.alike(state, enc.state(11, 11, b4a.from('hello world')))
621
622 state.start = 0
623 t.is(enc.raw.string.decode(state), 'hello world')
624 t.is(enc.raw.string.decode(state), '')
625})
626
627test('fixed32', function (t) {
628 const state = enc.state()
629
630 enc.fixed32.preencode(state, b4a.alloc(32).fill('a'))
631 t.alike(state, enc.state(0, 32))
632 enc.fixed32.preencode(state, b4a.alloc(32).fill('b'))
633 t.alike(state, enc.state(0, 64))
634
635 state.buffer = b4a.alloc(state.end)
636 enc.fixed32.encode(state, b4a.alloc(32).fill('a'))
637 t.alike(state, enc.state(32, 64, b4a.alloc(64).fill('a', 0, 32)))
638 enc.fixed32.encode(state, b4a.alloc(32).fill('b'))
639 t.alike(
640 state,
641 enc.state(64, 64, b4a.alloc(64).fill('a', 0, 32).fill('b', 32, 64))
642 )
643
644 state.start = 0
645 t.alike(enc.fixed32.decode(state), b4a.alloc(32).fill('a'))
646 t.alike(enc.fixed32.decode(state), b4a.alloc(32).fill('b'))
647 t.is(state.start, state.end)
648
649 t.exception(() => enc.fixed32.decode(state))
650})
651
652test('fixed64', function (t) {
653 const state = enc.state()
654
655 enc.fixed64.preencode(state, b4a.alloc(64).fill('a'))
656 t.alike(state, enc.state(0, 64))
657 enc.fixed64.preencode(state, b4a.alloc(64).fill('b'))
658 t.alike(state, enc.state(0, 128))
659
660 state.buffer = b4a.alloc(state.end)
661 enc.fixed64.encode(state, b4a.alloc(64).fill('a'))
662 t.alike(state, enc.state(64, 128, b4a.alloc(128).fill('a', 0, 64)))
663 enc.fixed64.encode(state, b4a.alloc(64).fill('b'))
664 t.alike(
665 state,
666 enc.state(128, 128, b4a.alloc(128).fill('a', 0, 64).fill('b', 64, 128))
667 )
668
669 state.start = 0
670 t.alike(enc.fixed64.decode(state), b4a.alloc(64).fill('a'))
671 t.alike(enc.fixed64.decode(state), b4a.alloc(64).fill('b'))
672 t.is(state.start, state.end)
673
674 t.exception(() => enc.fixed64.decode(state))
675})
676
677test('fixed n', function (t) {
678 const state = enc.state()
679 const fixed = enc.fixed(3)
680
681 fixed.preencode(state, b4a.alloc(3).fill('a'))
682 t.alike(state, enc.state(0, 3))
683 fixed.preencode(state, b4a.alloc(3).fill('b'))
684 t.alike(state, enc.state(0, 6))
685
686 state.buffer = b4a.alloc(state.end)
687 fixed.encode(state, b4a.alloc(3).fill('a'))
688 t.alike(state, enc.state(3, 6, b4a.alloc(6).fill('a', 0, 3)))
689 fixed.encode(state, b4a.alloc(3).fill('b'))
690 t.alike(state, enc.state(6, 6, b4a.alloc(6).fill('a', 0, 3).fill('b', 3, 6)))
691
692 state.start = 0
693 t.alike(fixed.decode(state), b4a.alloc(3).fill('a'))
694 t.alike(fixed.decode(state), b4a.alloc(3).fill('b'))
695 t.is(state.start, state.end)
696
697 t.exception(() => fixed.decode(state))
698 state.start = 4
699 t.exception(() => fixed.decode(state))
700})
701
702test('error for incorrect buffer sizes when encoding fixed-length buffers', function (t) {
703 const smallbuf = b4a.from('aa', 'hex')
704 const bigBuf = b4a.from('aa'.repeat(500), 'hex')
705
706 t.exception(() => enc.encode(enc.fixed32, smallbuf), /Incorrect buffer size/)
707 t.exception(() => enc.encode(enc.fixed64, smallbuf), /Incorrect buffer size/)
708 t.exception(
709 () => enc.encode(enc.fixed(100), smallbuf),
710 /Incorrect buffer size/
711 )
712
713 t.exception(() => enc.encode(enc.fixed32, bigBuf), /Incorrect buffer size/)
714 t.exception(() => enc.encode(enc.fixed64, bigBuf), /Incorrect buffer size/)
715 t.exception(() => enc.encode(enc.fixed(100), bigBuf), /Incorrect buffer size/)
716})
717
718test('array', function (t) {
719 const state = enc.state()
720 const arr = enc.array(enc.bool)
721
722 arr.preencode(state, [true, false, true])
723 t.alike(state, enc.state(0, 4))
724 arr.preencode(state, [false, false, true, true])
725 t.alike(state, enc.state(0, 9))
726
727 state.buffer = b4a.alloc(state.end)
728 arr.encode(state, [true, false, true])
729 t.alike(state, enc.state(4, 9, b4a.from([3, 1, 0, 1, 0, 0, 0, 0, 0])))
730 arr.encode(state, [false, false, true, true])
731 t.alike(state, enc.state(9, 9, b4a.from([3, 1, 0, 1, 4, 0, 0, 1, 1])))
732
733 state.start = 0
734 t.alike(arr.decode(state), [true, false, true])
735 t.alike(arr.decode(state), [false, false, true, true])
736 t.is(state.start, state.end)
737
738 t.exception(() => arr.decode(state))
739})
740
741test('raw array', function (t) {
742 const state = enc.state()
743 const arr = enc.raw.array(enc.bool)
744
745 arr.preencode(state, [true])
746 t.alike(state, enc.state(0, 1))
747 arr.preencode(state, [true])
748 t.alike(state, enc.state(0, 2))
749
750 state.buffer = b4a.alloc(state.end)
751 arr.encode(state, [true])
752 t.alike(state, enc.state(1, 2, b4a.from([1, 0])))
753 arr.encode(state, [true])
754 t.alike(state, enc.state(2, 2, b4a.from([1, 1])))
755
756 state.start = 0
757 t.alike(arr.decode(state), [true, true])
758 t.alike(arr.decode(state), [])
759})
760
761test('json', function (t) {
762 const state = enc.state()
763
764 enc.json.preencode(state, { a: 1, b: 2 })
765 t.alike(state, enc.state(0, 14))
766
767 state.buffer = b4a.alloc(state.end)
768 enc.json.encode(state, { a: 1, b: 2 })
769 t.alike(
770 state,
771 enc.state(14, 14, b4a.concat([b4a.from([13]), b4a.from('{"a":1,"b":2}')]))
772 )
773
774 state.start = 0
775 t.alike(enc.json.decode(state), { a: 1, b: 2 })
776
777 t.exception(() => enc.json.decode(state))
778})
779
780test('raw json', function (t) {
781 const state = enc.state()
782
783 enc.raw.json.preencode(state, { a: 1, b: 2 })
784 t.alike(state, enc.state(0, 13))
785
786 state.buffer = b4a.alloc(state.end)
787 enc.raw.json.encode(state, { a: 1, b: 2 })
788 t.alike(state, enc.state(13, 13, b4a.from('{"a":1,"b":2}')))
789
790 state.start = 0
791 t.alike(enc.raw.json.decode(state), { a: 1, b: 2 })
792
793 t.exception(() => enc.json.decode(state))
794})
795
796test('lexint: big numbers', function (t) {
797 t.plan(1)
798
799 let prev = enc.encode(enc.lexint, 0)
800
801 let n
802 let skip = 1
803
804 for (n = 1; n < Number.MAX_VALUE; n += skip) {
805 const cur = enc.encode(enc.lexint, n)
806 if (b4a.compare(cur, prev) < 1) break
807 prev = cur
808 skip = 1 + Math.pow(245, Math.ceil(Math.log(n) / Math.log(256)))
809 }
810 t.is(n, Infinity)
811})
812
813test('lexint: range precision', function (t) {
814 t.plan(2)
815 const a = 1e55
816 const b = 1.0000000000001e55
817 const ha = enc.encode(enc.lexint, a).toString('hex')
818 const hb = enc.encode(enc.lexint, b).toString('hex')
819 t.not(a, b)
820 t.not(ha, hb)
821})
822
823test('lexint: range precision', function (t) {
824 let prev = enc.encode(enc.lexint, 0)
825 const skip = 0.000000001e55
826 for (let i = 0, n = 1e55; i < 1000; n = 1e55 + skip * ++i) {
827 const cur = enc.encode(enc.lexint, n)
828 if (b4a.compare(cur, prev) < 1) t.fail('cur <= prev')
829 prev = cur
830 }
831 t.ok(true)
832 t.end()
833})
834
835test('lexint: small numbers', function (t) {
836 let prev = enc.encode(enc.lexint, 0)
837 for (let n = 1; n < 256 * 256 * 16; n++) {
838 const cur = enc.encode(enc.lexint, n)
839 if (b4a.compare(cur, prev) < 1) t.fail('cur <= prev')
840 prev = cur
841 }
842 t.ok(true)
843 t.end()
844})
845
846test('lexint: throws', function (t) {
847 t.exception(() => {
848 enc.decode(enc.lexint, b4a.alloc(1, 251))
849 })
850
851 let num = 252
852
853 const state = enc.state()
854
855 enc.lexint.preencode(state, num)
856 state.buffer = b4a.alloc(state.end - state.start)
857 enc.lexint.encode(state, num)
858
859 t.exception(() => {
860 enc.decode(
861 enc.lexint,
862 state.buffer.subarray(0, state.buffer.byteLength - 2)
863 )
864 })
865
866 num <<= 8
867
868 state.start = 0
869 state.end = 0
870 state.buffer = null
871
872 enc.lexint.preencode(state, num)
873 state.buffer = b4a.alloc(state.end - state.start)
874 enc.lexint.encode(state, num)
875
876 t.exception(() => {
877 enc.decode(
878 enc.lexint,
879 state.buffer.subarray(0, state.buffer.byteLength - 2)
880 )
881 })
882
883 num <<= 8
884
885 state.start = 0
886 state.end = 0
887 state.buffer = null
888
889 enc.lexint.preencode(state, num)
890 state.buffer = b4a.alloc(state.end - state.start)
891 enc.lexint.encode(state, num)
892
893 t.exception(() => {
894 enc.decode(
895 enc.lexint,
896 state.buffer.subarray(0, state.buffer.byteLength - 2)
897 )
898 })
899
900 num *= 256
901
902 state.start = 0
903 state.end = 0
904 state.buffer = null
905
906 enc.lexint.preencode(state, num)
907 state.buffer = b4a.alloc(state.end - state.start)
908 enc.lexint.encode(state, num)
909
910 t.exception(() => {
911 enc.decode(
912 enc.lexint,
913 state.buffer.subarray(0, state.buffer.byteLength - 2)
914 )
915 })
916
917 num *= 256 * 256
918
919 state.start = 0
920 state.end = 0
921 state.buffer = null
922
923 enc.lexint.preencode(state, num)
924 state.buffer = b4a.alloc(state.end - state.start)
925 enc.lexint.encode(state, num)
926
927 t.exception(() => {
928 enc.decode(
929 enc.lexint,
930 state.buffer.subarray(0, state.buffer.byteLength - 2)
931 )
932 })
933
934 t.end()
935})
936
937test('lexint: unpack', function (t) {
938 let n
939 let skip = 1
940
941 for (n = 1; n < Number.MAX_VALUE; n += skip) {
942 const cur = enc.encode(enc.lexint, n)
943 compare(n, enc.decode(enc.lexint, cur))
944 skip = 1 + Math.pow(245, Math.ceil(Math.log(n) / Math.log(256)))
945 }
946 t.is(n, Infinity)
947 t.end()
948
949 function compare(a, b) {
950 const desc = a + ' !=~ ' + b
951 if (/e\+\d+$/.test(a) || /e\+\d+$/.test(b)) {
952 if (
953 String(a).slice(0, 8) !== String(b).slice(0, 8) ||
954 /e\+(\d+)$/.exec(a)[1] !== /e\+(\d+)$/.exec(b)[1]
955 ) {
956 t.fail(desc)
957 }
958 } else {
959 if (
960 String(a).slice(0, 8) !== String(b).slice(0, 8) ||
961 String(a).length !== String(b).length
962 ) {
963 t.fail(desc)
964 }
965 }
966 }
967})
968
969test('date', function (t) {
970 const d = new Date()
971
972 t.alike(enc.decode(enc.date, enc.encode(enc.date, d)), d)
973})
974
975test('any', function (t) {
976 const o = {
977 hello: 'world',
978 num: 42,
979 neg: -42,
980 arr: [{ yes: 1 }, { no: false }],
981 nest: {},
982 today: new Date(),
983 float: 0.54
984 }
985
986 t.alike(enc.decode(enc.any, enc.encode(enc.any, o)), o)
987
988 const arr = new Array(3)
989
990 t.alike(enc.decode(enc.any, enc.encode(enc.any, arr)), [null, null, null])
991})
992
993test('framed', function (t) {
994 const e = enc.frame(enc.uint)
995 t.alike(enc.encode(e, 42), b4a.from([0x01, 0x2a]))
996 t.alike(enc.decode(e, b4a.from([0x01, 0x2a])), 42)
997 t.alike(enc.encode(e, 4200), b4a.from([0x03, 0xfd, 0x68, 0x10]))
998 t.alike(enc.decode(e, b4a.from([0x03, 0xfd, 0x68, 0x10])), 4200)
999})
1000
1001test('port', function (t) {
1002 const p = 0x1234
1003 const buf = Buffer.from([0x34, 0x12])
1004
1005 t.alike(enc.encode(enc.port, p), buf)
1006 t.alike(enc.decode(enc.port, buf), p)
1007})
1008
1009test('ipv4', function (t) {
1010 const ip = '1.2.3.4'
1011 const buf = Buffer.from([1, 2, 3, 4])
1012
1013 t.alike(enc.encode(enc.ipv4, ip), buf)
1014 t.alike(enc.decode(enc.ipv4, buf), ip)
1015})
1016
1017test('ipv4 + port', function (t) {
1018 const host = '1.2.3.4'
1019 const port = 1234
1020
1021 t.alike(
1022 enc.decode(enc.ipv4Address, enc.encode(enc.ipv4Address, { host, port })),
1023 {
1024 host,
1025 family: 4,
1026 port
1027 }
1028 )
1029})
1030
1031test('ipv6', function (t) {
1032 const ip = '1:2:3:4:5:6:7:8'
1033 const buf = Buffer.from([0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8])
1034
1035 t.alike(enc.encode(enc.ipv6, ip), buf)
1036 t.alike(enc.decode(enc.ipv6, buf), ip)
1037
1038 t.test('abbreviated', function (t) {
1039 const buf = Buffer.from([0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 8])
1040
1041 t.alike(enc.encode(enc.ipv6, '1:2::7:8'), buf)
1042 t.alike(enc.decode(enc.ipv6, buf), '1:2:0:0:0:0:7:8')
1043 })
1044
1045 t.test('prefix abbreviated', function (t) {
1046 const buf = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, 7, 0, 8])
1047
1048 t.alike(enc.encode(enc.ipv6, '::5:6:7:8'), buf)
1049 t.alike(enc.decode(enc.ipv6, buf), '0:0:0:0:5:6:7:8')
1050 })
1051
1052 t.test('suffix abbreviated', function (t) {
1053 const buf = Buffer.from([0, 1, 0, 2, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0])
1054
1055 t.alike(enc.encode(enc.ipv6, '1:2:3:4::'), buf)
1056 t.alike(enc.decode(enc.ipv6, buf), '1:2:3:4:0:0:0:0')
1057 })
1058
1059 t.test('any', function (t) {
1060 const buf = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
1061
1062 t.alike(enc.encode(enc.ipv6, '::'), buf)
1063 t.alike(enc.decode(enc.ipv6, buf), '0:0:0:0:0:0:0:0')
1064 })
1065
1066 t.test('lowercase hex', function (t) {
1067 const buf = Buffer.from([
1068 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xab, 0xcd
1069 ])
1070
1071 t.alike(enc.encode(enc.ipv6, '::abcd'), buf)
1072 t.alike(enc.decode(enc.ipv6, buf), '0:0:0:0:0:0:0:abcd')
1073 })
1074
1075 t.test('uppercase hex', function (t) {
1076 const buf = Buffer.from([
1077 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xab, 0xcd
1078 ])
1079
1080 t.alike(enc.encode(enc.ipv6, '::ABCD'), buf)
1081 t.alike(enc.decode(enc.ipv6, buf), '0:0:0:0:0:0:0:abcd')
1082 })
1083})
1084
1085test('ipv6 + port', function (t) {
1086 const host = '1:2:3:4:5:6:7:8'
1087 const port = 1234
1088
1089 t.alike(
1090 enc.decode(enc.ipv6Address, enc.encode(enc.ipv6Address, { host, port })),
1091 {
1092 host,
1093 family: 6,
1094 port
1095 }
1096 )
1097})
1098
1099test('dual ip', function (t) {
1100 {
1101 const host = '1.2.3.4'
1102
1103 t.alike(enc.decode(enc.ip, enc.encode(enc.ip, host)), host, 'ipv4')
1104 }
1105 {
1106 const host = '1:2:3:4:5:6:7:8'
1107
1108 t.alike(enc.decode(enc.ip, enc.encode(enc.ip, host)), host, 'ipv6')
1109 }
1110})
1111
1112test('dual ip + port', function (t) {
1113 const port = 1234
1114
1115 {
1116 const host = '1.2.3.4'
1117
1118 t.alike(
1119 enc.decode(enc.ipAddress, enc.encode(enc.ipAddress, { host, port })),
1120 {
1121 host,
1122 family: 4,
1123 port
1124 },
1125 'ipv4'
1126 )
1127 }
1128 {
1129 const host = '1:2:3:4:5:6:7:8'
1130
1131 t.alike(
1132 enc.decode(enc.ipAddress, enc.encode(enc.ipAddress, { host, port })),
1133 {
1134 host,
1135 family: 6,
1136 port
1137 },
1138 'ipv6'
1139 )
1140 }
1141})
1142
1143test('record', function (t) {
1144 const encoding = enc.record(enc.string, enc.string)
1145
1146 t.alike(
1147 enc.decode(encoding, enc.encode(encoding, { a: 'hello', b: 'world' })),
1148 Object.assign(Object.create(null), {
1149 a: 'hello',
1150 b: 'world'
1151 })
1152 )
1153})
1154
1155test('record - nested', function (t) {
1156 const encoding = enc.record(enc.string, enc.record(enc.string, enc.string))
1157
1158 t.alike(
1159 enc.decode(
1160 encoding,
1161 enc.encode(encoding, {
1162 a: { b: 'record' },
1163 c: { d: 'nested', e: 'test' }
1164 })
1165 ),
1166 Object.assign(Object.create(null), {
1167 a: Object.assign(Object.create(null), { b: 'record' }),
1168 c: Object.assign(Object.create(null), { d: 'nested', e: 'test' })
1169 })
1170 )
1171})
1172
1173test('stringRecord', function (t) {
1174 t.alike(
1175 enc.decode(
1176 enc.stringRecord,
1177 enc.encode(enc.stringRecord, { a: 'hello', b: 'world' })
1178 ),
1179 Object.assign(Object.create(null), {
1180 a: 'hello',
1181 b: 'world'
1182 })
1183 )
1184})
node_modules/corestore/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2023 Holepunch Inc
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/corestore/README.md +109 -0
……@@ -0,0 +1,109 @@
1# Corestore
2
3### [See the full API docs at docs.holepunch.to](https://docs.holepunch.to/helpers/corestore)
4
5Corestore is a Hypercore factory that makes it easier to manage large collections of named Hypercores.
6
7Corestore provides:
81. __Key Derivation__ - All writable Hypercore keys are derived from a single master key and a user-provided name.
92. __Session Handling__ - If a single Hypercore is loaded multiple times through the `get` method, the underlying resources will only be opened once (using Hypercore 10's new session feature). Once all sessions are closed, the resources will be released.
103. __Storage Management__ - Hypercores can be stored in any random-access-storage instance, where they will be keyed by their discovery keys.
114. __Namespacing__ - You can share a single Corestore instance between multiple applications or components without worrying about naming collisions by creating "namespaces" (e.g. `corestore.namespace('my-app').get({ name: 'main' })`)
12
13### Installation
14`npm install corestore`
15
16### Usage
17A corestore instance can be constructed with a random-access-storage module, a function that returns a random-access-storage module given a path, or a string. If a string is specified, it will be assumed to be a path to a local storage directory:
18```js
19const Corestore = require('corestore')
20
21const store = new Corestore('./my-storage')
22const core1 = store.get({ name: 'core-1' })
23const core2 = store.get({ name: 'core-2' })
24```
25
26### API
27#### `const store = new Corestore(storage, opts = {})`
28Create a new Corestore instance.
29
30`storage` can be either a random-access-storage module, a string, or a function that takes a path and returns an random-access-storage instance.
31
32Opts include:
33```js
34{
35 inflightRange: null // Advanced option. Forwarded to the Hypercores created by corestore.get(...)
36}
37```
38
39#### `const core = store.get(key | { name: 'a-name', exclusive, ...hypercoreOpts})`
40Loads a Hypercore, either by name (if the `name` option is provided), or from the provided key (if the first argument is a Buffer or String with hex/z32 key, or if the `key` options is set).
41
42If that Hypercore has previously been loaded, subsequent calls to `get` will return a new Hypercore session on the existing core.
43
44If you set the `exclusive` option and you are opening a writable session it will wait for all other exclusive writable to close before
45opening the Hypercore effectively meaning any op on the core will wait until its exclusive.
46
47All other options besides `name` and `key` and `exclusive` will be forwarded to the Hypercore constructor.
48
49#### `const stream = store.replicate(optsOrStream)`
50Creates a replication stream that's capable of replicating all Hypercores that are managed by the Corestore, assuming the remote peer has the correct capabilities.
51
52`opts` will be forwarded to Hypercore's `replicate` function.
53
54Corestore replicates in an "all-to-all" fashion, meaning that when replication begins, it will attempt to replicate every Hypercore that's currently loaded and in memory. These attempts will fail if the remote side doesn't have a Hypercore's capability -- Corestore replication does not exchange Hypercore keys.
55
56If the remote side dynamically adds a new Hypercore to the replication stream, Corestore will load and replicate that core if possible.
57
58Using [Hyperswarm](https://github.com/holepunchto/hyperswarm) you can easily replicate corestores
59
60``` js
61const swarm = new Hyperswarm()
62
63// join the relevant topic
64swarm.join(...)
65
66// simply pass the connection stream to corestore
67swarm.on('connection', (connection) => store.replicate(connection))
68```
69
70#### `const store = store.namespace(name)`
71Create a new namespaced Corestore. Namespacing is useful if you're going to be sharing a single Corestore instance between many applications or components, as it prevents name collisions.
72
73Namespaces can be chained:
74```js
75const ns1 = store.namespace('a')
76const ns2 = ns1.namespace('b')
77const core1 = ns1.get({ name: 'main' }) // These will load different Hypercores
78const core2 = ns2.get({ name: 'main' })
79```
80
81#### `const storeB = storeA.session(opts)`
82Create a new Corestore that shares resources with the original, like cache, cores, replication streams, and storage, while optionally resetting the namespace, overriding `primaryKey`.
83Useful when an application wants to accept an optional Corestore, but needs to maintain a predictable key derivation.
84
85`opts` are the same as the constructor options:
86
87```js
88{
89 primaryKey, // Overrides the primaryKey for this session
90 namespace, // If set to null it will reset to the DEFAULT_NAMESPACE
91 detach: true, // By disabling this, closing the session will also close the store that created the session
92 inflightRange: null // Advanced option. Forwarded to the Hypercores created by `session.get(...)
93}
94```
95
96#### `await store.close()`
97Fully close this Corestore instance.
98
99#### `store.on('core-open', core)`
100Emitted when the first session for a core is opened.
101
102*Note: This core may close at any time, so treat it as a weak reference*
103
104#### `store.on('core-close', core)`
105Emitted when the last session for a core is closed.
106
107### License
108MIT
109
node_modules/corestore/index.js +591 -0
……@@ -0,0 +1,591 @@
1const safetyCatch = require('safety-catch')
2const crypto = require('hypercore-crypto')
3const sodium = require('sodium-universal')
4const Hypercore = require('hypercore')
5const hypercoreId = require('hypercore-id-encoding')
6const Xache = require('xache')
7const b4a = require('b4a')
8const ReadyResource = require('ready-resource')
9const RW = require('read-write-mutexify')
10
11const [NS] = crypto.namespace('corestore', 1)
12const DEFAULT_NAMESPACE = b4a.alloc(32) // This is meant to be 32 0-bytes
13
14const CORES_DIR = 'cores'
15const PRIMARY_KEY_FILE_NAME = 'primary-key'
16const USERDATA_NAME_KEY = 'corestore/name'
17const USERDATA_NAMESPACE_KEY = 'corestore/namespace'
18const POOL_SIZE = 512 // how many open fds to aim for before cycling them
19const DEFAULT_MANIFEST = 0 // bump to 1 when this is more widely deployed
20const DEFAULT_COMPAT = true
21
22module.exports = class Corestore extends ReadyResource {
23 constructor (storage, opts = {}) {
24 super()
25
26 const root = opts._root
27
28 this.storage = Hypercore.defaultStorage(storage, { lock: PRIMARY_KEY_FILE_NAME, poolSize: opts.poolSize || POOL_SIZE, rmdir: true })
29 this.cores = root ? root.cores : new Map()
30 this.cache = !!opts.cache
31 this.primaryKey = opts.primaryKey || null
32 this.passive = !!opts.passive
33 this.manifestVersion = typeof opts.manifestVersion === 'number' ? opts.manifestVersion : (root ? root.manifestVersion : DEFAULT_MANIFEST)
34 this.compat = typeof opts.compat === 'boolean' ? opts.compat : (root ? root.compat : DEFAULT_COMPAT)
35 this.inflightRange = opts.inflightRange || null
36 this.globalCache = opts.globalCache || null
37
38 this._keyStorage = null
39 this._bootstrap = opts._bootstrap || null
40 this._namespace = opts.namespace || DEFAULT_NAMESPACE
41 this._noCoreCache = root ? root._noCoreCache : new Xache({ maxSize: 65536 })
42
43 this._root = root || this
44 this._replicationStreams = root ? root._replicationStreams : []
45 this._overwrite = opts.overwrite === true
46 this._readonly = opts.writable === false
47 this._attached = opts._attached || null
48 this._notDownloadingLinger = opts.notDownloadingLinger
49
50 this._sessions = new Set() // sessions for THIS namespace
51 this._rootStoreSessions = new Set()
52 this._locks = root ? root._locks : new Map()
53
54 this._findingPeersCount = 0
55 this._findingPeers = []
56 this._isCorestore = true
57
58 if (this._namespace.byteLength !== 32) throw new Error('Namespace must be a 32-byte Buffer or Uint8Array')
59 this.ready().catch(safetyCatch)
60 }
61
62 static isCorestore (obj) {
63 return !!(typeof obj === 'object' && obj && obj._isCorestore)
64 }
65
66 static from (storage, opts) {
67 return this.isCorestore(storage) ? storage : new this(storage, opts)
68 }
69
70 // for now just release the lock...
71 async suspend () {
72 if (this._root !== this) return this._root.suspend()
73
74 await this.ready()
75
76 if (this._keyStorage !== null) {
77 await new Promise((resolve, reject) => {
78 this._keyStorage.suspend((err) => {
79 if (err) return reject(err)
80 resolve()
81 })
82 })
83 }
84 }
85
86 async resume () {
87 if (this._root !== this) return this._root.resume()
88
89 await this.ready()
90
91 if (this._keyStorage !== null) {
92 await new Promise((resolve, reject) => {
93 this._keyStorage.open((err) => {
94 if (err) return reject(err)
95 resolve()
96 })
97 })
98 }
99 }
100
101 findingPeers () {
102 let done = false
103 this._incFindingPeers()
104
105 return () => {
106 if (done) return
107 done = true
108 this._decFindingPeers()
109 }
110 }
111
112 _emitCore (name, core) {
113 this.emit(name, core)
114 for (const session of this._root._rootStoreSessions) {
115 if (session !== this) {
116 session.emit(name, core)
117 }
118 }
119 if (this !== this._root) this._root.emit(name, core)
120 }
121
122 _incFindingPeers () {
123 if (++this._findingPeersCount !== 1) return
124
125 for (const core of this._sessions) {
126 this._findingPeers.push(core.findingPeers())
127 }
128 }
129
130 _decFindingPeers () {
131 if (--this._findingPeersCount !== 0) return
132
133 while (this._findingPeers.length > 0) {
134 this._findingPeers.pop()()
135 }
136 }
137
138 async _openNamespaceFromBootstrap () {
139 const ns = await this._bootstrap.getUserData(USERDATA_NAMESPACE_KEY)
140 if (ns) {
141 this._namespace = ns
142 }
143 }
144
145 async _open () {
146 if (this._root !== this) {
147 await this._root.ready()
148 if (!this.primaryKey) this.primaryKey = this._root.primaryKey
149 if (this._bootstrap) await this._openNamespaceFromBootstrap()
150 return
151 }
152
153 this._keyStorage = this.storage(PRIMARY_KEY_FILE_NAME)
154
155 this.primaryKey = await new Promise((resolve, reject) => {
156 this._keyStorage.stat((err, st) => {
157 if (err && err.code !== 'ENOENT') return reject(err)
158 if (err || st.size < 32 || this._overwrite) {
159 const key = this.primaryKey || crypto.randomBytes(32)
160 return this._keyStorage.write(0, key, err => {
161 if (err) return reject(err)
162 return resolve(key)
163 })
164 }
165 this._keyStorage.read(0, 32, (err, key) => {
166 if (err) return reject(err)
167 if (this.primaryKey) return resolve(this.primaryKey)
168 return resolve(key)
169 })
170 })
171 })
172
173 if (this._bootstrap) await this._openNamespaceFromBootstrap()
174 }
175
176 async _exists (discoveryKey) {
177 const id = b4a.toString(discoveryKey, 'hex')
178 const storageRoot = getStorageRoot(id)
179
180 const st = this.storage(storageRoot + '/oplog')
181
182 const exists = await new Promise((resolve) => st.stat((err, st) => resolve(!err && st.size > 0)))
183 await new Promise(resolve => st.close(resolve))
184
185 return exists
186 }
187
188 async _generateKeys (opts) {
189 if (opts._discoveryKey) {
190 return {
191 manifest: null,
192 keyPair: null,
193 key: null,
194 discoveryKey: opts._discoveryKey
195 }
196 }
197
198 const keyPair = opts.name
199 ? await this.createKeyPair(opts.name)
200 : (opts.secretKey)
201 ? { secretKey: opts.secretKey, publicKey: opts.publicKey }
202 : null
203
204 if (opts.manifest) {
205 const key = Hypercore.key(opts.manifest)
206
207 return {
208 manifest: opts.manifest,
209 keyPair,
210 key,
211 discoveryKey: crypto.discoveryKey(key)
212 }
213 }
214
215 if (opts.key) {
216 return {
217 manifest: null,
218 keyPair,
219 key: opts.key,
220 discoveryKey: crypto.discoveryKey(opts.key)
221 }
222 }
223
224 const publicKey = opts.publicKey || keyPair.publicKey
225
226 if (opts.compat === false || (opts.compat !== true && !this.compat)) {
227 let manifest = { version: this.manifestVersion, signers: [{ publicKey }] } // default manifest
228 let key = Hypercore.key(manifest)
229 let discoveryKey = crypto.discoveryKey(key)
230
231 if (!(await this._exists(discoveryKey)) && manifest.version !== 0) {
232 const manifestV0 = { version: 0, signers: [{ publicKey }] }
233 const keyV0 = Hypercore.key(manifestV0)
234 const discoveryKeyV0 = crypto.discoveryKey(keyV0)
235
236 if (await this._exists(discoveryKeyV0)) {
237 manifest = manifestV0
238 key = keyV0
239 discoveryKey = discoveryKeyV0
240 }
241 }
242
243 return {
244 manifest,
245 keyPair,
246 key,
247 discoveryKey
248 }
249 }
250
251 return {
252 manifest: null,
253 keyPair,
254 key: publicKey,
255 discoveryKey: crypto.discoveryKey(publicKey)
256 }
257 }
258
259 _getPrereadyUserData (core, key) {
260 // Need to manually read the header values before the Hypercore is ready, hence the ugliness.
261 for (const { key: savedKey, value } of core.core.header.userData) {
262 if (key === savedKey) return value
263 }
264 return null
265 }
266
267 async _preready (core) {
268 const name = this._getPrereadyUserData(core, USERDATA_NAME_KEY)
269 if (!name) return
270
271 const namespace = this._getPrereadyUserData(core, USERDATA_NAMESPACE_KEY)
272 const keyPair = await this.createKeyPair(b4a.toString(name), namespace)
273 core.setKeyPair(keyPair)
274 }
275
276 _getLock (id) {
277 let rw = this._locks.get(id)
278
279 if (!rw) {
280 rw = new RW()
281 this._locks.set(id, rw)
282 }
283
284 return rw
285 }
286
287 async _preload (id, keys, opts) {
288 const { manifest, keyPair, key } = keys
289
290 while (this.cores.has(id)) {
291 const existing = this.cores.get(id)
292 if (existing.opened && !existing.closing) return { from: existing, keyPair, manifest, cache: !!opts.cache }
293 if (existing.closing) {
294 await existing.close()
295 } else {
296 await existing.ready().catch(safetyCatch)
297 }
298 }
299
300 const hasKeyPair = !!(keyPair && keyPair.secretKey)
301 const userData = {}
302 if (opts.name) {
303 userData[USERDATA_NAME_KEY] = b4a.from(opts.name)
304 userData[USERDATA_NAMESPACE_KEY] = this._namespace
305 }
306
307 // No more async ticks allowed after this point -- necessary for caching
308
309 const storageRoot = getStorageRoot(id)
310 const core = new Hypercore(p => this.storage(storageRoot + '/' + p), {
311 _preready: this._preready.bind(this),
312 notDownloadingLinger: this._notDownloadingLinger,
313 inflightRange: this.inflightRange,
314 autoClose: true,
315 active: false,
316 encryptionKey: opts.encryptionKey || null,
317 isBlockKey: !!opts.isBlockKey,
318 userData,
319 manifest,
320 key,
321 compat: opts.compat,
322 cache: opts.cache,
323 globalCache: this.globalCache,
324 createIfMissing: opts.createIfMissing === false ? false : !opts._discoveryKey,
325 keyPair: hasKeyPair ? keyPair : null
326 })
327
328 if (this._root.closing) {
329 try {
330 await core.close()
331 } catch {}
332 throw new Error('The corestore is closed')
333 }
334
335 this.cores.set(id, core)
336 this._noCoreCache.delete(id)
337 core.ready().then(() => {
338 if (core.closing) return // extra safety here as ready is a tick after open
339 if (hasKeyPair) core.setKeyPair(keyPair)
340 this._emitCore('core-open', core)
341 if (this.passive) return
342
343 const ondownloading = () => {
344 for (const { stream } of this._replicationStreams) {
345 core.replicate(stream, { session: true })
346 }
347 }
348 // when the replicator says we are downloading, answer the call
349 core.replicator.ondownloading = ondownloading
350 // trigger once if the condition is already true
351 if (core.replicator.downloading) ondownloading()
352 }, () => {
353 this._noCoreCache.set(id, true)
354 this.cores.delete(id)
355 })
356 core.once('close', () => {
357 this._emitCore('core-close', core)
358 this.cores.delete(id)
359 })
360 core.on('conflict', (len, fork, proof) => {
361 this.emit('conflict', core, len, fork, proof)
362 })
363
364 return { from: core, keyPair, manifest, cache: !!opts.cache }
365 }
366
367 async createKeyPair (name, namespace = this._namespace) {
368 if (!this.opened) await this.ready()
369
370 const keyPair = {
371 publicKey: b4a.allocUnsafeSlow(sodium.crypto_sign_PUBLICKEYBYTES),
372 secretKey: b4a.alloc(sodium.crypto_sign_SECRETKEYBYTES)
373 }
374
375 const seed = deriveSeed(this.primaryKey, namespace, name)
376 sodium.crypto_sign_seed_keypair(keyPair.publicKey, keyPair.secretKey, seed)
377
378 return keyPair
379 }
380
381 get (opts = {}) {
382 if (this.closing || this._root.closing) throw new Error('The corestore is closed')
383 opts = validateGetOptions(opts)
384
385 if (opts.cache !== false) {
386 opts.cache = opts.cache === true || (this.cache && !opts.cache) ? defaultCache() : opts.cache
387 }
388 if (this._readonly && opts.writable !== false) {
389 opts.writable = false
390 }
391
392 let rw = null
393 let id = null
394
395 const core = new Hypercore(null, {
396 ...opts,
397 globalCache: this.globalCache,
398 name: null,
399 preload: async () => {
400 if (opts.preload) opts = { ...opts, ...(await opts.preload()) }
401 if (!this.opened) await this.ready()
402
403 const keys = await this._generateKeys(opts)
404
405 id = b4a.toString(keys.discoveryKey, 'hex')
406 rw = (opts.exclusive && opts.writable !== false) ? this._getLock(id) : null
407
408 if (rw) await rw.write.lock()
409 return await this._preload(id, keys, opts)
410 }
411 })
412
413 this._sessions.add(core)
414 if (this._findingPeersCount > 0) {
415 this._findingPeers.push(core.findingPeers())
416 }
417
418 const gc = () => {
419 // technically better to also clear _findingPeers if we added it,
420 // but the lifecycle for those are pretty short so prob not worth the complexity
421 // as _decFindingPeers clear them all.
422 this._sessions.delete(core)
423
424 if (!rw) return
425 rw.write.unlock()
426 if (!rw.write.locked) this._locks.delete(id)
427 }
428
429 core.ready().catch(gc)
430 core.once('close', gc)
431
432 return core
433 }
434
435 replicate (isInitiator, opts) {
436 const isExternal = isStream(isInitiator) || !!(opts && opts.stream)
437 const stream = Hypercore.createProtocolStream(isInitiator, {
438 ...opts,
439 ondiscoverykey: async discoveryKey => {
440 if (this.closing) return
441
442 const id = b4a.toString(discoveryKey, 'hex')
443 if (this._noCoreCache.get(id)) return
444
445 const core = this.get({ _discoveryKey: discoveryKey, active: false })
446
447 try {
448 await core.ready()
449 } catch {
450 return
451 }
452
453 // remote is asking for the core so we HAVE to answer even if not downloading
454 if (!core.closing) core.replicate(stream, { session: true })
455 await core.close()
456 }
457 })
458
459 if (!this.passive) {
460 const muxer = stream.noiseStream.userData
461 muxer.cork()
462 for (const core of this.cores.values()) {
463 // If the core is not opened, it will be replicated in preload.
464 if (!core.opened || core.closing || !core.replicator.downloading) continue
465 core.replicate(stream, { session: true })
466 }
467 stream.noiseStream.opened.then(() => muxer.uncork())
468 }
469
470 const streamRecord = { stream, isExternal }
471 this._replicationStreams.push(streamRecord)
472
473 stream.once('close', () => {
474 this._replicationStreams.splice(this._replicationStreams.indexOf(streamRecord), 1)
475 })
476
477 return stream
478 }
479
480 namespace (name, opts) {
481 if (name instanceof Hypercore) {
482 return this.session({ ...opts, _bootstrap: name })
483 }
484 return this.session({ ...opts, namespace: generateNamespace(this._namespace, name) })
485 }
486
487 session (opts) {
488 const session = new Corestore(this.storage, {
489 namespace: this._namespace,
490 cache: this.cache,
491 writable: !this._readonly,
492 _attached: opts && opts.detach === false ? this : null,
493 _root: this._root,
494 inflightRange: this.inflightRange,
495 globalCache: this.globalCache,
496 ...opts
497 })
498 if (this === this._root) this._rootStoreSessions.add(session)
499 return session
500 }
501
502 _closeNamespace () {
503 const closePromises = []
504 for (const session of this._sessions) {
505 closePromises.push(session.close())
506 }
507 return Promise.allSettled(closePromises)
508 }
509
510 async _closePrimaryNamespace () {
511 const closePromises = []
512 // At this point, the primary namespace is closing.
513 for (const { stream, isExternal } of this._replicationStreams) {
514 // Only close streams that were created by the Corestore
515 if (!isExternal) stream.destroy()
516 }
517 for (const core of this.cores.values()) {
518 closePromises.push(forceClose(core))
519 }
520 await Promise.allSettled(closePromises)
521 await new Promise((resolve, reject) => {
522 this._keyStorage.close(err => {
523 if (err) return reject(err)
524 return resolve(null)
525 })
526 })
527 }
528
529 async _close () {
530 this._root._rootStoreSessions.delete(this)
531
532 await this._closeNamespace()
533
534 if (this._root === this) {
535 await this._closePrimaryNamespace()
536 } else if (this._attached) {
537 await this._attached.close()
538 }
539 }
540}
541
542function validateGetOptions (opts) {
543 const key = (b4a.isBuffer(opts) || typeof opts === 'string') ? hypercoreId.decode(opts) : null
544 if (key) return { key }
545
546 if (opts.key) {
547 opts.key = hypercoreId.decode(opts.key)
548 }
549 if (opts.keyPair) {
550 opts.publicKey = opts.keyPair.publicKey
551 opts.secretKey = opts.keyPair.secretKey
552 }
553
554 if (opts.name && typeof opts.name !== 'string') throw new Error('name option must be a String')
555 if (opts.name && opts.secretKey) throw new Error('Cannot provide both a name and a secret key')
556 if (opts.publicKey && !b4a.isBuffer(opts.publicKey)) throw new Error('publicKey option must be a Buffer or Uint8Array')
557 if (opts.secretKey && !b4a.isBuffer(opts.secretKey)) throw new Error('secretKey option must be a Buffer or Uint8Array')
558 if (!opts._discoveryKey && (!opts.name && !opts.publicKey && !opts.manifest && !opts.key && !opts.preload)) throw new Error('Must provide either a name or a publicKey')
559 return opts
560}
561
562function generateNamespace (namespace, name) {
563 if (!b4a.isBuffer(name)) name = b4a.from(name)
564 const out = b4a.allocUnsafeSlow(32)
565 sodium.crypto_generichash_batch(out, [namespace, name])
566 return out
567}
568
569function deriveSeed (primaryKey, namespace, name) {
570 if (!b4a.isBuffer(name)) name = b4a.from(name)
571 const out = b4a.alloc(32)
572 sodium.crypto_generichash_batch(out, [NS, namespace, name], primaryKey)
573 return out
574}
575
576function defaultCache () {
577 return new Xache({ maxSize: 65536, maxAge: 0 })
578}
579
580function isStream (s) {
581 return typeof s === 'object' && s && typeof s.pipe === 'function'
582}
583
584async function forceClose (core) {
585 await core.ready()
586 return Promise.all(core.sessions.map(s => s.close()))
587}
588
589function getStorageRoot (id) {
590 return CORES_DIR + '/' + id.slice(0, 2) + '/' + id.slice(2, 4) + '/' + id
591}
node_modules/corestore/package.json +44 -0
……@@ -0,0 +1,44 @@
1{
2 "name": "corestore",
3 "version": "6.18.4",
4 "description": "A Hypercore factory that simplifies managing collections of cores.",
5 "main": "index.js",
6 "scripts": {
7 "test": "standard && brittle test/*.js"
8 },
9 "repository": {
10 "type": "git",
11 "url": "git+https://github.com/holepunchto/corestore.git"
12 },
13 "keywords": [
14 "corestore"
15 ],
16 "author": "Andrew Osheroff <andrewosh@gmail.com>",
17 "license": "MIT",
18 "bugs": {
19 "url": "https://github.com/holepunchto/corestore/issues"
20 },
21 "homepage": "https://github.com/holepunchto/corestore#readme",
22 "files": [
23 "index.js",
24 "lib/**.js"
25 ],
26 "devDependencies": {
27 "brittle": "^3.2.2",
28 "rache": "^1.0.0",
29 "random-access-memory": "^6.2.0",
30 "standard": "^17.1.0",
31 "test-tmp": "^1.0.2"
32 },
33 "dependencies": {
34 "b4a": "^1.6.4",
35 "hypercore": "^10.37.10",
36 "hypercore-crypto": "^3.4.0",
37 "hypercore-id-encoding": "^1.2.0",
38 "read-write-mutexify": "^2.1.0",
39 "ready-resource": "^1.0.0",
40 "safety-catch": "^1.0.1",
41 "sodium-universal": "^4.0.0",
42 "xache": "^1.1.0"
43 }
44}
node_modules/crc-native/CMakeLists.txt +47 -0
……@@ -0,0 +1,47 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6
7project(crc_native C)
8
9bare_target(target)
10
11if(target MATCHES "win32")
12 add_compile_options(/MT$<$<CONFIG:Debug>:d>)
13endif()
14
15fetch_package("github:holepunchto/libcrc#9a0c969")
16
17add_bare_module(crc_native_bare)
18
19target_sources(
20 ${crc_native_bare}
21 PRIVATE
22 binding.c
23)
24
25target_link_libraries(
26 ${crc_native_bare}
27 PRIVATE
28 $<TARGET_OBJECTS:crc>
29 PUBLIC
30 crc
31)
32
33add_napi_module(crc_native_node)
34
35target_sources(
36 ${crc_native_node}
37 PRIVATE
38 binding.c
39)
40
41target_link_libraries(
42 ${crc_native_node}
43 PRIVATE
44 $<TARGET_OBJECTS:crc>
45 PUBLIC
46 crc
47)
node_modules/crc-native/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/crc-native/README.md +26 -0
……@@ -0,0 +1,26 @@
1# crc-native
2
3https://github.com/holepunchto/libcrc JavaScript bindings for Node.js.
4
5```sh
6npm install crc-native
7```
8
9## Usage
10
11```js
12const { crc32 } = require('crc-native')
13
14const crc = crc32(Buffer.from('hello world'))
15// 0xd4a1185
16```
17
18## API
19
20#### `const crc = crc32(buffer)`
21
22Compute the CRC32 of the given buffer.
23
24## License
25
26Apache-2.0
node_modules/crc-native/binding.c +15 -0
……@@ -0,0 +1,15 @@
1#include <crc.h>
2#include <node_api.h>
3
4#include "macros.h"
5
6NAPI_METHOD(crc_u32_napi) {
7 NAPI_ARGV(1);
8 NAPI_ARGV_BUFFER_CAST(uint8_t *, buf, 0);
9
10 NAPI_RETURN_UINT32(crc_u32(buf, buf_len));
11}
12
13NAPI_INIT() {
14 NAPI_EXPORT_FUNCTION(crc_u32_napi);
15}
node_modules/crc-native/binding.js +3 -0
……@@ -0,0 +1,3 @@
1require.addon = require('require-addon')
2
3module.exports = require.addon('.', __filename)
node_modules/crc-native/index.js +5 -0
……@@ -0,0 +1,5 @@
1const binding = require('./binding')
2
3exports.crc32 = function crc32 (buffer) {
4 return binding.crc_u32_napi(buffer)
5}
node_modules/crc-native/macros.h +255 -0
……@@ -0,0 +1,255 @@
1#ifndef NAPI_MACROS
2#define NAPI_MACROS
3
4#define NAPI_INIT() \
5 static void napi_macros_init(napi_env env, napi_value exports); \
6 static napi_value napi_macros_init_wrap(napi_env env, napi_value exports) { \
7 napi_macros_init(env, exports); \
8 return exports; \
9 } \
10 NAPI_MODULE(NODE_GYP_MODULE_NAME, napi_macros_init_wrap) \
11 static void napi_macros_init(napi_env env, napi_value exports)
12
13#define NAPI_TEST_GC(env) \
14 { \
15 napi_handle_scope scope; \
16 napi_open_handle_scope(env, &scope); \
17 napi_value s; \
18 napi_value r; \
19 napi_create_string_utf8(env, "try { global.gc() } catch {}", NAPI_AUTO_LENGTH, &s); \
20 napi_run_script(env, s, &r); \
21 napi_close_handle_scope(env, scope); \
22 }
23
24#define NAPI_UV_ERROR_MAP_ITER(NAME, DESC) \
25 { \
26 napi_create_array(env, &entry); \
27 napi_create_array(env, &val); \
28 napi_value name; \
29 napi_create_string_utf8(env, #NAME, NAPI_AUTO_LENGTH, &name); \
30 napi_set_element(env, val, 0, name); \
31 napi_value desc; \
32 napi_create_string_utf8(env, DESC, NAPI_AUTO_LENGTH, &desc); \
33 napi_set_element(env, val, 1, desc); \
34 napi_create_int32(env, UV_##NAME, &key); \
35 napi_set_element(env, entry, 0, key); \
36 napi_set_element(env, entry, 1, val); \
37 napi_set_element(env, arr, i++, entry); \
38 }
39
40#define NAPI_MAKE_CALLBACK(env, nil, ctx, cb, n, argv, res) \
41 if (napi_make_callback(env, nil, ctx, cb, n, argv, res) == napi_pending_exception) { \
42 napi_value fatal_exception; \
43 napi_get_and_clear_last_exception(env, &fatal_exception); \
44 napi_fatal_exception(env, fatal_exception); \
45 }
46
47#define NAPI_STATUS_THROWS_VOID(call) \
48 if ((call) != napi_ok) { \
49 napi_throw_error(env, NULL, #call " failed!"); \
50 return; \
51 }
52
53#define NAPI_STATUS_THROWS(call) \
54 if ((call) != napi_ok) { \
55 napi_throw_error(env, NULL, #call " failed!"); \
56 return NULL; \
57 }
58
59#define NAPI_METHOD(name) \
60 napi_value name(napi_env env, napi_callback_info info)
61
62#define NAPI_UV_THROWS(err, fn) \
63 err = fn; \
64 if (err < 0) { \
65 napi_throw_error(env, uv_err_name(err), uv_strerror(err)); \
66 return NULL; \
67 }
68
69#define NAPI_EXPORT_OFFSETOF(type, name) \
70 { \
71 napi_value name##_offsetof; \
72 type tmp; \
73 void *ptr = &(tmp.name); \
74 void *ptr_base = &tmp; \
75 int offset = (char *) ptr - (char *) ptr_base; \
76 NAPI_STATUS_THROWS_VOID(napi_create_uint32(env, offset, &name##_offsetof)) \
77 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, "offsetof_" #type "_" #name, name##_offsetof)) \
78 }
79
80#define NAPI_EXPORT_OFFSETOF_STRUCT(type, name) \
81 { \
82 napi_value name##_offsetof; \
83 struct type tmp; \
84 void *ptr = &(tmp.name); \
85 void *ptr_base = &tmp; \
86 int offset = (char *) ptr - (char *) ptr_base; \
87 NAPI_STATUS_THROWS_VOID(napi_create_uint32(env, offset, &name##_offsetof)) \
88 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, "offsetof_struct_" #type "_" #name, name##_offsetof)) \
89 }
90
91#define NAPI_EXPORT_ALIGNMENTOF(name) \
92 { \
93 napi_value name##_alignmentof; \
94 struct tmp { \
95 char a; \
96 name b; \
97 }; \
98 NAPI_STATUS_THROWS_VOID(napi_create_uint32(env, sizeof(struct tmp) - sizeof(name), &name##_alignmentof)) \
99 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, "alignmentof_" #name, name##_alignmentof)) \
100 }
101
102#define NAPI_EXPORT_ALIGNMENTOF_STRUCT(name) \
103 { \
104 napi_value name##_alignmentof; \
105 struct tmp { \
106 char a; \
107 struct name b; \
108 }; \
109 NAPI_STATUS_THROWS_VOID(napi_create_uint32(env, sizeof(struct tmp) - sizeof(struct name), &name##_alignmentof)) \
110 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, "alignmentof_" #name, name##_alignmentof)) \
111 }
112
113#define NAPI_EXPORT_UV_ERROR_MAP() \
114 { \
115 napi_value arr; \
116 napi_value key; \
117 napi_value val; \
118 napi_value entry; \
119 napi_create_array(env, &arr); \
120 int i = 0; \
121 UV_ERRNO_MAP(NAPI_UV_ERROR_MAP_ITER) \
122 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, "uv_error_map", arr)) \
123 }
124
125#define NAPI_EXPORT_SIZEOF(name) \
126 { \
127 napi_value name##_sizeof; \
128 NAPI_STATUS_THROWS_VOID(napi_create_uint32(env, sizeof(name), &name##_sizeof)) \
129 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, "sizeof_" #name, name##_sizeof)) \
130 }
131
132#define NAPI_EXPORT_SIZEOF_STRUCT(name) \
133 { \
134 napi_value name##_sizeof; \
135 NAPI_STATUS_THROWS_VOID(napi_create_uint32(env, sizeof(struct name), &name##_sizeof)) \
136 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, "sizeof_" #name, name##_sizeof)) \
137 }
138
139#define NAPI_EXPORT_UINT32(name) \
140 { \
141 napi_value name##_uint32; \
142 NAPI_STATUS_THROWS_VOID(napi_create_uint32(env, name, &name##_uint32)) \
143 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, #name, name##_uint32)) \
144 }
145
146#define NAPI_EXPORT_INT32(name) \
147 { \
148 napi_value name##_int32; \
149 NAPI_STATUS_THROWS_VOID(napi_create_int32(env, name, &name##_int32)) \
150 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, #name, name##_int32)) \
151 }
152
153#define NAPI_EXPORT_FUNCTION(name) \
154 { \
155 napi_value name##_fn; \
156 NAPI_STATUS_THROWS_VOID(napi_create_function(env, NULL, 0, name, NULL, &name##_fn)) \
157 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, #name, name##_fn)) \
158 }
159
160#define NAPI_EXPORT_UTF8(name, len) \
161 { \
162 napi_value name##_utf8; \
163 NAPI_STATUS_THROWS_VOID(napi_create_string_utf8(env, name, len, &name##_utf8)) \
164 NAPI_STATUS_THROWS_VOID(napi_set_named_property(env, exports, #name, name##_utf8)) \
165 }
166
167#define NAPI_EXPORT_STRING(name) \
168 NAPI_EXPORT_UTF8(name, NAPI_AUTO_LENGTH)
169
170#define NAPI_RETURN_INT32(name) \
171 napi_value return_int32; \
172 NAPI_STATUS_THROWS(napi_create_int32(env, name, &return_int32)) \
173 return return_int32;
174
175#define NAPI_RETURN_UINT32(name) \
176 napi_value return_uint32; \
177 NAPI_STATUS_THROWS(napi_create_uint32(env, name, &return_uint32)) \
178 return return_uint32;
179
180#define NAPI_RETURN_UTF8(name, len) \
181 napi_value return_utf8; \
182 NAPI_STATUS_THROWS(napi_create_string_utf8(env, name, len, &return_utf8)) \
183 return return_utf8;
184
185#define NAPI_RETURN_STRING(name) \
186 NAPI_RETURN_UTF8(name, NAPI_AUTO_LENGTH)
187
188#define NAPI_UTF8(name, size, val) \
189 char name[size]; \
190 size_t name##_len; \
191 if (napi_get_value_string_utf8(env, val, (char *) &name, size, &name##_len) != napi_ok) { \
192 napi_throw_error(env, "EINVAL", "Expected string"); \
193 return NULL; \
194 }
195
196#define NAPI_UTF8_MALLOC(name, val) \
197 size_t name##_size = 0; \
198 NAPI_STATUS_THROWS(napi_get_value_string_utf8(env, val, NULL, 0, &name##_size)) \
199 char *name = (char *) malloc((name##_size + 1) * sizeof(char)); \
200 size_t name##_len; \
201 NAPI_STATUS_THROWS(napi_get_value_string_utf8(env, val, name, name##_size + 1, &name##_len)) \
202 name[name##_size] = '\0';
203
204#define NAPI_UINT32(name, val) \
205 uint32_t name; \
206 if (napi_get_value_uint32(env, val, &name) != napi_ok) { \
207 napi_throw_error(env, "EINVAL", "Expected unsigned number"); \
208 return NULL; \
209 }
210
211#define NAPI_INT32(name, val) \
212 int32_t name; \
213 if (napi_get_value_int32(env, val, &name) != napi_ok) { \
214 napi_throw_error(env, "EINVAL", "Expected number"); \
215 return NULL; \
216 }
217
218#define NAPI_BUFFER_CAST(type, name, val) \
219 type name; \
220 size_t name##_len; \
221 NAPI_STATUS_THROWS(napi_get_buffer_info(env, val, (void **) &name, &name##_len))
222
223#define NAPI_BUFFER(name, val) \
224 NAPI_BUFFER_CAST(char *, name, val)
225
226#define NAPI_FOR_EACH(arr, element) \
227 uint32_t arr##_len; \
228 napi_get_array_length(env, arr, &arr##_len); \
229 napi_value element; \
230 for (uint32_t i = 0; i < arr##_len && napi_get_element(env, arr, i, &element) == napi_ok; i++)
231
232#define NAPI_ARGV(n) \
233 napi_value argv[n]; \
234 size_t argc = n; \
235 NAPI_STATUS_THROWS(napi_get_cb_info(env, info, &argc, argv, NULL, NULL))
236
237#define NAPI_ARGV_UTF8(name, size, i) \
238 NAPI_UTF8(name, size, argv[i])
239
240#define NAPI_ARGV_UTF8_MALLOC(name, i) \
241 NAPI_UTF8_MALLOC(name, argv[i])
242
243#define NAPI_ARGV_UINT32(name, i) \
244 NAPI_UINT32(name, argv[i])
245
246#define NAPI_ARGV_INT32(name, i) \
247 NAPI_INT32(name, argv[i])
248
249#define NAPI_ARGV_BUFFER_CAST(type, name, i) \
250 NAPI_BUFFER_CAST(type, name, argv[i])
251
252#define NAPI_ARGV_BUFFER(name, i) \
253 NAPI_ARGV_BUFFER_CAST(char *, name, i)
254
255#endif
node_modules/crc-native/package.json +41 -0
……@@ -0,0 +1,41 @@
1{
2 "name": "crc-native",
3 "version": "1.1.8",
4 "description": "libcrc JavaScript bindings for Node.js",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "macros.h",
9 "binding.c",
10 "binding.js",
11 "CMakeLists.txt",
12 "prebuilds"
13 ],
14 "addon": true,
15 "scripts": {
16 "test": "npm run lint && npm run test:bare && npm run test:node",
17 "test:bare": "bare test.mjs",
18 "test:node": "node test.mjs",
19 "lint": "standard"
20 },
21 "repository": {
22 "type": "git",
23 "url": "git+https://github.com/holepunchto/crc-native.git"
24 },
25 "author": "Holepunch",
26 "license": "Apache-2.0",
27 "bugs": {
28 "url": "https://github.com/holepunchto/crc-native/issues"
29 },
30 "homepage": "https://github.com/holepunchto/crc-native#readme",
31 "dependencies": {
32 "require-addon": "^1.1.0"
33 },
34 "devDependencies": {
35 "brittle": "^3.1.0",
36 "cmake-bare": "^1.1.7",
37 "cmake-fetch": "^1.1.0",
38 "cmake-napi": "^1.0.2",
39 "standard": "^17.0.0"
40 }
41}
node_modules/crc-native/prebuilds/android-arm/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/android-arm/crc-native.node +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/android-arm64/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/android-arm64/crc-native.node +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/android-ia32/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/android-ia32/crc-native.node +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/android-x64/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/android-x64/crc-native.node +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/darwin-arm64/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/darwin-arm64/crc-native.node +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/darwin-x64/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/darwin-x64/crc-native.node +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/ios-arm64-simulator/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/ios-arm64/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/ios-x64-simulator/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/linux-arm64/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/linux-arm64/crc-native.node +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/linux-x64/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/linux-x64/crc-native.node +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/win32-arm64/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/win32-arm64/crc-native.node +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/win32-x64/crc-native.bare +0 -0
(no content changes — binary or rename)
node_modules/crc-native/prebuilds/win32-x64/crc-native.node +0 -0
(no content changes — binary or rename)
node_modules/crc-universal/LICENSE +15 -0
……@@ -0,0 +1,15 @@
1ISC License
2
3Copyright (c) 2022 Contributors
4
5Permission to use, copy, modify, and/or distribute this software for any
6purpose with or without fee is hereby granted, provided that the above
7copyright notice and this permission notice appear in all copies.
8
9THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15PERFORMANCE OF THIS SOFTWARE.
node_modules/crc-universal/README.md +26 -0
……@@ -0,0 +1,26 @@
1# crc-universal
2
3Universal wrapper for https://github.com/holepunchto/libcrc with a JavaScript fallback.
4
5```sh
6npm install crc-universal
7```
8
9## Usage
10
11```js
12const { crc32 } = require('crc-universal')
13
14const crc = crc32(Buffer.from('hello world'))
15// 0xd4a1185
16```
17
18## API
19
20#### `const crc = crc32(buffer)`
21
22Compute the CRC32 of the given buffer.
23
24## License
25
26ISC
node_modules/crc-universal/fallback.js +57 -0
……@@ -0,0 +1,57 @@
1/**
2 * The JavaScript implementation of CRC32 is a version of the slice-by-16 algorithm
3 * as implemented by Stephan Brumme, see https://github.com/stbrumme/crc32.
4 *
5 * Copyright (c) 2011-2016 Stephan Brumme
6 *
7 * This software is provided 'as-is', without any express or implied warranty.
8 * In no event will the authors be held liable for any damages arising from the
9 * use of this software.
10 *
11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it freely,
13 * subject to the following restrictions:
14 *
15 * 1. The origin of this software must not be misrepresented; you must not claim
16 * that you wrote the original software.
17 * If you use this software in a product, an acknowledgment in the product
18 * documentation would be appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be
20 * misrepresented as being the original software.
21 * 3. This notice may not be removed or altered from any source distribution.
22 */
23
24const lookup = require('./lookup')
25
26exports.crc32 = function crc32 (buffer) {
27 let crc = ~0
28 let i = 0
29 let length = buffer.byteLength
30
31 while (length >= 16) {
32 crc = lookup[15][buffer[i++] ^ (crc & 0xff)] ^
33 lookup[14][buffer[i++] ^ ((crc >>> 8) & 0xff)] ^
34 lookup[13][buffer[i++] ^ ((crc >>> 16) & 0xff)] ^
35 lookup[12][buffer[i++] ^ (crc >>> 24)] ^
36 lookup[11][buffer[i++]] ^
37 lookup[10][buffer[i++]] ^
38 lookup[9][buffer[i++]] ^
39 lookup[8][buffer[i++]] ^
40 lookup[7][buffer[i++]] ^
41 lookup[6][buffer[i++]] ^
42 lookup[5][buffer[i++]] ^
43 lookup[4][buffer[i++]] ^
44 lookup[3][buffer[i++]] ^
45 lookup[2][buffer[i++]] ^
46 lookup[1][buffer[i++]] ^
47 lookup[0][buffer[i++]]
48
49 length -= 16
50 }
51
52 while (length-- > 0) {
53 crc = (crc >>> 8) ^ lookup[0][(crc & 0xff) ^ buffer[i++]]
54 }
55
56 return ~crc >>> 0
57}
node_modules/crc-universal/index.js +11 -0
……@@ -0,0 +1,11 @@
1const fallback = require('./fallback')
2
3try {
4 const native = require('crc-native')
5
6 exports.crc32 = function crc32 (buffer) {
7 return buffer.byteLength <= 24 ? fallback.crc32(buffer) : native.crc32(buffer)
8 }
9} catch {
10 module.exports = fallback
11}
node_modules/crc-universal/lookup.js +23 -0
……@@ -0,0 +1,23 @@
1const lookup = new Array(16)
2
3for (let i = 0; i < 16; i++) {
4 lookup[i] = new Uint32Array(0x100)
5}
6
7for (let i = 0; i <= 0xff; i++) {
8 let crc = i
9
10 for (let j = 0; j < 8; j++) {
11 crc = (crc >>> 1) ^ ((crc & 1) * 0xedb88320)
12 }
13
14 lookup[0][i] = crc
15}
16
17for (let i = 0; i <= 0xff; i++) {
18 for (let j = 1; j < 16; j++) {
19 lookup[j][i] = (lookup[j - 1][i] >>> 8) ^ lookup[0][lookup[j - 1][i] & 0xff]
20 }
21}
22
23module.exports = lookup
node_modules/crc-universal/package.json +34 -0
……@@ -0,0 +1,34 @@
1{
2 "name": "crc-universal",
3 "version": "1.0.4",
4 "description": "Universal wrapper for libcrc with a JavaScript fallback",
5 "main": "index.js",
6 "files": [
7 "fallback.js",
8 "index.js",
9 "lookup.js"
10 ],
11 "browser": {
12 "./index.js": "./fallback.js"
13 },
14 "scripts": {
15 "test": "standard && brittle test.mjs"
16 },
17 "repository": {
18 "type": "git",
19 "url": "git+https://github.com/holepunchto/crc-universal.git"
20 },
21 "author": "Kasper Isager Dalsgarð <kasper@funktionel.co>",
22 "license": "ISC",
23 "bugs": {
24 "url": "https://github.com/holepunchto/crc-universal/issues"
25 },
26 "homepage": "https://github.com/holepunchto/crc-universal#readme",
27 "optionalDependencies": {
28 "crc-native": "^1.0.3"
29 },
30 "devDependencies": {
31 "brittle": "^3.1.0",
32 "standard": "^17.0.0"
33 }
34}
node_modules/debounceify/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2020 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/debounceify/README.md +47 -0
……@@ -0,0 +1,47 @@
1# debounceify
2
3Tiny async debouncer
4
5```
6npm install debounceify
7```
8
9## Usage
10
11``` js
12const debounceify = require('debounceify')
13
14const debounced = debounceify(async function () {
15 console.log('Running...')
16 await new Promise(resolve => setTimeout(1000, resolve))
17})
18
19const a = debounced() // triggers the about function
20const b = debounced()
21const c = debounced()
22const d = debounced() // these last 3 wait for the first one to finish
23 // then trigger one more.
24
25await a
26await b
27await c
28await d
29```
30
31## API
32
33#### `fn = debounceify(asyncFunction)`
34
35Debounces the `asyncFunction` so that
36
371. No parallel executions of `asyncFunction` will happen
382. Debounces the stack, so if 10 calls happen while `asyncFunction` is running only one more will be triggered when it finishes.
393. Forwards errors and return values.
40
41#### `debounceify.running`
42
43The active running job, `null` if none.
44
45## License
46
47MIT
node_modules/debounceify/index.js +25 -0
……@@ -0,0 +1,25 @@
1module.exports = function debounce (worker, context = null) {
2 debounced.running = null
3 return debounced
4
5 async function debounced () {
6 if (debounced.running !== null) {
7 try {
8 await debounced.running
9 } catch (_) {
10 // ignore - do not fail on old errors
11 }
12 }
13
14 // another "thread" beat us to it, just piggy pack on that one
15 if (debounced.running !== null) return debounced.running
16
17 debounced.running = worker.call(context)
18
19 try {
20 return await debounced.running
21 } finally {
22 debounced.running = null
23 }
24 }
25}
node_modules/debounceify/package.json +24 -0
……@@ -0,0 +1,24 @@
1{
2 "name": "debounceify",
3 "version": "1.1.0",
4 "description": "Tiny async debouncer",
5 "main": "index.js",
6 "dependencies": {},
7 "devDependencies": {
8 "standard": "^16.0.3",
9 "tape": "^5.1.1"
10 },
11 "repository": {
12 "type": "git",
13 "url": "https://github.com/mafintosh/debounceify.git"
14 },
15 "scripts": {
16 "test": "standard && tape test.js"
17 },
18 "author": "Mathias Buus (@mafintosh)",
19 "license": "MIT",
20 "bugs": {
21 "url": "https://github.com/mafintosh/debounceify/issues"
22 },
23 "homepage": "https://github.com/mafintosh/debounceify"
24}
node_modules/debounceify/test.js +45 -0
……@@ -0,0 +1,45 @@
1const tape = require('tape')
2const debounce = require('./')
3
4tape('basic', async function (t) {
5 t.plan(2)
6 const d = debounce(() => {
7 t.pass('called')
8 })
9
10 for (let i = 0; i < 100; i++) d()
11 await d()
12})
13
14tape('debounced returns', async function (t) {
15 t.plan(3)
16
17 let cnt = 0
18 const d = debounce(() => {
19 t.pass('called')
20 return cnt++
21 })
22
23 for (let i = 0; i < 100; i++) d()
24 t.same(await d(), 1)
25})
26
27tape('debounced throws', async function (t) {
28 t.plan(4)
29
30 let cnt = 0
31 const d = debounce(async () => {
32 t.pass('called')
33 cnt++
34 if (cnt === 1) {
35 throw new Error('sup')
36 }
37 return cnt
38 })
39
40 d().catch(err => t.same(err, new Error('sup')))
41 d()
42 d()
43 d()
44 t.same(await d(), 2)
45})
node_modules/events-universal/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/events-universal/README.md +17 -0
……@@ -0,0 +1,17 @@
1# events-universal
2
3Universal wrapper for the Node.js `events` module.
4
5```
6npm i events-universal
7```
8
9## Usage
10
11```js
12const EventEmitter = require('events-universal')
13```
14
15## License
16
17Apache-2.0
node_modules/events-universal/bare.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('bare-events')
node_modules/events-universal/default.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('events')
node_modules/events-universal/index.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('bare-events')
node_modules/events-universal/package.json +39 -0
……@@ -0,0 +1,39 @@
1{
2 "name": "events-universal",
3 "version": "1.0.1",
4 "description": "Universal wrapper for the Node.js events module",
5 "exports": {
6 "./package": "./package.json",
7 ".": {
8 "bare": "./bare.js",
9 "react-native": "./react-native.js",
10 "default": "./default.js"
11 }
12 },
13 "files": [
14 "index.js",
15 "default.js",
16 "bare.js",
17 "react-native.js"
18 ],
19 "scripts": {
20 "test": "prettier . --check"
21 },
22 "repository": {
23 "type": "git",
24 "url": "git+https://github.com/holepunchto/events-universal.git"
25 },
26 "author": "Holepunch",
27 "license": "Apache-2.0",
28 "bugs": {
29 "url": "https://github.com/holepunchto/events-universal/issues"
30 },
31 "homepage": "https://github.com/holepunchto/events-universal#readme",
32 "dependencies": {
33 "bare-events": "^2.7.0"
34 },
35 "devDependencies": {
36 "prettier": "^3.4.2",
37 "prettier-config-holepunch": "^1.0.0"
38 }
39}
node_modules/events-universal/react-native.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('bare-events')
node_modules/fast-fifo/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2019 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/fast-fifo/README.md +78 -0
……@@ -0,0 +1,78 @@
1# fast-fifo
2
3A fast fifo implementation similar to the one powering nextTick in Node.js core
4
5```
6npm install fast-fifo
7```
8
9Uses a linked list of growing fixed sized arrays to implement the FIFO to avoid
10allocating a wrapper object for each item.
11
12## Usage
13
14``` js
15const FIFO = require('fast-fifo')
16
17const q = new FIFO()
18
19q.push('hello')
20q.push('world')
21
22q.shift() // returns hello
23q.shift() // returns world
24```
25
26## API
27
28#### `q = new FIFO()`
29
30Create a new FIFO.
31
32#### `q.push(value)`
33
34Push a value to the FIFO. `value` can be anything other than undefined.
35
36#### `value = q.shift()`
37
38Return the oldest value from the FIFO.
39
40#### `q.clear()`
41
42Remove all values from the FIFO.
43
44#### `bool = q.isEmpty()`
45
46Returns `true` if the FIFO is empty and false otherwise.
47
48#### `value = q.peek()`
49
50Return the oldest value from the FIFO without shifting it out.
51
52#### `len = q.length`
53
54Get the number of entries remaining in the FIFO.
55
56## Benchmarks
57
58Included in bench.js is a simple benchmark that benchmarks this against a simple
59linked list based FIFO.
60
61On my machine the benchmark looks like this:
62
63```
64fifo bulk push and shift: 2881.508ms
65fifo individual push and shift: 3248.437ms
66fast-fifo bulk push and shift: 1606.972ms
67fast-fifo individual push and shift: 1328.064ms
68fifo bulk push and shift: 3266.902ms
69fifo individual push and shift: 3320.944ms
70fast-fifo bulk push and shift: 1858.307ms
71fast-fifo individual push and shift: 1516.983ms
72```
73
74YMMV
75
76## License
77
78MIT
node_modules/fast-fifo/fixed-size.js +39 -0
……@@ -0,0 +1,39 @@
1module.exports = class FixedFIFO {
2 constructor (hwm) {
3 if (!(hwm > 0) || ((hwm - 1) & hwm) !== 0) throw new Error('Max size for a FixedFIFO should be a power of two')
4 this.buffer = new Array(hwm)
5 this.mask = hwm - 1
6 this.top = 0
7 this.btm = 0
8 this.next = null
9 }
10
11 clear () {
12 this.top = this.btm = 0
13 this.next = null
14 this.buffer.fill(undefined)
15 }
16
17 push (data) {
18 if (this.buffer[this.top] !== undefined) return false
19 this.buffer[this.top] = data
20 this.top = (this.top + 1) & this.mask
21 return true
22 }
23
24 shift () {
25 const last = this.buffer[this.btm]
26 if (last === undefined) return undefined
27 this.buffer[this.btm] = undefined
28 this.btm = (this.btm + 1) & this.mask
29 return last
30 }
31
32 peek () {
33 return this.buffer[this.btm]
34 }
35
36 isEmpty () {
37 return this.buffer[this.btm] === undefined
38 }
39}
node_modules/fast-fifo/index.js +48 -0
……@@ -0,0 +1,48 @@
1const FixedFIFO = require('./fixed-size')
2
3module.exports = class FastFIFO {
4 constructor (hwm) {
5 this.hwm = hwm || 16
6 this.head = new FixedFIFO(this.hwm)
7 this.tail = this.head
8 this.length = 0
9 }
10
11 clear () {
12 this.head = this.tail
13 this.head.clear()
14 this.length = 0
15 }
16
17 push (val) {
18 this.length++
19 if (!this.head.push(val)) {
20 const prev = this.head
21 this.head = prev.next = new FixedFIFO(2 * this.head.buffer.length)
22 this.head.push(val)
23 }
24 }
25
26 shift () {
27 if (this.length !== 0) this.length--
28 const val = this.tail.shift()
29 if (val === undefined && this.tail.next) {
30 const next = this.tail.next
31 this.tail.next = null
32 this.tail = next
33 return this.tail.shift()
34 }
35
36 return val
37 }
38
39 peek () {
40 const val = this.tail.peek()
41 if (val === undefined && this.tail.next) return this.tail.next.peek()
42 return val
43 }
44
45 isEmpty () {
46 return this.length === 0
47 }
48}
node_modules/fast-fifo/package.json +28 -0
……@@ -0,0 +1,28 @@
1{
2 "name": "fast-fifo",
3 "version": "1.3.2",
4 "description": "A fast fifo implementation similar to the one powering nextTick in Node.js core",
5 "main": "index.js",
6 "files": [
7 "./index.js",
8 "./fixed-size.js"
9 ],
10 "dependencies": {},
11 "devDependencies": {
12 "standard": "^17.1.0",
13 "brittle": "^3.3.2"
14 },
15 "scripts": {
16 "test": "standard && brittle test.js"
17 },
18 "repository": {
19 "type": "git",
20 "url": "https://github.com/mafintosh/fast-fifo.git"
21 },
22 "author": "Mathias Buus (@mafintosh)",
23 "license": "MIT",
24 "bugs": {
25 "url": "https://github.com/mafintosh/fast-fifo/issues"
26 },
27 "homepage": "https://github.com/mafintosh/fast-fifo"
28}
node_modules/flat-tree/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2015 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/flat-tree/README.md +167 -0
……@@ -0,0 +1,167 @@
1# flat-tree
2
3A series of functions to map a binary tree to a list
4
5```
6npm install flat-tree
7```
8
9## Usage
10
11You can represent a binary tree in a simple flat list using the following structure
12
13```
14 3
15 1 5
160 2 4 6 ...
17```
18
19This module exposes a series of functions to help you build and maintain this data structure
20
21``` js
22var tree = require('flat-tree')
23var list = []
24
25var i = tree.index(0, 0) // get array index for depth: 0, offset: 0
26var j = tree.index(1, 0) // get array index for depth: 1, offset: 0
27
28// use these indexes to store some data
29
30list[i] = 'a'
31list[j] = 'b'
32list[tree.parent(i)] = 'parent of a and b'
33```
34
35## API
36
37#### `index = tree.index(depth, offset)`
38
39Returns an array index for the tree element at the given depth and offset.
40
41#### `parentIndex = tree.parent(index)`
42
43Returns the index of the parent element in tree.
44
45#### `siblingIndex = tree.sibling(index)`
46
47Returns the index of this elements sibling.
48
49#### `children = tree.children(index)`
50
51Returns an array `[leftChild, rightChild]` with the indexes of this elements children.
52If this element does not have any children it returns `null`.
53
54#### `range = tree.spans(index)`
55
56Returns the range (inclusive) the tree root at `index` spans.
57For example `tree.spans(3)` would return `[0, 6]` (see the usage example).
58
59#### `index = tree.leftSpan(index)`
60
61Returns the left spanning in index in the tree `index` spans.
62
63#### `index = tree.rightSpan(index)`
64
65Returns the right spanning in index in the tree `index` spans.
66
67#### `count = tree.count(index)`
68
69Returns how many nodes (including parent nodes) a tree contains.
70
71#### `count = tree.countLeaves(index)`
72
73Returns how many nodes (excluding parent nodes) a tree contains.
74
75#### `depth = tree.depth(index)`
76
77Returns the depth of an element.
78
79#### `offset = tree.offset(index, [depth])`
80
81Returns the relative offset of an element.
82
83#### `roots = tree.fullRoots(index)`
84
85Returns a list of all the full roots (subtrees where all nodes have either 2 or 0 children) `<` index.
86For example `fullRoots(8)` returns `[3]` since the subtree rooted at `3` spans `0 -> 6` and the tree
87rooted at `7` has a child located at `9` which is `>= 8`.
88
89#### `iterator = tree.iterator(index)`
90
91Create a stateful tree iterator starting at a given index.
92The iterator exposes the following methods.
93
94#### `index = iterator.next()`
95
96Move the iterator the next item in the tree.
97
98#### `index = iterator.prev()`
99
100Move the iterator the prev item in the tree.
101
102#### `iterator.seek(index)`
103
104Move the iterator the this specific tree index.
105
106#### `index = iterator.parent()`
107
108Move the iterator to the current parent index.
109
110#### `index = iterator.leftChild()`
111
112Move the iterator to the current left child index.
113
114#### `index = iterator.rightChild()`
115
116Move the iterator to the current right child index.
117
118#### `index = iterator.leftSpan()`
119
120Move the iterator to the current left span index.
121
122#### `index = iterator.rightSpan()`
123
124Move the iterator to the current right span index.
125
126#### `bool = iterator.isLeft()`
127
128Is the iterator at a left sibling?
129
130#### `bool = iterator.isRight()`
131
132Is the iterator at a right sibling?
133
134#### `index = iterator.sibling()`
135
136Move the iterator to the current sibling.
137
138#### `count = iterator.count()`
139
140Returns how many nodes (including parent nodes) the current tree contains.
141
142#### `count = iterator.countLeaves()`
143
144Returns how many nodes (excluding parent nodes) the current tree contains.
145
146## See also
147
148- [mafintosh/print-flat-tree][print]: A cli that can pretty print flat-trees.
149- [bcomnes/flattree][ftg]: A port of the node module to Go.
150- [arablocks/flat-tree.c](c): A port of the module to C
151- [datkt/flat-tree][kt]: A port of the module to Kotlin
152- [datrs/flat-tree][rs]: A port to Rust.
153- [bcomnes/flattree][ftg]: A port to Go.
154- [noffle/cl-flat-tree][clft]: A port to Common Lisp.
155- [dukeraphaelng/flat_tree][cr]: A port to Crystal.
156
157## License
158
159MIT
160
161[print]: https://github.com/mafintosh/print-flat-tree
162[rs]: https://github.com/datrs/flat-tree
163[ftg]: https://github.com/bcomnes/flattree
164[c]: https://github.com/arablocks/flat-tree.c
165[kt]: https://github.com/datkt/flat-tree
166[clft]: https://github.com/noffle/cl-flat-tree
167[cr]: https://github.com/dukeraphaelng/flat_tree
node_modules/flat-tree/index.js +362 -0
……@@ -0,0 +1,362 @@
1exports.fullRoots = function (index, result) {
2 if (index & 1) throw new Error('You can only look up roots for depth(0) blocks')
3 if (!result) result = []
4
5 index /= 2
6
7 let offset = 0
8 let factor = 1
9
10 while (true) {
11 if (!index) return result
12 while (factor * 2 <= index) factor *= 2
13 result.push(offset + factor - 1)
14 offset = offset + 2 * factor
15 index -= factor
16 factor = 1
17 }
18}
19
20exports.futureRoots = function (index, result) {
21 if (index & 1) throw new Error('You can only look up future roots for depth(0) blocks')
22 if (!result) result = []
23
24 let factor = 1
25
26 // make first root
27 while (factor * 2 <= index) factor *= 2
28
29 // full factor of 2 - done
30 if (factor * 2 - 2 === index) return result
31
32 let pos = factor / 2 - 1
33
34 // while its not a full tree
35 while ((pos + factor / 2 - 1) !== index) {
36 pos += factor
37
38 // read too far, to to left child
39 while ((pos + factor / 2 - 1) > index) {
40 factor /= 2
41 pos -= factor / 2
42 }
43
44 // the "gap" is a future root
45 result.push(pos - factor / 2)
46 }
47
48 return result
49}
50
51exports.patch = function (from, to) {
52 if (from === 0 || from >= to) return []
53
54 const roots = exports.fullRoots(from)
55 const target = exports.fullRoots(to)
56
57 // first find the first root that is different
58
59 let i = 0
60 for (; i < target.length; i++) {
61 if (i >= roots.length || roots[i] !== target[i]) break
62 }
63
64 const patch = []
65
66 if (i < roots.length) {
67 // now we need to grow the newest root until it hits the diff one
68 let prev = roots.length - 1
69
70 const ite = exports.iterator(roots[prev--])
71
72 while (ite.index !== target[i]) {
73 ite.sibling()
74
75 if (prev >= 0 && ite.index === roots[prev]) {
76 prev--
77 } else {
78 patch.push(ite.index)
79 }
80
81 patch.push(ite.parent())
82 }
83
84 i++ // patched to next root, so inc
85 }
86
87 // include the rest
88
89 for (; i < target.length; i++) patch.push(target[i])
90
91 return patch
92}
93
94exports.depth = function (index) {
95 let depth = 0
96
97 index += 1
98 while (!(index & 1)) {
99 depth++
100 index = rightShift(index)
101 }
102
103 return depth
104}
105
106exports.sibling = function (index, depth) {
107 if (!depth) depth = exports.depth(index)
108 const offset = exports.offset(index, depth)
109
110 return exports.index(depth, offset & 1 ? offset - 1 : offset + 1)
111}
112
113exports.parent = function (index, depth) {
114 if (!depth) depth = exports.depth(index)
115 const offset = exports.offset(index, depth)
116
117 return exports.index(depth + 1, rightShift(offset))
118}
119
120exports.leftChild = function (index, depth) {
121 if (!(index & 1)) return -1
122 if (!depth) depth = exports.depth(index)
123 return exports.index(depth - 1, exports.offset(index, depth) * 2)
124}
125
126exports.rightChild = function (index, depth) {
127 if (!(index & 1)) return -1
128 if (!depth) depth = exports.depth(index)
129 return exports.index(depth - 1, 1 + (exports.offset(index, depth) * 2))
130}
131
132exports.children = function (index, depth) {
133 if (!(index & 1)) return null
134
135 if (!depth) depth = exports.depth(index)
136 const offset = exports.offset(index, depth) * 2
137
138 return [
139 exports.index(depth - 1, offset),
140 exports.index(depth - 1, offset + 1)
141 ]
142}
143
144exports.leftSpan = function (index, depth) {
145 if (!(index & 1)) return index
146 if (!depth) depth = exports.depth(index)
147 return exports.offset(index, depth) * twoPow(depth + 1)
148}
149
150exports.rightSpan = function (index, depth) {
151 if (!(index & 1)) return index
152 if (!depth) depth = exports.depth(index)
153 return (exports.offset(index, depth) + 1) * twoPow(depth + 1) - 2
154}
155
156exports.nextLeaf = function (index) {
157 let factor = 1
158 let r = index
159
160 while ((r & 1) === 1) {
161 r = (r - 1) / 2
162 factor *= 2
163 }
164
165 return index + factor + 1
166}
167
168exports.count = function (index, depth) {
169 if (!(index & 1)) return 1
170 if (!depth) depth = exports.depth(index)
171 return twoPow(depth + 1) - 1
172}
173
174exports.countLeaves = function (index) {
175 return (exports.count(index) + 1) / 2
176}
177
178exports.spans = function (index, depth) {
179 if (!(index & 1)) return [index, index]
180 if (!depth) depth = exports.depth(index)
181
182 const offset = exports.offset(index, depth)
183 const width = twoPow(depth + 1)
184
185 return [offset * width, (offset + 1) * width - 2]
186}
187
188exports.index = function (depth, offset) {
189 return (1 + 2 * offset) * twoPow(depth) - 1
190}
191
192exports.offset = function (index, depth) {
193 if (!(index & 1)) return index / 2
194 if (!depth) depth = exports.depth(index)
195
196 return ((index + 1) / twoPow(depth) - 1) / 2
197}
198
199exports.iterator = function (index) {
200 const ite = new Iterator()
201 ite.seek(index || 0)
202 return ite
203}
204
205function twoPow (n) {
206 return n < 31 ? 1 << n : ((1 << 30) * (1 << (n - 30)))
207}
208
209function rightShift (n) {
210 return (n - (n & 1)) / 2
211}
212
213function Iterator () {
214 this.index = 0
215 this.offset = 0
216 this.factor = 0
217}
218
219Iterator.prototype.seek = function (index) {
220 this.index = index
221 if (this.index & 1) {
222 this.offset = exports.offset(index)
223 this.factor = twoPow(exports.depth(index) + 1)
224 } else {
225 this.offset = index / 2
226 this.factor = 2
227 }
228}
229
230Iterator.prototype.isLeft = function () {
231 return (this.offset & 1) === 0
232}
233
234Iterator.prototype.isRight = function () {
235 return (this.offset & 1) === 1
236}
237
238Iterator.prototype.isRoot = function (length) {
239 const currentLength = 1 + (this.index + this.factor / 2 - 1) / 2
240 if (length < currentLength) return false
241
242 const factor = this.factor * 2
243 const index = (this.offset & 1)
244 ? this.index - this.factor / 2
245 : this.index + this.factor / 2
246
247 const parentLength = 1 + (index + factor / 2 - 1) / 2
248 return parentLength > length
249}
250
251Iterator.prototype.contains = function (index) {
252 return index > this.index
253 ? index < (this.index + this.factor / 2)
254 : index < this.index
255 ? index > (this.index - this.factor / 2)
256 : true
257}
258
259Iterator.prototype.prev = function () {
260 if (!this.offset) return this.index
261 this.offset--
262 this.index -= this.factor
263 return this.index
264}
265
266Iterator.prototype.next = function () {
267 this.offset++
268 this.index += this.factor
269 return this.index
270}
271
272Iterator.prototype.count = function () {
273 if (!(this.index & 1)) return 1
274 return this.factor - 1
275}
276
277Iterator.prototype.countLeaves = function () {
278 return (this.count() + 1) / 2
279}
280
281Iterator.prototype.sibling = function () {
282 return this.isLeft() ? this.next() : this.prev()
283}
284
285Iterator.prototype.parent = function () {
286 if (this.offset & 1) {
287 this.index -= this.factor / 2
288 this.offset = (this.offset - 1) / 2
289 } else {
290 this.index += this.factor / 2
291 this.offset /= 2
292 }
293 this.factor *= 2
294 return this.index
295}
296
297Iterator.prototype.leftSpan = function () {
298 this.index = this.index - this.factor / 2 + 1
299 this.offset = this.index / 2
300 this.factor = 2
301 return this.index
302}
303
304Iterator.prototype.peekLeftSpan = function () {
305 return this.index - this.factor / 2 + 1
306}
307
308Iterator.prototype.rightSpan = function () {
309 this.index = this.index + this.factor / 2 - 1
310 this.offset = this.index / 2
311 this.factor = 2
312 return this.index
313}
314
315Iterator.prototype.peekRightSpan = function () {
316 return this.index + this.factor / 2 - 1
317}
318
319Iterator.prototype.leftChild = function () {
320 if (this.factor === 2) return this.index
321 this.factor /= 2
322 this.index -= this.factor / 2
323 this.offset *= 2
324 return this.index
325}
326
327Iterator.prototype.rightChild = function () {
328 if (this.factor === 2) return this.index
329 this.factor /= 2
330 this.index += this.factor / 2
331 this.offset = 2 * this.offset + 1
332 return this.index
333}
334
335Iterator.prototype.nextTree = function () {
336 this.index = this.index + this.factor / 2 + 1
337 this.offset = this.index / 2
338 this.factor = 2
339 return this.index
340}
341
342Iterator.prototype.prevTree = function () {
343 if (!this.offset) {
344 this.index = 0
345 this.factor = 2
346 } else {
347 this.index = this.index - this.factor / 2 - 1
348 this.offset = this.index / 2
349 this.factor = 2
350 }
351 return this.index
352}
353
354Iterator.prototype.fullRoot = function (index) {
355 if (index <= this.index || (this.index & 1) > 0) return false
356 while (index > this.index + this.factor + this.factor / 2) {
357 this.index += this.factor / 2
358 this.factor *= 2
359 this.offset /= 2
360 }
361 return true
362}
node_modules/flat-tree/package.json +27 -0
……@@ -0,0 +1,27 @@
1{
2 "name": "flat-tree",
3 "version": "1.13.0",
4 "description": "A series of functions to map a binary tree to a list",
5 "main": "index.js",
6 "files": [
7 "index.js"
8 ],
9 "dependencies": {},
10 "devDependencies": {
11 "brittle": "^3.3.2",
12 "standard": "^17.1.0"
13 },
14 "scripts": {
15 "test": "standard && brittle test.js"
16 },
17 "repository": {
18 "type": "git",
19 "url": "https://github.com/mafintosh/flat-tree.git"
20 },
21 "author": "Mathias Buus (@mafintosh)",
22 "license": "MIT",
23 "bugs": {
24 "url": "https://github.com/mafintosh/flat-tree/issues"
25 },
26 "homepage": "https://github.com/mafintosh/flat-tree"
27}
node_modules/fs-native-extensions/CMakeLists.txt +118 -0
……@@ -0,0 +1,118 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6find_package(cmake-npm REQUIRED PATHS node_modules/cmake-npm)
7
8project(fs_native_extensions C)
9
10fetch_package("github:libuv/libuv@1.51.0")
11
12add_library(fs_native_extensions STATIC)
13
14target_sources(
15 fs_native_extensions
16 INTERFACE
17 include/fs-ext.h
18 PRIVATE
19 src/platform.h
20 src/shared.c
21)
22
23target_include_directories(
24 fs_native_extensions
25 INTERFACE
26 include
27 PRIVATE
28 $<TARGET_PROPERTY:uv,INTERFACE_INCLUDE_DIRECTORIES>
29)
30
31if(APPLE)
32 target_sources(
33 fs_native_extensions
34 PRIVATE
35 src/apple.c
36 )
37endif()
38
39if(LINUX OR ANDROID)
40 target_sources(
41 fs_native_extensions
42 PRIVATE
43 src/linux.c
44 )
45endif()
46
47if(WIN32)
48 target_sources(
49 fs_native_extensions
50 PRIVATE
51 src/win32.c
52 src/win32/nt.h
53 )
54else()
55 target_sources(
56 fs_native_extensions
57 PRIVATE
58 src/posix.c
59 )
60endif()
61
62add_bare_module(fs_native_extensions_bare)
63
64target_sources(
65 ${fs_native_extensions_bare}
66 PRIVATE
67 binding.c
68)
69
70target_link_libraries(
71 ${fs_native_extensions_bare}
72 PRIVATE
73 fs_native_extensions
74)
75
76if(WIN32)
77 target_link_libraries(
78 ${fs_native_extensions_bare}
79 PUBLIC
80 ntdll
81 )
82endif()
83
84add_napi_module(fs_native_extensions_napi)
85
86target_sources(
87 ${fs_native_extensions_napi}
88 PRIVATE
89 binding.c
90)
91
92target_link_libraries(
93 ${fs_native_extensions_napi}
94 PRIVATE
95 fs_native_extensions
96)
97
98target_compile_definitions(
99 ${fs_native_extensions_napi}
100 PRIVATE
101 NAPI_VERSION=9
102)
103
104resolve_node_module(bare-compat-napi compat)
105
106target_include_directories(
107 ${fs_native_extensions_napi}
108 PRIVATE
109 "${compat}/include"
110)
111
112if(WIN32)
113 target_link_libraries(
114 ${fs_native_extensions_napi}
115 PUBLIC
116 ntdll
117 )
118endif()
node_modules/fs-native-extensions/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/fs-native-extensions/README.md +118 -0
……@@ -0,0 +1,118 @@
1# fs-native-extensions
2
3Native file system extensions for advanced file operations
4
5```
6npm install fs-native-extensions
7```
8
9## Usage
10
11Write to a file using an exclusive lock:
12
13```js
14const { open } = require('fs/promises')
15const { waitForLock, unlock } = require('fs-native-extensions')
16
17const file = await open('file.txt', 'a+')
18
19await waitForLock(file.fd)
20
21try {
22 await file.write('hello world')
23} finally {
24 unlock(file.fd)
25}
26```
27
28## API
29
30#### `const granted = tryLock(fd[, offset[, length]][, options])`
31
32Request a lock on a file, returning `true` if the lock was granted or `false` if another file descriptor currently holds the lock.
33
34To lock only a portion of the file, `offset` and `length` may be passed. A `length` of `0` will request a lock from `offset` to the end of the file.
35
36On macOS, BSD locks are used and so only locks on the whole file are supported.
37
38Note that the lock is only advisory and there is nothing stopping another process from accessing the file by simply ignoring the lock.
39
40Options include:
41
42```js
43{
44 // If `true`, request a shared lock, i.e. a read lock, on the file. By
45 // default, an exclusive lock, i.e. a write lock, is requested.
46 // Be aware that an exclusive lock can only be granted to files that are
47 // writable!
48 shared: false
49}
50```
51
52#### `await waitForLock(fd[, offset[, length]][, options])`
53
54Request a lock on a file, resolving when the lock is granted. If another file descriptor holds the lock, the lock will not be granted until the other file descriptor releases the lock.
55
56Options are the same as `tryLock()`.
57
58#### `const granted = tryDowngradeLock(fd[, offset[, length]])`
59
60Request a downgrade from an already held exclusive lock to a shared lock, returning `true` if the lock was granted or `false` if another process currently holds the lock. If `false` is returned, the exclusive lock is lost and must be requested again.
61
62On Windows, the downgrade will happen atomically and be immediately granted.
63
64#### `await waitForDowngradeLock(fd[, offset[, length]])`
65
66Request a downgrade from an already held exclusive lock to a shared lock.
67
68On Windows, the downgrade will happen atomically and be immediately granted.
69
70#### `const granted = tryUpgradeLock(fd[, offset[, length]])`
71
72Request an upgrade from an already held shared lock to an exclusive lock, returning `true` if the lock was granted or `false` if another process currently holds the lock. If `false` is returned, the shared lock is lost and must be requested again.
73
74#### `await waitForUpgradeLock(fd[, offset[, length]])`
75
76Request an upgrade from an already held shared lock to an exclusive lock.
77
78#### `unlock(fd[, offset[, length]])`
79
80Release a lock on a file.
81
82#### `await trim(fd, offset, length)`
83
84Create a hole in a file at `offset` for `length` bytes. On file systems that support sparse files, file blocks wholly covered by a hole will take up no physical space.
85
86On Windows, the file must first be marked sparse using `sparse(fd)`. Otherwise, zeros will be explicitly written to the hole.
87
88#### `await sparse(fd)`
89
90Mark a file as sparse. On Windows, this operation is required before holes can be created in the file. On other systems, this operation has no effect.
91
92#### `await swap(from, to)`
93
94Swap the paths `from` and `to`, making `from` assume the identity of `to` and `to` assume the identity of `from`.
95
96On Windows, the swap is performed by first moving `to` to a temporary path, then moving `from` to `to`, and finally moving the temporary path to `from`.
97
98On macOS and Linux, the swap is performed atomically.
99
100#### `const value = await getAttr(fd, name)`
101
102Get the value of the extended file attribute `name`. If the attribute doesn't exist, `null` is returned.
103
104#### `await setAttr(fd, name, value[, encoding])`
105
106Set the value of the extended file attribute `name` to `value`.
107
108#### `await removeAttr(fd, name)`
109
110Remove the extended file attribute `name`.
111
112#### `const names = await listAttrs(fd)`
113
114List all extended file attributes.
115
116## License
117
118Apache-2.0
node_modules/fs-native-extensions/binding.c +1415 -0
……@@ -0,0 +1,1415 @@
1#include <bare.h>
2#include <js.h>
3#include <stdlib.h>
4#include <string.h>
5#include <utf.h>
6#include <uv.h>
7
8#include "include/fs-ext.h"
9
10typedef utf8_t fs_ext_js_path_t[4096 + 1 /* NULL */];
11
12typedef struct {
13 fs_ext_lock_t req;
14
15 js_env_t *env;
16 js_ref_t *ctx;
17 js_ref_t *cb;
18
19 bool exiting;
20
21 js_deferred_teardown_t *teardown;
22} fs_ext_js_lock_t;
23
24typedef struct {
25 fs_ext_trim_t req;
26
27 js_env_t *env;
28 js_ref_t *ctx;
29 js_ref_t *cb;
30
31 bool exiting;
32
33 js_deferred_teardown_t *teardown;
34} fs_ext_js_trim_t;
35
36typedef struct {
37 fs_ext_sparse_t req;
38
39 js_env_t *env;
40 js_ref_t *ctx;
41 js_ref_t *cb;
42
43 bool exiting;
44
45 js_deferred_teardown_t *teardown;
46} fs_ext_js_sparse_t;
47
48typedef struct {
49 fs_ext_swap_t req;
50
51 js_env_t *env;
52 js_ref_t *ctx;
53 js_ref_t *cb;
54
55 bool exiting;
56
57 js_deferred_teardown_t *teardown;
58} fs_ext_js_swap_t;
59
60typedef struct {
61 fs_ext_get_attr_t req;
62
63 js_env_t *env;
64 js_ref_t *ctx;
65 js_ref_t *cb;
66
67 bool exiting;
68
69 js_deferred_teardown_t *teardown;
70} fs_ext_js_get_attr_t;
71
72typedef struct {
73 fs_ext_set_attr_t req;
74
75 js_env_t *env;
76 js_ref_t *ctx;
77 js_ref_t *cb;
78
79 bool exiting;
80
81 js_deferred_teardown_t *teardown;
82} fs_ext_js_set_attr_t;
83
84typedef struct {
85 fs_ext_remove_attr_t req;
86
87 js_env_t *env;
88 js_ref_t *ctx;
89 js_ref_t *cb;
90
91 bool exiting;
92
93 js_deferred_teardown_t *teardown;
94} fs_ext_js_remove_attr_t;
95
96typedef struct {
97 fs_ext_list_attrs_t req;
98
99 js_env_t *env;
100 js_ref_t *ctx;
101 js_ref_t *cb;
102
103 bool exiting;
104
105 js_deferred_teardown_t *teardown;
106} fs_ext_js_list_attrs_t;
107
108static void
109fs_ext_js__on_teardown(js_deferred_teardown_t *teardown, void *data) {
110 bool *exiting = data;
111
112 *exiting = true;
113}
114
115static void
116fs_ext_js__on_lock(fs_ext_lock_t *req, int status) {
117 int err;
118
119 fs_ext_js_lock_t *r = (fs_ext_js_lock_t *) req;
120
121 js_env_t *env = r->env;
122
123 js_deferred_teardown_t *teardown = r->teardown;
124
125 js_handle_scope_t *scope;
126 err = js_open_handle_scope(env, &scope);
127 assert(err == 0);
128
129 js_value_t *argv[1];
130
131 js_value_t *ctx;
132 err = js_get_reference_value(env, r->ctx, &ctx);
133 assert(err == 0);
134
135 js_value_t *callback;
136 err = js_get_reference_value(env, r->cb, &callback);
137 assert(err == 0);
138
139 err = js_delete_reference(env, r->cb);
140 assert(err == 0);
141
142 err = js_delete_reference(env, r->ctx);
143 assert(err == 0);
144
145 if (req->result < 0) {
146 js_value_t *code;
147 err = js_create_string_utf8(env, (const utf8_t *) uv_err_name(req->result), -1, &code);
148 assert(err == 0);
149
150 js_value_t *message;
151 err = js_create_string_utf8(env, (const utf8_t *) uv_strerror(req->result), -1, &message);
152 assert(err == 0);
153
154 err = js_create_error(env, code, message, &argv[0]);
155 assert(err == 0);
156 } else {
157 err = js_get_null(env, &argv[0]);
158 assert(err == 0);
159 }
160
161 if (!r->exiting) js_call_function_with_checkpoint(env, ctx, callback, 1, argv, NULL);
162
163 err = js_close_handle_scope(env, scope);
164 assert(err == 0);
165
166 err = js_finish_deferred_teardown_callback(teardown);
167 assert(err == 0);
168}
169
170static void
171fs_ext_js__on_trim(fs_ext_trim_t *req, int status) {
172 int err;
173
174 fs_ext_js_trim_t *r = (fs_ext_js_trim_t *) req;
175
176 js_env_t *env = r->env;
177
178 js_deferred_teardown_t *teardown = r->teardown;
179
180 js_handle_scope_t *scope;
181 err = js_open_handle_scope(env, &scope);
182 assert(err == 0);
183
184 js_value_t *argv[1];
185
186 js_value_t *ctx;
187 err = js_get_reference_value(env, r->ctx, &ctx);
188 assert(err == 0);
189
190 js_value_t *callback;
191 err = js_get_reference_value(env, r->cb, &callback);
192 assert(err == 0);
193
194 err = js_delete_reference(env, r->cb);
195 assert(err == 0);
196
197 err = js_delete_reference(env, r->ctx);
198 assert(err == 0);
199
200 if (req->result < 0) {
201 js_value_t *code;
202 err = js_create_string_utf8(env, (const utf8_t *) uv_err_name(req->result), -1, &code);
203 assert(err == 0);
204
205 js_value_t *message;
206 err = js_create_string_utf8(env, (const utf8_t *) uv_strerror(req->result), -1, &message);
207 assert(err == 0);
208
209 err = js_create_error(env, code, message, &argv[0]);
210 assert(err == 0);
211 } else {
212 err = js_get_null(env, &argv[0]);
213 assert(err == 0);
214 }
215
216 if (!r->exiting) js_call_function_with_checkpoint(env, ctx, callback, 1, argv, NULL);
217
218 err = js_close_handle_scope(env, scope);
219 assert(err == 0);
220
221 err = js_finish_deferred_teardown_callback(teardown);
222 assert(err == 0);
223}
224
225static void
226fs_ext_js__on_sparse(fs_ext_sparse_t *req, int status) {
227 int err;
228
229 fs_ext_js_sparse_t *r = (fs_ext_js_sparse_t *) req;
230
231 js_env_t *env = r->env;
232
233 js_deferred_teardown_t *teardown = r->teardown;
234
235 js_handle_scope_t *scope;
236 err = js_open_handle_scope(env, &scope);
237 assert(err == 0);
238
239 js_value_t *argv[1];
240
241 js_value_t *ctx;
242 err = js_get_reference_value(env, r->ctx, &ctx);
243 assert(err == 0);
244
245 js_value_t *callback;
246 err = js_get_reference_value(env, r->cb, &callback);
247 assert(err == 0);
248
249 err = js_delete_reference(env, r->cb);
250 assert(err == 0);
251
252 err = js_delete_reference(env, r->ctx);
253 assert(err == 0);
254
255 if (req->result < 0) {
256 js_value_t *code;
257 err = js_create_string_utf8(env, (const utf8_t *) uv_err_name(req->result), -1, &code);
258 assert(err == 0);
259
260 js_value_t *message;
261 err = js_create_string_utf8(env, (const utf8_t *) uv_strerror(req->result), -1, &message);
262 assert(err == 0);
263
264 err = js_create_error(env, code, message, &argv[0]);
265 assert(err == 0);
266 } else {
267 err = js_get_null(env, &argv[0]);
268 assert(err == 0);
269 }
270
271 if (!r->exiting) js_call_function_with_checkpoint(env, ctx, callback, 1, argv, NULL);
272
273 err = js_close_handle_scope(env, scope);
274 assert(err == 0);
275
276 err = js_finish_deferred_teardown_callback(teardown);
277 assert(err == 0);
278}
279
280static void
281fs_ext_js__on_swap(fs_ext_swap_t *req, int status) {
282 int err;
283
284 fs_ext_js_swap_t *r = (fs_ext_js_swap_t *) req;
285
286 js_env_t *env = r->env;
287
288 js_deferred_teardown_t *teardown = r->teardown;
289
290 js_handle_scope_t *scope;
291 err = js_open_handle_scope(env, &scope);
292 assert(err == 0);
293
294 js_value_t *argv[1];
295
296 js_value_t *ctx;
297 err = js_get_reference_value(env, r->ctx, &ctx);
298 assert(err == 0);
299
300 js_value_t *callback;
301 err = js_get_reference_value(env, r->cb, &callback);
302 assert(err == 0);
303
304 err = js_delete_reference(env, r->cb);
305 assert(err == 0);
306
307 err = js_delete_reference(env, r->ctx);
308 assert(err == 0);
309
310 if (req->result < 0) {
311 js_value_t *code;
312 err = js_create_string_utf8(env, (const utf8_t *) uv_err_name(req->result), -1, &code);
313 assert(err == 0);
314
315 js_value_t *message;
316 err = js_create_string_utf8(env, (const utf8_t *) uv_strerror(req->result), -1, &message);
317 assert(err == 0);
318
319 err = js_create_error(env, code, message, &argv[0]);
320 assert(err == 0);
321 } else {
322 err = js_get_null(env, &argv[0]);
323 assert(err == 0);
324 }
325
326 if (!r->exiting) js_call_function_with_checkpoint(env, ctx, callback, 1, argv, NULL);
327
328 err = js_close_handle_scope(env, scope);
329 assert(err == 0);
330
331 err = js_finish_deferred_teardown_callback(teardown);
332 assert(err == 0);
333}
334
335static void
336fs_ext_js__on_get_attr(fs_ext_get_attr_t *req, int status, const uv_buf_t *value) {
337 int err;
338
339 fs_ext_js_get_attr_t *r = (fs_ext_js_get_attr_t *) req;
340
341 js_env_t *env = r->env;
342
343 js_deferred_teardown_t *teardown = r->teardown;
344
345 js_handle_scope_t *scope;
346 err = js_open_handle_scope(env, &scope);
347 assert(err == 0);
348
349 js_value_t *argv[2];
350
351 js_value_t *ctx;
352 err = js_get_reference_value(env, r->ctx, &ctx);
353 assert(err == 0);
354
355 js_value_t *callback;
356 err = js_get_reference_value(env, r->cb, &callback);
357 assert(err == 0);
358
359 err = js_delete_reference(env, r->cb);
360 assert(err == 0);
361
362 err = js_delete_reference(env, r->ctx);
363 assert(err == 0);
364
365 if (req->result < 0 && req->result != UV_ENODATA) {
366 js_value_t *code;
367 err = js_create_string_utf8(env, (const utf8_t *) uv_err_name(req->result), -1, &code);
368 assert(err == 0);
369
370 js_value_t *message;
371 err = js_create_string_utf8(env, (const utf8_t *) uv_strerror(req->result), -1, &message);
372 assert(err == 0);
373
374 err = js_create_error(env, code, message, &argv[0]);
375 assert(err == 0);
376
377 err = js_get_null(env, &argv[1]);
378 assert(err == 0);
379 } else {
380 err = js_get_null(env, &argv[0]);
381 assert(err == 0);
382
383 if (req->result == UV_ENODATA) {
384 err = js_get_null(env, &argv[1]);
385 assert(err == 0);
386 } else {
387 void *data;
388 err = js_create_arraybuffer(env, value->len, &data, &argv[1]);
389 assert(err == 0);
390
391 memcpy(data, value->base, value->len);
392 }
393 }
394
395 if (!r->exiting) js_call_function_with_checkpoint(env, ctx, callback, 2, argv, NULL);
396
397 err = js_close_handle_scope(env, scope);
398 assert(err == 0);
399
400 err = js_finish_deferred_teardown_callback(teardown);
401 assert(err == 0);
402}
403
404static void
405fs_ext_js__on_set_attr(fs_ext_set_attr_t *req, int status) {
406 int err;
407
408 fs_ext_js_set_attr_t *r = (fs_ext_js_set_attr_t *) req;
409
410 js_env_t *env = r->env;
411
412 js_deferred_teardown_t *teardown = r->teardown;
413
414 js_handle_scope_t *scope;
415 err = js_open_handle_scope(env, &scope);
416 assert(err == 0);
417
418 js_value_t *argv[1];
419
420 js_value_t *ctx;
421 err = js_get_reference_value(env, r->ctx, &ctx);
422 assert(err == 0);
423
424 js_value_t *callback;
425 err = js_get_reference_value(env, r->cb, &callback);
426 assert(err == 0);
427
428 err = js_delete_reference(env, r->cb);
429 assert(err == 0);
430
431 err = js_delete_reference(env, r->ctx);
432 assert(err == 0);
433
434 if (req->result < 0) {
435 js_value_t *code;
436 err = js_create_string_utf8(env, (const utf8_t *) uv_err_name(req->result), -1, &code);
437 assert(err == 0);
438
439 js_value_t *message;
440 err = js_create_string_utf8(env, (const utf8_t *) uv_strerror(req->result), -1, &message);
441 assert(err == 0);
442
443 err = js_create_error(env, code, message, &argv[0]);
444 assert(err == 0);
445 } else {
446 err = js_get_null(env, &argv[0]);
447 assert(err == 0);
448 }
449
450 if (!r->exiting) js_call_function_with_checkpoint(env, ctx, callback, 1, argv, NULL);
451
452 err = js_close_handle_scope(env, scope);
453 assert(err == 0);
454
455 err = js_finish_deferred_teardown_callback(teardown);
456 assert(err == 0);
457}
458
459static void
460fs_ext_js__on_remove_attr(fs_ext_remove_attr_t *req, int status) {
461 int err;
462
463 fs_ext_js_remove_attr_t *r = (fs_ext_js_remove_attr_t *) req;
464
465 js_env_t *env = r->env;
466
467 js_deferred_teardown_t *teardown = r->teardown;
468
469 js_handle_scope_t *scope;
470 err = js_open_handle_scope(env, &scope);
471 assert(err == 0);
472
473 js_value_t *argv[1];
474
475 js_value_t *ctx;
476 err = js_get_reference_value(env, r->ctx, &ctx);
477 assert(err == 0);
478
479 js_value_t *callback;
480 err = js_get_reference_value(env, r->cb, &callback);
481 assert(err == 0);
482
483 err = js_delete_reference(env, r->cb);
484 assert(err == 0);
485
486 err = js_delete_reference(env, r->ctx);
487 assert(err == 0);
488
489 if (req->result < 0 && req->result != UV_ENODATA) {
490 js_value_t *code;
491 err = js_create_string_utf8(env, (const utf8_t *) uv_err_name(req->result), -1, &code);
492 assert(err == 0);
493
494 js_value_t *message;
495 err = js_create_string_utf8(env, (const utf8_t *) uv_strerror(req->result), -1, &message);
496 assert(err == 0);
497
498 err = js_create_error(env, code, message, &argv[0]);
499 assert(err == 0);
500 } else {
501 err = js_get_null(env, &argv[0]);
502 assert(err == 0);
503 }
504
505 if (!r->exiting) js_call_function_with_checkpoint(env, ctx, callback, 1, argv, NULL);
506
507 err = js_close_handle_scope(env, scope);
508 assert(err == 0);
509
510 err = js_finish_deferred_teardown_callback(teardown);
511 assert(err == 0);
512}
513
514static void
515fs_ext_js__on_list_attrs(fs_ext_list_attrs_t *req, int status, const char *attrs[], ssize_t len) {
516 int err;
517
518 fs_ext_js_list_attrs_t *r = (fs_ext_js_list_attrs_t *) req;
519
520 js_env_t *env = r->env;
521
522 js_deferred_teardown_t *teardown = r->teardown;
523
524 js_handle_scope_t *scope;
525 err = js_open_handle_scope(env, &scope);
526 assert(err == 0);
527
528 js_value_t *argv[2];
529
530 js_value_t *ctx;
531 err = js_get_reference_value(env, r->ctx, &ctx);
532 assert(err == 0);
533
534 js_value_t *callback;
535 err = js_get_reference_value(env, r->cb, &callback);
536 assert(err == 0);
537
538 err = js_delete_reference(env, r->cb);
539 assert(err == 0);
540
541 err = js_delete_reference(env, r->ctx);
542 assert(err == 0);
543
544 if (req->result < 0) {
545 js_value_t *code;
546 err = js_create_string_utf8(env, (const utf8_t *) uv_err_name(req->result), -1, &code);
547 assert(err == 0);
548
549 js_value_t *message;
550 err = js_create_string_utf8(env, (const utf8_t *) uv_strerror(req->result), -1, &message);
551 assert(err == 0);
552
553 err = js_create_error(env, code, message, &argv[0]);
554 assert(err == 0);
555
556 err = js_get_null(env, &argv[1]);
557 assert(err == 0);
558 } else {
559 err = js_get_null(env, &argv[0]);
560 assert(err == 0);
561
562 err = js_create_array_with_length(env, len, &argv[1]);
563 assert(err == 0);
564
565 for (size_t i = 0; i < len; i++) {
566 js_value_t *value;
567 err = js_create_string_utf8(env, (const utf8_t *) attrs[i], -1, &value);
568 assert(err == 0);
569
570 err = js_set_element(env, argv[1], i, value);
571 assert(err == 0);
572 }
573 }
574
575 if (!r->exiting) js_call_function_with_checkpoint(env, ctx, callback, 2, argv, NULL);
576
577 err = js_close_handle_scope(env, scope);
578 assert(err == 0);
579
580 err = js_finish_deferred_teardown_callback(teardown);
581 assert(err == 0);
582}
583
584static js_value_t *
585fs_ext_js_try_lock(js_env_t *env, js_callback_info_t *info) {
586 int err;
587
588 size_t argc = 4;
589 js_value_t *argv[4];
590
591 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
592 assert(err == 0);
593
594 assert(argc == 4);
595
596 int64_t fd;
597 err = js_get_value_int64(env, argv[0], &fd);
598 assert(err == 0);
599
600 int64_t offset;
601 err = js_get_value_int64(env, argv[1], &offset);
602 assert(err == 0);
603
604 int64_t len;
605 err = js_get_value_int64(env, argv[2], &len);
606 assert(err == 0);
607
608 bool exclusive;
609 err = js_get_value_bool(env, argv[3], &exclusive);
610 assert(err == 0);
611
612 err = fs_ext_try_lock(
613 uv_get_osfhandle(fd),
614 offset,
615 len,
616 exclusive ? FS_EXT_WRLOCK : FS_EXT_RDLOCK
617 );
618
619 if (err < 0) {
620 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
621 assert(err == 0);
622 }
623
624 return NULL;
625}
626
627static js_value_t *
628fs_ext_js_wait_for_lock(js_env_t *env, js_callback_info_t *info) {
629 int err;
630
631 size_t argc = 6;
632 js_value_t *argv[6];
633
634 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
635 assert(err == 0);
636
637 assert(argc == 6);
638
639 int64_t fd;
640 err = js_get_value_int64(env, argv[0], &fd);
641 assert(err == 0);
642
643 int64_t offset;
644 err = js_get_value_int64(env, argv[1], &offset);
645 assert(err == 0);
646
647 int64_t len;
648 err = js_get_value_int64(env, argv[2], &len);
649 assert(err == 0);
650
651 bool exclusive;
652 err = js_get_value_bool(env, argv[3], &exclusive);
653 assert(err == 0);
654
655 js_value_t *handle;
656
657 fs_ext_js_lock_t *req;
658 err = js_create_arraybuffer(env, sizeof(fs_ext_js_lock_t), (void **) &req, &handle);
659 assert(err == 0);
660
661 uv_loop_t *loop;
662 err = js_get_env_loop(env, &loop);
663 assert(err == 0);
664
665 err = fs_ext_wait_for_lock(
666 loop,
667 (fs_ext_lock_t *) req,
668 uv_get_osfhandle(fd),
669 offset,
670 len,
671 exclusive ? FS_EXT_WRLOCK : FS_EXT_RDLOCK,
672 fs_ext_js__on_lock
673 );
674
675 if (err < 0) {
676 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
677 assert(err == 0);
678
679 return NULL;
680 }
681
682 req->env = env;
683 req->exiting = false;
684
685 err = js_create_reference(env, argv[4], 1, &req->ctx);
686 assert(err == 0);
687
688 err = js_create_reference(env, argv[5], 1, &req->cb);
689 assert(err == 0);
690
691 err = js_add_deferred_teardown_callback(env, fs_ext_js__on_teardown, (void *) &req->exiting, &req->teardown);
692 assert(err == 0);
693
694 return handle;
695}
696
697static js_value_t *
698fs_ext_js_try_downgrade_lock(js_env_t *env, js_callback_info_t *info) {
699 int err;
700
701 size_t argc = 3;
702 js_value_t *argv[3];
703
704 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
705 assert(err == 0);
706
707 assert(argc == 3);
708
709 int64_t fd;
710 err = js_get_value_int64(env, argv[0], &fd);
711 assert(err == 0);
712
713 int64_t offset;
714 err = js_get_value_int64(env, argv[1], &offset);
715 assert(err == 0);
716
717 int64_t len;
718 err = js_get_value_int64(env, argv[2], &len);
719 assert(err == 0);
720
721 err = fs_ext_try_downgrade_lock(uv_get_osfhandle(fd), offset, len);
722
723 if (err < 0) {
724 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
725 assert(err == 0);
726 }
727
728 return NULL;
729}
730
731static js_value_t *
732fs_ext_js_wait_for_downgrade_lock(js_env_t *env, js_callback_info_t *info) {
733 int err;
734
735 size_t argc = 5;
736 js_value_t *argv[5];
737
738 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
739 assert(err == 0);
740
741 assert(argc == 5);
742
743 int64_t fd;
744 err = js_get_value_int64(env, argv[0], &fd);
745 assert(err == 0);
746
747 int64_t offset;
748 err = js_get_value_int64(env, argv[1], &offset);
749 assert(err == 0);
750
751 int64_t len;
752 err = js_get_value_int64(env, argv[2], &len);
753 assert(err == 0);
754
755 js_value_t *handle;
756
757 fs_ext_js_lock_t *req;
758 err = js_create_arraybuffer(env, sizeof(fs_ext_js_lock_t), (void **) &req, &handle);
759 assert(err == 0);
760
761 uv_loop_t *loop;
762 err = js_get_env_loop(env, &loop);
763 assert(err == 0);
764
765 err = fs_ext_wait_for_downgrade_lock(
766 loop,
767 (fs_ext_lock_t *) req,
768 uv_get_osfhandle(fd),
769 offset,
770 len,
771 fs_ext_js__on_lock
772 );
773
774 if (err < 0) {
775 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
776 assert(err == 0);
777
778 return NULL;
779 }
780
781 req->env = env;
782 req->exiting = false;
783
784 err = js_create_reference(env, argv[3], 1, &req->ctx);
785 assert(err == 0);
786
787 err = js_create_reference(env, argv[4], 1, &req->cb);
788 assert(err == 0);
789
790 err = js_add_deferred_teardown_callback(env, fs_ext_js__on_teardown, (void *) &req->exiting, &req->teardown);
791 assert(err == 0);
792
793 return handle;
794}
795
796static js_value_t *
797fs_ext_js_try_upgrade_lock(js_env_t *env, js_callback_info_t *info) {
798 int err;
799
800 size_t argc = 3;
801 js_value_t *argv[3];
802
803 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
804 assert(err == 0);
805
806 assert(argc == 3);
807
808 int64_t fd;
809 err = js_get_value_int64(env, argv[0], &fd);
810 assert(err == 0);
811
812 int64_t offset;
813 err = js_get_value_int64(env, argv[1], &offset);
814 assert(err == 0);
815
816 int64_t len;
817 err = js_get_value_int64(env, argv[2], &len);
818 assert(err == 0);
819
820 err = fs_ext_try_upgrade_lock(uv_get_osfhandle(fd), offset, len);
821
822 if (err < 0) {
823 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
824 assert(err == 0);
825 }
826
827 return NULL;
828}
829
830static js_value_t *
831fs_ext_js_wait_for_upgrade_lock(js_env_t *env, js_callback_info_t *info) {
832 int err;
833
834 size_t argc = 5;
835 js_value_t *argv[5];
836
837 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
838 assert(err == 0);
839
840 assert(argc == 5);
841
842 int64_t fd;
843 err = js_get_value_int64(env, argv[0], &fd);
844 assert(err == 0);
845
846 int64_t offset;
847 err = js_get_value_int64(env, argv[1], &offset);
848 assert(err == 0);
849
850 int64_t len;
851 err = js_get_value_int64(env, argv[2], &len);
852 assert(err == 0);
853
854 js_value_t *handle;
855
856 fs_ext_js_lock_t *req;
857 err = js_create_arraybuffer(env, sizeof(fs_ext_js_lock_t), (void **) &req, &handle);
858 assert(err == 0);
859
860 uv_loop_t *loop;
861 err = js_get_env_loop(env, &loop);
862 assert(err == 0);
863
864 err = fs_ext_wait_for_upgrade_lock(
865 loop,
866 (fs_ext_lock_t *) req,
867 uv_get_osfhandle(fd),
868 offset,
869 len,
870 fs_ext_js__on_lock
871 );
872
873 if (err < 0) {
874 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
875 assert(err == 0);
876
877 return NULL;
878 }
879
880 req->env = env;
881 req->exiting = false;
882
883 err = js_create_reference(env, argv[3], 1, &req->ctx);
884 assert(err == 0);
885
886 err = js_create_reference(env, argv[4], 1, &req->cb);
887 assert(err == 0);
888
889 err = js_add_deferred_teardown_callback(env, fs_ext_js__on_teardown, (void *) &req->exiting, &req->teardown);
890 assert(err == 0);
891
892 return handle;
893}
894
895static js_value_t *
896fs_ext_js_unlock(js_env_t *env, js_callback_info_t *info) {
897 int err;
898
899 size_t argc = 3;
900 js_value_t *argv[3];
901
902 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
903 assert(err == 0);
904
905 assert(argc == 3);
906
907 int64_t fd;
908 err = js_get_value_int64(env, argv[0], &fd);
909 assert(err == 0);
910
911 int64_t offset;
912 err = js_get_value_int64(env, argv[1], &offset);
913 assert(err == 0);
914
915 int64_t len;
916 err = js_get_value_int64(env, argv[2], &len);
917 assert(err == 0);
918
919 err = fs_ext_unlock(uv_get_osfhandle(fd), offset, len);
920
921 if (err < 0) {
922 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
923 assert(err == 0);
924 }
925
926 return NULL;
927}
928
929static js_value_t *
930fs_ext_js_trim(js_env_t *env, js_callback_info_t *info) {
931 int err;
932
933 size_t argc = 5;
934 js_value_t *argv[5];
935
936 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
937 assert(err == 0);
938
939 assert(argc == 5);
940
941 int64_t fd;
942 err = js_get_value_int64(env, argv[0], &fd);
943 assert(err == 0);
944
945 int64_t offset;
946 err = js_get_value_int64(env, argv[1], &offset);
947 assert(err == 0);
948
949 int64_t len;
950 err = js_get_value_int64(env, argv[2], &len);
951 assert(err == 0);
952
953 js_value_t *handle;
954
955 fs_ext_js_trim_t *req;
956 err = js_create_arraybuffer(env, sizeof(fs_ext_js_trim_t), (void **) &req, &handle);
957 assert(err == 0);
958
959 uv_loop_t *loop;
960 err = js_get_env_loop(env, &loop);
961 assert(err == 0);
962
963 err = fs_ext_trim(
964 loop,
965 (fs_ext_trim_t *) req,
966 uv_get_osfhandle(fd),
967 offset,
968 len,
969 fs_ext_js__on_trim
970 );
971
972 if (err < 0) {
973 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
974 assert(err == 0);
975
976 return NULL;
977 }
978
979 req->env = env;
980 req->exiting = false;
981
982 err = js_create_reference(env, argv[3], 1, &req->ctx);
983 assert(err == 0);
984
985 err = js_create_reference(env, argv[4], 1, &req->cb);
986 assert(err == 0);
987
988 err = js_add_deferred_teardown_callback(env, fs_ext_js__on_teardown, (void *) &req->exiting, &req->teardown);
989 assert(err == 0);
990
991 return handle;
992}
993
994static js_value_t *
995fs_ext_js_sparse(js_env_t *env, js_callback_info_t *info) {
996 int err;
997
998 size_t argc = 3;
999 js_value_t *argv[3];
1000
1001 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1002 assert(err == 0);
1003
1004 assert(argc == 3);
1005
1006 int64_t fd;
1007 err = js_get_value_int64(env, argv[0], &fd);
1008 assert(err == 0);
1009
1010 js_value_t *handle;
1011
1012 fs_ext_js_sparse_t *req;
1013 err = js_create_arraybuffer(env, sizeof(fs_ext_js_sparse_t), (void **) &req, &handle);
1014 assert(err == 0);
1015
1016 uv_loop_t *loop;
1017 err = js_get_env_loop(env, &loop);
1018 assert(err == 0);
1019
1020 err = fs_ext_sparse(
1021 loop,
1022 (fs_ext_sparse_t *) req,
1023 uv_get_osfhandle(fd),
1024 fs_ext_js__on_sparse
1025 );
1026
1027 if (err < 0) {
1028 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1029 assert(err == 0);
1030
1031 return NULL;
1032 }
1033
1034 req->env = env;
1035 req->exiting = false;
1036
1037 err = js_create_reference(env, argv[1], 1, &req->ctx);
1038 assert(err == 0);
1039
1040 err = js_create_reference(env, argv[2], 1, &req->cb);
1041 assert(err == 0);
1042
1043 err = js_add_deferred_teardown_callback(env, fs_ext_js__on_teardown, (void *) &req->exiting, &req->teardown);
1044 assert(err == 0);
1045
1046 return handle;
1047}
1048
1049static js_value_t *
1050fs_ext_js_swap(js_env_t *env, js_callback_info_t *info) {
1051 int err;
1052
1053 size_t argc = 4;
1054 js_value_t *argv[4];
1055
1056 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1057 assert(err == 0);
1058
1059 assert(argc == 4);
1060
1061 fs_ext_js_path_t from;
1062 err = js_get_value_string_utf8(env, argv[0], from, sizeof(from), NULL);
1063 assert(err == 0);
1064
1065 fs_ext_js_path_t to;
1066 err = js_get_value_string_utf8(env, argv[1], to, sizeof(to), NULL);
1067 assert(err == 0);
1068
1069 js_value_t *handle;
1070
1071 fs_ext_js_swap_t *req;
1072 err = js_create_arraybuffer(env, sizeof(fs_ext_js_swap_t), (void **) &req, &handle);
1073 assert(err == 0);
1074
1075 uv_loop_t *loop;
1076 err = js_get_env_loop(env, &loop);
1077 assert(err == 0);
1078
1079 err = fs_ext_swap(
1080 loop,
1081 (fs_ext_swap_t *) req,
1082 (const char *) from,
1083 (const char *) to,
1084 fs_ext_js__on_swap
1085 );
1086
1087 if (err < 0) {
1088 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1089 assert(err == 0);
1090
1091 return NULL;
1092 }
1093
1094 req->env = env;
1095 req->exiting = false;
1096
1097 err = js_create_reference(env, argv[2], 1, &req->ctx);
1098 assert(err == 0);
1099
1100 err = js_create_reference(env, argv[3], 1, &req->cb);
1101 assert(err == 0);
1102
1103 err = js_add_deferred_teardown_callback(env, fs_ext_js__on_teardown, (void *) &req->exiting, &req->teardown);
1104 assert(err == 0);
1105
1106 return handle;
1107}
1108
1109static js_value_t *
1110fs_ext_js_get_attr(js_env_t *env, js_callback_info_t *info) {
1111 int err;
1112
1113 size_t argc = 4;
1114 js_value_t *argv[4];
1115
1116 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1117 assert(err == 0);
1118
1119 assert(argc == 4);
1120
1121 int64_t fd;
1122 err = js_get_value_int64(env, argv[0], &fd);
1123 assert(err == 0);
1124
1125 size_t name_len;
1126 err = js_get_value_string_utf8(env, argv[1], NULL, 0, &name_len);
1127 assert(err == 0);
1128
1129 name_len += 1 /* NULL */;
1130
1131 utf8_t *name = malloc(name_len);
1132 err = js_get_value_string_utf8(env, argv[1], name, name_len, NULL);
1133 assert(err == 0);
1134
1135 js_value_t *handle;
1136
1137 fs_ext_js_get_attr_t *req;
1138 err = js_create_arraybuffer(env, sizeof(fs_ext_js_get_attr_t), (void **) &req, &handle);
1139 assert(err == 0);
1140
1141 uv_loop_t *loop;
1142 err = js_get_env_loop(env, &loop);
1143 assert(err == 0);
1144
1145 err = fs_ext_get_attr(
1146 loop,
1147 (fs_ext_get_attr_t *) req,
1148 uv_get_osfhandle(fd),
1149 (const char *) name,
1150 fs_ext_js__on_get_attr
1151 );
1152
1153 free(name);
1154
1155 if (err < 0) {
1156 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1157 assert(err == 0);
1158
1159 return NULL;
1160 }
1161
1162 req->env = env;
1163 req->exiting = false;
1164
1165 err = js_create_reference(env, argv[2], 1, &req->ctx);
1166 assert(err == 0);
1167
1168 err = js_create_reference(env, argv[3], 1, &req->cb);
1169 assert(err == 0);
1170
1171 err = js_add_deferred_teardown_callback(env, fs_ext_js__on_teardown, (void *) &req->exiting, &req->teardown);
1172 assert(err == 0);
1173
1174 return handle;
1175}
1176
1177static js_value_t *
1178fs_ext_js_set_attr(js_env_t *env, js_callback_info_t *info) {
1179 int err;
1180
1181 size_t argc = 7;
1182 js_value_t *argv[7];
1183
1184 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1185 assert(err == 0);
1186
1187 assert(argc == 7);
1188
1189 int64_t fd;
1190 err = js_get_value_int64(env, argv[0], &fd);
1191 assert(err == 0);
1192
1193 size_t name_len;
1194 err = js_get_value_string_utf8(env, argv[1], NULL, 0, &name_len);
1195 assert(err == 0);
1196
1197 name_len += 1 /* NULL */;
1198
1199 utf8_t *name = malloc(name_len);
1200 err = js_get_value_string_utf8(env, argv[1], name, name_len, NULL);
1201 assert(err == 0);
1202
1203 char *data;
1204 err = js_get_arraybuffer_info(env, argv[2], (void **) &data, NULL);
1205 assert(err == 0);
1206
1207 int64_t data_offset;
1208 err = js_get_value_int64(env, argv[3], &data_offset);
1209 assert(err == 0);
1210
1211 int64_t data_len;
1212 err = js_get_value_int64(env, argv[4], &data_len);
1213 assert(err == 0);
1214
1215 js_value_t *handle;
1216
1217 fs_ext_js_set_attr_t *req;
1218 err = js_create_arraybuffer(env, sizeof(fs_ext_js_set_attr_t), (void **) &req, &handle);
1219 assert(err == 0);
1220
1221 uv_loop_t *loop;
1222 err = js_get_env_loop(env, &loop);
1223 assert(err == 0);
1224
1225 uv_buf_t buf = uv_buf_init(&data[data_offset], data_len);
1226
1227 err = fs_ext_set_attr(
1228 loop,
1229 (fs_ext_set_attr_t *) req,
1230 uv_get_osfhandle(fd),
1231 (const char *) name,
1232 &buf,
1233 fs_ext_js__on_set_attr
1234 );
1235
1236 free(name);
1237
1238 if (err < 0) {
1239 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1240 assert(err == 0);
1241
1242 return NULL;
1243 }
1244
1245 req->env = env;
1246 req->exiting = false;
1247
1248 err = js_create_reference(env, argv[5], 1, &req->ctx);
1249 assert(err == 0);
1250
1251 err = js_create_reference(env, argv[6], 1, &req->cb);
1252 assert(err == 0);
1253
1254 err = js_add_deferred_teardown_callback(env, fs_ext_js__on_teardown, (void *) &req->exiting, &req->teardown);
1255 assert(err == 0);
1256
1257 return handle;
1258}
1259
1260static js_value_t *
1261fs_ext_js_remove_attr(js_env_t *env, js_callback_info_t *info) {
1262 int err;
1263
1264 size_t argc = 4;
1265 js_value_t *argv[4];
1266
1267 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1268 assert(err == 0);
1269
1270 assert(argc == 4);
1271
1272 int64_t fd;
1273 err = js_get_value_int64(env, argv[0], &fd);
1274 assert(err == 0);
1275
1276 size_t name_len;
1277 err = js_get_value_string_utf8(env, argv[1], NULL, 0, &name_len);
1278 assert(err == 0);
1279
1280 name_len += 1 /* NULL */;
1281
1282 utf8_t *name = malloc(name_len);
1283 err = js_get_value_string_utf8(env, argv[1], name, name_len, NULL);
1284 assert(err == 0);
1285
1286 js_value_t *handle;
1287
1288 fs_ext_js_remove_attr_t *req;
1289 err = js_create_arraybuffer(env, sizeof(fs_ext_js_remove_attr_t), (void **) &req, &handle);
1290 assert(err == 0);
1291
1292 uv_loop_t *loop;
1293 err = js_get_env_loop(env, &loop);
1294 assert(err == 0);
1295
1296 err = fs_ext_remove_attr(
1297 loop,
1298 (fs_ext_remove_attr_t *) req,
1299 uv_get_osfhandle(fd),
1300 (const char *) name,
1301 fs_ext_js__on_remove_attr
1302 );
1303
1304 free(name);
1305
1306 if (err < 0) {
1307 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1308 assert(err == 0);
1309
1310 return NULL;
1311 }
1312
1313 req->env = env;
1314 req->exiting = false;
1315
1316 err = js_create_reference(env, argv[2], 1, &req->ctx);
1317 assert(err == 0);
1318
1319 err = js_create_reference(env, argv[3], 1, &req->cb);
1320 assert(err == 0);
1321
1322 err = js_add_deferred_teardown_callback(env, fs_ext_js__on_teardown, (void *) &req->exiting, &req->teardown);
1323 assert(err == 0);
1324
1325 return handle;
1326}
1327
1328static js_value_t *
1329fs_ext_js_list_attrs(js_env_t *env, js_callback_info_t *info) {
1330 int err;
1331
1332 size_t argc = 3;
1333 js_value_t *argv[3];
1334
1335 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1336 assert(err == 0);
1337
1338 assert(argc == 3);
1339
1340 int64_t fd;
1341 err = js_get_value_int64(env, argv[0], &fd);
1342 assert(err == 0);
1343
1344 js_value_t *handle;
1345
1346 fs_ext_js_list_attrs_t *req;
1347 err = js_create_arraybuffer(env, sizeof(fs_ext_js_list_attrs_t), (void **) &req, &handle);
1348 assert(err == 0);
1349
1350 uv_loop_t *loop;
1351 err = js_get_env_loop(env, &loop);
1352 assert(err == 0);
1353
1354 err = fs_ext_list_attrs(
1355 loop,
1356 (fs_ext_list_attrs_t *) req,
1357 uv_get_osfhandle(fd),
1358 fs_ext_js__on_list_attrs
1359 );
1360
1361 if (err < 0) {
1362 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1363 assert(err == 0);
1364
1365 return NULL;
1366 }
1367
1368 req->env = env;
1369 req->exiting = false;
1370
1371 err = js_create_reference(env, argv[1], 1, &req->ctx);
1372 assert(err == 0);
1373
1374 err = js_create_reference(env, argv[2], 1, &req->cb);
1375 assert(err == 0);
1376
1377 err = js_add_deferred_teardown_callback(env, fs_ext_js__on_teardown, (void *) &req->exiting, &req->teardown);
1378 assert(err == 0);
1379
1380 return handle;
1381}
1382
1383static js_value_t *
1384fs_ext_js_exports(js_env_t *env, js_value_t *exports) {
1385 int err;
1386
1387#define V(name, fn) \
1388 { \
1389 js_value_t *val; \
1390 err = js_create_function(env, name, -1, fn, NULL, &val); \
1391 assert(err == 0); \
1392 err = js_set_named_property(env, exports, name, val); \
1393 assert(err == 0); \
1394 }
1395
1396 V("tryLock", fs_ext_js_try_lock)
1397 V("waitForLock", fs_ext_js_wait_for_lock)
1398 V("tryDowngradeLock", fs_ext_js_try_downgrade_lock)
1399 V("waitForDowngradeLock", fs_ext_js_wait_for_downgrade_lock)
1400 V("tryUpgradeLock", fs_ext_js_try_upgrade_lock)
1401 V("waitForUpgradeLock", fs_ext_js_wait_for_upgrade_lock)
1402 V("unlock", fs_ext_js_unlock)
1403 V("trim", fs_ext_js_trim)
1404 V("sparse", fs_ext_js_sparse)
1405 V("swap", fs_ext_js_swap)
1406 V("getAttr", fs_ext_js_get_attr)
1407 V("setAttr", fs_ext_js_set_attr)
1408 V("removeAttr", fs_ext_js_remove_attr)
1409 V("listAttrs", fs_ext_js_list_attrs)
1410#undef V
1411
1412 return exports;
1413}
1414
1415BARE_MODULE(fs_ext_js, fs_ext_js_exports)
node_modules/fs-native-extensions/binding.js +3 -0
……@@ -0,0 +1,3 @@
1require.addon = require('require-addon')
2
3module.exports = require.addon('.', __filename)
node_modules/fs-native-extensions/include/fs-ext.h +193 -0
……@@ -0,0 +1,193 @@
1#ifndef FS_EXT_H
2#define FS_EXT_H
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8#include <stdint.h>
9#include <uv.h>
10
11// Requests
12
13typedef struct fs_ext_lock_s fs_ext_lock_t;
14typedef struct fs_ext_trim_s fs_ext_trim_t;
15typedef struct fs_ext_sparse_s fs_ext_sparse_t;
16typedef struct fs_ext_swap_s fs_ext_swap_t;
17typedef struct fs_ext_get_attr_s fs_ext_get_attr_t;
18typedef struct fs_ext_set_attr_s fs_ext_set_attr_t;
19typedef struct fs_ext_remove_attr_s fs_ext_remove_attr_t;
20typedef struct fs_ext_list_attrs_s fs_ext_list_attrs_t;
21
22// Callbacks
23
24typedef void (*fs_ext_lock_cb)(fs_ext_lock_t *req, int status);
25typedef void (*fs_ext_trim_cb)(fs_ext_trim_t *req, int status);
26typedef void (*fs_ext_sparse_cb)(fs_ext_sparse_t *req, int status);
27typedef void (*fs_ext_swap_cb)(fs_ext_swap_t *req, int status);
28typedef void (*fs_ext_get_attr_cb)(fs_ext_get_attr_t *req, int status, const uv_buf_t *value);
29typedef void (*fs_ext_set_attr_cb)(fs_ext_set_attr_t *req, int status);
30typedef void (*fs_ext_remove_attr_cb)(fs_ext_remove_attr_t *req, int status);
31typedef void (*fs_ext_list_attrs_cb)(fs_ext_list_attrs_t *req, int status, const char *attrs[], ssize_t len);
32
33typedef enum {
34 FS_EXT_RDLOCK = 1,
35 FS_EXT_WRLOCK,
36} fs_ext_lock_type_t;
37
38struct fs_ext_lock_s {
39 uv_thread_t thread;
40 uv_async_t signal;
41
42 uv_os_fd_t fd;
43 uint64_t offset;
44 uint64_t length;
45 fs_ext_lock_type_t type;
46
47 fs_ext_lock_cb cb;
48
49 int result;
50
51 void *data;
52};
53
54struct fs_ext_trim_s {
55 uv_work_t req;
56
57 uv_os_fd_t fd;
58 uint64_t offset;
59 uint64_t length;
60
61 fs_ext_trim_cb cb;
62
63 int result;
64
65 void *data;
66};
67
68struct fs_ext_sparse_s {
69 uv_work_t req;
70
71 uv_os_fd_t fd;
72
73 fs_ext_sparse_cb cb;
74
75 int result;
76
77 void *data;
78};
79
80struct fs_ext_swap_s {
81 uv_work_t req;
82
83 char *from;
84 char *to;
85
86 fs_ext_swap_cb cb;
87
88 int result;
89
90 void *data;
91};
92
93struct fs_ext_get_attr_s {
94 uv_work_t req;
95
96 uv_os_fd_t fd;
97 char *name;
98 uv_buf_t value;
99
100 fs_ext_get_attr_cb cb;
101
102 int result;
103
104 void *data;
105};
106
107struct fs_ext_set_attr_s {
108 uv_work_t req;
109
110 uv_os_fd_t fd;
111 char *name;
112 uv_buf_t value;
113
114 fs_ext_set_attr_cb cb;
115
116 int result;
117
118 void *data;
119};
120
121struct fs_ext_remove_attr_s {
122 uv_work_t req;
123
124 uv_os_fd_t fd;
125 char *name;
126
127 fs_ext_remove_attr_cb cb;
128
129 int result;
130
131 void *data;
132};
133
134struct fs_ext_list_attrs_s {
135 uv_work_t req;
136
137 uv_os_fd_t fd;
138 char *names;
139 size_t length;
140
141 fs_ext_list_attrs_cb cb;
142
143 int result;
144
145 void *data;
146};
147
148int
149fs_ext_try_lock(uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type);
150
151int
152fs_ext_wait_for_lock(uv_loop_t *loop, fs_ext_lock_t *req, uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type, fs_ext_lock_cb cb);
153
154int
155fs_ext_try_downgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length);
156
157int
158fs_ext_wait_for_downgrade_lock(uv_loop_t *loop, fs_ext_lock_t *req, uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_cb cb);
159
160int
161fs_ext_try_upgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length);
162
163int
164fs_ext_wait_for_upgrade_lock(uv_loop_t *loop, fs_ext_lock_t *req, uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_cb cb);
165
166int
167fs_ext_unlock(uv_os_fd_t fd, uint64_t offset, size_t length);
168
169int
170fs_ext_trim(uv_loop_t *loop, fs_ext_trim_t *req, uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_trim_cb cb);
171
172int
173fs_ext_sparse(uv_loop_t *loop, fs_ext_sparse_t *req, uv_os_fd_t fd, fs_ext_sparse_cb cb);
174
175int
176fs_ext_swap(uv_loop_t *loop, fs_ext_swap_t *req, const char *from, const char *to, fs_ext_swap_cb cb);
177
178int
179fs_ext_get_attr(uv_loop_t *loop, fs_ext_get_attr_t *req, uv_os_fd_t fd, const char *name, fs_ext_get_attr_cb cb);
180
181int
182fs_ext_set_attr(uv_loop_t *loop, fs_ext_set_attr_t *req, uv_os_fd_t fd, const char *name, const uv_buf_t *value, fs_ext_set_attr_cb cb);
183
184int
185fs_ext_remove_attr(uv_loop_t *loop, fs_ext_remove_attr_t *req, uv_os_fd_t fd, const char *name, fs_ext_remove_attr_cb cb);
186
187int
188fs_ext_list_attrs(uv_loop_t *loop, fs_ext_list_attrs_t *req, uv_os_fd_t fd, fs_ext_list_attrs_cb cb);
189
190#ifdef __cplusplus
191}
192#endif
193#endif // FS_EXT_H
node_modules/fs-native-extensions/index.js +318 -0
……@@ -0,0 +1,318 @@
1const { isWindows } = require('which-runtime')
2const binding = require('./binding')
3
4function onwork(err, result) {
5 if (err) this.reject(err)
6 else this.resolve(result)
7}
8
9exports.tryLock = function tryLock(fd, offset = 0, length = 0, opts = {}) {
10 if (typeof offset === 'object') {
11 opts = offset
12 offset = 0
13 }
14
15 if (typeof length === 'object') {
16 opts = length
17 length = 0
18 }
19
20 if (typeof opts !== 'object' || opts === null) {
21 opts = {}
22 }
23
24 try {
25 binding.tryLock(fd, offset, length, opts.shared !== true)
26 } catch (err) {
27 if (err.code === 'EAGAIN') return false
28 throw err
29 }
30
31 return true
32}
33
34exports.waitForLock = function waitForLock(
35 fd,
36 offset = 0,
37 length = 0,
38 opts = {}
39) {
40 if (typeof offset === 'object') {
41 opts = offset
42 offset = 0
43 }
44
45 if (typeof length === 'object') {
46 opts = length
47 length = 0
48 }
49
50 if (typeof opts !== 'object' || opts === null) {
51 opts = {}
52 }
53
54 const req = {
55 handle: null,
56 resolve: null,
57 reject: null
58 }
59
60 const promise = new Promise((resolve, reject) => {
61 req.resolve = resolve
62 req.reject = reject
63 })
64
65 try {
66 req.handle = binding.waitForLock(
67 fd,
68 offset,
69 length,
70 opts.shared !== true,
71 req,
72 onwork
73 )
74 } catch (err) {
75 return Promise.reject(err)
76 }
77
78 return promise
79}
80
81exports.tryDowngradeLock = function tryDowngradeLock(
82 fd,
83 offset = 0,
84 length = 0
85) {
86 try {
87 binding.tryDowngradeLock(fd, offset, length)
88 } catch (err) {
89 if (err.code === 'EAGAIN') return false
90 throw err
91 }
92
93 return true
94}
95
96exports.waitForDowngradeLock = function downgradeLock(
97 fd,
98 offset = 0,
99 length = 0
100) {
101 const req = {
102 handle: null,
103 resolve: null,
104 reject: null
105 }
106
107 const promise = new Promise((resolve, reject) => {
108 req.resolve = resolve
109 req.reject = reject
110 })
111
112 try {
113 req.handle = binding.waitForDowngradeLock(fd, offset, length, req, onwork)
114 } catch (err) {
115 return Promise.reject(err)
116 }
117
118 return promise
119}
120
121exports.tryUpgradeLock = function tryUpgradeLock(fd, offset = 0, length = 0) {
122 try {
123 binding.tryUpgradeLock(fd, offset, length)
124 } catch (err) {
125 if (err.code === 'EAGAIN') return false
126 throw err
127 }
128
129 return true
130}
131
132exports.waitForUpgradeLock = function upgradeLock(fd, offset = 0, length = 0) {
133 const req = {
134 handle: null,
135 resolve: null,
136 reject: null
137 }
138
139 const promise = new Promise((resolve, reject) => {
140 req.resolve = resolve
141 req.reject = reject
142 })
143
144 try {
145 req.handle = binding.waitForUpgradeLock(fd, offset, length, req, onwork)
146 } catch (err) {
147 return Promise.reject(err)
148 }
149
150 return promise
151}
152
153exports.unlock = function unlock(fd, offset = 0, length = 0) {
154 binding.unlock(fd, offset, length)
155}
156
157exports.trim = function trim(fd, offset, length) {
158 const req = {
159 handle: null,
160 resolve: null,
161 reject: null
162 }
163
164 const promise = new Promise((resolve, reject) => {
165 req.resolve = resolve
166 req.reject = reject
167 })
168
169 try {
170 req.handle = binding.trim(fd, offset, length, req, onwork)
171 } catch (err) {
172 return Promise.reject(err)
173 }
174
175 return promise
176}
177
178exports.sparse = function sparse(fd) {
179 // Short circuit on everything but Windows
180 if (!isWindows) return Promise.resolve()
181
182 const req = {
183 handle: null,
184 resolve: null,
185 reject: null
186 }
187
188 const promise = new Promise((resolve, reject) => {
189 req.resolve = resolve
190 req.reject = reject
191 })
192
193 try {
194 req.handle = binding.sparse(fd, req, onwork)
195 } catch (err) {
196 return Promise.reject(err)
197 }
198
199 return promise
200}
201
202exports.swap = function swap(from, to) {
203 const req = {
204 handle: null,
205 resolve: null,
206 reject: null
207 }
208
209 const promise = new Promise((resolve, reject) => {
210 req.resolve = resolve
211 req.reject = reject
212 })
213
214 try {
215 req.handle = binding.swap(from, to, req, onwork)
216 } catch (err) {
217 return Promise.reject(err)
218 }
219
220 return promise
221}
222
223exports.getAttr = function getAttr(fd, name) {
224 const req = {
225 handle: null,
226 resolve: null,
227 reject: null
228 }
229
230 const promise = new Promise((resolve, reject) => {
231 req.resolve = resolve
232 req.reject = reject
233 })
234
235 try {
236 req.handle = binding.getAttr(fd, name, req, onwork)
237 } catch (err) {
238 return Promise.reject(err)
239 }
240
241 return promise.then((buffer) =>
242 buffer === null ? null : Buffer.from(buffer)
243 )
244}
245
246exports.setAttr = function setAttr(fd, name, value, encoding) {
247 if (typeof value === 'string') value = Buffer.from(value, encoding)
248
249 const req = {
250 value,
251 handle: null,
252 resolve: null,
253 reject: null
254 }
255
256 const promise = new Promise((resolve, reject) => {
257 req.resolve = resolve
258 req.reject = reject
259 })
260
261 try {
262 req.handle = binding.setAttr(
263 fd,
264 name,
265 value.buffer,
266 value.byteOffset,
267 value.byteLength,
268 req,
269 onwork
270 )
271 } catch (err) {
272 return Promise.reject(err)
273 }
274
275 return promise
276}
277
278exports.removeAttr = function removeAttr(fd, name) {
279 const req = {
280 handle: null,
281 resolve: null,
282 reject: null
283 }
284
285 const promise = new Promise((resolve, reject) => {
286 req.resolve = resolve
287 req.reject = reject
288 })
289
290 try {
291 req.handle = binding.removeAttr(fd, name, req, onwork)
292 } catch (err) {
293 return Promise.reject(err)
294 }
295
296 return promise
297}
298
299exports.listAttrs = function listAttrs(fd) {
300 const req = {
301 handle: null,
302 resolve: null,
303 reject: null
304 }
305
306 const promise = new Promise((resolve, reject) => {
307 req.resolve = resolve
308 req.reject = reject
309 })
310
311 try {
312 req.handle = binding.listAttrs(fd, req, onwork)
313 } catch (err) {
314 return Promise.reject(err)
315 }
316
317 return promise
318}
node_modules/fs-native-extensions/package.json +70 -0
……@@ -0,0 +1,70 @@
1{
2 "name": "fs-native-extensions",
3 "version": "1.4.5",
4 "description": "Native file system extensions for advanced file operations",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "macros.h",
9 "binding.c",
10 "binding.js",
11 "CMakeLists.txt",
12 "include",
13 "src",
14 "prebuilds"
15 ],
16 "imports": {
17 "child_process": {
18 "bare": "bare-subprocess",
19 "default": "child_process"
20 },
21 "fs": {
22 "bare": "bare-fs",
23 "default": "fs"
24 },
25 "fs/*": {
26 "bare": "bare-fs/*",
27 "default": "fs/*"
28 },
29 "path": {
30 "bare": "bare-path",
31 "default": "path"
32 }
33 },
34 "addon": true,
35 "scripts": {
36 "test": "npm run lint && npm run test:bare && npm run test:node",
37 "test:bare": "bare test.js",
38 "test:node": "node test.js",
39 "lint": "prettier . --check"
40 },
41 "repository": {
42 "type": "git",
43 "url": "git+https://github.com/holepunchto/fs-native-extensions.git"
44 },
45 "author": "Kasper Isager Dalsgarð <kasper@funktionel.co>",
46 "license": "Apache-2.0",
47 "bugs": {
48 "url": "https://github.com/holepunchto/fs-native-extensions/issues"
49 },
50 "homepage": "https://github.com/holepunchto/fs-native-extensions#readme",
51 "dependencies": {
52 "require-addon": "^1.1.0",
53 "which-runtime": "^1.2.0"
54 },
55 "devDependencies": {
56 "bare-compat-napi": "^1.3.8",
57 "bare-fs": "^4.4.4",
58 "bare-path": "^3.0.0",
59 "bare-subprocess": "^4.0.5",
60 "brittle": "^3.1.1",
61 "cmake-bare": "^1.1.10",
62 "cmake-fetch": "^1.4.7",
63 "cmake-napi": "^1.0.5",
64 "cmake-npm": "^1.1.0",
65 "minimist": "^1.2.6",
66 "prettier": "^3.5.3",
67 "prettier-config-standard": "^7.0.0",
68 "test-tmp": "^1.2.1"
69 }
70}
node_modules/fs-native-extensions/prebuilds/android-arm/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/android-arm/fs-native-extensions.node +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/android-arm64/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/android-arm64/fs-native-extensions.node +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/android-ia32/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/android-ia32/fs-native-extensions.node +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/android-x64/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/android-x64/fs-native-extensions.node +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/darwin-arm64/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/darwin-arm64/fs-native-extensions.node +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/darwin-x64/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/darwin-x64/fs-native-extensions.node +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/ios-arm64-simulator/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/ios-arm64/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/ios-x64-simulator/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/linux-arm64/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/linux-arm64/fs-native-extensions.node +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/linux-x64/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/linux-x64/fs-native-extensions.node +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/win32-arm64/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/win32-arm64/fs-native-extensions.node +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/win32-x64/fs-native-extensions.bare +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/prebuilds/win32-x64/fs-native-extensions.node +0 -0
(no content changes — binary or rename)
node_modules/fs-native-extensions/src/apple.c +197 -0
……@@ -0,0 +1,197 @@
1#include <errno.h>
2#include <fcntl.h>
3#include <stdint.h>
4#include <stdlib.h>
5#include <string.h>
6#include <sys/xattr.h>
7#include <unistd.h>
8#include <uv.h>
9
10#include "../include/fs-ext.h"
11
12#include "platform.h"
13
14int
15fs_ext__try_lock(uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type) {
16 if (offset != 0 || length != 0) return UV_EINVAL;
17
18 int res = flock(fd, (type == FS_EXT_WRLOCK ? LOCK_EX : LOCK_SH) | LOCK_NB);
19
20 return res == -1 ? uv_translate_sys_error(errno) : res;
21}
22
23int
24fs_ext__wait_for_lock(uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type) {
25 if (offset != 0 || length != 0) return UV_EINVAL;
26
27 int res = flock(fd, type == FS_EXT_WRLOCK ? LOCK_EX : LOCK_SH);
28
29 return res == -1 ? uv_translate_sys_error(errno) : res;
30}
31
32int
33fs_ext__unlock(uv_os_fd_t fd, uint64_t offset, size_t length) {
34 if (offset != 0 || length != 0) return UV_EINVAL;
35
36 int res = flock(fd, LOCK_UN);
37
38 return res == -1 ? uv_translate_sys_error(errno) : res;
39}
40
41static inline size_t
42fs_ext__align_up(size_t n, size_t align) {
43 return (n + (align - 1)) & -align;
44}
45
46static inline size_t
47fs_ext__align_down(size_t n, size_t align) {
48 return n & -align;
49}
50
51static inline size_t
52fs_ext__min(size_t a, size_t b) {
53 return a < b ? a : b;
54}
55
56int
57fs_ext__trim(uv_os_fd_t fd, uint64_t offset, size_t length) {
58 struct stat st;
59
60 int res = fstat(fd, &st);
61
62 if (res == -1) return uv_translate_sys_error(errno);
63
64 size_t align = st.st_blksize;
65
66 size_t aligned_offset = fs_ext__align_up(offset, align);
67
68 if (aligned_offset != offset) {
69 size_t zero_length = fs_ext__min(length, aligned_offset - offset);
70
71 void *buf = calloc(1, zero_length);
72
73 ssize_t res = pwrite(fd, buf, zero_length, offset);
74
75 free(buf);
76
77 if (res == -1) return uv_translate_sys_error(errno);
78
79 offset += zero_length;
80 length -= zero_length;
81 }
82
83 size_t aligned_length = fs_ext__align_down(length, align);
84
85 if (aligned_length >= align) {
86 struct fpunchhole data = {
87 .fp_flags = 0,
88 .reserved = 0,
89 .fp_offset = offset,
90 .fp_length = aligned_length,
91 };
92
93 int res = fcntl(fd, F_PUNCHHOLE, &data);
94
95 if (res == -1) return uv_translate_sys_error(errno);
96
97 offset += aligned_length;
98 length -= aligned_length;
99 }
100
101 if (length > 0) {
102 void *buf = calloc(1, length);
103
104 ssize_t res = pwrite(fd, buf, length, offset);
105
106 free(buf);
107
108 if (res == -1) return uv_translate_sys_error(errno);
109 }
110
111 return 0;
112}
113
114int
115fs_ext__swap(const char *from, const char *to) {
116 int res = renameatx_np(AT_FDCWD, from, AT_FDCWD, to, RENAME_SWAP);
117
118 return res == -1 ? uv_translate_sys_error(errno) : res;
119}
120
121int
122fs_ext__get_attr(uv_os_fd_t fd, const char *name, uv_buf_t *value) {
123 int res = fgetxattr(fd, name, NULL, 0, 0, 0);
124
125 if (res == -1) {
126 if (errno == ENOATTR) return UV_ENODATA;
127
128 return uv_translate_sys_error(errno);
129 }
130
131 *value = uv_buf_init(malloc(res), res);
132
133 res = fgetxattr(fd, name, value->base, value->len, 0, 0);
134
135 return res == -1 ? uv_translate_sys_error(errno) : 0;
136}
137
138int
139fs_ext__set_attr(uv_os_fd_t fd, const char *name, const uv_buf_t *value) {
140 int res = fsetxattr(fd, name, value->base, value->len, 0, 0);
141
142 return res == -1 ? uv_translate_sys_error(errno) : 0;
143}
144
145int
146fs_ext__remove_attr(uv_os_fd_t fd, const char *name) {
147 int res = fremovexattr(fd, name, 0);
148
149 if (res == -1) {
150 if (errno == ENOATTR) return UV_ENODATA;
151
152 return uv_translate_sys_error(errno);
153 }
154
155 return 0;
156}
157
158int
159fs_ext__list_attrs(uv_os_fd_t fd, char **names, size_t *length) {
160 int res = flistxattr(fd, NULL, 0, 0);
161
162 if (res == -1) return uv_translate_sys_error(errno);
163
164 *names = malloc(res);
165 *length = res;
166
167 res = flistxattr(fd, *names, *length, 0);
168
169 if (res == -1) return uv_translate_sys_error(errno);
170
171 size_t i = 0, j = 0, n = *length;
172
173 *length = 0;
174
175 while (i < n) {
176 i += strlen(*names + i) + 1;
177 *length += 1;
178 }
179
180 size_t offset = *length * sizeof(char *);
181
182 *names = realloc(*names, offset + n);
183
184 memmove(*names + offset, *names, n);
185
186 i = 0;
187
188 while (i < n) {
189 char *name = *names + offset + i;
190 i += strlen(name) + 1;
191
192 memcpy(*names + j, &name, sizeof(char *));
193 j += sizeof(char *);
194 }
195
196 return 0;
197}
node_modules/fs-native-extensions/src/linux.c +146 -0
……@@ -0,0 +1,146 @@
1#define _GNU_SOURCE
2
3#include <errno.h>
4#include <fcntl.h>
5#include <stdint.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/syscall.h>
9#include <sys/xattr.h>
10#include <unistd.h>
11#include <uv.h>
12
13#include "../include/fs-ext.h"
14
15#include "platform.h"
16
17#ifndef RENAME_EXCHANGE
18#define RENAME_EXCHANGE 2
19#endif
20
21int
22fs_ext__try_lock(uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type) {
23 struct flock data = {
24 .l_start = offset,
25 .l_len = length,
26 .l_pid = 0,
27 .l_type = type == FS_EXT_WRLOCK ? F_WRLCK : F_RDLCK,
28 .l_whence = SEEK_SET,
29 };
30
31 int res = fcntl(fd, F_OFD_SETLK, &data);
32
33 return res == -1 ? uv_translate_sys_error(errno) : res;
34}
35
36int
37fs_ext__wait_for_lock(uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type) {
38 struct flock data = {
39 .l_start = offset,
40 .l_len = length,
41 .l_pid = 0,
42 .l_type = type == FS_EXT_WRLOCK ? F_WRLCK : F_RDLCK,
43 .l_whence = SEEK_SET,
44 };
45
46 int res = fcntl(fd, F_OFD_SETLKW, &data);
47
48 return res == -1 ? uv_translate_sys_error(errno) : res;
49}
50
51int
52fs_ext__unlock(uv_os_fd_t fd, uint64_t offset, size_t length) {
53 struct flock data = {
54 .l_start = offset,
55 .l_len = length,
56 .l_pid = 0,
57 .l_type = F_UNLCK,
58 .l_whence = SEEK_SET,
59 };
60
61 int res = fcntl(fd, F_OFD_SETLK, &data);
62
63 return res == -1 ? uv_translate_sys_error(errno) : res;
64}
65
66int
67fs_ext__trim(uv_os_fd_t fd, uint64_t offset, size_t length) {
68 int res = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, length);
69
70 return res == -1 ? uv_translate_sys_error(errno) : res;
71}
72
73int
74fs_ext__swap(const char *from, const char *to) {
75 int res = syscall(SYS_renameat2, AT_FDCWD, from, AT_FDCWD, to, RENAME_EXCHANGE);
76
77 return res == -1 ? uv_translate_sys_error(errno) : res;
78}
79
80int
81fs_ext__get_attr(uv_os_fd_t fd, const char *name, uv_buf_t *value) {
82 int res = fgetxattr(fd, name, NULL, 0);
83
84 if (res == -1) return uv_translate_sys_error(errno);
85
86 *value = uv_buf_init(malloc(res), res);
87
88 res = fgetxattr(fd, name, value->base, value->len);
89
90 return res == -1 ? uv_translate_sys_error(errno) : 0;
91}
92
93int
94fs_ext__set_attr(uv_os_fd_t fd, const char *name, const uv_buf_t *value) {
95 int res = fsetxattr(fd, name, value->base, value->len, 0);
96
97 return res == -1 ? uv_translate_sys_error(errno) : 0;
98}
99
100int
101fs_ext__remove_attr(uv_os_fd_t fd, const char *name) {
102 int res = fremovexattr(fd, name);
103
104 return res == -1 ? uv_translate_sys_error(errno) : 0;
105}
106
107int
108fs_ext__list_attrs(uv_os_fd_t fd, char **names, size_t *length) {
109 int res = flistxattr(fd, NULL, 0);
110
111 if (res == -1) return uv_translate_sys_error(errno);
112
113 *names = malloc(res);
114 *length = res;
115
116 res = flistxattr(fd, *names, *length);
117
118 if (res == -1) return uv_translate_sys_error(errno);
119
120 size_t i = 0, j = 0, n = *length;
121
122 *length = 0;
123
124 while (i < n) {
125 i += strlen(*names + i) + 1;
126 *length += 1;
127 }
128
129 size_t offset = *length * sizeof(char *);
130
131 *names = realloc(*names, offset + n);
132
133 memmove(*names + offset, *names, n);
134
135 i = 0;
136
137 while (i < n) {
138 char *name = *names + offset + i;
139 i += strlen(name) + 1;
140
141 memcpy(*names + j, &name, sizeof(char *));
142 j += sizeof(char *);
143 }
144
145 return 0;
146}
node_modules/fs-native-extensions/src/platform.h +51 -0
……@@ -0,0 +1,51 @@
1#ifndef FS_EXT_PLATFORM_H
2#define FS_EXT_PLATFORM_H
3
4#include <stdint.h>
5#include <uv.h>
6
7#include "../include/fs-ext.h"
8
9int
10fs_ext__try_lock(uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type);
11
12int
13fs_ext__wait_for_lock(uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type);
14
15int
16fs_ext__try_downgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length);
17
18int
19fs_ext__wait_for_downgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length);
20
21int
22fs_ext__try_upgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length);
23
24int
25fs_ext__wait_for_upgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length);
26
27int
28fs_ext__unlock(uv_os_fd_t fd, uint64_t offset, size_t length);
29
30int
31fs_ext__trim(uv_os_fd_t fd, uint64_t offset, size_t length);
32
33int
34fs_ext__sparse(uv_os_fd_t fd);
35
36int
37fs_ext__swap(const char *from, const char *to);
38
39int
40fs_ext__get_attr(uv_os_fd_t fd, const char *name, uv_buf_t *value);
41
42int
43fs_ext__set_attr(uv_os_fd_t fd, const char *name, const uv_buf_t *value);
44
45int
46fs_ext__remove_attr(uv_os_fd_t fd, const char *name);
47
48int
49fs_ext__list_attrs(uv_os_fd_t fd, char **names, size_t *length);
50
51#endif // FS_EXT_PLATFORM_H
node_modules/fs-native-extensions/src/posix.c +33 -0
……@@ -0,0 +1,33 @@
1#include <errno.h>
2#include <fcntl.h>
3#include <stdint.h>
4#include <uv.h>
5
6#include "../include/fs-ext.h"
7
8#include "platform.h"
9
10int
11fs_ext__try_downgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length) {
12 return fs_ext__try_lock(fd, offset, length, FS_EXT_RDLOCK);
13}
14
15int
16fs_ext__wait_for_downgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length) {
17 return fs_ext__wait_for_lock(fd, offset, length, FS_EXT_RDLOCK);
18}
19
20int
21fs_ext__try_upgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length) {
22 return fs_ext__try_lock(fd, offset, length, FS_EXT_WRLOCK);
23}
24
25int
26fs_ext__wait_for_upgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length) {
27 return fs_ext__wait_for_lock(fd, offset, length, FS_EXT_WRLOCK);
28}
29
30int
31fs_ext__sparse(uv_os_fd_t fd) {
32 return 0;
33}
node_modules/fs-native-extensions/src/shared.c +397 -0
……@@ -0,0 +1,397 @@
1#include <assert.h>
2#include <stdint.h>
3#include <stdlib.h>
4#include <string.h>
5#include <uv.h>
6
7#include "../include/fs-ext.h"
8
9#include "platform.h"
10
11int
12fs_ext_try_lock(uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type) {
13 int err = fs_ext__try_lock(fd, offset, length, type);
14
15 if (err == UV_EACCES || err == UV_EAGAIN || err == UV_EBUSY) {
16 err = UV_EAGAIN;
17 }
18
19 return err;
20}
21
22static void
23fs_ext__lock_close(uv_handle_t *handle) {
24 fs_ext_lock_t *r = (fs_ext_lock_t *) handle->data;
25
26 if (r->cb) r->cb(r, r->result);
27}
28
29static void
30fs_ext__lock_after_work(uv_async_t *signal) {
31 int err;
32
33 fs_ext_lock_t *r = (fs_ext_lock_t *) signal->data;
34
35 err = uv_thread_join(&r->thread);
36 assert(err == 0);
37
38 uv_close((uv_handle_t *) signal, fs_ext__lock_close);
39}
40
41static void
42fs_ext__lock_work(void *data) {
43 int err;
44
45 fs_ext_lock_t *r = (fs_ext_lock_t *) data;
46
47 r->result = fs_ext__wait_for_lock(r->fd, r->offset, r->length, r->type);
48
49 err = uv_async_send(&r->signal);
50 assert(err == 0);
51}
52
53int
54fs_ext_wait_for_lock(uv_loop_t *loop, fs_ext_lock_t *req, uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type, fs_ext_lock_cb cb) {
55 int err;
56
57 req->fd = fd;
58 req->offset = offset;
59 req->length = length;
60 req->type = type;
61 req->cb = cb;
62 req->signal.data = (void *) req;
63
64 err = uv_async_init(loop, &req->signal, fs_ext__lock_after_work);
65 assert(err == 0);
66
67 err = uv_thread_create(&req->thread, fs_ext__lock_work, (void *) req);
68 assert(err == 0);
69
70 return 0;
71}
72
73int
74fs_ext_try_downgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length) {
75 int err = fs_ext__try_downgrade_lock(fd, offset, length);
76
77 if (err == UV_EACCES || err == UV_EAGAIN || err == UV_EBUSY) {
78 err = UV_EAGAIN;
79 }
80
81 return err;
82}
83
84static void
85fs_ext__downgrade_lock_work(void *data) {
86 int err;
87
88 fs_ext_lock_t *r = (fs_ext_lock_t *) data;
89
90 r->result = fs_ext__wait_for_downgrade_lock(r->fd, r->offset, r->length);
91
92 err = uv_async_send(&r->signal);
93 assert(err == 0);
94}
95
96int
97fs_ext_wait_for_downgrade_lock(uv_loop_t *loop, fs_ext_lock_t *req, uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_cb cb) {
98 int err;
99
100 req->fd = fd;
101 req->offset = offset;
102 req->length = length;
103 req->type = FS_EXT_RDLOCK;
104 req->cb = cb;
105 req->signal.data = (void *) req;
106
107 err = uv_async_init(loop, &req->signal, fs_ext__lock_after_work);
108 assert(err == 0);
109
110 err = uv_thread_create(&req->thread, fs_ext__downgrade_lock_work, (void *) req);
111 assert(err == 0);
112
113 return 0;
114}
115
116static void
117fs_ext__upgrade_lock_work(void *data) {
118 int err;
119
120 fs_ext_lock_t *r = (fs_ext_lock_t *) data;
121
122 r->result = fs_ext__wait_for_upgrade_lock(r->fd, r->offset, r->length);
123
124 err = uv_async_send(&r->signal);
125 assert(err == 0);
126}
127
128int
129fs_ext_try_upgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length) {
130 int err = fs_ext__try_upgrade_lock(fd, offset, length);
131
132 if (err == UV_EACCES || err == UV_EAGAIN || err == UV_EBUSY) {
133 err = UV_EAGAIN;
134 }
135
136 return err;
137}
138
139int
140fs_ext_wait_for_upgrade_lock(uv_loop_t *loop, fs_ext_lock_t *req, uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_cb cb) {
141 int err;
142
143 req->fd = fd;
144 req->offset = offset;
145 req->length = length;
146 req->type = FS_EXT_WRLOCK;
147 req->cb = cb;
148 req->signal.data = (void *) req;
149
150 err = uv_async_init(loop, &req->signal, fs_ext__lock_after_work);
151 assert(err == 0);
152
153 err = uv_thread_create(&req->thread, fs_ext__upgrade_lock_work, (void *) req);
154 assert(err == 0);
155
156 return 0;
157}
158
159int
160fs_ext_unlock(uv_os_fd_t fd, uint64_t offset, size_t length) {
161 return fs_ext__unlock(fd, offset, length);
162}
163
164static void
165fs_ext__trim_work(uv_work_t *req) {
166 fs_ext_trim_t *r = (fs_ext_trim_t *) req->data;
167
168 r->result = fs_ext__trim(r->fd, r->offset, r->length);
169}
170
171static void
172fs_ext__trim_after_work(uv_work_t *req, int status) {
173 fs_ext_trim_t *r = (fs_ext_trim_t *) req->data;
174
175 if (r->cb) r->cb(r, r->result);
176}
177
178int
179fs_ext_trim(uv_loop_t *loop, fs_ext_trim_t *req, uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_trim_cb cb) {
180 req->fd = fd;
181 req->offset = offset;
182 req->length = length;
183 req->cb = cb;
184 req->req.data = (void *) req;
185
186 return uv_queue_work(loop, &req->req, fs_ext__trim_work, fs_ext__trim_after_work);
187}
188
189static void
190fs_ext__sparse_work(uv_work_t *req) {
191 fs_ext_sparse_t *r = (fs_ext_sparse_t *) req->data;
192
193 r->result = fs_ext__sparse(r->fd);
194}
195
196static void
197fs_ext__sparse_after_work(uv_work_t *req, int status) {
198 fs_ext_sparse_t *r = (fs_ext_sparse_t *) req->data;
199
200 if (r->cb) r->cb(r, r->result);
201}
202
203int
204fs_ext_sparse(uv_loop_t *loop, fs_ext_sparse_t *req, uv_os_fd_t fd, fs_ext_sparse_cb cb) {
205 req->fd = fd;
206 req->cb = cb;
207 req->req.data = (void *) req;
208
209 return uv_queue_work(loop, &req->req, fs_ext__sparse_work, fs_ext__sparse_after_work);
210}
211
212static void
213fs_ext__swap_work(uv_work_t *req) {
214 fs_ext_swap_t *r = (fs_ext_swap_t *) req->data;
215
216 r->result = fs_ext__swap(r->from, r->to);
217}
218
219static void
220fs_ext__swap_after_work(uv_work_t *req, int status) {
221 fs_ext_swap_t *r = (fs_ext_swap_t *) req->data;
222
223 char *from = r->from;
224 char *to = r->to;
225
226 if (r->cb) r->cb(r, r->result);
227
228 free(from);
229 free(to);
230}
231
232int
233fs_ext_swap(uv_loop_t *loop, fs_ext_swap_t *req, const char *from, const char *to, fs_ext_swap_cb cb) {
234 int err;
235
236 req->from = strdup(from);
237 req->to = strdup(to);
238 req->cb = cb;
239 req->req.data = (void *) req;
240
241 err = uv_queue_work(loop, &req->req, fs_ext__swap_work, fs_ext__swap_after_work);
242
243 if (err < 0) {
244 free(req->from);
245 free(req->to);
246
247 return err;
248 }
249
250 return 0;
251}
252
253static void
254fs_ext__get_attr_work(uv_work_t *req) {
255 fs_ext_get_attr_t *r = (fs_ext_get_attr_t *) req->data;
256
257 r->result = fs_ext__get_attr(r->fd, r->name, &r->value);
258}
259
260static void
261fs_ext__get_attr_after_work(uv_work_t *req, int status) {
262 fs_ext_get_attr_t *r = (fs_ext_get_attr_t *) req->data;
263
264 uv_buf_t value = r->value;
265 char *name = r->name;
266
267 if (r->cb) r->cb(r, r->result, &value);
268
269 free(value.base);
270 free(name);
271}
272
273int
274fs_ext_get_attr(uv_loop_t *loop, fs_ext_get_attr_t *req, uv_os_fd_t fd, const char *name, fs_ext_get_attr_cb cb) {
275 int err;
276
277 req->fd = fd;
278 req->name = strdup(name);
279 req->value.base = NULL;
280 req->value.len = 0;
281 req->cb = cb;
282 req->req.data = (void *) req;
283
284 err = uv_queue_work(loop, &req->req, fs_ext__get_attr_work, fs_ext__get_attr_after_work);
285
286 if (err < 0) {
287 free(req->name);
288
289 return err;
290 }
291
292 return 0;
293}
294
295static void
296fs_ext__set_attr_work(uv_work_t *req) {
297 fs_ext_set_attr_t *r = (fs_ext_set_attr_t *) req->data;
298
299 r->result = fs_ext__set_attr(r->fd, r->name, &r->value);
300}
301
302static void
303fs_ext__set_attr_after_work(uv_work_t *req, int status) {
304 fs_ext_set_attr_t *r = (fs_ext_set_attr_t *) req->data;
305
306 char *name = r->name;
307
308 if (r->cb) r->cb(r, r->result);
309
310 free(name);
311}
312
313int
314fs_ext_set_attr(uv_loop_t *loop, fs_ext_set_attr_t *req, uv_os_fd_t fd, const char *name, const uv_buf_t *value, fs_ext_set_attr_cb cb) {
315 int err;
316
317 req->fd = fd;
318 req->name = strdup(name);
319 req->value = *value;
320 req->cb = cb;
321 req->req.data = (void *) req;
322
323 err = uv_queue_work(loop, &req->req, fs_ext__set_attr_work, fs_ext__set_attr_after_work);
324
325 if (err < 0) {
326 free(req->name);
327
328 return err;
329 }
330
331 return 0;
332}
333
334static void
335fs_ext__remove_attr_work(uv_work_t *req) {
336 fs_ext_remove_attr_t *r = (fs_ext_remove_attr_t *) req->data;
337
338 r->result = fs_ext__remove_attr(r->fd, r->name);
339}
340
341static void
342fs_ext__remove_attr_after_work(uv_work_t *req, int status) {
343 fs_ext_remove_attr_t *r = (fs_ext_remove_attr_t *) req->data;
344
345 char *name = r->name;
346
347 if (r->cb) r->cb(r, r->result);
348
349 free(name);
350}
351
352int
353fs_ext_remove_attr(uv_loop_t *loop, fs_ext_remove_attr_t *req, uv_os_fd_t fd, const char *name, fs_ext_remove_attr_cb cb) {
354 int err;
355
356 req->fd = fd;
357 req->name = strdup(name);
358 req->cb = cb;
359 req->req.data = (void *) req;
360
361 err = uv_queue_work(loop, &req->req, fs_ext__remove_attr_work, fs_ext__remove_attr_after_work);
362
363 if (err < 0) {
364 free(req->name);
365
366 return err;
367 }
368
369 return 0;
370}
371
372static void
373fs_ext__list_attrs_work(uv_work_t *req) {
374 fs_ext_list_attrs_t *r = (fs_ext_list_attrs_t *) req->data;
375
376 r->result = fs_ext__list_attrs(r->fd, &r->names, &r->length);
377}
378
379static void
380fs_ext__list_attrs_after_work(uv_work_t *req, int status) {
381 fs_ext_list_attrs_t *r = (fs_ext_list_attrs_t *) req->data;
382
383 const char **names = (const char **) r->names;
384
385 if (r->cb) r->cb(r, r->result, names, r->length);
386
387 free(names);
388}
389
390int
391fs_ext_list_attrs(uv_loop_t *loop, fs_ext_list_attrs_t *req, uv_os_fd_t fd, fs_ext_list_attrs_cb cb) {
392 req->fd = fd;
393 req->cb = cb;
394 req->req.data = (void *) req;
395
396 return uv_queue_work(loop, &req->req, fs_ext__list_attrs_work, fs_ext__list_attrs_after_work);
397}
node_modules/fs-native-extensions/src/win32.c +490 -0
……@@ -0,0 +1,490 @@
1#include <io.h>
2#include <stdbool.h>
3#include <stdint.h>
4#include <string.h>
5#include <strsafe.h>
6#include <uv.h>
7
8#include "../include/fs-ext.h"
9
10#include "platform.h"
11#include "win32/nt.h"
12
13int
14fs_ext__try_lock(uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type) {
15 if (length == 0) length = SIZE_MAX;
16
17 DWORD flags = LOCKFILE_FAIL_IMMEDIATELY;
18
19 if (type == FS_EXT_WRLOCK) flags |= LOCKFILE_EXCLUSIVE_LOCK;
20
21 OVERLAPPED data = {
22 .hEvent = 0,
23 .Offset = offset,
24 .OffsetHigh = offset >> 32,
25 };
26
27 BOOL res = LockFileEx(
28 fd,
29 flags,
30 0,
31 length,
32 length >> 32,
33 &data
34 );
35
36 return res ? 0 : uv_translate_sys_error(GetLastError());
37}
38
39int
40fs_ext__wait_for_lock(uv_os_fd_t fd, uint64_t offset, size_t length, fs_ext_lock_type_t type) {
41 if (length == 0) length = SIZE_MAX;
42
43 DWORD flags = 0;
44
45 if (type == FS_EXT_WRLOCK) flags |= LOCKFILE_EXCLUSIVE_LOCK;
46
47 OVERLAPPED data = {
48 .hEvent = 0,
49 .Offset = offset,
50 .OffsetHigh = offset >> 32,
51 };
52
53 BOOL res = LockFileEx(
54 fd,
55 flags,
56 0,
57 length,
58 length >> 32,
59 &data
60 );
61
62 return res ? 0 : uv_translate_sys_error(GetLastError());
63}
64
65int
66fs_ext__try_downgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length) {
67 int res = fs_ext__try_lock(fd, offset, length, FS_EXT_RDLOCK);
68 if (res < 0) return res;
69
70 return fs_ext__unlock(fd, offset, length);
71}
72
73int
74fs_ext__wait_for_downgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length) {
75 int res = fs_ext__wait_for_lock(fd, offset, length, FS_EXT_RDLOCK);
76 if (res < 0) return res;
77
78 return fs_ext__unlock(fd, offset, length);
79}
80
81int
82fs_ext__try_upgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length) {
83 int res = fs_ext__unlock(fd, offset, length);
84 if (res < 0) return res;
85
86 return fs_ext__try_lock(fd, offset, length, FS_EXT_WRLOCK);
87}
88
89int
90fs_ext__wait_for_upgrade_lock(uv_os_fd_t fd, uint64_t offset, size_t length) {
91 int res = fs_ext__unlock(fd, offset, length);
92 if (res < 0) return res;
93
94 return fs_ext__wait_for_lock(fd, offset, length, FS_EXT_WRLOCK);
95}
96
97int
98fs_ext__unlock(uv_os_fd_t fd, uint64_t offset, size_t length) {
99 if (length == 0) length = SIZE_MAX;
100
101 OVERLAPPED data = {
102 .hEvent = 0,
103 .Offset = offset,
104 .OffsetHigh = offset >> 32,
105 };
106
107 BOOL res = UnlockFileEx(
108 fd,
109 0,
110 length,
111 length >> 32,
112 &data
113 );
114
115 return res ? 0 : uv_translate_sys_error(GetLastError());
116}
117
118int
119fs_ext__trim(uv_os_fd_t fd, uint64_t offset, size_t length) {
120 FILE_ZERO_DATA_INFORMATION data = {
121 .FileOffset = {
122 .QuadPart = offset,
123 },
124 .BeyondFinalZero = {
125 .QuadPart = offset + length,
126 },
127 };
128
129 DWORD bytes;
130
131 BOOL res = DeviceIoControl(
132 fd,
133 FSCTL_SET_ZERO_DATA,
134 &data,
135 sizeof(data),
136 NULL,
137 0,
138 &bytes, // Must be passed when lpOverlapped is NULL
139 NULL
140 );
141
142 return res ? 0 : uv_translate_sys_error(GetLastError());
143}
144
145int
146fs_ext__sparse(uv_os_fd_t fd) {
147 DWORD bytes;
148
149 BOOL res = DeviceIoControl(
150 fd,
151 FSCTL_SET_SPARSE,
152 NULL,
153 0,
154 NULL,
155 0,
156 &bytes, // Must be passed when lpOverlapped is NULL
157 NULL
158 );
159
160 return res ? 0 : uv_translate_sys_error(GetLastError());
161}
162
163static int
164fs_ext__temp_path(char *path) {
165 TCHAR temp_path[MAX_PATH];
166
167 DWORD bytes = GetTempPath(MAX_PATH, temp_path);
168
169 if (bytes == 0) return uv_translate_sys_error(GetLastError());
170
171 bytes = GetTempFileName(temp_path, NULL, 0, path);
172
173 return bytes > 0 ? 0 : uv_translate_sys_error(GetLastError());
174}
175
176static int
177fs_ext__move(const char *from, const char *to) {
178 BOOL res = MoveFileEx(
179 from,
180 to,
181 MOVEFILE_REPLACE_EXISTING
182 );
183
184 return res ? 0 : uv_translate_sys_error(GetLastError());
185}
186
187int
188fs_ext__swap(const char *from, const char *to) {
189 TCHAR swap[MAX_PATH];
190
191 int err = fs_ext__temp_path(swap);
192 if (err < 0) return err;
193
194 err = fs_ext__move(to, from);
195 if (err < 0) return err;
196
197 err = fs_ext__move(from, to);
198 if (err < 0) return err;
199
200 return fs_ext__move(swap, from);
201}
202
203int
204fs_ext__get_attr(uv_os_fd_t fd, const char *name, uv_buf_t *value) {
205 HANDLE handle = fd;
206 HANDLE stream_handle;
207
208 size_t len = strlen(name);
209
210 WCHAR unicode_name[MAX_PATH] = L":";
211 MultiByteToWideChar(CP_OEMCP, 0, name, -1, &unicode_name[1], len + 1);
212
213 len = wcslen(unicode_name) * 2;
214
215 UNICODE_STRING object_name = {
216 .Length = len,
217 .MaximumLength = len + 2,
218 .Buffer = unicode_name,
219 };
220
221 OBJECT_ATTRIBUTES object_attributes = {
222 .Length = sizeof(object_attributes),
223 .RootDirectory = handle,
224 .ObjectName = &object_name,
225 };
226
227 IO_STATUS_BLOCK status;
228
229 NTSTATUS res = NtOpenFile(
230 &stream_handle,
231 GENERIC_READ,
232 &object_attributes,
233 &status,
234 FILE_SHARE_READ,
235 0
236 );
237
238 if (res < 0) {
239 if (res == STATUS_OBJECT_NAME_NOT_FOUND) return UV_ENODATA;
240
241 return UV_EIO;
242 }
243
244 FILE_STANDARD_INFORMATION info;
245
246 res = NtQueryInformationFile(
247 stream_handle,
248 &status,
249 &info,
250 sizeof(info),
251 FileStandardInformation
252 );
253
254 if (res < 0) {
255 NtClose(stream_handle);
256
257 return UV_EIO;
258 }
259
260 size_t length = info.EndOfFile.QuadPart;
261
262 *value = uv_buf_init(malloc(length), length);
263
264 LARGE_INTEGER offset = {
265 .QuadPart = 0,
266 };
267
268 res = NtReadFile(
269 stream_handle,
270 NULL,
271 NULL,
272 NULL,
273 &status,
274 value->base,
275 value->len,
276 &offset,
277 NULL
278 );
279
280 NtClose(stream_handle);
281
282 if (res < 0) return UV_EIO;
283
284 return 0;
285}
286
287int
288fs_ext__set_attr(uv_os_fd_t fd, const char *name, const uv_buf_t *value) {
289 HANDLE handle = fd;
290 HANDLE stream_handle;
291
292 size_t len = strlen(name);
293
294 WCHAR unicode_name[MAX_PATH] = L":";
295 MultiByteToWideChar(CP_OEMCP, 0, name, -1, &unicode_name[1], len + 1);
296
297 len = wcslen(unicode_name) * 2;
298
299 UNICODE_STRING object_name = {
300 .Length = len,
301 .MaximumLength = len + 2,
302 .Buffer = unicode_name,
303 };
304
305 OBJECT_ATTRIBUTES object_attributes = {
306 .Length = sizeof(object_attributes),
307 .RootDirectory = handle,
308 .ObjectName = &object_name,
309 };
310
311 IO_STATUS_BLOCK status;
312
313 NTSTATUS res = NtCreateFile(
314 &stream_handle,
315 GENERIC_WRITE,
316 &object_attributes,
317 &status,
318 NULL,
319 FILE_ATTRIBUTE_NORMAL,
320 0,
321 FILE_OVERWRITE_IF,
322 0,
323 NULL,
324 0
325 );
326
327 if (res < 0) return UV_EIO;
328
329 LARGE_INTEGER offset = {
330 .QuadPart = 0,
331 };
332
333 res = NtWriteFile(
334 stream_handle,
335 NULL,
336 NULL,
337 NULL,
338 &status,
339 value->base,
340 value->len,
341 &offset,
342 NULL
343 );
344
345 NtClose(stream_handle);
346
347 if (res < 0) return UV_EIO;
348
349 return 0;
350}
351
352int
353fs_ext__remove_attr(uv_os_fd_t fd, const char *name) {
354 HANDLE handle = fd;
355 HANDLE stream_handle;
356
357 size_t len = strlen(name);
358
359 WCHAR unicode_name[MAX_PATH] = L":";
360 MultiByteToWideChar(CP_OEMCP, 0, name, -1, &unicode_name[1], len + 1);
361
362 len = wcslen(unicode_name) * 2;
363
364 UNICODE_STRING object_name = {
365 .Length = len,
366 .MaximumLength = len + 2,
367 .Buffer = unicode_name,
368 };
369
370 OBJECT_ATTRIBUTES object_attributes = {
371 .Length = sizeof(object_attributes),
372 .RootDirectory = handle,
373 .ObjectName = &object_name,
374 };
375
376 IO_STATUS_BLOCK status;
377
378 NTSTATUS res = NtOpenFile(
379 &stream_handle,
380 DELETE,
381 &object_attributes,
382 &status,
383 FILE_SHARE_DELETE,
384 0
385 );
386
387 if (res < 0) {
388 if (res == STATUS_OBJECT_NAME_NOT_FOUND) return UV_ENODATA;
389
390 return UV_EIO;
391 }
392
393 res = NtDeleteFile(&object_attributes);
394
395 NtClose(stream_handle);
396
397 if (res < 0) return UV_EIO;
398
399 return 0;
400}
401
402int
403fs_ext__list_attrs(uv_os_fd_t fd, char **names, size_t *length) {
404 HANDLE handle = fd;
405
406 size_t info_size = 64;
407
408 PFILE_STREAM_INFORMATION info = malloc(info_size);
409 memset(info, 0, info_size);
410
411 NTSTATUS res;
412
413 do {
414 IO_STATUS_BLOCK status;
415
416 res = NtQueryInformationFile(
417 handle,
418 &status,
419 &info[0],
420 info_size,
421 FileStreamInformation
422 );
423
424 if (res == STATUS_BUFFER_OVERFLOW) {
425 info = realloc(info, info_size *= 2);
426 memset(info, 0, info_size);
427 } else {
428 break;
429 }
430 } while (true);
431
432 if (res < 0) return UV_EIO;
433
434 PFILE_STREAM_INFORMATION next = info;
435
436 size_t names_len = 0;
437 *length = 0;
438
439 do {
440 PWCHAR unicode_name = &next->StreamName[1];
441
442 unicode_name[wcslen(unicode_name) - wcslen(L":$DATA")] = L'\0';
443
444 if (wcscmp(unicode_name, L"") != 0) {
445 size_t name_len = WideCharToMultiByte(CP_UTF8, 0, unicode_name, -1, NULL, 0, NULL, NULL);
446
447 *length += 1;
448
449 names_len += sizeof(char *) + name_len;
450 }
451
452 if (next->NextEntryOffset) {
453 next = (PFILE_STREAM_INFORMATION) (((uintptr_t) next) + next->NextEntryOffset);
454 } else {
455 break;
456 }
457 } while (true);
458
459 *names = malloc(names_len);
460
461 size_t offset = *length * sizeof(char *), i = 0, j = 0;
462
463 next = info;
464
465 do {
466 PWCHAR unicode_name = &next->StreamName[1];
467
468 if (wcscmp(unicode_name, L"") != 0) {
469 size_t name_len = WideCharToMultiByte(CP_UTF8, 0, unicode_name, -1, NULL, 0, NULL, NULL);
470
471 char *name = *names + offset + i;
472 i += name_len;
473
474 WideCharToMultiByte(CP_UTF8, 0, unicode_name, -1, name, name_len, NULL, NULL);
475
476 memcpy(*names + j, &name, sizeof(char *));
477 j += sizeof(char *);
478 }
479
480 if (next->NextEntryOffset) {
481 next = (PFILE_STREAM_INFORMATION) (((uintptr_t) next) + next->NextEntryOffset);
482 } else {
483 break;
484 }
485 } while (true);
486
487 free(info);
488
489 return 0;
490}
node_modules/fs-native-extensions/src/win32/nt.h +224 -0
……@@ -0,0 +1,224 @@
1#ifndef FS_NT_H
2#define FS_NT_H
3
4// Definitions of needed Windows kernel APIs, mostly taken from winternl.h and
5// the Windows SDK documentation.
6//
7// Copyright (c) Microsoft Corp. All rights reserved.
8
9#include <windows.h>
10
11#include <ntstatus.h>
12
13#define FILE_SUPERSEDE 0x00000000
14#define FILE_OPEN 0x00000001
15#define FILE_CREATE 0x00000002
16#define FILE_OPEN_IF 0x00000003
17#define FILE_OVERWRITE 0x00000004
18#define FILE_OVERWRITE_IF 0x00000005
19#define FILE_MAXIMUM_DISPOSITION 0x00000005
20
21#define FILE_SUPERSEDED 0x00000000
22#define FILE_OPENED 0x00000001
23#define FILE_CREATED 0x00000002
24#define FILE_OVERWRITTEN 0x00000003
25#define FILE_EXISTS 0x00000004
26#define FILE_DOES_NOT_EXIST 0x00000005
27
28typedef struct _UNICODE_STRING {
29 USHORT Length;
30 USHORT MaximumLength;
31 PWSTR Buffer;
32} UNICODE_STRING, *PUNICODE_STRING;
33
34typedef struct _OBJECT_ATTRIBUTES {
35 ULONG Length;
36 HANDLE RootDirectory;
37 PUNICODE_STRING ObjectName;
38 ULONG Attributes;
39 PVOID SecurityDescriptor;
40 PVOID SecurityQualityOfService;
41} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
42
43typedef struct _IO_STATUS_BLOCK {
44 union {
45 NTSTATUS Status;
46 PVOID Pointer;
47 };
48 ULONG_PTR Information;
49} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
50
51typedef struct _FILE_STANDARD_INFORMATION {
52 LARGE_INTEGER AllocationSize;
53 LARGE_INTEGER EndOfFile;
54 ULONG NumberOfLinks;
55 BOOLEAN DeletePending;
56 BOOLEAN Directory;
57} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
58
59typedef struct _FILE_STREAM_INFORMATION {
60 ULONG NextEntryOffset;
61 ULONG StreamNameLength;
62 LARGE_INTEGER StreamSize;
63 LARGE_INTEGER StreamAllocationSize;
64 WCHAR StreamName[1];
65} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;
66
67typedef enum _FILE_INFORMATION_CLASS {
68 FileDirectoryInformation = 1,
69 FileFullDirectoryInformation, // 2
70 FileBothDirectoryInformation, // 3
71 FileBasicInformation, // 4
72 FileStandardInformation, // 5
73 FileInternalInformation, // 6
74 FileEaInformation, // 7
75 FileAccessInformation, // 8
76 FileNameInformation, // 9
77 FileRenameInformation, // 10
78 FileLinkInformation, // 11
79 FileNamesInformation, // 12
80 FileDispositionInformation, // 13
81 FilePositionInformation, // 14
82 FileFullEaInformation, // 15
83 FileModeInformation, // 16
84 FileAlignmentInformation, // 17
85 FileAllInformation, // 18
86 FileAllocationInformation, // 19
87 FileEndOfFileInformation, // 20
88 FileAlternateNameInformation, // 21
89 FileStreamInformation, // 22
90 FilePipeInformation, // 23
91 FilePipeLocalInformation, // 24
92 FilePipeRemoteInformation, // 25
93 FileMailslotQueryInformation, // 26
94 FileMailslotSetInformation, // 27
95 FileCompressionInformation, // 28
96 FileObjectIdInformation, // 29
97 FileCompletionInformation, // 30
98 FileMoveClusterInformation, // 31
99 FileQuotaInformation, // 32
100 FileReparsePointInformation, // 33
101 FileNetworkOpenInformation, // 34
102 FileAttributeTagInformation, // 35
103 FileTrackingInformation, // 36
104 FileIdBothDirectoryInformation, // 37
105 FileIdFullDirectoryInformation, // 38
106 FileValidDataLengthInformation, // 39
107 FileShortNameInformation, // 40
108 FileIoCompletionNotificationInformation, // 41
109 FileIoStatusBlockRangeInformation, // 42
110 FileIoPriorityHintInformation, // 43
111 FileSfioReserveInformation, // 44
112 FileSfioVolumeInformation, // 45
113 FileHardLinkInformation, // 46
114 FileProcessIdsUsingFileInformation, // 47
115 FileNormalizedNameInformation, // 48
116 FileNetworkPhysicalNameInformation, // 49
117 FileIdGlobalTxDirectoryInformation, // 50
118 FileIsRemoteDeviceInformation, // 51
119 FileUnusedInformation, // 52
120 FileNumaNodeInformation, // 53
121 FileStandardLinkInformation, // 54
122 FileRemoteProtocolInformation, // 55
123 FileRenameInformationBypassAccessCheck, // 56
124 FileLinkInformationBypassAccessCheck, // 57
125 FileVolumeNameInformation, // 58
126 FileIdInformation, // 59
127 FileIdExtdDirectoryInformation, // 60
128 FileReplaceCompletionInformation, // 61
129 FileHardLinkFullIdInformation, // 62
130 FileIdExtdBothDirectoryInformation, // 63
131 FileDispositionInformationEx, // 64
132 FileRenameInformationEx, // 65
133 FileRenameInformationExBypassAccessCheck, // 66
134 FileDesiredStorageClassInformation, // 67
135 FileStatInformation, // 68
136 FileMemoryPartitionInformation, // 69
137 FileStatLxInformation, // 70
138 FileCaseSensitiveInformation, // 71
139 FileLinkInformationEx, // 72
140 FileLinkInformationExBypassAccessCheck, // 73
141 FileStorageReserveIdInformation, // 74
142 FileCaseSensitiveInformationForceAccessCheck, // 75
143 FileKnownFolderInformation, // 76
144 FileMaximumInformation
145} FILE_INFORMATION_CLASS,
146 *PFILE_INFORMATION_CLASS;
147
148typedef VOID(NTAPI *PIO_APC_ROUTINE)(
149 IN PVOID ApcContext,
150 IN PIO_STATUS_BLOCK IoStatusBlock,
151 IN ULONG Reserved
152);
153
154__kernel_entry NTSYSCALLAPI NTSTATUS NTAPI
155NtClose(
156 IN HANDLE Handle
157);
158
159__kernel_entry NTSYSCALLAPI NTSTATUS NTAPI
160NtCreateFile(
161 OUT PHANDLE FileHandle,
162 IN ACCESS_MASK DesiredAccess,
163 IN POBJECT_ATTRIBUTES ObjectAttributes,
164 OUT PIO_STATUS_BLOCK IoStatusBlock,
165 IN PLARGE_INTEGER AllocationSize OPTIONAL,
166 IN ULONG FileAttributes,
167 IN ULONG ShareAccess,
168 IN ULONG CreateDisposition,
169 IN ULONG CreateOptions,
170 IN PVOID EaBuffer OPTIONAL,
171 IN ULONG EaLength
172);
173
174__kernel_entry NTSYSCALLAPI NTSTATUS NTAPI
175NtOpenFile(
176 OUT PHANDLE FileHandle,
177 IN ACCESS_MASK DesiredAccess,
178 IN POBJECT_ATTRIBUTES ObjectAttributes,
179 OUT PIO_STATUS_BLOCK IoStatusBlock,
180 IN ULONG ShareAccess,
181 IN ULONG OpenOptions
182);
183
184__kernel_entry NTSYSCALLAPI NTSTATUS NTAPI
185NtReadFile(
186 IN HANDLE FileHandle,
187 IN HANDLE Event,
188 IN PIO_APC_ROUTINE ApcRoutine,
189 IN PVOID ApcContext,
190 OUT PIO_STATUS_BLOCK IoStatusBlock,
191 OUT PVOID Buffer,
192 IN ULONG Length,
193 IN PLARGE_INTEGER ByteOffset,
194 IN PULONG Key
195);
196
197__kernel_entry NTSYSCALLAPI NTSTATUS NTAPI
198NtWriteFile(
199 IN HANDLE FileHandle,
200 IN HANDLE Event,
201 IN PIO_APC_ROUTINE ApcRoutine,
202 IN PVOID ApcContext,
203 OUT PIO_STATUS_BLOCK IoStatusBlock,
204 IN PVOID Buffer,
205 IN ULONG Length,
206 IN PLARGE_INTEGER ByteOffset,
207 IN PULONG Key
208);
209
210__kernel_entry NTSYSCALLAPI NTSTATUS NTAPI
211NtDeleteFile(
212 IN POBJECT_ATTRIBUTES ObjectAttributes
213);
214
215__kernel_entry NTSYSCALLAPI NTSTATUS NTAPI
216NtQueryInformationFile(
217 IN HANDLE FileHandle,
218 OUT PIO_STATUS_BLOCK IoStatusBlock,
219 OUT PVOID FileInformation,
220 IN ULONG Length,
221 IN FILE_INFORMATION_CLASS FileInformationClass
222);
223
224#endif // FS_NT_H
node_modules/hyperbee/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2020 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/hyperbee/README.md +402 -0
……@@ -0,0 +1,402 @@
1# Hyperbee 🐝
2
3[See API docs at docs.pears.com](https://docs.pears.com/building-blocks/hyperbee)
4
5An append-only B-tree running on a Hypercore. Allows sorted iteration and more.
6
7```
8npm install hyperbee
9```
10
11## Usage
12
13```js
14const Hyperbee = require('hyperbee')
15const Hypercore = require('hypercore')
16
17const core = new Hypercore('./storage')
18const db = new Hyperbee(core, { keyEncoding: 'utf-8', valueEncoding: 'binary' })
19
20// If you own the core
21await db.put('key1', 'value1')
22await db.put('key2', 'value2')
23await db.del('some-key')
24
25// If you want to insert/delete batched values
26const batch = db.batch()
27
28await batch.put('key', 'value')
29await batch.del('some-key')
30await batch.flush() // Execute the batch
31
32// Query the core
33const entry = await db.get('key') // => null or { key, value }
34
35// Read all entries
36for await (const entry of db.createReadStream()) {
37 // ..
38}
39
40// Read a range
41for await (const entry of db.createReadStream({ gte: 'a', lt: 'd' })) {
42 // Anything >=a and <d
43}
44
45// Get the last written entry
46for await (const entry of db.createHistoryStream({ reverse: true, limit: 1 })) {
47 // ..
48}
49```
50
51It works with sparse cores, only a small subset of the full core is downloaded to satisfy your queries.
52
53## API
54
55#### `const db = new Hyperbee(core, [options])`
56
57Make a new Hyperbee instance. `core` should be a [Hypercore](https://github.com/holepunchto/hypercore).
58
59`options` include:
60
61```js
62{
63 keyEncoding: 'binary', // "binary" (default), "utf-8", "ascii", "json", or an abstract-encoding
64 valueEncoding: 'binary' // Same options as keyEncoding like "json", etc
65}
66```
67
68Note that currently read/diff streams sort based on the encoded value of the keys.
69
70#### `await db.ready()`
71
72Waits until internal state is loaded.
73
74Use it once before reading synchronous properties like `db.version`, unless you called any of the other APIs.
75
76#### `await db.close()`
77
78Fully close this bee, including its core.
79
80#### `db.core`
81
82The underlying Hypercore backing this bee.
83
84#### `db.version`
85
86Number that indicates how many modifications were made, useful as a version identifier.
87
88#### `db.id`
89
90String containing the id (z-base-32 of the public key) identifying this bee.
91
92#### `db.key`
93
94Buffer containing the public key identifying this bee.
95
96#### `db.discoveryKey`
97
98Buffer containing a key derived from `db.key`.
99
100This discovery key does not allow you to verify the data, it's only to announce or look for peers that are sharing the same bee, without leaking the bee key.
101
102#### `db.writable`
103
104Boolean indicating if we can put or delete data in this bee.
105
106#### `db.readable`
107
108Boolean indicating if we can read from this bee. After closing the bee this will be `false`.
109
110#### `await db.put(key, [value], [options])`
111
112Insert a new key. Value can be optional.
113
114If you're inserting a series of data atomically or want more performance then check the `db.batch` API.
115
116`options` includes:
117
118```js
119{
120 cas (prev, next) { return true }
121}
122```
123
124##### Compare And Swap (cas)
125
126`cas` option is a function comparator to control whether the `put` succeeds.
127
128By returning `true` it will insert the value, otherwise it won't.
129
130It receives two args: `prev` is the current node entry, and `next` is the potential new node.
131
132```js
133await db.put('number', '123', { cas })
134console.log(await db.get('number')) // => { seq: 1, key: 'number', value: '123' }
135
136await db.put('number', '123', { cas })
137console.log(await db.get('number')) // => { seq: 1, key: 'number', value: '123' }
138// Without cas this would have been { seq: 2, ... }, and the next { seq: 3 }
139
140await db.put('number', '456', { cas })
141console.log(await db.get('number')) // => { seq: 2, key: 'number', value: '456' }
142
143function cas(prev, next) {
144 // You can use same-data or same-object lib, depending on the value complexity
145 return prev.value !== next.value
146}
147```
148
149#### `const { seq, key, value } = await db.get(key)`
150
151Get a key's value. Returns `null` if key doesn't exists.
152
153`seq` is the Hypercore index at which this key was inserted.
154
155#### `await db.del(key, [options])`
156
157Delete a key.
158
159`options` include:
160
161```js
162{
163 cas (prev, next) { return true }
164}
165```
166
167##### Compare And Swap (cas)
168
169`cas` option is a function comparator to control whether the `del` succeeds.
170
171By returning `true` it will delete the value, otherwise it won't.
172
173It only receives one arg: `prev` which is the current node entry.
174
175```js
176// This won't get deleted
177await db.del('number', { cas })
178console.log(await db.get('number')) // => { seq: 1, key: 'number', value: 'value' }
179
180// Change the value so the next time we try to delete it then "cas" will return true
181await db.put('number', 'can-be-deleted')
182
183await db.del('number', { cas })
184console.log(await db.get('number')) // => null
185
186function cas(prev) {
187 return prev.value === 'can-be-deleted'
188}
189```
190
191#### `const { key, value } = await db.getBySeq(seq, [options])`
192
193Get the key and value from a block number.
194
195`seq` is the Hypercore index. Returns `null` if block doesn't exists.
196
197#### `const stream = db.replicate(isInitiatorOrStream)`
198
199See more about how replicate works at [core.replicate][core-replicate-docs].
200
201#### `const batch = db.batch()`
202
203Make a new atomic batch that is either fully processed or not processed at all.
204
205If you have several inserts and deletions then a batch can be much faster.
206
207#### `await batch.put(key, [value], [options])`
208
209Insert a key into a batch.
210
211`options` are the same as `db.put` method.
212
213#### `const { seq, key, value } = await batch.get(key)`
214
215Get a key, value out of a batch.
216
217#### `await batch.del(key, [options])`
218
219Delete a key into the batch.
220
221`options` are the same as `db.del` method.
222
223#### `await batch.flush()`
224
225Commit the batch to the database, and releases any locks it has acquired.
226
227#### `await batch.close()`
228
229Destroy a batch, and releases any locks it has acquired on the db.
230
231Call this if you want to abort a batch without flushing it.
232
233#### `const stream = db.createReadStream([range], [options])`
234
235Make a read stream. Sort order is based on the binary value of the keys.
236
237All entries in the stream are similar to the ones returned from `db.get`.
238
239`range` should specify the range you want to read and looks like this:
240
241```js
242{
243 gt: 'only return keys > than this',
244 gte: 'only return keys >= than this',
245 lt: 'only return keys < than this',
246 lte: 'only return keys <= than this'
247}
248```
249
250`options` include:
251
252```js
253{
254 reverse: false // Set to true to get them in reverse order,
255 limit: -1 // Set to the max number of entries you want
256}
257```
258
259#### `const { seq, key, value } = await db.peek([range], [options])`
260
261Similar to doing a read stream and returning the first value, but a bit faster than that.
262
263#### `const stream = db.createHistoryStream([options])`
264
265Create a stream of all entries ever inserted or deleted from the db.
266
267Each entry has an additional `type` property indicating if it was a `put` or `del` operation.
268
269`options` include:
270
271```js
272{
273 live: false, // If true the stream will wait for new data and never end
274 reverse: false, // If true get from the newest to the oldest
275 gte: seq, // Start with this seq (inclusive)
276 gt: seq, // Start after this index
277 lte: seq, // Stop after this index
278 lt: seq, // Stop before this index
279 limit: -1 // Set to the max number of entries you want
280}
281```
282
283If any of the `gte`, `gt`, `lte`, `lt` arguments are `< 0` then
284they'll implicitly be added with the version before starting so
285doing `{ gte: -1 }` makes a stream starting at the last index.
286
287#### `const stream = db.createDiffStream(otherVersion, [options])`
288
289Efficiently create a stream of the shallow changes between two versions of the db.
290
291`options` are the same as `db.createReadStream`, except for `reverse`.
292
293Each entry is sorted by key and looks like this:
294
295```js
296{
297 left: Object, // The entry in the `db`
298 right: Object // The entry in `otherVersion`
299}
300```
301
302If an entry exists in db but not in the other version, then `left` is set
303and `right` will be null, and vice versa.
304
305If the entries are causally equal (i.e. the have the same seq), they are not
306returned, only the diff.
307
308#### `const entryWatcher = await db.getAndWatch(key, [options])`
309
310Returns a watcher which listens to changes on the given key.
311
312`entryWatcher.node` contains the current entry in the same format as the result of `bee.get(key)`, and will be updated as it changes.
313
314By default, the node will have the bee's key- and value encoding, but you can overwrite it by setting the `keyEncoding` and `valueEncoding` options.
315
316You can listen to `entryWatcher.on('update')` to be notified when the value of node has changed.
317
318Call `await watcher.close()` to stop the watcher.
319
320#### `const watcher = db.watch([range])`
321
322Listens to changes that are on the optional `range`.
323
324`range` options are the same as `db.createReadStream` except for `reverse`.
325
326By default, the yielded snapshots will have the bee's key- and value encoding, but you can overwrite them by setting the `keyEncoding` and `valueEncoding` options.
327
328Usage example:
329
330```js
331for await (const [current, previous] of watcher) {
332 console.log(current.version)
333 console.log(previous.version)
334}
335```
336
337Returns a new value after a change, `current` and `previous` are snapshots that are auto-closed before next value.
338
339Don't close those snapshots yourself because they're used internally, let them be auto-closed.
340
341Watchers on subs and checkouts are not supported. Instead, use the range option to limit scope.
342
343`await watcher.ready()`
344
345Waits until the watcher is loaded and detecting changes.
346
347`await watcher.close()`
348
349Stops the watcher. You could also stop it by using `break` in the loop.
350
351#### `const snapshot = db.checkout(version)`
352
353Get a read-only snapshot of a previous version.
354
355#### `const snapshot = db.snapshot()`
356
357Shorthand for getting a checkout for the current version.
358
359#### `const sub = db.sub('sub-prefix', options = {})`
360
361Create a sub-database where all entries will be prefixed by a given value.
362
363This makes it easy to create namespaces within a single Hyperbee.
364
365`options` include:
366
367```
368{
369 sep: Buffer.alloc(1), // A namespace separator
370 valueEncoding, // Optional sub valueEncoding (defaults to the parents)
371 keyEncoding // Optional sub keyEncoding (defaults to the parents)
372}
373```
374
375For example:
376
377```js
378const root = new Hyperbee(core)
379const sub = root.sub('a')
380
381// In root, this will have the key ('a' + separator + 'b')
382await sub.put('b', 'hello')
383
384// Returns => { key: 'b', value: 'hello')
385await sub.get('b')
386```
387
388#### `const header = await db.getHeader([options])`
389
390Returns the header contained in the first block. Throws if undecodable.
391
392`options` are the same as the `core.get` method.
393
394#### `const isHyperbee = await Hyperbee.isHyperbee(core, [options])`
395
396Returns `true` if the core contains a Hyperbee, `false` otherwise.
397
398This requests the first block on the core, so it can throw depending on the options.
399
400`options` are the same as the `core.get` method.
401
402[core-replicate-docs]: https://github.com/holepunchto/hypercore#const-stream--corereplicateisinitiatororreplicationstream
node_modules/hyperbee/index.js +1904 -0
……@@ -0,0 +1,1904 @@
1const codecs = require('codecs')
2const { Readable } = require('streamx')
3const mutexify = require('mutexify/promise')
4const b4a = require('b4a')
5const safetyCatch = require('safety-catch')
6const ReadyResource = require('ready-resource')
7const debounce = require('debounceify')
8const Rache = require('rache')
9const rrp = require('resolve-reject-promise')
10
11const { all: unslabAll } = require('unslab')
12
13const RangeIterator = require('./iterators/range')
14const HistoryIterator = require('./iterators/history')
15const DiffIterator = require('./iterators/diff')
16const LocalBlockIterator = require('./iterators/local')
17const Extension = require('./lib/extension')
18const { YoloIndex, Node, Header } = require('./lib/messages')
19const { BLOCK_NOT_AVAILABLE, DECODING_ERROR } = require('hypercore-errors')
20
21const T = 5
22const MIN_KEYS = T - 1
23const MAX_CHILDREN = MIN_KEYS * 2 + 1
24
25const SEP = b4a.alloc(1)
26const EMPTY = b4a.alloc(0)
27
28class Key {
29 constructor(seq, value) {
30 this.seq = seq
31 this.value = value
32 }
33}
34
35class Child {
36 constructor(seq, offset, value) {
37 this.seq = seq
38 this.offset = offset
39 this.value = value
40 }
41}
42
43class Cache {
44 constructor(rache) {
45 this.keys = rache
46 this.length = 0
47 }
48
49 get(seq) {
50 return this.keys.get(seq) || null
51 }
52
53 set(seq, key) {
54 this.keys.set(seq, key)
55 if (seq >= this.length) this.length = seq + 1
56 }
57
58 gc(length) {
59 // if we need to "work" more than 128 ticks, just bust the cache...
60 if (this.length - length > 128) {
61 this.keys.clear()
62 } else {
63 for (let i = length; i < this.length; i++) {
64 this.keys.delete(i)
65 }
66 }
67
68 this.length = length
69 }
70
71 clear() {
72 this.keys.clear()
73 }
74}
75
76class Pointers {
77 constructor(decoded) {
78 this.levels = decoded.levels.map((l) => {
79 const children = []
80 const keys = []
81
82 for (let i = 0; i < l.keys.length; i++) {
83 keys.push(new Key(l.keys[i], null))
84 }
85
86 for (let i = 0; i < l.children.length; i += 2) {
87 children.push(new Child(l.children[i], l.children[i + 1], null))
88 }
89
90 return { keys, children }
91 })
92 }
93
94 get(i) {
95 return this.levels[i]
96 }
97
98 hasKey(seq) {
99 for (const lvl of this.levels) {
100 for (const key of lvl.keys) {
101 if (key.seq === seq) return true
102 }
103 }
104 return false
105 }
106}
107
108function inflate(entry) {
109 if (entry.inflated === null) {
110 entry.inflated = YoloIndex.decode(entry.index)
111 entry.index = null
112 }
113 return new Pointers(entry.inflated)
114}
115
116function deflate(index) {
117 const levels = index.map((l) => {
118 const keys = []
119 const children = []
120
121 for (let i = 0; i < l.value.keys.length; i++) {
122 keys.push(l.value.keys[i].seq)
123 }
124
125 for (let i = 0; i < l.value.children.length; i++) {
126 children.push(l.value.children[i].seq, l.value.children[i].offset)
127 }
128
129 return { keys, children }
130 })
131
132 return YoloIndex.encode({ levels })
133}
134
135class TreeNode {
136 constructor(block, keys, children, offset) {
137 this.block = block
138 this.offset = offset
139 this.keys = keys
140 this.children = children
141 this.changed = false
142
143 this.preload()
144 }
145
146 preload() {
147 if (this.block === null) return
148
149 const core = getBackingCore(this.block.tree.core)
150 if (!core) return
151
152 const bitfield = core.core.bitfield
153 const blocks = []
154
155 for (let i = 0; i < this.keys.length; i++) {
156 const k = this.keys[i]
157 if (k.value) continue
158 if (k.seq >= core.signedLength || (bitfield && bitfield.get(k.seq))) continue
159 blocks.push(k.seq)
160 }
161 for (let i = 0; i < this.children.length; i++) {
162 const c = this.children[i]
163 if (c.value) continue
164 if (c.seq >= core.signedLength || (bitfield && bitfield.get(c.seq))) continue
165 blocks.push(c.seq)
166 }
167
168 if (blocks.length) core.download({ blocks })
169 }
170
171 async insertKey(key, value, child, node, encoding, cas) {
172 let s = 0
173 let e = this.keys.length
174 let c
175
176 while (s < e) {
177 const mid = (s + e) >> 1
178 c = b4a.compare(key.value, await this.getKey(mid))
179
180 if (c === 0) {
181 if (cas) {
182 const prev = await this.getKeyNode(mid)
183 if (!(await cas(prev.final(encoding), node))) return true
184 }
185 if (!this.block.tree.tree.alwaysDuplicate) {
186 const prev = await this.getKeyNode(mid)
187 if (sameValue(prev.value, value)) return true
188 }
189 this.changed = true
190 this.keys[mid] = key
191 return true
192 }
193
194 if (c < 0) e = mid
195 else s = mid + 1
196 }
197
198 const i = c < 0 ? e : s
199 this.keys.splice(i, 0, key)
200 if (child) this.children.splice(i + 1, 0, new Child(0, 0, child))
201 this.changed = true
202
203 return this.keys.length < MAX_CHILDREN
204 }
205
206 removeKey(index) {
207 this.keys.splice(index, 1)
208 if (this.children.length) {
209 this.children[index + 1].seq = 0 // mark as freed
210 this.children.splice(index + 1, 1)
211 }
212 this.changed = true
213 }
214
215 async siblings(parent) {
216 for (let i = 0; i < parent.children.length; i++) {
217 if (parent.children[i].value === this) {
218 const [left, right] = await Promise.all([
219 i ? parent.getChildNode(i - 1) : null,
220 i < parent.children.length - 1 ? parent.getChildNode(i + 1) : null
221 ])
222 return { left, index: i, right }
223 }
224 }
225
226 throw new Error('Bad parent')
227 }
228
229 merge(node, median) {
230 this.changed = true
231 this.keys.push(median)
232 for (let i = 0; i < node.keys.length; i++) this.keys.push(node.keys[i])
233 for (let i = 0; i < node.children.length; i++) this.children.push(node.children[i])
234 }
235
236 async split() {
237 const len = this.keys.length >> 1
238 const right = TreeNode.create(this.block)
239
240 while (right.keys.length < len) right.keys.push(this.keys.pop())
241 right.keys.reverse()
242
243 await this.getKey(this.keys.length - 1) // make sure the median is loaded
244 const median = this.keys.pop()
245
246 if (this.children.length) {
247 while (right.children.length < len + 1) right.children.push(this.children.pop())
248 right.children.reverse()
249 }
250
251 this.changed = true
252
253 return {
254 left: this,
255 median,
256 right
257 }
258 }
259
260 getKeyNode(index) {
261 return this.block.tree.getBlock(this.keys[index].seq)
262 }
263
264 async getChildNode(index) {
265 const child = this.children[index]
266 if (child.value) return child.value
267 const block =
268 child.seq === this.block.seq ? this.block : await this.block.tree.getBlock(child.seq)
269 return (child.value = block.getTreeNode(child.offset))
270 }
271
272 setKey(index, key) {
273 this.keys[index] = key
274 this.changed = true
275 }
276
277 async getKey(index) {
278 const key = this.keys[index]
279 if (key.value) return key.value
280 const k = key.seq === this.block.seq ? this.block.key : await this.block.tree.getKey(key.seq)
281 return (key.value = k)
282 }
283
284 indexChanges(index, seq) {
285 const offset = index.push(null) - 1
286 this.changed = false
287
288 for (const child of this.children) {
289 if (!child.value || !child.value.changed) continue
290 child.seq = seq
291 child.offset = child.value.indexChanges(index, seq)
292 index[child.offset] = child
293 }
294
295 return offset
296 }
297
298 updateChildren(seq, block) {
299 for (const child of this.children) {
300 if (!child.value || child.seq !== seq) continue
301 child.value.block = block
302 child.value.updateChildren(seq, block)
303 }
304 }
305
306 static create(block) {
307 const node = new TreeNode(block, [], [], 0)
308 node.changed = true
309 return node
310 }
311}
312
313class BlockEntry {
314 constructor(seq, tree, entry) {
315 this.seq = seq
316 this.tree = tree
317 this.index = null
318 this.entry = entry
319 this.key = entry.key
320 this.value = entry.value
321 }
322
323 isTarget(key) {
324 return b4a.equals(this.key, key)
325 }
326
327 inflate() {
328 if (this.index === null) {
329 this.index = inflate(this.entry)
330 }
331 }
332
333 isDeletion() {
334 if (this.value !== null) return false
335
336 if (this.index === null) {
337 this.index = inflate(this.entry)
338 }
339
340 return !this.index.hasKey(this.seq)
341 }
342
343 final(encoding) {
344 return {
345 seq: this.seq,
346 key: encoding.key ? encoding.key.decode(this.key) : this.key,
347 value: this.value && (encoding.value ? encoding.value.decode(this.value) : this.value)
348 }
349 }
350
351 getTreeNode(offset) {
352 if (this.index === null) {
353 this.index = inflate(this.entry)
354 }
355 const entry = this.index.get(offset)
356 return new TreeNode(this, entry.keys, entry.children, offset)
357 }
358}
359
360class CacheLock {
361 constructor() {
362 this.map = new Map()
363 }
364
365 enter(seq) {
366 const pending = this.map.get(seq)
367
368 if (!pending) {
369 this.map.set(seq, [])
370 return Promise.resolve()
371 }
372
373 const { resolve, promise } = rrp()
374 pending.push(resolve)
375 return promise
376 }
377
378 exit(seq) {
379 const pending = this.map.get(seq)
380 if (!pending.length) {
381 this.map.delete(seq)
382 return
383 }
384
385 pending.pop()()
386 }
387}
388
389class BatchEntry extends BlockEntry {
390 constructor(seq, tree, key, value, index) {
391 super(seq, tree, { key, value, index: null, inflated: null })
392 this.pendingIndex = index
393 }
394
395 isTarget(key) {
396 return false
397 }
398
399 getTreeNode(offset) {
400 return this.pendingIndex[offset].value
401 }
402}
403
404class Hyperbee extends ReadyResource {
405 constructor(core, opts = {}) {
406 super()
407 // this.feed is now deprecated, and will be this.core going forward
408 this.feed = core
409 this.core = core
410
411 this.keyEncoding = opts.keyEncoding ? codecs(opts.keyEncoding) : null
412 this.valueEncoding = opts.valueEncoding ? codecs(opts.valueEncoding) : null
413 this.extension = opts.extension !== false ? getExtension(this, opts) : null
414 this.metadata = opts.metadata || null
415 this.lock = opts.lock || mutexify()
416 this.sep = opts.sep || SEP
417 this.readonly = !!opts.readonly
418 this.prefix = opts.prefix || null
419
420 // In a future version, this should be false by default
421 this.alwaysDuplicate = opts.alwaysDuplicate !== false
422
423 this._unprefixedKeyEncoding = this.keyEncoding
424 this._sub = !!this.prefix
425 this._checkout = opts.checkout || 0
426 this._view = !!opts._view
427
428 this._onappendBound = this._view ? null : this._onappend.bind(this)
429 this._ontruncateBound = this._view ? null : this._ontruncate.bind(this)
430 this._watchers = this._onappendBound ? [] : null
431 this._entryWatchers = this._onappendBound ? [] : null
432 this._sessions = opts.sessions !== false
433
434 this._keyCache = null
435 this._nodeCache = null
436 this._cacheLock = new CacheLock()
437
438 this._batches = []
439
440 if (this._watchers) {
441 this.core.on('append', this._onappendBound)
442 this.core.on('truncate', this._ontruncateBound)
443 }
444
445 if (this.prefix && opts._sub) {
446 this.keyEncoding = prefixEncoding(this.prefix, this.keyEncoding)
447 }
448
449 this.ready().catch(safetyCatch)
450 }
451
452 async _open() {
453 if (this.core.opened === false) await this.core.ready()
454 // bump the internal ranges since the nodes are small
455 if (this._watchers && this.core.replicator.setInflightRange) {
456 this.core.replicator.setInflightRange(256, 512)
457 }
458
459 // snapshot
460 if (this._checkout === -1) this._checkout = Math.max(1, this.core.length)
461
462 const baseCache = Rache.from(this.core.globalCache)
463 this._keyCache = new Cache(baseCache)
464 this._nodeCache = new Cache(Rache.from(baseCache))
465 }
466
467 get version() {
468 return Math.max(1, this._checkout || this.core.length)
469 }
470
471 get id() {
472 return this.core.id
473 }
474
475 get key() {
476 return this.core.key
477 }
478
479 get discoveryKey() {
480 return this.core.discoveryKey
481 }
482
483 get writable() {
484 return this.core.writable
485 }
486
487 get readable() {
488 return this.core.readable
489 }
490
491 replicate(isInitiator, opts) {
492 return this.core.replicate(isInitiator, opts)
493 }
494
495 update(opts) {
496 return this.core.update(opts)
497 }
498
499 peek(range, opts) {
500 return iteratorPeek(this.createRangeIterator(range, { ...opts, limit: 1 }))
501 }
502
503 createRangeIterator(range, opts = {}) {
504 // backwards compat range arg
505 opts = opts ? { ...opts, ...range } : range
506
507 const extension = opts.extension === false && opts.limit !== 0 ? null : this.extension
508 const keyEncoding = opts.keyEncoding ? codecs(opts.keyEncoding) : this.keyEncoding
509
510 if (extension) {
511 const { onseq, onwait } = opts
512 let version = 0
513 let next = 0
514
515 opts = encRange(keyEncoding, {
516 ...opts,
517 sub: this._sub,
518 onseq(seq) {
519 if (!version) version = seq + 1
520 if (next) next--
521 if (onseq) onseq(seq)
522 },
523 onwait(seq) {
524 if (!next) {
525 next = Extension.BATCH_SIZE
526 extension.iterator(ite.snapshot(version))
527 }
528 if (onwait) onwait(seq)
529 }
530 })
531 } else {
532 opts = encRange(keyEncoding, { ...opts, sub: this._sub })
533 }
534
535 const ite = new RangeIterator(
536 new Batch(this, this._makeSnapshot(), null, false, opts),
537 null,
538 opts
539 )
540 return ite
541 }
542
543 createReadStream(range, opts) {
544 const signal = (opts && opts.signal) || null
545 return iteratorToStream(this.createRangeIterator(range, opts), signal)
546 }
547
548 createHistoryStream(opts) {
549 const session = opts && opts.live ? this.core.session() : this._makeSnapshot()
550 const signal = (opts && opts.signal) || null
551 return iteratorToStream(
552 new HistoryIterator(new Batch(this, session, null, false, opts), opts),
553 signal
554 )
555 }
556
557 createDiffStream(right, range, opts) {
558 if (typeof right === 'number') right = this.checkout(Math.max(1, right), { reuseSession: true })
559
560 // backwards compat range arg
561 opts = opts ? { ...opts, ...range } : range
562
563 const signal = (opts && opts.signal) || null
564
565 const keyEncoding = opts && opts.keyEncoding ? codecs(opts.keyEncoding) : this.keyEncoding
566 if (keyEncoding) opts = encRange(keyEncoding, { ...opts, sub: this._sub })
567
568 let done
569 let closing
570 let ite
571
572 const left = this
573
574 const rs = new Readable({
575 signal,
576 eagerOpen: true,
577 async open(cb) {
578 try {
579 if (right.opened === false) await right.ready()
580 if (left.opened === false) await left.ready()
581 } catch (err) {
582 cb(err)
583 return
584 }
585
586 if (closing) {
587 cb(null)
588 return
589 }
590
591 if (left.core.closing || right.core.closing) {
592 cb(new Error('Bee closed'))
593 return
594 }
595
596 const snapshot = right.version > left.version ? right._makeSnapshot() : left._makeSnapshot()
597
598 done = cb
599 ite = new DiffIterator(
600 new Batch(left, snapshot, null, false, opts),
601 new Batch(right, snapshot, null, false, opts),
602 opts
603 )
604 ite.open().then(fin, fin)
605 },
606 read(cb) {
607 done = cb
608 ite.next().then(push, fin)
609 },
610 predestroy() {
611 if (!ite) {
612 closing = Promise.resolve()
613 } else {
614 closing = ite.close()
615 closing.catch(noop)
616 }
617 },
618 destroy(cb) {
619 done = cb
620 if (!closing) closing = ite.close()
621 closing.then(fin, fin)
622 }
623 })
624
625 return rs
626
627 function fin(err) {
628 done(err)
629 }
630
631 function push(val) {
632 rs.push(val)
633 done(null)
634 }
635 }
636
637 get(key, opts) {
638 const b = new Batch(this, this._makeSnapshot(), null, true, opts)
639 return b.get(key)
640 }
641
642 getBySeq(seq, opts) {
643 const b = new Batch(this, this._makeSnapshot(), null, true, opts)
644 return b.getBySeq(seq)
645 }
646
647 put(key, value, opts) {
648 const b = new Batch(this, this.core, null, true, opts)
649 return b.put(key, value, opts)
650 }
651
652 batch(opts) {
653 return new Batch(this, this.core, mutexify(), true, opts)
654 }
655
656 del(key, opts) {
657 const b = new Batch(this, this.core, null, true, opts)
658 return b.del(key, opts)
659 }
660
661 watch(range, opts) {
662 if (!this._watchers) throw new Error('Can only watch the main bee instance')
663 return new Watcher(this, range, opts)
664 }
665
666 async getAndWatch(key, opts) {
667 if (!this._watchers) throw new Error('Can only watch the main bee instance')
668
669 const watcher = new EntryWatcher(this, key, opts)
670 await watcher._debouncedUpdate()
671
672 if (this.closing) {
673 await watcher.close()
674 throw new Error('Bee closed')
675 }
676
677 return watcher
678 }
679
680 _onappend() {
681 for (const watcher of this._watchers) {
682 watcher._onappend()
683 }
684
685 for (const watcher of this._entryWatchers) {
686 watcher._onappend()
687 }
688 }
689
690 _ontruncate(length) {
691 for (const watcher of this._watchers) {
692 watcher._ontruncate()
693 }
694
695 for (const watcher of this._entryWatchers) {
696 watcher._ontruncate()
697 }
698
699 this._nodeCache.gc(length)
700 this._keyCache.gc(length)
701 }
702
703 _makeSnapshot() {
704 if (this._sessions === false) return this.core
705 // TODO: better if we could encapsulate this in hypercore in the future
706 return this._checkout <= this.core.length || this._checkout <= 1
707 ? this.core.snapshot()
708 : this.core.session({ snapshot: false })
709 }
710
711 async clearUnlinked(options = {}) {
712 await this.ready()
713
714 const { gte = 0, lt = this.version - 1, batchSize = 4096, wait = true } = options
715 const checkout = this.version
716
717 let prev = this.batch({ wait: false, checkout: gte })
718 let b = this.batch({ wait, checkout })
719
720 const iteBatch = this.batch({ wait: false, checkout })
721 const ite = new LocalBlockIterator(iteBatch, { gte, lt })
722 await ite.open()
723
724 let ticks = 0
725
726 while (true) {
727 const data = await ite.next()
728 if (!data) break
729
730 if (!(await isLinked(b, data))) {
731 if (b.core.closing || this.core.closing || this.closing) break
732 await this.core.clear(data.seq)
733 }
734
735 const prevNode = await prev.get(data.key, { finalize: false }).catch(toNull)
736
737 if (prevNode && !(await isLinked(b, prevNode))) {
738 if (b.core.closing || this.core.closing || this.closing) break
739 await this.core.clear(prevNode.seq)
740 }
741
742 if (ticks++ >= batchSize) {
743 ticks = 0
744 await prev.close()
745 await b.close()
746
747 prev = this.batch({ wait: false, checkout: gte })
748 b = this.batch({ wait, checkout })
749 }
750 }
751
752 if (b.core.closing || this.core.closing || this.closing) throw new Error('Core is closed')
753
754 await b.close()
755 await prev.close()
756 await ite.close()
757 await iteBatch.close()
758
759 return lt
760 }
761
762 checkout(version, opts = {}) {
763 if (version === 0) version = 1
764
765 // same as above, just checkout isn't set yet...
766 const snap =
767 opts.reuseSession || this._sessions === false
768 ? this.core
769 : version <= this.core.length || version <= 1
770 ? this.core.snapshot()
771 : this.core.session({ snapshot: false })
772
773 return new Hyperbee(snap, {
774 _view: true,
775 _sub: false,
776 prefix: this.prefix,
777 sep: this.sep,
778 lock: this.lock,
779 checkout: version,
780 keyEncoding: opts.keyEncoding || this.keyEncoding,
781 valueEncoding: opts.valueEncoding || this.valueEncoding,
782 extension: this.extension !== null ? this.extension : false
783 })
784 }
785
786 snapshot(opts) {
787 return this.checkout(
788 this.core.opened === false || this._checkout <= 0 ? -1 : Math.max(1, this.version),
789 opts
790 )
791 }
792
793 sub(prefix, opts = {}) {
794 let sep = opts.sep || this.sep
795 if (!b4a.isBuffer(sep)) sep = b4a.from(sep)
796
797 prefix = b4a.concat([this.prefix || EMPTY, b4a.from(prefix), sep])
798
799 const valueEncoding = codecs(opts.valueEncoding || this.valueEncoding)
800 const keyEncoding = codecs(opts.keyEncoding || this._unprefixedKeyEncoding)
801
802 return new Hyperbee(this.core, {
803 _view: true,
804 _sub: true,
805 prefix,
806 sep: this.sep,
807 lock: this.lock,
808 checkout: this._checkout,
809 valueEncoding,
810 keyEncoding,
811 extension: this.extension !== null ? this.extension : false,
812 metadata: this.metadata
813 })
814 }
815
816 async getHeader(opts) {
817 const blk = await this.core.get(0, opts)
818 try {
819 return blk && Header.decode(blk)
820 } catch {
821 throw DECODING_ERROR()
822 }
823 }
824
825 async _close() {
826 if (!this._view) {
827 if (this._keyCache) this._keyCache.clear()
828 if (this._nodeCache) this._nodeCache.clear()
829 }
830
831 if (this._watchers) {
832 this.core.off('append', this._onappendBound)
833 this.core.off('truncate', this._ontruncateBound)
834
835 while (this._watchers.length) {
836 await this._watchers[this._watchers.length - 1].close()
837 }
838 }
839
840 if (this._entryWatchers) {
841 while (this._entryWatchers.length) {
842 await this._entryWatchers[this._entryWatchers.length - 1].close()
843 }
844 }
845
846 while (this._batches.length) {
847 await this._batches[this._batches.length - 1].close()
848 }
849
850 return this.core.close()
851 }
852
853 static async isHyperbee(core, opts) {
854 await core.ready()
855
856 const blk0 = await core.get(0, opts)
857 if (blk0 === null) throw BLOCK_NOT_AVAILABLE()
858
859 try {
860 return Header.decode(blk0).protocol === 'hyperbee'
861 } catch (err) {
862 // undecodable
863 return false
864 }
865 }
866}
867
868class Batch {
869 constructor(tree, core, batchLock, cache, options = {}) {
870 this.tree = tree
871 // this.feed is now deprecated, and will be this.core going forward
872 this.feed = core
873 this.core = core
874 this.index = tree._batches.push(this) - 1
875 this.blocks = cache ? new Map() : null
876 this.autoFlush = !batchLock
877 this.maxBlocksCached = options.maxBlocksCached || 128
878 this.rootSeq = 0
879 this.root = null
880 this.length = 0
881 this.checkout = options.checkout === undefined ? -1 : options.checkout
882 this.options = options
883 this.locked = null
884 this.batchLock = batchLock
885 this.onseq = this.options.onseq || noop
886 this.appending = null
887 this.isSnapshot = this.core !== this.tree.core
888 this.shouldUpdate = this.options.update !== false
889 this.updating = null
890 this.encoding = {
891 key: options.keyEncoding ? codecs(options.keyEncoding) : tree.keyEncoding,
892 value: options.valueEncoding ? codecs(options.valueEncoding) : tree.valueEncoding
893 }
894 }
895
896 async ready() {
897 if (this.core.opened === false) await this.core.ready()
898 if (this.tree.opened === false) await this.tree.ready()
899 }
900
901 async lock() {
902 if (this.tree.readonly) throw new Error('Hyperbee is marked as read-only')
903 if (this.locked === null) this.locked = await this.tree.lock()
904 }
905
906 get version() {
907 if (this.checkout !== -1) return Math.max(1, this.checkout)
908 return Math.max(1, this.tree._checkout || this.core.length + this.length)
909 }
910
911 async getRoot(ensureHeader) {
912 await this.ready()
913 if (ensureHeader) {
914 if (this.core.length === 0 && this.core.writable && !this.tree.readonly) {
915 await this.core.append(
916 Header.encode({
917 protocol: 'hyperbee',
918 metadata: this.tree.metadata
919 })
920 )
921 }
922 }
923 if (this.tree._checkout === 0 && this.checkout === -1 && this.shouldUpdate) {
924 if (this.updating === null) this.updating = this.core.update()
925 await this.updating
926 }
927 if (this.version < 2) return null
928 return (await this.getBlock(this.version - 1)).getTreeNode(0)
929 }
930
931 async getKey(seq) {
932 await this.tree._cacheLock.enter(seq)
933
934 try {
935 const k = this.core.fork === this.tree.core.fork ? this.tree._keyCache.get(seq) : null
936 if (k !== null) return k
937 const key = (await this._getBlock(seq)).key
938 if (this.core.fork === this.tree.core.fork) this.tree._keyCache.set(seq, key)
939 return key
940 } finally {
941 this.tree._cacheLock.exit(seq)
942 }
943 }
944
945 async _getNode(seq) {
946 const cached =
947 this.tree._nodeCache !== null && this.core.fork === this.tree.core.fork
948 ? this.tree._nodeCache.get(seq)
949 : null
950 if (cached !== null) return cached
951 const entry = await this.core.get(seq, {
952 ...this.options,
953 valueEncoding: Node
954 })
955 if (entry === null) throw BLOCK_NOT_AVAILABLE()
956 const wrap = copyEntry(entry)
957 if (this.core.fork === this.tree.core.fork && this.tree._nodeCache !== null) {
958 this.tree._nodeCache.set(seq, wrap)
959 }
960 return wrap
961 }
962
963 async getBlock(seq) {
964 if (this.rootSeq === 0) this.rootSeq = seq
965 await this.tree._cacheLock.enter(seq)
966
967 try {
968 return await this._getBlock(seq)
969 } finally {
970 this.tree._cacheLock.exit(seq)
971 }
972 }
973
974 async _getBlock(seq) {
975 let b = this.blocks && this.blocks.get(seq)
976 if (b) return b
977 this.onseq(seq)
978 const entry = await this._getNode(seq)
979 b = this.blocks && this.blocks.get(seq)
980 if (b) return b
981 b = new BlockEntry(seq, this, entry)
982 if (this.blocks && this.blocks.size - this.length < this.maxBlocksCached) {
983 this.blocks.set(seq, b)
984 }
985 return b
986 }
987
988 _onwait(key) {
989 this.options.onwait = null
990 this.tree.extension.get(this.rootSeq + 1, key)
991 }
992
993 _getEncoding(opts) {
994 if (!opts) return this.encoding
995 return {
996 key: opts.keyEncoding ? codecs(opts.keyEncoding) : this.encoding.key,
997 value: opts.valueEncoding ? codecs(opts.valueEncoding) : this.encoding.value
998 }
999 }
1000
1001 peek(range, opts) {
1002 return iteratorPeek(this.createRangeIterator(range, { ...opts, limit: 1 }))
1003 }
1004
1005 createRangeIterator(range, opts = {}) {
1006 // backwards compat range arg
1007 opts = opts ? { ...opts, ...range } : range
1008
1009 const encoding = this._getEncoding(opts)
1010 return new RangeIterator(
1011 this,
1012 encoding,
1013 encRange(encoding.key, { ...opts, sub: this.tree._sub })
1014 )
1015 }
1016
1017 createReadStream(range, opts) {
1018 const signal = (opts && opts.signal) || null
1019 return iteratorToStream(this.createRangeIterator(range, opts), signal)
1020 }
1021
1022 async getBySeq(seq, opts) {
1023 const encoding = this._getEncoding(opts)
1024
1025 try {
1026 const block = (await this.getBlock(seq)).final(encoding)
1027 return { key: block.key, value: block.value }
1028 } finally {
1029 await this._closeSnapshot()
1030 }
1031 }
1032
1033 async get(key, opts) {
1034 const encoding = this._getEncoding(opts)
1035 const finalize = opts ? opts.finalize !== false : true
1036
1037 try {
1038 return await this._get(key, encoding, finalize)
1039 } finally {
1040 await this._closeSnapshot()
1041 }
1042 }
1043
1044 async _get(key, encoding, finalize) {
1045 key = enc(encoding.key, key)
1046
1047 if (this.tree.extension !== null && this.options.extension !== false) {
1048 this.options.onwait = this._onwait.bind(this, key)
1049 }
1050
1051 let node = await this.getRoot(false)
1052 if (!node) return null
1053
1054 while (true) {
1055 if (node.block.isTarget(key)) {
1056 return node.block.isDeletion() ? null : finalize ? node.block.final(encoding) : node.block
1057 }
1058
1059 let s = 0
1060 let e = node.keys.length
1061 let c
1062
1063 while (s < e) {
1064 const mid = (s + e) >> 1
1065
1066 c = b4a.compare(key, await node.getKey(mid))
1067
1068 if (c === 0) {
1069 const block = await this.getBlock(node.keys[mid].seq)
1070 return finalize ? block.final(encoding) : block
1071 }
1072
1073 if (c < 0) e = mid
1074 else s = mid + 1
1075 }
1076
1077 if (!node.children.length) return null
1078
1079 const i = c < 0 ? e : s
1080 node = await node.getChildNode(i)
1081 }
1082 }
1083
1084 async links(key, seq) {
1085 let node = await this.getRoot(false)
1086 if (!node) return false
1087
1088 if (node.block.seq === seq) return true
1089
1090 while (true) {
1091 if (node.block.isTarget(key)) return false
1092
1093 let s = 0
1094 let e = node.keys.length
1095 let c
1096
1097 while (s < e) {
1098 const mid = (s + e) >> 1
1099
1100 if (node.keys[mid].seq === seq) return true
1101 c = b4a.compare(key, await node.getKey(mid))
1102
1103 if (c === 0) return false
1104
1105 if (c < 0) e = mid
1106 else s = mid + 1
1107 }
1108
1109 if (!node.children.length) return false
1110
1111 const i = c < 0 ? e : s
1112 node = await node.getChildNode(i)
1113 if (node.block.seq === seq) return true
1114 }
1115 }
1116
1117 async put(key, value, opts) {
1118 const release = this.batchLock ? await this.batchLock() : null
1119
1120 const cas = (opts && opts.cas) || null
1121 const encoding = this._getEncoding(opts)
1122
1123 if (!this.locked) await this.lock()
1124 if (!release) return this._put(key, value, encoding, cas)
1125
1126 try {
1127 return await this._put(key, value, encoding, cas)
1128 } finally {
1129 release()
1130 }
1131 }
1132
1133 async _put(key, value, encoding, cas) {
1134 const newNode = {
1135 seq: 0,
1136 key,
1137 value
1138 }
1139 key = enc(encoding.key, key)
1140 value = enc(encoding.value, value)
1141
1142 const stack = []
1143
1144 let root
1145 let node = (root = await this.getRoot(true))
1146 if (!node) node = root = TreeNode.create(null)
1147
1148 const seq = (newNode.seq = this.core.length + this.length)
1149 const target = new Key(seq, key)
1150
1151 while (node.children.length) {
1152 stack.push(node)
1153 node.changed = true // changed, but compressible
1154
1155 let s = 0
1156 let e = node.keys.length
1157 let c
1158
1159 while (s < e) {
1160 const mid = (s + e) >> 1
1161 c = b4a.compare(target.value, await node.getKey(mid))
1162
1163 if (c === 0) {
1164 if (cas) {
1165 const prev = await node.getKeyNode(mid)
1166 if (!(await cas(prev.final(encoding), newNode))) return this._unlockMaybe()
1167 }
1168 if (!this.tree.alwaysDuplicate) {
1169 const prev = await node.getKeyNode(mid)
1170 if (sameValue(prev.value, value)) return this._unlockMaybe()
1171 }
1172 node.setKey(mid, target)
1173 return this._append(root, seq, key, value)
1174 }
1175
1176 if (c < 0) e = mid
1177 else s = mid + 1
1178 }
1179
1180 const i = c < 0 ? e : s
1181 node = await node.getChildNode(i)
1182 }
1183
1184 let needsSplit = !(await node.insertKey(target, value, null, newNode, encoding, cas))
1185 if (!node.changed) return this._unlockMaybe()
1186
1187 while (needsSplit) {
1188 const parent = stack.pop()
1189 const { median, right } = await node.split()
1190
1191 if (parent) {
1192 needsSplit = !(await parent.insertKey(median, value, right, null, encoding, null))
1193 node = parent
1194 } else {
1195 root = TreeNode.create(node.block)
1196 root.changed = true
1197 root.keys.push(median)
1198 root.children.push(new Child(0, 0, node), new Child(0, 0, right))
1199 needsSplit = false
1200 }
1201 }
1202
1203 return this._append(root, seq, key, value)
1204 }
1205
1206 async del(key, opts) {
1207 const release = this.batchLock ? await this.batchLock() : null
1208 const cas = (opts && opts.cas) || null
1209 const encoding = this._getEncoding(opts)
1210
1211 if (!this.locked) await this.lock()
1212 if (!release) return this._del(key, encoding, cas)
1213
1214 try {
1215 return await this._del(key, encoding, cas)
1216 } finally {
1217 release()
1218 }
1219 }
1220
1221 async _del(key, encoding, cas) {
1222 const delNode = {
1223 seq: 0,
1224 key,
1225 value: null
1226 }
1227
1228 key = enc(encoding.key, key)
1229
1230 const stack = []
1231
1232 let node = await this.getRoot(true)
1233 if (!node) return this._unlockMaybe()
1234
1235 const seq = (delNode.seq = this.core.length + this.length)
1236
1237 while (true) {
1238 stack.push(node)
1239
1240 let s = 0
1241 let e = node.keys.length
1242 let c
1243
1244 while (s < e) {
1245 const mid = (s + e) >> 1
1246 c = b4a.compare(key, await node.getKey(mid))
1247
1248 if (c === 0) {
1249 if (cas) {
1250 const prev = await node.getKeyNode(mid)
1251 if (!(await cas(prev.final(encoding), delNode))) return this._unlockMaybe()
1252 }
1253 if (node.children.length) await setKeyToNearestLeaf(node, mid, stack)
1254 else node.removeKey(mid)
1255 // we mark these as changed late, so we don't rewrite them if it is a 404
1256 for (const node of stack) node.changed = true
1257 return this._append(await rebalance(stack), seq, key, null)
1258 }
1259
1260 if (c < 0) e = mid
1261 else s = mid + 1
1262 }
1263
1264 if (!node.children.length) return this._unlockMaybe()
1265
1266 const i = c < 0 ? e : s
1267 node = await node.getChildNode(i)
1268 }
1269 }
1270
1271 async _closeSnapshot() {
1272 if (this.isSnapshot) {
1273 await this.core.close()
1274 this._finalize()
1275 }
1276 }
1277
1278 async close() {
1279 if (this.isSnapshot) return this._closeSnapshot()
1280
1281 this.root = null
1282 if (this.blocks) this.blocks.clear()
1283 this.length = 0
1284 this._unlock()
1285 }
1286
1287 destroy() {
1288 // compat, remove later
1289 this.close().catch(noop)
1290 }
1291
1292 toBlocks() {
1293 if (this.appending) return this.appending
1294
1295 const batch = new Array(this.length)
1296
1297 for (let i = 0; i < this.length; i++) {
1298 const seq = this.core.length + i
1299 const { pendingIndex, key, value } = this.blocks.get(seq)
1300
1301 if (i < this.length - 1) {
1302 pendingIndex[0] = null
1303 let j = 0
1304
1305 while (j < pendingIndex.length) {
1306 const idx = pendingIndex[j]
1307 if (idx !== null && idx.seq === seq) {
1308 idx.offset = j++
1309 continue
1310 }
1311 if (j === pendingIndex.length - 1) pendingIndex.pop()
1312 else pendingIndex[j] = pendingIndex.pop()
1313 }
1314 }
1315
1316 batch[i] = Node.encode({
1317 key,
1318 value,
1319 index: deflate(pendingIndex)
1320 })
1321 }
1322
1323 this.appending = batch
1324 return batch
1325 }
1326
1327 flush() {
1328 if (!this.length) return this.close()
1329
1330 const batch = this.toBlocks()
1331
1332 this.root = null
1333 this.blocks.clear()
1334 this.length = 0
1335
1336 return this._appendBatch(batch)
1337 }
1338
1339 _unlockMaybe() {
1340 if (this.autoFlush) this._unlock()
1341 }
1342
1343 _unlock() {
1344 const locked = this.locked
1345 this.locked = null
1346 if (locked !== null) locked()
1347 this._finalize()
1348 }
1349
1350 _finalize() {
1351 // technically finalize can be called more than once, so here we just check if we already have been removed
1352 if (this.index >= this.tree._batches.length || this.tree._batches[this.index] !== this) return
1353 const top = this.tree._batches.pop()
1354 if (top === this) return
1355 top.index = this.index
1356 this.tree._batches[top.index] = top
1357 }
1358
1359 _append(root, seq, key, value) {
1360 const index = []
1361 root.indexChanges(index, seq)
1362 index[0] = new Child(seq, 0, root)
1363
1364 if (!this.autoFlush) {
1365 const block = new BatchEntry(seq, this, key, value, index)
1366 root.block = block
1367 this.root = root
1368 this.length++
1369 this.blocks.set(seq, block)
1370
1371 root.updateChildren(seq, block)
1372 return
1373 }
1374
1375 return this._appendBatch(
1376 Node.encode({
1377 key,
1378 value,
1379 index: deflate(index)
1380 })
1381 )
1382 }
1383
1384 async _appendBatch(raw) {
1385 try {
1386 await this.core.append(raw)
1387 } finally {
1388 this._unlock()
1389 }
1390 }
1391}
1392
1393class EntryWatcher extends ReadyResource {
1394 constructor(bee, key, opts = {}) {
1395 super()
1396
1397 this.keyEncoding = opts.keyEncoding || bee.keyEncoding
1398 this.valueEncoding = opts.valueEncoding || bee.valueEncoding
1399
1400 this.index = bee._entryWatchers.push(this) - 1
1401 this.bee = bee
1402
1403 this.key = key
1404 this.node = null
1405
1406 this._forceUpdate = false
1407 this._debouncedUpdate = debounce(this._processUpdate.bind(this))
1408 }
1409
1410 _close() {
1411 const top = this.bee._entryWatchers.pop()
1412 if (top !== this) {
1413 top.index = this.index
1414 this.bee._entryWatchers[top.index] = top
1415 }
1416 }
1417
1418 _onappend() {
1419 this._debouncedUpdate()
1420 }
1421
1422 _ontruncate() {
1423 this._forceUpdate = true
1424 this._debouncedUpdate()
1425 }
1426
1427 async _processUpdate() {
1428 const force = this._forceUpdate
1429 this._forceUpdate = false
1430
1431 let newNode
1432 try {
1433 newNode = await this.bee.get(this.key, {
1434 keyEncoding: this.keyEncoding,
1435 valueEncoding: this.valueEncoding
1436 })
1437 } catch (e) {
1438 if (e.code === 'SNAPSHOT_NOT_AVAILABLE') {
1439 // There was a truncate event before the get resolved
1440 // So this handler will run again anyway
1441 return
1442 } else if (this.bee.closing) {
1443 this.close().catch(safetyCatch)
1444 return
1445 }
1446 this.emit('error', e)
1447 return
1448 }
1449
1450 if (force || newNode?.seq !== this.node?.seq) {
1451 this.node = newNode
1452 this.emit('update')
1453 }
1454 }
1455}
1456
1457class Watcher extends ReadyResource {
1458 constructor(bee, range, opts = {}) {
1459 super()
1460
1461 this.keyEncoding = opts.keyEncoding || bee.keyEncoding
1462 this.valueEncoding = opts.valueEncoding || bee.valueEncoding
1463 this.index = bee._watchers.push(this) - 1
1464 this.bee = bee
1465 this.core = bee.core
1466
1467 this.latestDiff = 0
1468 this.range = range
1469 this.map = opts.map || defaultWatchMap
1470
1471 this.current = null
1472 this.previous = null
1473 this.currentMapped = null
1474 this.previousMapped = null
1475 this.stream = null
1476
1477 this._lock = mutexify()
1478 this._flowing = false
1479 this._resolveOnChange = null
1480 this._differ = opts.differ || defaultDiffer
1481 this._eager = !!opts.eager
1482 this._onchange = opts.onchange || null
1483
1484 this.on('newListener', autoFlowOnUpdate)
1485
1486 this.ready().catch(safetyCatch)
1487 }
1488
1489 async _consume() {
1490 if (this._flowing) return
1491 try {
1492 for await (const _ of this) {
1493 } // eslint-disable-line
1494 } catch {}
1495 }
1496
1497 async _open() {
1498 await this.bee.ready()
1499
1500 const opts = {
1501 keyEncoding: this.keyEncoding,
1502 valueEncoding: this.valueEncoding
1503 }
1504
1505 // Point from which to start watching
1506 this.current = this._eager ? this.bee.checkout(1, opts) : this.bee.snapshot(opts)
1507 await this.current.ready()
1508
1509 if (this._onchange) {
1510 if (this._eager) await this._onchange()
1511 this._consume()
1512 }
1513 }
1514
1515 [Symbol.asyncIterator]() {
1516 this._flowing = true
1517 return this
1518 }
1519
1520 _ontruncate() {
1521 this._onappend()
1522 }
1523
1524 _onappend() {
1525 const resolve = this._resolveOnChange
1526 this._resolveOnChange = null
1527 if (resolve) resolve()
1528 }
1529
1530 async _waitForChanges() {
1531 if (this.current.version < this.bee.version || this.closing) return
1532
1533 await new Promise((resolve) => {
1534 this._resolveOnChange = resolve
1535 })
1536 }
1537
1538 async next() {
1539 try {
1540 return await this._next()
1541 } catch (err) {
1542 if (this.closing) return { value: undefined, done: true }
1543 await this.close()
1544 throw err
1545 }
1546 }
1547
1548 async _next() {
1549 const release = await this._lock()
1550
1551 try {
1552 if (this.closing) return { value: undefined, done: true }
1553
1554 if (!this.opened) await this.ready()
1555
1556 while (true) {
1557 await this._waitForChanges()
1558
1559 if (this.closing) return { value: undefined, done: true }
1560
1561 await this._closePrevious()
1562 this.previous = this.current.snapshot()
1563
1564 await this._closeCurrent()
1565 this.current = this.bee.snapshot({
1566 keyEncoding: this.keyEncoding,
1567 valueEncoding: this.valueEncoding
1568 })
1569
1570 await this.current.ready()
1571 await this.previous.ready()
1572
1573 if (this.current.core.fork !== this.previous.core.fork) {
1574 return await this._yield()
1575 }
1576
1577 this.stream = this._differ(this.current, this.previous, this.range)
1578
1579 try {
1580 for await (const data of this.stream) {
1581 // eslint-disable-line
1582 return await this._yield()
1583 }
1584 } finally {
1585 this.stream = null
1586 }
1587 }
1588 } finally {
1589 release()
1590 }
1591 }
1592
1593 async _yield() {
1594 this.currentMapped = this.map(this.current)
1595 this.previousMapped = this.map(this.previous)
1596
1597 if (this._onchange) {
1598 try {
1599 await this._onchange()
1600 } catch (err) {
1601 safetyCatch(err)
1602 }
1603 }
1604
1605 this.emit('update')
1606 return { done: false, value: [this.currentMapped, this.previousMapped] }
1607 }
1608
1609 async return() {
1610 await this.close()
1611 return { done: true }
1612 }
1613
1614 async _close() {
1615 const top = this.bee._watchers.pop()
1616 if (top !== this) {
1617 top.index = this.index
1618 this.bee._watchers[top.index] = top
1619 }
1620
1621 if (this.stream && !this.stream.destroying) {
1622 this.stream.destroy()
1623 }
1624
1625 this._onappend() // Continue execution being closed
1626
1627 await this._closeCurrent().catch(safetyCatch)
1628 await this._closePrevious().catch(safetyCatch)
1629
1630 const release = await this._lock()
1631 release()
1632 }
1633
1634 destroy() {
1635 return this.close()
1636 }
1637
1638 async _closeCurrent() {
1639 if (this.currentMapped) await this.currentMapped.close()
1640 if (this.current) await this.current.close()
1641 this.current = this.currentMapped = null
1642 }
1643
1644 async _closePrevious() {
1645 if (this.previousMapped) await this.previousMapped.close()
1646 if (this.previous) await this.previous.close()
1647 this.previous = this.previousMapped = null
1648 }
1649}
1650
1651function autoFlowOnUpdate(name) {
1652 if (name === 'update') this._consume()
1653}
1654
1655function defaultWatchMap(snapshot) {
1656 return snapshot
1657}
1658
1659async function leafSize(node, goLeft) {
1660 while (node.children.length) node = await node.getChildNode(goLeft ? 0 : node.children.length - 1)
1661 return node.keys.length
1662}
1663
1664async function setKeyToNearestLeaf(node, index, stack) {
1665 let [left, right] = await Promise.all([node.getChildNode(index), node.getChildNode(index + 1)])
1666 const [ls, rs] = await Promise.all([leafSize(left, false), leafSize(right, true)])
1667
1668 if (ls < rs) {
1669 // if fewer leaves on the left
1670 stack.push(right)
1671 while (right.children.length) stack.push((right = right.children[0].value))
1672 node.keys[index] = right.keys.shift()
1673 } else {
1674 // if fewer leaves on the right
1675 stack.push(left)
1676 while (left.children.length) stack.push((left = left.children[left.children.length - 1].value))
1677 node.keys[index] = left.keys.pop()
1678 }
1679}
1680
1681async function rebalance(stack) {
1682 const root = stack[0]
1683
1684 while (stack.length > 1) {
1685 const node = stack.pop()
1686 const parent = stack[stack.length - 1]
1687
1688 if (node.keys.length >= MIN_KEYS) return root
1689
1690 let { left, index, right } = await node.siblings(parent)
1691
1692 // maybe borrow from left sibling?
1693 if (left && left.keys.length > MIN_KEYS) {
1694 left.changed = true
1695 node.keys.unshift(parent.keys[index - 1])
1696 if (left.children.length) node.children.unshift(left.children.pop())
1697 parent.keys[index - 1] = left.keys.pop()
1698 return root
1699 }
1700
1701 // maybe borrow from right sibling?
1702 if (right && right.keys.length > MIN_KEYS) {
1703 right.changed = true
1704 node.keys.push(parent.keys[index])
1705 if (right.children.length) node.children.push(right.children.shift())
1706 parent.keys[index] = right.keys.shift()
1707 return root
1708 }
1709
1710 // merge node with another sibling
1711 if (left) {
1712 index--
1713 right = node
1714 } else {
1715 left = node
1716 }
1717
1718 left.merge(right, parent.keys[index])
1719 parent.removeKey(index)
1720 }
1721
1722 // check if the tree shrunk
1723 if (!root.keys.length && root.children.length) return root.getChildNode(0)
1724 return root
1725}
1726
1727function iteratorToStream(ite, signal) {
1728 let done
1729 let closing
1730
1731 const rs = new Readable({
1732 signal,
1733 open(cb) {
1734 done = cb
1735 ite.open().then(fin, fin)
1736 },
1737 read(cb) {
1738 done = cb
1739 ite.next().then(push, fin)
1740 },
1741 predestroy() {
1742 closing = ite.close()
1743 closing.catch(noop)
1744 },
1745 destroy(cb) {
1746 done = cb
1747 if (!closing) closing = ite.close()
1748 closing.then(fin, fin)
1749 }
1750 })
1751
1752 return rs
1753
1754 function fin(err) {
1755 done(err)
1756 }
1757
1758 function push(val) {
1759 rs.push(val)
1760 done(null)
1761 }
1762}
1763
1764async function iteratorPeek(ite) {
1765 try {
1766 await ite.open()
1767 return await ite.next()
1768 } finally {
1769 await ite.close()
1770 }
1771}
1772
1773function encRange(e, opts) {
1774 if (!e) return opts
1775
1776 if (e.encodeRange) {
1777 const r = e.encodeRange({
1778 gt: opts.gt,
1779 gte: opts.gte,
1780 lt: opts.lt,
1781 lte: opts.lte
1782 })
1783 opts.gt = r.gt
1784 opts.gte = r.gte
1785 opts.lt = r.lt
1786 opts.lte = r.lte
1787 return opts
1788 }
1789
1790 if (opts.gt !== undefined) opts.gt = enc(e, opts.gt)
1791 if (opts.gte !== undefined) opts.gte = enc(e, opts.gte)
1792 if (opts.lt !== undefined) opts.lt = enc(e, opts.lt)
1793 if (opts.lte !== undefined) opts.lte = enc(e, opts.lte)
1794 if (opts.sub && !opts.gt && !opts.gte) opts.gt = enc(e, SEP)
1795 if (opts.sub && !opts.lt && !opts.lte) opts.lt = bump(enc(e, EMPTY))
1796
1797 return opts
1798}
1799
1800function bump(key) {
1801 // key should have been copied by enc above before hitting this
1802 key[key.length - 1]++
1803 return key
1804}
1805
1806function enc(e, v) {
1807 if (v === undefined || v === null) return null
1808 if (e !== null) return e.encode(v)
1809 if (typeof v === 'string') return b4a.from(v)
1810 return v
1811}
1812
1813function prefixEncoding(prefix, keyEncoding) {
1814 return {
1815 encode(key) {
1816 return b4a.concat([prefix, b4a.isBuffer(key) ? key : enc(keyEncoding, key)])
1817 },
1818 decode(key) {
1819 const sliced = key.slice(prefix.length, key.length)
1820 return keyEncoding ? keyEncoding.decode(sliced) : sliced
1821 }
1822 }
1823}
1824
1825function copyEntry(entry) {
1826 let key = entry.key
1827 let value = entry.value
1828 let index = entry.index
1829
1830 // key, value and index all refer to the same buffer (one hypercore block)
1831 // If together they are larger than half the buffer's byteLength,
1832 // this means that they got their own private slab (see Buffer.allocUnsafe docs)
1833 // so no need to unslab
1834 const size =
1835 key.byteLength +
1836 (value === null ? 0 : value.byteLength) +
1837 (index === null ? 0 : index.byteLength)
1838 if (2 * size < key.buffer.byteLength) {
1839 const [newKey, newValue, newIndex] = unslabAll([entry.key, entry.value, entry.index])
1840 key = newKey
1841 value = newValue
1842 index = newIndex
1843 }
1844
1845 return {
1846 key,
1847 value,
1848 index,
1849 inflated: null
1850 }
1851}
1852
1853function defaultDiffer(currentSnap, previousSnap, opts) {
1854 return currentSnap.createDiffStream(previousSnap, opts)
1855}
1856
1857function toNull() {
1858 return null
1859}
1860
1861function getBackingCore(core) {
1862 if (core.core) return core
1863 if (core.getBackingCore) return core.getBackingCore().session
1864 return null
1865}
1866
1867function sameValue(a, b) {
1868 return a === b || (a !== null && b !== null && b4a.equals(a, b))
1869}
1870
1871function noop() {}
1872
1873function getExtension(db, opts) {
1874 if (opts.extension === false) return null
1875 if (opts.extension && opts.extension !== true) return opts.extension
1876 return Extension.register(db)
1877}
1878
1879async function isLinked(batch, block) {
1880 const seq = block.seq
1881 block.inflate()
1882
1883 const keys = [block.key]
1884 const wait = batch.options.wait
1885
1886 for (const l of block.index.levels) {
1887 if (!l.keys.length) continue
1888 batch.options.wait = false
1889 try {
1890 keys.push(await batch.getKey(l.keys[0].seq))
1891 } catch {}
1892 batch.options.wait = wait
1893 }
1894
1895 for (const k of keys) {
1896 if (await batch.links(k, seq)) return true
1897 }
1898
1899 if (batch.core.closing) throw new Error('Core is closed')
1900
1901 return false
1902}
1903
1904module.exports = Hyperbee
node_modules/hyperbee/iterators/diff.js +220 -0
……@@ -0,0 +1,220 @@
1const b4a = require('b4a')
2
3class SubTree {
4 constructor(node, parent) {
5 this.node = node
6 this.parent = parent
7
8 this.isKey = node.children.length === 0
9 this.i = this.isKey ? 1 : 0
10 this.n = 0
11
12 const child = this.isKey ? null : this.node.children[0]
13 this.seq = child !== null ? child.seq : this.node.keys[0].seq
14 this.offset = child !== null ? child.offset : 0
15 }
16
17 next() {
18 this.i++
19 this.isKey = (this.i & 1) === 1
20 if (!this.isKey && !this.node.children.length) this.i++
21 return this.update()
22 }
23
24 async bisect(key, incl) {
25 let s = 0
26 let e = this.node.keys.length
27 let c
28
29 while (s < e) {
30 const mid = (s + e) >> 1
31 c = cmp(key, await this.node.getKey(mid))
32
33 if (c === 0) {
34 if (incl) this.i = mid * 2 + 1
35 else this.i = mid * 2 + (this.node.children.length ? 2 : 3)
36 return true
37 }
38
39 if (c < 0) e = mid
40 else s = mid + 1
41 }
42
43 const i = c < 0 ? e : s
44 this.i = 2 * i + (this.node.children.length ? 0 : 1)
45 return this.node.children.length === 0
46 }
47
48 update() {
49 this.isKey = (this.i & 1) === 1
50 this.n = this.i >> 1
51 if (this.n >= (this.isKey ? this.node.keys.length : this.node.children.length)) return false
52 const child = this.isKey ? null : this.node.children[this.n]
53 this.seq = child !== null ? child.seq : this.node.keys[this.n].seq
54 this.offset = child !== null ? child.offset : 0
55 return true
56 }
57
58 async key() {
59 return this.n < this.node.keys.length
60 ? this.node.getKey(this.n)
61 : this.parent && this.parent.key()
62 }
63
64 async compare(tree) {
65 const [a, b] = await Promise.all([this.key(), tree.key()])
66 return cmp(a, b)
67 }
68}
69
70class TreeIterator {
71 constructor(batch, opts) {
72 this.batch = batch
73 this.stack = []
74 this.lt = opts.lt || opts.lte || null
75 this.lte = !!opts.lte
76 this.gt = opts.gt || opts.gte || null
77 this.gte = !!opts.gte
78 this.seeking = !!this.gt
79 this.encoding = opts.encoding || batch.encoding
80 }
81
82 async open() {
83 const node = await this.batch.getRoot(false)
84 if (!node || !node.keys.length) return
85 const tree = new SubTree(node, null)
86 if (this.seeking && !(await this._seek(tree))) return
87 this.stack.push(tree)
88 }
89
90 async _seek(tree) {
91 const done = await tree.bisect(this.gt, this.gte)
92 const oob = !tree.update()
93 if (done || oob) {
94 this.seeking = false
95 if (oob) return false
96 }
97 return true
98 }
99
100 peek() {
101 if (!this.stack.length) return null
102 return this.stack[this.stack.length - 1]
103 }
104
105 skip() {
106 if (!this.stack.length) return
107 if (!this.stack[this.stack.length - 1].next()) this.stack.pop()
108 }
109
110 async nextKey() {
111 let n = null
112 while (this.stack.length && n === null) n = await this.next()
113 if (n === null) return null
114 if (!this.lt) return n.final(this.encoding)
115
116 const c = cmp(n.key, this.lt)
117 if (this.lte ? c <= 0 : c < 0) return n.final(this.encoding)
118 this.stack = []
119 return null
120 }
121
122 async next() {
123 if (!this.stack.length) return null
124
125 const top = this.stack[this.stack.length - 1]
126 const { isKey, n, seq } = top
127
128 if (!top.next()) {
129 this.stack.pop()
130 }
131
132 if (isKey) {
133 this.seeking = false
134 return this.batch.getBlock(seq)
135 }
136
137 const child = await top.node.getChildNode(n)
138 top.node.children[n] = null // unlink to save memory
139 const tree = new SubTree(child, top)
140 if (this.seeking && !(await this._seek(tree))) return null
141 this.stack.push(tree)
142
143 return null
144 }
145
146 close() {
147 return this.batch._closeSnapshot()
148 }
149}
150
151module.exports = class DiffIterator {
152 constructor(left, right, opts = {}) {
153 this.left = new TreeIterator(left, opts)
154 this.right = new TreeIterator(right, opts)
155 this.limit = typeof opts.limit === 'number' ? opts.limit : -1
156 }
157
158 async open() {
159 await Promise.all([this.left.open(), this.right.open()])
160 }
161
162 async next() {
163 if (this.limit === 0) return null
164 const res = await this._next()
165 if (!res || (res.left === null && res.right === null)) return null
166 this.limit--
167 return res
168 }
169
170 async _next() {
171 const a = this.left
172 const b = this.right
173
174 while (true) {
175 const [l, r] = await Promise.all([a.peek(), b.peek()])
176
177 if (!l && !r) return null
178 if (!l) return { left: null, right: await b.nextKey() }
179 if (!r) return { left: await a.nextKey(), right: null }
180
181 if (l.seq === r.seq && l.isKey === r.isKey && l.offset === r.offset) {
182 a.skip()
183 b.skip()
184 continue
185 }
186
187 const c = await l.compare(r)
188
189 if (l.isKey && !r.isKey) {
190 await b.next()
191 continue
192 }
193
194 if (!l.isKey && r.isKey) {
195 await a.next()
196 continue
197 }
198
199 if (l.isKey && r.isKey) {
200 if (c === 0) return { left: await a.nextKey(), right: await b.nextKey() }
201 if (c < 0) return { left: await a.nextKey(), right: null }
202 return { left: null, right: await b.nextKey() }
203 }
204
205 if (c === 0) await Promise.all([a.next(), b.next()])
206 else if (c < 0) await b.next()
207 else await a.next()
208 }
209 }
210
211 async close() {
212 await Promise.all([this.left.close(), this.right.close()])
213 }
214}
215
216function cmp(a, b) {
217 if (!a) return b ? 1 : 0
218 if (!b) return a ? -1 : 0
219 return b4a.compare(a, b)
220}
node_modules/hyperbee/iterators/history.js +57 -0
……@@ -0,0 +1,57 @@
1module.exports = class HistoryIterator {
2 constructor(batch, opts = {}) {
3 this.batch = batch
4 this.options = opts
5 this.live = !!opts.live
6 this.gte = 0
7 this.lt = 0
8 this.reverse = !!opts.reverse
9 this.limit = typeof opts.limit === 'number' ? opts.limit : -1
10 this.encoding = opts.encoding || batch.encoding
11 if (this.live && this.reverse) {
12 throw new Error('Cannot have both live and reverse enabled')
13 }
14 }
15
16 async open() {
17 await this.batch.getRoot(false) // does the update dance
18 this.gte = gte(this.options, this.batch.version)
19 this.lt = this.live ? Infinity : lt(this.options, this.batch.version)
20 }
21
22 async next() {
23 if (this.limit === 0) return null
24 if (this.limit > 0) this.limit--
25
26 if (this.gte >= this.lt) return null
27
28 if (this.reverse) {
29 if (this.lt <= 1) return null
30 return final(await this.batch.getBlock(--this.lt), this.encoding)
31 }
32
33 return final(await this.batch.getBlock(this.gte++), this.encoding)
34 }
35
36 close() {
37 return this.batch._closeSnapshot()
38 }
39}
40
41function final(node, encoding) {
42 const type = node.isDeletion() ? 'del' : 'put'
43 return { type, ...node.final(encoding) }
44}
45
46function gte(opts, version) {
47 if (opts.gt) return (opts.gt < 0 ? opts.gt + version : opts.gt) + 1
48 const gte = opts.gte || opts.since || 1
49 return gte < 0 ? gte + version : gte
50}
51
52function lt(opts, version) {
53 if (opts.lte === 0 || opts.lt === 0 || opts.end === 0) return 0
54 if (opts.lte) return (opts.lte < 0 ? opts.lte + version : opts.lte) + 1
55 const lt = opts.lt || opts.end || version
56 return lt < 0 ? lt + version : lt
57}
node_modules/hyperbee/iterators/local.js +47 -0
……@@ -0,0 +1,47 @@
1module.exports = class LocalBlocksIterator {
2 constructor(batch, opts = {}) {
3 this.batch = batch
4 this.options = opts
5 this.gte = 0
6 this.lt = 0
7 this.limit = typeof opts.limit === 'number' ? opts.limit : -1
8 }
9
10 async open() {
11 await this.batch.getRoot(false) // does the update dance
12 this.gte = gte(this.options, this.batch.version)
13 this.lt = lt(this.options, this.batch.version)
14 }
15
16 async next() {
17 if (this.limit === 0) return null
18 if (this.limit > 0) this.limit--
19
20 while (this.gte < this.lt) {
21 try {
22 return await this.batch.getBlock(this.gte++)
23 } catch {
24 continue
25 }
26 }
27
28 return null
29 }
30
31 close() {
32 return this.batch._closeSnapshot()
33 }
34}
35
36function gte(opts, version) {
37 if (opts.gt) return (opts.gt < 0 ? opts.gt + version : opts.gt) + 1
38 const gte = opts.gte || opts.since || 1
39 return gte < 0 ? gte + version : gte
40}
41
42function lt(opts, version) {
43 if (opts.lte === 0 || opts.lt === 0 || opts.end === 0) return 0
44 if (opts.lte) return (opts.lte < 0 ? opts.lte + version : opts.lte) + 1
45 const lt = opts.lt || opts.end || version
46 return lt < 0 ? lt + version : lt
47}
node_modules/hyperbee/iterators/range.js +207 -0
……@@ -0,0 +1,207 @@
1const b4a = require('b4a')
2
3module.exports = class RangeIterator {
4 constructor(batch, encoding, opts = {}) {
5 this.batch = batch
6 this.stack = []
7 this.opened = false
8 this.encoding = encoding || batch.encoding
9
10 this._limit = typeof opts.limit === 'number' ? opts.limit : -1
11 this._gIncl = !opts.gt
12 this._gKey = opts.gt || opts.gte || null
13 this._lIncl = !opts.lt
14 this._lKey = opts.lt || opts.lte || null
15 this._reverse = !!opts.reverse
16 this._version = 0
17 this._checkpoint = opts.checkpoint && opts.checkpoint.length ? opts.checkpoint : null
18 this._nexting = false
19 this._closed = false
20 }
21
22 snapshot(version = this.batch.version) {
23 const checkpoint = []
24 for (const s of this.stack) {
25 let { node, i } = s
26 if (this._nexting && s === this.stack[this.stack.length - 1]) {
27 i = this._reverse ? i + 1 : i - 1
28 }
29 if (!node.block) continue
30 if (i < 0) continue
31 checkpoint.push(node.block.seq, node.offset, i)
32 }
33
34 return {
35 version,
36 gte: this._gIncl ? this._gKey : null,
37 gt: this._gIncl ? null : this._gKey,
38 lte: this._lIncl ? this._lKey : null,
39 lt: this._lIncl ? null : this._lKey,
40 limit: this._limit,
41 reverse: this._reverse,
42 ended: this.opened && !checkpoint.length,
43 checkpoint: this.opened ? checkpoint : []
44 }
45 }
46
47 async open() {
48 await this._open()
49 this.opened = true
50 }
51
52 async _open() {
53 if (this._checkpoint) {
54 for (let j = 0; j < this._checkpoint.length; j += 3) {
55 const seq = this._checkpoint[j]
56 const offset = this._checkpoint[j + 1]
57 const i = this._checkpoint[j + 2]
58 this.stack.push({
59 node: (await this.batch.getBlock(seq)).getTreeNode(offset),
60 i
61 })
62 }
63 return
64 }
65
66 this._nexting = true
67
68 let node = await this.batch.getRoot(false)
69 if (!node) {
70 this._nexting = false
71 return
72 }
73
74 const incl = this._reverse ? this._lIncl : this._gIncl
75 const start = this._reverse ? this._lKey : this._gKey
76
77 if (!start) {
78 this.stack.push({ node, i: this._reverse ? node.keys.length << 1 : 0 })
79 this._nexting = false
80 this._preloadQuery()
81 return
82 }
83
84 while (true) {
85 const entry = { node, i: this._reverse ? node.keys.length << 1 : 0 }
86
87 let s = 0
88 let e = node.keys.length
89 let c
90
91 while (s < e) {
92 const mid = (s + e) >> 1
93 c = b4a.compare(start, await node.getKey(mid))
94
95 if (c === 0) {
96 if (incl) entry.i = mid * 2 + 1
97 else entry.i = mid * 2 + (this._reverse ? 0 : 2)
98 this.stack.push(entry)
99 this._nexting = false
100 this._preloadQuery()
101 return
102 }
103
104 if (c < 0) e = mid
105 else s = mid + 1
106 }
107
108 const i = c < 0 ? e : s
109 entry.i = 2 * i + (this._reverse ? -1 : 1)
110
111 if (entry.i >= 0 && entry.i <= node.keys.length << 1) this.stack.push(entry)
112 if (!node.children.length) {
113 this._nexting = false
114 this._preloadQuery()
115 return
116 }
117
118 node = await node.getChildNode(i)
119 }
120 }
121
122 _preloadQuery() {
123 const max = { nodes: 0, max: 2048 }
124
125 if (this._limit === -1 && !this._reverse && this.stack.length) {
126 for (const s of this.stack) {
127 const k = (s.i - (s.i & 1)) / 2
128 this._preload(s.node, k + 1, this._lKey, max).catch(noop)
129 }
130 }
131 }
132
133 async _preload(node, i, end, max) {
134 for (; i < node.keys.length; i++) {
135 const key = node.keys[i]
136 const block = await this.batch.getBlock(key.seq)
137 if (this._closed) return
138 const c = end ? b4a.compare(block.key, end) : -1
139 if (c >= 0 || max.nodes >= max.max || i >= node.children.length) return
140 max.nodes++
141 const next = await node.getChildNode(i)
142 if (this._closed) return
143 this._preload(next, 0, end, max).catch(noop)
144 }
145
146 if (node.children.length && max.nodes < max.max) {
147 const next = await node.getChildNode(node.children.length - 1)
148 if (this._closed) return
149 this._preload(next, 0, end, max).catch(noop)
150 }
151 }
152
153 async next() {
154 // TODO: this nexting flag is only needed if someone asks for a snapshot during
155 // a lookup (ie the extension, pretty important...).
156 // A better solution would be to refactor this so top.i is incremented eagerly
157 // to get the current block instead of the way it is done now (++i vs i++)
158 this._nexting = true
159
160 const end = this._reverse ? this._gKey : this._lKey
161 const incl = this._reverse ? this._gIncl : this._lIncl
162
163 while (this.stack.length && (this._limit === -1 || this._limit > 0)) {
164 const top = this.stack[this.stack.length - 1]
165 const isKey = (top.i & 1) === 1
166 const n = this._reverse ? (top.i < 0 ? top.node.keys.length : top.i-- >> 1) : top.i++ >> 1
167
168 if (!isKey) {
169 if (!top.node.children.length) continue
170 const node = await top.node.getChildNode(n)
171 if (top.node.block.seq < this.batch.core.length) {
172 top.node.children[n].value = null // unlink it to save memory
173 }
174 this.stack.push({ i: this._reverse ? node.keys.length << 1 : 0, node })
175 continue
176 }
177
178 if (n >= top.node.keys.length) {
179 this.stack.pop()
180 continue
181 }
182
183 const key = top.node.keys[n]
184 const block = await this.batch.getBlock(key.seq)
185 if (end) {
186 const c = b4a.compare(block.key, end)
187 if (c === 0 ? !incl : this._reverse ? c < 0 : c > 0) {
188 this._limit = 0
189 break
190 }
191 }
192 if (this._limit > 0) this._limit--
193 this._nexting = false
194 return block.final(this.encoding)
195 }
196
197 this._nexting = false
198 return null
199 }
200
201 close() {
202 this._closed = true
203 return this.batch._closeSnapshot()
204 }
205}
206
207function noop() {}
node_modules/hyperbee/lib/extension.js +161 -0
……@@ -0,0 +1,161 @@
1const { Extension } = require('./messages')
2
3// const MAX_ACTIVE = 32
4const FLUSH_BATCH = 128
5const MAX_PASSIVE_BATCH = 2048
6const MAX_ACTIVE_BATCH = MAX_PASSIVE_BATCH + FLUSH_BATCH
7
8class Batch {
9 constructor(outgoing, from) {
10 this.blocks = []
11 this.start = 0
12 this.end = 0
13 this.outgoing = outgoing
14 this.from = from
15 }
16
17 push(seq) {
18 const len = this.blocks.push(seq)
19 if (len === 1 || seq < this.start) this.start = seq
20 if (len === 1 || seq >= this.end) this.end = seq + 1
21 if (len >= FLUSH_BATCH) {
22 this.send()
23 this.clear()
24 }
25 }
26
27 send() {
28 if (!this.blocks.length) return
29 this.outgoing.send(
30 Extension.encode({
31 cache: { blocks: this.blocks, start: this.start, end: this.end }
32 }),
33 this.from
34 )
35 }
36
37 clear() {
38 this.start = this.end = 0
39 this.blocks = []
40 }
41}
42
43class HyperbeeExtension {
44 constructor(db) {
45 this.encoding = null
46 this.outgoing = null
47 this.db = db
48 this.active = 0
49 }
50
51 get(version, key) {
52 this.outgoing.broadcast(Extension.encode({ get: { version, key } }))
53 }
54
55 iterator(snapshot) {
56 if (snapshot.ended) return
57 if (snapshot.limit === 0) return
58 if (snapshot.limit === -1) snapshot.limit = 0
59 this.outgoing.broadcast(Extension.encode({ iterator: snapshot }))
60 }
61
62 onmessage(buf, from) {
63 // TODO: handle max active extension messages
64 // this.active++
65
66 const message = decode(buf)
67 if (!message) return
68
69 if (message.cache) this.oncache(message.cache, from)
70 if (message.get) this.onget(message.get, from)
71 if (message.iterator) this.oniterator(message.iterator, from)
72 }
73
74 oncache(message, from) {
75 if (!message.blocks.length) return
76 this.db.core.download(message)
77 }
78
79 onget(message, from) {
80 if (!message.version || message.version > this.db.version) return
81
82 const b = new Batch(this.outgoing, from)
83 const db = this.db.checkout(message.version)
84
85 db.get(message.key, {
86 extension: false,
87 wait: false,
88 update: false,
89 onseq
90 }).then(done, done)
91
92 function done() {
93 db.close().catch(noop)
94 b.send()
95 }
96
97 function onseq(seq) {
98 b.push(seq)
99 }
100 }
101
102 async oniterator(message, from) {
103 if (!message.version || message.version > this.db.version) return
104
105 const b = new Batch(this.outgoing, from)
106 const seqs = new Set()
107
108 let skip = message.checkpoint.length
109 let work = 0
110
111 const db = this.db.checkout(message.version)
112 const ite = db.createRangeIterator({
113 ...message,
114 wait: false,
115 extension: false,
116 update: false,
117 limit: message.limit === 0 ? -1 : message.limit,
118 onseq(seq) {
119 if (skip && skip--) return
120 if (seqs.has(seq)) return
121 work++
122 seqs.add(seq)
123 b.push(seq)
124 }
125 })
126
127 try {
128 await ite.open()
129 // eslint-disable-next-line no-unmodified-loop-condition
130 while (work < MAX_ACTIVE_BATCH) {
131 if (!(await ite.next())) break
132 }
133 } catch (_) {
134 // do nothing
135 } finally {
136 ite.close().catch(noop)
137 db.close().catch(noop)
138 b.send()
139 }
140 }
141
142 static register(db) {
143 const e = new this(db)
144 e.outgoing = db.core.registerExtension('hyperbee', e)
145 return e
146 }
147}
148
149HyperbeeExtension.BATCH_SIZE = MAX_PASSIVE_BATCH
150
151module.exports = HyperbeeExtension
152
153function decode(buf) {
154 try {
155 return Extension.decode(buf)
156 } catch (err) {
157 return null
158 }
159}
160
161function noop() {}
node_modules/hyperbee/lib/messages.js +956 -0
……@@ -0,0 +1,956 @@
1// This file is auto generated by the protocol-buffers compiler
2
3/* eslint-disable quotes */
4/* eslint-disable indent */
5/* eslint-disable no-redeclare */
6/* eslint-disable camelcase */
7/* eslint-disable no-var */
8
9// Remember to `npm install --save protocol-buffers-encodings`
10var encodings = require('protocol-buffers-encodings')
11var b4a = require('b4a')
12var varint = encodings.varint
13var skip = encodings.skip
14
15var YoloIndex = exports.YoloIndex = {
16 buffer: true,
17 encodingLength: null,
18 encode: null,
19 decode: null
20}
21
22var Header = exports.Header = {
23 buffer: true,
24 encodingLength: null,
25 encode: null,
26 decode: null
27}
28
29var Node = exports.Node = {
30 buffer: true,
31 encodingLength: null,
32 encode: null,
33 decode: null
34}
35
36var Extension = exports.Extension = {
37 buffer: true,
38 encodingLength: null,
39 encode: null,
40 decode: null
41}
42
43defineYoloIndex()
44defineHeader()
45defineNode()
46defineExtension()
47
48function defineYoloIndex () {
49 var Level = YoloIndex.Level = {
50 buffer: true,
51 encodingLength: null,
52 encode: null,
53 decode: null
54 }
55
56 defineLevel()
57
58 function defineLevel () {
59 Level.encodingLength = encodingLength
60 Level.encode = encode
61 Level.decode = decode
62
63 function encodingLength (obj) {
64 var length = 0
65 if (defined(obj.keys)) {
66 var packedLen = 0
67 for (var i = 0; i < obj.keys.length; i++) {
68 if (!defined(obj.keys[i])) continue
69 var len = encodings.varint.encodingLength(obj.keys[i])
70 packedLen += len
71 }
72 if (packedLen) {
73 length += 1 + packedLen + varint.encodingLength(packedLen)
74 }
75 }
76 if (defined(obj.children)) {
77 var packedLen = 0
78 for (var i = 0; i < obj.children.length; i++) {
79 if (!defined(obj.children[i])) continue
80 var len = encodings.varint.encodingLength(obj.children[i])
81 packedLen += len
82 }
83 if (packedLen) {
84 length += 1 + packedLen + varint.encodingLength(packedLen)
85 }
86 }
87 return length
88 }
89
90 function encode (obj, buf, offset) {
91 if (!offset) offset = 0
92 if (!buf) buf = b4a.allocUnsafe(encodingLength(obj))
93 var oldOffset = offset
94 if (defined(obj.keys)) {
95 var packedLen = 0
96 for (var i = 0; i < obj.keys.length; i++) {
97 if (!defined(obj.keys[i])) continue
98 packedLen += encodings.varint.encodingLength(obj.keys[i])
99 }
100 if (packedLen) {
101 buf[offset++] = 10
102 varint.encode(packedLen, buf, offset)
103 offset += varint.encode.bytes
104 }
105 for (var i = 0; i < obj.keys.length; i++) {
106 if (!defined(obj.keys[i])) continue
107 encodings.varint.encode(obj.keys[i], buf, offset)
108 offset += encodings.varint.encode.bytes
109 }
110 }
111 if (defined(obj.children)) {
112 var packedLen = 0
113 for (var i = 0; i < obj.children.length; i++) {
114 if (!defined(obj.children[i])) continue
115 packedLen += encodings.varint.encodingLength(obj.children[i])
116 }
117 if (packedLen) {
118 buf[offset++] = 18
119 varint.encode(packedLen, buf, offset)
120 offset += varint.encode.bytes
121 }
122 for (var i = 0; i < obj.children.length; i++) {
123 if (!defined(obj.children[i])) continue
124 encodings.varint.encode(obj.children[i], buf, offset)
125 offset += encodings.varint.encode.bytes
126 }
127 }
128 encode.bytes = offset - oldOffset
129 return buf
130 }
131
132 function decode (buf, offset, end) {
133 if (!offset) offset = 0
134 if (!end) end = buf.length
135 if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid")
136 var oldOffset = offset
137 var obj = {
138 keys: [],
139 children: []
140 }
141 while (true) {
142 if (end <= offset) {
143 decode.bytes = offset - oldOffset
144 return obj
145 }
146 var prefix = varint.decode(buf, offset)
147 offset += varint.decode.bytes
148 var tag = prefix >> 3
149 switch (tag) {
150 case 1:
151 var packedEnd = varint.decode(buf, offset)
152 offset += varint.decode.bytes
153 packedEnd += offset
154 while (offset < packedEnd) {
155 obj.keys.push(encodings.varint.decode(buf, offset))
156 offset += encodings.varint.decode.bytes
157 }
158 break
159 case 2:
160 var packedEnd = varint.decode(buf, offset)
161 offset += varint.decode.bytes
162 packedEnd += offset
163 while (offset < packedEnd) {
164 obj.children.push(encodings.varint.decode(buf, offset))
165 offset += encodings.varint.decode.bytes
166 }
167 break
168 default:
169 offset = skip(prefix & 7, buf, offset)
170 }
171 }
172 }
173 }
174
175 YoloIndex.encodingLength = encodingLength
176 YoloIndex.encode = encode
177 YoloIndex.decode = decode
178
179 function encodingLength (obj) {
180 var length = 0
181 if (defined(obj.levels)) {
182 for (var i = 0; i < obj.levels.length; i++) {
183 if (!defined(obj.levels[i])) continue
184 var len = Level.encodingLength(obj.levels[i])
185 length += varint.encodingLength(len)
186 length += 1 + len
187 }
188 }
189 return length
190 }
191
192 function encode (obj, buf, offset) {
193 if (!offset) offset = 0
194 if (!buf) buf = b4a.allocUnsafe(encodingLength(obj))
195 var oldOffset = offset
196 if (defined(obj.levels)) {
197 for (var i = 0; i < obj.levels.length; i++) {
198 if (!defined(obj.levels[i])) continue
199 buf[offset++] = 10
200 varint.encode(Level.encodingLength(obj.levels[i]), buf, offset)
201 offset += varint.encode.bytes
202 Level.encode(obj.levels[i], buf, offset)
203 offset += Level.encode.bytes
204 }
205 }
206 encode.bytes = offset - oldOffset
207 return buf
208 }
209
210 function decode (buf, offset, end) {
211 if (!offset) offset = 0
212 if (!end) end = buf.length
213 if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid")
214 var oldOffset = offset
215 var obj = {
216 levels: []
217 }
218 while (true) {
219 if (end <= offset) {
220 decode.bytes = offset - oldOffset
221 return obj
222 }
223 var prefix = varint.decode(buf, offset)
224 offset += varint.decode.bytes
225 var tag = prefix >> 3
226 switch (tag) {
227 case 1:
228 var len = varint.decode(buf, offset)
229 offset += varint.decode.bytes
230 obj.levels.push(Level.decode(buf, offset, offset + len))
231 offset += Level.decode.bytes
232 break
233 default:
234 offset = skip(prefix & 7, buf, offset)
235 }
236 }
237 }
238}
239
240function defineHeader () {
241 var Metadata = Header.Metadata = {
242 buffer: true,
243 encodingLength: null,
244 encode: null,
245 decode: null
246 }
247
248 defineMetadata()
249
250 function defineMetadata () {
251 Metadata.encodingLength = encodingLength
252 Metadata.encode = encode
253 Metadata.decode = decode
254
255 function encodingLength (obj) {
256 var length = 0
257 if (defined(obj.contentFeed)) {
258 var len = encodings.bytes.encodingLength(obj.contentFeed)
259 length += 1 + len
260 }
261 if (defined(obj.userData)) {
262 var len = encodings.bytes.encodingLength(obj.userData)
263 length += 1 + len
264 }
265 return length
266 }
267
268 function encode (obj, buf, offset) {
269 if (!offset) offset = 0
270 if (!buf) buf = b4a.allocUnsafe(encodingLength(obj))
271 var oldOffset = offset
272 if (defined(obj.contentFeed)) {
273 buf[offset++] = 10
274 encodings.bytes.encode(obj.contentFeed, buf, offset)
275 offset += encodings.bytes.encode.bytes
276 }
277 if (defined(obj.userData)) {
278 buf[offset++] = 18
279 encodings.bytes.encode(obj.userData, buf, offset)
280 offset += encodings.bytes.encode.bytes
281 }
282 encode.bytes = offset - oldOffset
283 return buf
284 }
285
286 function decode (buf, offset, end) {
287 if (!offset) offset = 0
288 if (!end) end = buf.length
289 if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid")
290 var oldOffset = offset
291 var obj = {
292 contentFeed: null,
293 userData: null
294 }
295 while (true) {
296 if (end <= offset) {
297 decode.bytes = offset - oldOffset
298 return obj
299 }
300 var prefix = varint.decode(buf, offset)
301 offset += varint.decode.bytes
302 var tag = prefix >> 3
303 switch (tag) {
304 case 1:
305 obj.contentFeed = encodings.bytes.decode(buf, offset)
306 offset += encodings.bytes.decode.bytes
307 break
308 case 2:
309 obj.userData = encodings.bytes.decode(buf, offset)
310 offset += encodings.bytes.decode.bytes
311 break
312 default:
313 offset = skip(prefix & 7, buf, offset)
314 }
315 }
316 }
317 }
318
319 Header.encodingLength = encodingLength
320 Header.encode = encode
321 Header.decode = decode
322
323 function encodingLength (obj) {
324 var length = 0
325 if (!defined(obj.protocol)) throw new Error("protocol is required")
326 var len = encodings.string.encodingLength(obj.protocol)
327 length += 1 + len
328 if (defined(obj.metadata)) {
329 var len = Metadata.encodingLength(obj.metadata)
330 length += varint.encodingLength(len)
331 length += 1 + len
332 }
333 return length
334 }
335
336 function encode (obj, buf, offset) {
337 if (!offset) offset = 0
338 if (!buf) buf = b4a.allocUnsafe(encodingLength(obj))
339 var oldOffset = offset
340 if (!defined(obj.protocol)) throw new Error("protocol is required")
341 buf[offset++] = 10
342 encodings.string.encode(obj.protocol, buf, offset)
343 offset += encodings.string.encode.bytes
344 if (defined(obj.metadata)) {
345 buf[offset++] = 18
346 varint.encode(Metadata.encodingLength(obj.metadata), buf, offset)
347 offset += varint.encode.bytes
348 Metadata.encode(obj.metadata, buf, offset)
349 offset += Metadata.encode.bytes
350 }
351 encode.bytes = offset - oldOffset
352 return buf
353 }
354
355 function decode (buf, offset, end) {
356 if (!offset) offset = 0
357 if (!end) end = buf.length
358 if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid")
359 var oldOffset = offset
360 var obj = {
361 protocol: "",
362 metadata: null
363 }
364 var found0 = false
365 while (true) {
366 if (end <= offset) {
367 if (!found0) throw new Error("Decoded message is not valid")
368 decode.bytes = offset - oldOffset
369 return obj
370 }
371 var prefix = varint.decode(buf, offset)
372 offset += varint.decode.bytes
373 var tag = prefix >> 3
374 switch (tag) {
375 case 1:
376 obj.protocol = encodings.string.decode(buf, offset)
377 offset += encodings.string.decode.bytes
378 found0 = true
379 break
380 case 2:
381 var len = varint.decode(buf, offset)
382 offset += varint.decode.bytes
383 obj.metadata = Metadata.decode(buf, offset, offset + len)
384 offset += Metadata.decode.bytes
385 break
386 default:
387 offset = skip(prefix & 7, buf, offset)
388 }
389 }
390 }
391}
392
393function defineNode () {
394 Node.encodingLength = encodingLength
395 Node.encode = encode
396 Node.decode = decode
397
398 function encodingLength (obj) {
399 var length = 0
400 if (!defined(obj.index)) throw new Error("index is required")
401 var len = encodings.bytes.encodingLength(obj.index)
402 length += 1 + len
403 if (!defined(obj.key)) throw new Error("key is required")
404 var len = encodings.bytes.encodingLength(obj.key)
405 length += 1 + len
406 if (defined(obj.value)) {
407 var len = encodings.bytes.encodingLength(obj.value)
408 length += 1 + len
409 }
410 return length
411 }
412
413 function encode (obj, buf, offset) {
414 if (!offset) offset = 0
415 if (!buf) buf = b4a.allocUnsafe(encodingLength(obj))
416 var oldOffset = offset
417 if (!defined(obj.index)) throw new Error("index is required")
418 buf[offset++] = 10
419 encodings.bytes.encode(obj.index, buf, offset)
420 offset += encodings.bytes.encode.bytes
421 if (!defined(obj.key)) throw new Error("key is required")
422 buf[offset++] = 18
423 encodings.bytes.encode(obj.key, buf, offset)
424 offset += encodings.bytes.encode.bytes
425 if (defined(obj.value)) {
426 buf[offset++] = 26
427 encodings.bytes.encode(obj.value, buf, offset)
428 offset += encodings.bytes.encode.bytes
429 }
430 encode.bytes = offset - oldOffset
431 return buf
432 }
433
434 function decode (buf, offset, end) {
435 if (!offset) offset = 0
436 if (!end) end = buf.length
437 if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid")
438 var oldOffset = offset
439 var obj = {
440 index: null,
441 key: null,
442 value: null
443 }
444 var found0 = false
445 var found1 = false
446 while (true) {
447 if (end <= offset) {
448 if (!found0 || !found1) throw new Error("Decoded message is not valid")
449 decode.bytes = offset - oldOffset
450 return obj
451 }
452 var prefix = varint.decode(buf, offset)
453 offset += varint.decode.bytes
454 var tag = prefix >> 3
455 switch (tag) {
456 case 1:
457 obj.index = encodings.bytes.decode(buf, offset)
458 offset += encodings.bytes.decode.bytes
459 found0 = true
460 break
461 case 2:
462 obj.key = encodings.bytes.decode(buf, offset)
463 offset += encodings.bytes.decode.bytes
464 found1 = true
465 break
466 case 3:
467 obj.value = encodings.bytes.decode(buf, offset)
468 offset += encodings.bytes.decode.bytes
469 break
470 default:
471 offset = skip(prefix & 7, buf, offset)
472 }
473 }
474 }
475}
476
477function defineExtension () {
478 var Get = Extension.Get = {
479 buffer: true,
480 encodingLength: null,
481 encode: null,
482 decode: null
483 }
484
485 var Iterator = Extension.Iterator = {
486 buffer: true,
487 encodingLength: null,
488 encode: null,
489 decode: null
490 }
491
492 var Cache = Extension.Cache = {
493 buffer: true,
494 encodingLength: null,
495 encode: null,
496 decode: null
497 }
498
499 defineGet()
500 defineIterator()
501 defineCache()
502
503 function defineGet () {
504 Get.encodingLength = encodingLength
505 Get.encode = encode
506 Get.decode = decode
507
508 function encodingLength (obj) {
509 var length = 0
510 if (defined(obj.version)) {
511 var len = encodings.varint.encodingLength(obj.version)
512 length += 1 + len
513 }
514 if (defined(obj.key)) {
515 var len = encodings.bytes.encodingLength(obj.key)
516 length += 1 + len
517 }
518 return length
519 }
520
521 function encode (obj, buf, offset) {
522 if (!offset) offset = 0
523 if (!buf) buf = b4a.allocUnsafe(encodingLength(obj))
524 var oldOffset = offset
525 if (defined(obj.version)) {
526 buf[offset++] = 8
527 encodings.varint.encode(obj.version, buf, offset)
528 offset += encodings.varint.encode.bytes
529 }
530 if (defined(obj.key)) {
531 buf[offset++] = 18
532 encodings.bytes.encode(obj.key, buf, offset)
533 offset += encodings.bytes.encode.bytes
534 }
535 encode.bytes = offset - oldOffset
536 return buf
537 }
538
539 function decode (buf, offset, end) {
540 if (!offset) offset = 0
541 if (!end) end = buf.length
542 if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid")
543 var oldOffset = offset
544 var obj = {
545 version: 0,
546 key: null
547 }
548 while (true) {
549 if (end <= offset) {
550 decode.bytes = offset - oldOffset
551 return obj
552 }
553 var prefix = varint.decode(buf, offset)
554 offset += varint.decode.bytes
555 var tag = prefix >> 3
556 switch (tag) {
557 case 1:
558 obj.version = encodings.varint.decode(buf, offset)
559 offset += encodings.varint.decode.bytes
560 break
561 case 2:
562 obj.key = encodings.bytes.decode(buf, offset)
563 offset += encodings.bytes.decode.bytes
564 break
565 default:
566 offset = skip(prefix & 7, buf, offset)
567 }
568 }
569 }
570 }
571
572 function defineIterator () {
573 Iterator.encodingLength = encodingLength
574 Iterator.encode = encode
575 Iterator.decode = decode
576
577 function encodingLength (obj) {
578 var length = 0
579 if (defined(obj.version)) {
580 var len = encodings.varint.encodingLength(obj.version)
581 length += 1 + len
582 }
583 if (defined(obj.gte)) {
584 var len = encodings.bytes.encodingLength(obj.gte)
585 length += 1 + len
586 }
587 if (defined(obj.gt)) {
588 var len = encodings.bytes.encodingLength(obj.gt)
589 length += 1 + len
590 }
591 if (defined(obj.lte)) {
592 var len = encodings.bytes.encodingLength(obj.lte)
593 length += 1 + len
594 }
595 if (defined(obj.lt)) {
596 var len = encodings.bytes.encodingLength(obj.lt)
597 length += 1 + len
598 }
599 if (defined(obj.limit)) {
600 var len = encodings.varint.encodingLength(obj.limit)
601 length += 1 + len
602 }
603 if (defined(obj.reverse)) {
604 var len = encodings.bool.encodingLength(obj.reverse)
605 length += 1 + len
606 }
607 if (defined(obj.checkpoint)) {
608 var packedLen = 0
609 for (var i = 0; i < obj.checkpoint.length; i++) {
610 if (!defined(obj.checkpoint[i])) continue
611 var len = encodings.varint.encodingLength(obj.checkpoint[i])
612 packedLen += len
613 }
614 if (packedLen) {
615 length += 1 + packedLen + varint.encodingLength(packedLen)
616 }
617 }
618 return length
619 }
620
621 function encode (obj, buf, offset) {
622 if (!offset) offset = 0
623 if (!buf) buf = b4a.allocUnsafe(encodingLength(obj))
624 var oldOffset = offset
625 if (defined(obj.version)) {
626 buf[offset++] = 8
627 encodings.varint.encode(obj.version, buf, offset)
628 offset += encodings.varint.encode.bytes
629 }
630 if (defined(obj.gte)) {
631 buf[offset++] = 18
632 encodings.bytes.encode(obj.gte, buf, offset)
633 offset += encodings.bytes.encode.bytes
634 }
635 if (defined(obj.gt)) {
636 buf[offset++] = 26
637 encodings.bytes.encode(obj.gt, buf, offset)
638 offset += encodings.bytes.encode.bytes
639 }
640 if (defined(obj.lte)) {
641 buf[offset++] = 34
642 encodings.bytes.encode(obj.lte, buf, offset)
643 offset += encodings.bytes.encode.bytes
644 }
645 if (defined(obj.lt)) {
646 buf[offset++] = 42
647 encodings.bytes.encode(obj.lt, buf, offset)
648 offset += encodings.bytes.encode.bytes
649 }
650 if (defined(obj.limit)) {
651 buf[offset++] = 48
652 encodings.varint.encode(obj.limit, buf, offset)
653 offset += encodings.varint.encode.bytes
654 }
655 if (defined(obj.reverse)) {
656 buf[offset++] = 56
657 encodings.bool.encode(obj.reverse, buf, offset)
658 offset += encodings.bool.encode.bytes
659 }
660 if (defined(obj.checkpoint)) {
661 var packedLen = 0
662 for (var i = 0; i < obj.checkpoint.length; i++) {
663 if (!defined(obj.checkpoint[i])) continue
664 packedLen += encodings.varint.encodingLength(obj.checkpoint[i])
665 }
666 if (packedLen) {
667 buf[offset++] = 66
668 varint.encode(packedLen, buf, offset)
669 offset += varint.encode.bytes
670 }
671 for (var i = 0; i < obj.checkpoint.length; i++) {
672 if (!defined(obj.checkpoint[i])) continue
673 encodings.varint.encode(obj.checkpoint[i], buf, offset)
674 offset += encodings.varint.encode.bytes
675 }
676 }
677 encode.bytes = offset - oldOffset
678 return buf
679 }
680
681 function decode (buf, offset, end) {
682 if (!offset) offset = 0
683 if (!end) end = buf.length
684 if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid")
685 var oldOffset = offset
686 var obj = {
687 version: 0,
688 gte: null,
689 gt: null,
690 lte: null,
691 lt: null,
692 limit: 0,
693 reverse: false,
694 checkpoint: []
695 }
696 while (true) {
697 if (end <= offset) {
698 decode.bytes = offset - oldOffset
699 return obj
700 }
701 var prefix = varint.decode(buf, offset)
702 offset += varint.decode.bytes
703 var tag = prefix >> 3
704 switch (tag) {
705 case 1:
706 obj.version = encodings.varint.decode(buf, offset)
707 offset += encodings.varint.decode.bytes
708 break
709 case 2:
710 obj.gte = encodings.bytes.decode(buf, offset)
711 offset += encodings.bytes.decode.bytes
712 break
713 case 3:
714 obj.gt = encodings.bytes.decode(buf, offset)
715 offset += encodings.bytes.decode.bytes
716 break
717 case 4:
718 obj.lte = encodings.bytes.decode(buf, offset)
719 offset += encodings.bytes.decode.bytes
720 break
721 case 5:
722 obj.lt = encodings.bytes.decode(buf, offset)
723 offset += encodings.bytes.decode.bytes
724 break
725 case 6:
726 obj.limit = encodings.varint.decode(buf, offset)
727 offset += encodings.varint.decode.bytes
728 break
729 case 7:
730 obj.reverse = encodings.bool.decode(buf, offset)
731 offset += encodings.bool.decode.bytes
732 break
733 case 8:
734 var packedEnd = varint.decode(buf, offset)
735 offset += varint.decode.bytes
736 packedEnd += offset
737 while (offset < packedEnd) {
738 obj.checkpoint.push(encodings.varint.decode(buf, offset))
739 offset += encodings.varint.decode.bytes
740 }
741 break
742 default:
743 offset = skip(prefix & 7, buf, offset)
744 }
745 }
746 }
747 }
748
749 function defineCache () {
750 Cache.encodingLength = encodingLength
751 Cache.encode = encode
752 Cache.decode = decode
753
754 function encodingLength (obj) {
755 var length = 0
756 if (!defined(obj.start)) throw new Error("start is required")
757 var len = encodings.varint.encodingLength(obj.start)
758 length += 1 + len
759 if (!defined(obj.end)) throw new Error("end is required")
760 var len = encodings.varint.encodingLength(obj.end)
761 length += 1 + len
762 if (defined(obj.blocks)) {
763 var packedLen = 0
764 for (var i = 0; i < obj.blocks.length; i++) {
765 if (!defined(obj.blocks[i])) continue
766 var len = encodings.varint.encodingLength(obj.blocks[i])
767 packedLen += len
768 }
769 if (packedLen) {
770 length += 1 + packedLen + varint.encodingLength(packedLen)
771 }
772 }
773 return length
774 }
775
776 function encode (obj, buf, offset) {
777 if (!offset) offset = 0
778 if (!buf) buf = b4a.allocUnsafe(encodingLength(obj))
779 var oldOffset = offset
780 if (!defined(obj.start)) throw new Error("start is required")
781 buf[offset++] = 8
782 encodings.varint.encode(obj.start, buf, offset)
783 offset += encodings.varint.encode.bytes
784 if (!defined(obj.end)) throw new Error("end is required")
785 buf[offset++] = 16
786 encodings.varint.encode(obj.end, buf, offset)
787 offset += encodings.varint.encode.bytes
788 if (defined(obj.blocks)) {
789 var packedLen = 0
790 for (var i = 0; i < obj.blocks.length; i++) {
791 if (!defined(obj.blocks[i])) continue
792 packedLen += encodings.varint.encodingLength(obj.blocks[i])
793 }
794 if (packedLen) {
795 buf[offset++] = 26
796 varint.encode(packedLen, buf, offset)
797 offset += varint.encode.bytes
798 }
799 for (var i = 0; i < obj.blocks.length; i++) {
800 if (!defined(obj.blocks[i])) continue
801 encodings.varint.encode(obj.blocks[i], buf, offset)
802 offset += encodings.varint.encode.bytes
803 }
804 }
805 encode.bytes = offset - oldOffset
806 return buf
807 }
808
809 function decode (buf, offset, end) {
810 if (!offset) offset = 0
811 if (!end) end = buf.length
812 if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid")
813 var oldOffset = offset
814 var obj = {
815 start: 0,
816 end: 0,
817 blocks: []
818 }
819 var found0 = false
820 var found1 = false
821 while (true) {
822 if (end <= offset) {
823 if (!found0 || !found1) throw new Error("Decoded message is not valid")
824 decode.bytes = offset - oldOffset
825 return obj
826 }
827 var prefix = varint.decode(buf, offset)
828 offset += varint.decode.bytes
829 var tag = prefix >> 3
830 switch (tag) {
831 case 1:
832 obj.start = encodings.varint.decode(buf, offset)
833 offset += encodings.varint.decode.bytes
834 found0 = true
835 break
836 case 2:
837 obj.end = encodings.varint.decode(buf, offset)
838 offset += encodings.varint.decode.bytes
839 found1 = true
840 break
841 case 3:
842 var packedEnd = varint.decode(buf, offset)
843 offset += varint.decode.bytes
844 packedEnd += offset
845 while (offset < packedEnd) {
846 obj.blocks.push(encodings.varint.decode(buf, offset))
847 offset += encodings.varint.decode.bytes
848 }
849 break
850 default:
851 offset = skip(prefix & 7, buf, offset)
852 }
853 }
854 }
855 }
856
857 Extension.encodingLength = encodingLength
858 Extension.encode = encode
859 Extension.decode = decode
860
861 function encodingLength (obj) {
862 var length = 0
863 if (defined(obj.cache)) {
864 var len = Cache.encodingLength(obj.cache)
865 length += varint.encodingLength(len)
866 length += 1 + len
867 }
868 if (defined(obj.get)) {
869 var len = Get.encodingLength(obj.get)
870 length += varint.encodingLength(len)
871 length += 1 + len
872 }
873 if (defined(obj.iterator)) {
874 var len = Iterator.encodingLength(obj.iterator)
875 length += varint.encodingLength(len)
876 length += 1 + len
877 }
878 return length
879 }
880
881 function encode (obj, buf, offset) {
882 if (!offset) offset = 0
883 if (!buf) buf = b4a.allocUnsafe(encodingLength(obj))
884 var oldOffset = offset
885 if (defined(obj.cache)) {
886 buf[offset++] = 10
887 varint.encode(Cache.encodingLength(obj.cache), buf, offset)
888 offset += varint.encode.bytes
889 Cache.encode(obj.cache, buf, offset)
890 offset += Cache.encode.bytes
891 }
892 if (defined(obj.get)) {
893 buf[offset++] = 18
894 varint.encode(Get.encodingLength(obj.get), buf, offset)
895 offset += varint.encode.bytes
896 Get.encode(obj.get, buf, offset)
897 offset += Get.encode.bytes
898 }
899 if (defined(obj.iterator)) {
900 buf[offset++] = 26
901 varint.encode(Iterator.encodingLength(obj.iterator), buf, offset)
902 offset += varint.encode.bytes
903 Iterator.encode(obj.iterator, buf, offset)
904 offset += Iterator.encode.bytes
905 }
906 encode.bytes = offset - oldOffset
907 return buf
908 }
909
910 function decode (buf, offset, end) {
911 if (!offset) offset = 0
912 if (!end) end = buf.length
913 if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid")
914 var oldOffset = offset
915 var obj = {
916 cache: null,
917 get: null,
918 iterator: null
919 }
920 while (true) {
921 if (end <= offset) {
922 decode.bytes = offset - oldOffset
923 return obj
924 }
925 var prefix = varint.decode(buf, offset)
926 offset += varint.decode.bytes
927 var tag = prefix >> 3
928 switch (tag) {
929 case 1:
930 var len = varint.decode(buf, offset)
931 offset += varint.decode.bytes
932 obj.cache = Cache.decode(buf, offset, offset + len)
933 offset += Cache.decode.bytes
934 break
935 case 2:
936 var len = varint.decode(buf, offset)
937 offset += varint.decode.bytes
938 obj.get = Get.decode(buf, offset, offset + len)
939 offset += Get.decode.bytes
940 break
941 case 3:
942 var len = varint.decode(buf, offset)
943 offset += varint.decode.bytes
944 obj.iterator = Iterator.decode(buf, offset, offset + len)
945 offset += Iterator.decode.bytes
946 break
947 default:
948 offset = skip(prefix & 7, buf, offset)
949 }
950 }
951 }
952}
953
954function defined (val) {
955 return val !== null && val !== undefined && (typeof val !== 'number' || !isNaN(val))
956}
node_modules/hyperbee/package.json +60 -0
……@@ -0,0 +1,60 @@
1{
2 "name": "hyperbee",
3 "version": "2.27.3",
4 "description": "An append-only B-tree running on a Hypercore.",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "lib/**.js",
9 "iterators/**.js"
10 ],
11 "dependencies": {
12 "b4a": "^1.6.0",
13 "codecs": "^3.0.0",
14 "debounceify": "^1.0.0",
15 "hypercore-errors": "^1.0.0",
16 "mutexify": "^1.4.0",
17 "protocol-buffers-encodings": "^1.2.0",
18 "rache": "^1.0.0",
19 "ready-resource": "^1.0.0",
20 "resolve-reject-promise": "^1.1.0",
21 "safety-catch": "^1.0.2",
22 "streamx": "^2.12.4",
23 "unslab": "^1.2.0"
24 },
25 "devDependencies": {
26 "bare-process": "^4.2.2",
27 "brittle": "^3.1.0",
28 "hypercore": "^11.0.0",
29 "lunte": "^1.0.0",
30 "prettier": "^3.6.2",
31 "prettier-config-holepunch": "^2.0.0",
32 "protocol-buffers": "^4.2.0",
33 "sub-encoder": "^1.0.6",
34 "tree-to-string": "^1.1.1"
35 },
36 "imports": {
37 "process": {
38 "bare": "bare-process",
39 "default": "process"
40 }
41 },
42 "scripts": {
43 "format": "prettier --write .",
44 "lint": "prettier --check . && lunte",
45 "test": "npm run test:node && npm run test:bare",
46 "test:node": "brittle-node test/*.js",
47 "test:bare": "brittle-bare test/*.js",
48 "protobuf": "protocol-buffers schema.proto -o ./lib/messages.js"
49 },
50 "repository": {
51 "type": "git",
52 "url": "https://github.com/holepunchto/hyperbee.git"
53 },
54 "author": "Mathias Buus (@mafintosh)",
55 "license": "MIT",
56 "bugs": {
57 "url": "https://github.com/holepunchto/hyperbee/issues"
58 },
59 "homepage": "https://github.com/holepunchto/hyperbee"
60}
node_modules/hyperblobs/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/hyperblobs/README.md +101 -0
……@@ -0,0 +1,101 @@
1# hyperblobs
2
3A simple blob store for Hypercore.
4
5Each blob is identified by its unique bounds within the Hypercore, e.g. `{ byteOffset: 0, blockOffset: 0, blockLength: 5, byteLength: 327680 }`, which makes them easy to save and retrieve:
6
7```js
8const blobs = new Hyperblobs(core)
9// ID is { byteOffset: 0, blockOffset: 0, blockLength: 1, byteLength: 11 }
10const id = await blobs.put(Buffer.from('hello world', 'utf-8'))
11await blobs.get(id) // Buffer.from('hello world', 'utf-8')
12```
13
14You can also get from start/end bounds within a single blob:
15
16```js
17const blobs = new Hyperblobs(core)
18// ID is { byteOffset: 0, blockOffset: 0, blockLength: 1, byteLength: 11 }
19const id = await blobs.put(Buffer.from('hello world', 'utf-8'))
20await blobs.get(id, { start: 1, length: 2 }) // Buffer.from('el', 'utf-8')
21```
22
23If the blob is large, there's a Streams interface (`createReadStream` and `createWriteStream`) too.
24
25## Installation
26
27```
28npm i hyperblobs
29```
30
31## API
32
33```js
34const Hyperblobs = require('hyperblobs')
35```
36
37#### `const blobs = new Hyperblobs(core, opts)`
38
39Create a new blob store wrapping a single Hypercore.
40
41Options can include:
42
43```js
44{
45 blockSize: 64KB // The block size that will be used when storing large blobs.
46}
47```
48
49#### `const id = await blobs.put(blob, opts)`
50
51Store a new blob. If the blob is large, it will be chunked according to `opts.blockSize` (default 64KB).
52
53Options can include:
54
55```js
56{
57 blockSize: 64KB, // The block size that will be used when storing large blobs.
58 start: 0, // Relative offset to start within the blob
59 end: blob.length - 1, // End offset within the blob (inclusive)
60 length: blob.length, // Number of bytes to read.
61 core // A custom core to write (overrides the default core)
62}
63```
64
65#### `const content = await blobs.get(id, opts)`
66
67Return a complete blob as a `Buffer`.
68
69`id` is the value returned by `put`
70
71Options can include:
72
73```js
74{
75 core, // A custom core to read from (overrides the default core)
76 wait: true, // Wait for block to be downloaded
77 timeout: 0 // Wait at max some milliseconds (0 means no timeout)
78}
79```
80
81#### `await blobs.clear(id, opts)`
82
83Remove a blob from the core.
84
85`opts` are the same as `Hypercore.clear` method.
86
87#### `const stream = blobs.createReadStream(id, opts)`
88
89Create a Readable stream that will yield the `id` blob.
90
91Options match the `get` options.
92
93#### `const stream = blobs.createWriteStream(opts)`
94
95Create a Writable stream that will save a blob.
96
97The corresponding ID will be set on the stream at `stream.id`.
98
99## License
100
101Apache-2.0
node_modules/hyperblobs/index.js +241 -0
……@@ -0,0 +1,241 @@
1const mutexify = require('mutexify')
2const b4a = require('b4a')
3
4const { BlockMapReadStream, BlobReadStream, BlobWriteStream } = require('./lib/streams')
5const Monitor = require('./lib/monitor')
6const blockMap = require('./lib/block-map')
7
8const DEFAULT_BLOCK_SIZE = 2 ** 16
9
10class HyperBlobsBatch {
11 constructor(blobs) {
12 this.blobs = blobs
13 this.blocks = []
14 this.bytes = 0
15 }
16
17 ready() {
18 return this.blobs.ready()
19 }
20
21 async put(buffer) {
22 if (!this.blobs.core.opened) await this.blobs.core.ready()
23
24 const blockSize = this.blobs.blockSize
25 const result = {
26 blockOffset: this.blobs.core.length + this.blocks.length,
27 blockLength: 0,
28 byteOffset: this.blobs.core.byteLength + this.bytes,
29 byteLength: 0
30 }
31
32 let offset = 0
33 while (offset < buffer.byteLength) {
34 const blk = buffer.subarray(offset, offset + blockSize)
35 offset += blockSize
36
37 result.blockLength++
38 result.byteLength += blk.byteLength
39 this.bytes += blk.byteLength
40 this.blocks.push(blk)
41 }
42
43 return result
44 }
45
46 async get(id) {
47 if (id.blockOffset < this.blobs.core.length) {
48 return this.blobs.get(id)
49 }
50
51 const bufs = []
52
53 for (
54 let i = id.blockOffset - this.blobs.core.length;
55 i < id.blockOffset + id.blockLength;
56 i++
57 ) {
58 if (i >= this.blocks.length) return null
59 bufs.push(this.blocks[i])
60 }
61
62 return bufs.length === 1 ? bufs[0] : b4a.concat(bufs)
63 }
64
65 async flush() {
66 await this.blobs.core.append(this.blocks)
67 this.blocks = []
68 this.bytes = 0
69 }
70
71 close() {
72 // noop, atm nothing to unlink
73 }
74}
75
76class Hyperblobs {
77 constructor(core, opts = {}) {
78 this.core = core
79 this.blockSize = opts.blockSize || DEFAULT_BLOCK_SIZE
80
81 this._lock = mutexify()
82 this._monitors = new Set()
83
84 this._boundUpdatePeers = this._updatePeers.bind(this)
85 this._boundOnUpload = this._onUpload.bind(this)
86 this._boundOnDownload = this._onDownload.bind(this)
87 }
88
89 get key() {
90 return this.core.key
91 }
92
93 get discoveryKey() {
94 return this.core.discoveryKey
95 }
96
97 get feed() {
98 return this.core
99 }
100
101 get locked() {
102 return this._lock.locked
103 }
104
105 replicate(isInitiator, opts) {
106 return this.core.replicate(isInitiator, opts)
107 }
108
109 ready() {
110 return this.core.ready()
111 }
112
113 close() {
114 return this.core.close()
115 }
116
117 batch() {
118 return new HyperBlobsBatch(this)
119 }
120
121 snapshot() {
122 return new Hyperblobs(this.core.snapshot())
123 }
124
125 async put(blob, opts) {
126 if (!b4a.isBuffer(blob)) blob = b4a.from(blob)
127 const blockSize = (opts && opts.blockSize) || this.blockSize
128
129 const stream = this.createWriteStream(opts)
130 for (let i = 0; i < blob.length; i += blockSize) {
131 stream.write(blob.subarray(i, i + blockSize))
132 }
133 stream.end()
134
135 return new Promise((resolve, reject) => {
136 stream.once('error', reject)
137 stream.once('close', () => resolve(stream.id))
138 })
139 }
140
141 async _getAll(id, opts) {
142 if (id.blockLength === 1) return this.core.get(id.blockOffset, opts)
143
144 const promises = new Array(id.blockLength)
145 for (let i = 0; i < id.blockLength; i++) {
146 promises[i] = this.core.get(id.blockOffset + i, opts)
147 }
148
149 const blocks = await Promise.all(promises)
150 for (let i = 0; i < id.blockLength; i++) {
151 if (blocks[i] === null) return null
152 }
153 return b4a.concat(blocks)
154 }
155
156 async get(id, opts) {
157 if (isAll(id, opts)) return this._getAll(id, opts)
158
159 const res = []
160 try {
161 for await (const block of this.createReadStream(id, opts)) {
162 res.push(block)
163 }
164 } catch (error) {
165 if (error.code === 'BLOCK_NOT_AVAILABLE') return null
166 throw error
167 }
168
169 if (res.length === 1) return res[0]
170 return b4a.concat(res)
171 }
172
173 async clear(id, opts) {
174 if (id.blockMap) {
175 const map = await blockMap.get(this.core, id, { wait: false })
176 if (map) {
177 for (const b of map.blocks) await this.core.clear(b.index, b.index + 1, opts)
178 }
179 }
180 return this.core.clear(id.blockOffset, id.blockOffset + id.blockLength, opts)
181 }
182
183 createReadStream(id, opts) {
184 const core = opts && opts.core ? opts.core : this.core
185 return id.blockMap ? new BlockMapReadStream(core, id, opts) : new BlobReadStream(core, id, opts)
186 }
187
188 createWriteStream(opts) {
189 const core = opts && opts.core ? opts.core : this.core
190 return new BlobWriteStream(core, this._lock, opts)
191 }
192
193 monitor(id) {
194 const monitor = new Monitor(this, id)
195 if (this._monitors.size === 0) this._startListening()
196 this._monitors.add(monitor)
197 return monitor
198 }
199
200 _removeMonitor(mon) {
201 this._monitors.delete(mon)
202 if (this._monitors.size === 0) this._stopListening()
203 }
204
205 _updatePeers() {
206 for (const m of this._monitors) m._updatePeers()
207 }
208
209 _onUpload(index, bytes, from) {
210 for (const m of this._monitors) m._onUpload(index, bytes, from)
211 }
212
213 _onDownload(index, bytes, from) {
214 for (const m of this._monitors) m._onDownload(index, bytes, from)
215 }
216
217 _startListening() {
218 this.core.on('peer-add', this._boundUpdatePeers)
219 this.core.on('peer-remove', this._boundUpdatePeers)
220 this.core.on('upload', this._boundOnUpload)
221 this.core.on('download', this._boundOnDownload)
222 }
223
224 _stopListening() {
225 this.core.off('peer-add', this._boundUpdatePeers)
226 this.core.off('peer-remove', this._boundUpdatePeers)
227 this.core.off('upload', this._boundOnUpload)
228 this.core.off('download', this._boundOnDownload)
229 }
230}
231
232module.exports = Hyperblobs
233
234function isAll(id, opts) {
235 if (id.blockMap) return false
236 if (!opts) return true
237 if (opts.start) return false
238 if (opts.length !== undefined || opts.end !== undefined) return false
239 if (opts.core) return false
240 return true
241}
node_modules/hyperblobs/lib/block-map.js +157 -0
……@@ -0,0 +1,157 @@
1const c = require('compact-encoding')
2const b4a = require('b4a')
3const crypto = require('hypercore-crypto')
4
5const block = {
6 preencode(state, m) {
7 c.uint.preencode(state, m.index)
8 c.uint.preencode(state, m.byteLength)
9 },
10 encode(state, m) {
11 c.uint.encode(state, m.index)
12 c.uint.encode(state, m.byteLength)
13 },
14 decode(state) {
15 return {
16 index: c.uint.decode(state),
17 byteLength: c.uint.decode(state)
18 }
19 }
20}
21
22const list = c.array(block)
23
24const map = {
25 preencode(state, m) {
26 c.uint.preencode(state, 0)
27 list.preencode(state, m.blocks)
28 },
29 encode(state, m) {
30 c.uint.encode(state, 0)
31 list.encode(state, m.blocks)
32 },
33 decode(state) {
34 const version = c.uint.decode(state)
35 if (version > 0) throw new Error('Unsupported block map version')
36
37 return {
38 version,
39 blocks: list.decode(state)
40 }
41 }
42}
43
44exports.hash = hashId
45
46function hashId(block) {
47 return b4a.toString(crypto.hash(block), 'hex')
48}
49
50exports.get = getBlockMap
51
52async function inferBlockMap(core, id, opts = {}) {
53 const hashes = !!opts.hashes
54
55 const map = {
56 hashes: hashes ? new Map() : null,
57 blocks: []
58 }
59
60 for (let i = id.blockOffset; i < id.blockOffset + id.blockLength; i++) {
61 const block = await core.get(i)
62 const entry = { index: i, byteLength: block.byteLength }
63 map.blocks.push(entry)
64 if (hashes) map.hashes.set(hashId(block), entry)
65 }
66
67 return map
68}
69
70async function getBlockMap(core, id, opts = {}) {
71 if (!id.blockMap) return inferBlockMap(core, id, opts)
72
73 if (id.blockLength > 64) {
74 throw new Error('Block map is too large')
75 }
76
77 const hashes = !!opts.hashes
78
79 const map = {
80 hashes: hashes ? new Map() : null,
81 blocks: null
82 }
83
84 const promises = []
85
86 for (let i = id.blockOffset; i < id.blockOffset + id.blockLength; i++) {
87 promises.push(core.get(i))
88 }
89
90 const buffers = await Promise.all(promises)
91 const m = decodeBlockMap(buffers)
92 if (!m) return null
93
94 map.blocks = m.blocks
95
96 if (hashes && !core.writable) {
97 const blocks = []
98 for (let i = 0; i < map.blocks.length; i++) blocks.push(map.blocks[i].index)
99 core.download({ blocks })
100 }
101
102 if (hashes) {
103 for (let i = 0; i < map.blocks.length; i++) {
104 const b = map.blocks[i]
105 const block = await core.get(b.index)
106 if (block === null) return null
107 map.hashes.set(hashId(block), b)
108 }
109 }
110
111 return map
112}
113
114exports.encode = encodeBlockMap
115
116function encodeBlockMap(header) {
117 const result = []
118
119 for (let i = 0; i < header.blocks.length; i += 8192) {
120 const blocks =
121 i === 0 && header.blocks.length < 8192 ? header.blocks : header.blocks.slice(i, i + 8192)
122
123 const state = { start: 0, end: 0, buffer: null }
124 const m = { version: 0, blocks }
125
126 map.preencode(state, m)
127 state.buffer = b4a.allocUnsafe(state.end)
128 map.encode(state, m)
129
130 result.push(state.buffer)
131 }
132
133 return result
134}
135
136exports.decode = decodeBlockMap
137
138function decodeBlockMap(buffers) {
139 const result = {
140 version: 0,
141 blocks: null
142 }
143
144 for (let i = 0; i < buffers.length; i++) {
145 if (!buffers[i]) return null
146
147 const state = { start: 0, end: buffers[i].byteLength, buffer: buffers[i] }
148 const r = map.decode(state)
149
150 result.version = r.version
151
152 if (result.blocks) result.blocks.push(...r.blocks)
153 else result.blocks = r.blocks
154 }
155
156 return result
157}
node_modules/hyperblobs/lib/monitor.js +92 -0
……@@ -0,0 +1,92 @@
1const EventEmitter = require('events')
2const speedometer = require('speedometer')
3
4module.exports = class Monitor extends EventEmitter {
5 constructor(blobs, id) {
6 super()
7
8 if (!id) throw new Error('id is required')
9
10 this.blobs = blobs
11 this.id = id
12 this.peers = 0
13 this.uploadSpeedometer = null
14 this.downloadSpeedometer = null
15
16 const stats = {
17 startTime: 0,
18 percentage: 0,
19 peers: 0,
20 speed: 0,
21 blocks: 0,
22 totalBytes: 0, // local + bytes loaded during monitoring
23 monitoringBytes: 0, // bytes loaded during monitoring
24 targetBytes: 0,
25 targetBlocks: 0
26 }
27
28 this.uploadStats = { ...stats }
29 this.downloadStats = { ...stats }
30 this.uploadStats.targetBytes = this.downloadStats.targetBytes = this.id.byteLength
31 this.uploadStats.targetBlocks = this.downloadStats.targetBlocks = this.id.blockLength
32 this.uploadStats.peers = this.downloadStats.peers = this.peers = this.blobs.core.peers.length
33
34 this.uploadSpeedometer = speedometer()
35 this.downloadSpeedometer = speedometer()
36
37 // Handlers
38 }
39
40 // just an alias
41 destroy() {
42 return this.close()
43 }
44
45 close() {
46 this.blobs._removeMonitor(this)
47 }
48
49 _onUpload(index, bytes, from) {
50 this._updateStats(this.uploadSpeedometer, this.uploadStats, index, bytes, from)
51 }
52
53 _onDownload(index, bytes, from) {
54 this._updateStats(this.downloadSpeedometer, this.downloadStats, index, bytes, from)
55 }
56
57 _updatePeers() {
58 this.uploadStats.peers = this.downloadStats.peers = this.peers = this.blobs.core.peers.length
59 this.emit('update')
60 }
61
62 _updateStats(speed, stats, index, bytes) {
63 if (this.closing) return
64 if (!isWithinRange(index, this.id)) return
65
66 if (!stats.startTime) stats.startTime = Date.now()
67
68 stats.speed = speed(bytes)
69 stats.blocks++
70 stats.totalBytes += bytes
71 stats.monitoringBytes += bytes
72 stats.percentage = toFixed((stats.blocks / stats.targetBlocks) * 100)
73
74 this.emit('update')
75 }
76
77 downloadSpeed() {
78 return this.downloadSpeedometer ? this.downloadSpeedometer() : 0
79 }
80
81 uploadSpeed() {
82 return this.uploadSpeedometer ? this.uploadSpeedometer() : 0
83 }
84}
85
86function isWithinRange(index, { blockOffset, blockLength }) {
87 return index >= blockOffset && index < blockOffset + blockLength
88}
89
90function toFixed(n) {
91 return Math.round(n * 100) / 100
92}
node_modules/hyperblobs/lib/prefetcher.js +67 -0
……@@ -0,0 +1,67 @@
1// should move to hypercore itself
2
3const MAX_READAHEAD_TARGET = 0.05 // aim to buffer 5% always
4
5module.exports = class Prefetcher {
6 constructor(core, { max = 64, start = 0, end = core.length, linear = true } = {}) {
7 this.core = core
8 this.max = max
9 this.range = null
10 this.startBound = start
11 this.endBound = end
12 this.maxReadAhead = Math.max(max * 2, Math.floor((end - start) * MAX_READAHEAD_TARGET))
13
14 this.start = start
15 this.end = start
16 this.linear = linear
17 this.missing = 0
18
19 this._ondownloadBound = this._ondownload.bind(this)
20 this.core.on('download', this._ondownloadBound)
21 }
22
23 _ondownload(index) {
24 if (this.range && index < this.end && this.start <= index) {
25 this.missing--
26 this._update()
27 }
28 }
29
30 destroy() {
31 this.core.off('download', this._ondownloadBound)
32 if (this.range) this.range.destroy()
33 this.range = null
34 this.max = 0
35 }
36
37 update(position) {
38 this.start = position
39 if (!this.range) this._update()
40 }
41
42 _update() {
43 if (this.missing >= this.max) return
44 if (this.range) this.range.destroy()
45
46 let end = this.end
47
48 while (end < this.endBound && this.missing < this.max) {
49 end = this.core.core.bitfield.firstUnset(end) + 1
50 if (end >= this.endBound) break
51 this.missing++
52 }
53
54 if (end > this.start + this.maxReadAhead) end = this.start + this.maxReadAhead
55 if (end >= this.endBound) end = this.endBound
56
57 this.end = end
58
59 if (this.start >= this.end) return
60
61 this.range = this.core.download({
62 start: this.start,
63 end: this.end,
64 linear: this.linear
65 })
66 }
67}
node_modules/hyperblobs/lib/streams.js +343 -0
……@@ -0,0 +1,343 @@
1const { Readable, Writable } = require('streamx')
2const { BLOCK_NOT_AVAILABLE } = require('hypercore-errors')
3const Prefetcher = require('./prefetcher')
4const blockMap = require('./block-map')
5
6class BlobWriteStream extends Writable {
7 constructor(core, lock, opts = {}) {
8 super(opts)
9 this.id = { blockOffset: 0, byteOffset: 0, blockLength: 0, byteLength: 0 }
10 this.core = core
11
12 this._dedup = !!opts.dedup
13 this._blob = opts.blob || null
14 this._hashes = null
15 this._addBlockMap = !!opts.blockMap || this._dedup
16 this._blockMap = this._addBlockMap ? { version: 0, blocks: [] } : null
17 this._lock = lock
18 this._release = null
19 this._batch = []
20
21 if (this._addBlockMap) this.id.blockMap = true
22 }
23
24 async _openp() {
25 await this.core.ready()
26 const release = await new Promise((resolve) => this._lock(resolve))
27
28 this._release = release
29 this.id.byteOffset = this.core.byteLength
30 this.id.blockOffset = this.core.length
31
32 if (!this._dedup) return
33
34 if (this._blob) {
35 const map = await blockMap.get(this.core, this._blob, { hashes: true })
36 this._hashes = map.hashes
37 } else {
38 this._hashes = new Map()
39 }
40 }
41
42 _open(cb) {
43 this._openp().then(cb, cb)
44 }
45
46 async _finalp() {
47 await this._append()
48
49 if (this._blockMap) {
50 const buffers = await blockMap.encode(this._blockMap)
51 this.id.blockOffset = this.core.length
52 this.id.byteOffset = this.core.byteLength
53 await this.core.append(buffers)
54 }
55
56 this.id.blockLength = this.core.length - this.id.blockOffset
57 this.id.byteLength = this.core.byteLength - this.id.byteOffset
58 }
59
60 _final(cb) {
61 this._finalp().then(cb, cb)
62 }
63
64 _destroy(cb) {
65 if (this._release) this._release()
66 cb(null)
67 }
68
69 async _append() {
70 if (!this._batch.length) return
71
72 const batch = this._batch
73 this._batch = []
74
75 await this.core.append(batch)
76 }
77
78 _write(data, cb) {
79 let dup = false
80
81 if (this._blockMap) {
82 let entry = {
83 index: this.core.length + this._batch.length,
84 byteLength: data.byteLength
85 }
86
87 if (this._hashes) {
88 const id = blockMap.hash(data)
89 const existing = this._hashes.get(id)
90
91 if (existing) {
92 entry = existing
93 dup = true
94 } else {
95 this._hashes.set(id, entry)
96 }
97 }
98
99 this._blockMap.blocks.push(entry)
100 }
101
102 if (dup) return cb()
103
104 this._batch.push(data)
105
106 if (this._batch.length >= 16) {
107 this._append().then(cb, cb)
108 return
109 }
110
111 return cb()
112 }
113}
114
115class BlockMapReadStream extends Readable {
116 constructor(core, id, opts = {}) {
117 super(opts)
118 this.id = id
119 this.core = core.session({ wait: opts.wait, timeout: opts.timeout })
120
121 const noPrefetch = opts.wait === false || opts.prefetch === false || !core.core
122 const start = opts.start || 0
123 const end =
124 opts.end === undefined ? (opts.length === undefined ? -1 : start + opts.length) : opts.end + 1
125
126 this._blockMap = null
127
128 this._rangeStart = start
129 this._rangeEnd = end
130
131 this._startIndex = 0
132 this._startOffset = 0
133 this._endIndex = -1
134 this._endOffset = -1
135
136 this._range = null
137 this._noPrefetch = noPrefetch
138 }
139
140 async _openp() {
141 this._blockMap = await blockMap.get(this.core, this.id)
142
143 const [startIndex, startOffset, endIndex, endLength] = seekBlockMap(
144 this._blockMap,
145 this._rangeStart,
146 this._rangeEnd
147 )
148
149 this._startIndex = startIndex
150 this._startOffset = startOffset
151 this._endIndex = endIndex
152 this._endOffset = endLength
153
154 if (this._endIndex === -1) {
155 this._endIndex = this._blockMap.blocks.length
156 this._endOffset = 0
157 }
158 }
159
160 _open(cb) {
161 this._openp().then(cb, cb)
162 }
163
164 _predestroy() {
165 if (this._range) this._range.destroy()
166 this.core.close().then(noop, noop)
167 }
168
169 _destroy(cb) {
170 if (this._range) this._range.destroy()
171 this.core.close().then(cb, cb)
172 }
173
174 _prefetch(index) {
175 const blocks = []
176 for (; index < this._endIndex; index++) blocks.push(this._blockMap.blocks[index])
177 this._range = this.core.download({ blocks })
178 }
179
180 async _readp() {
181 if (this._startIndex >= this._endIndex) {
182 this.push(null)
183 return
184 }
185
186 let block = null
187
188 const index = this._startIndex++
189 const b = this._blockMap.blocks[index]
190
191 if (!this._range && !this._noPrefetch) {
192 block = await this.core.get(b.index, { wait: false })
193 if (!block) this._prefetch(index)
194 }
195
196 if (!block) {
197 block = await this.core.get(b.index)
198 }
199
200 if (!block) throw BLOCK_NOT_AVAILABLE()
201
202 if (this._startOffset) {
203 block = block.subarray(this._startOffset)
204 this._startOffset = 0
205 }
206
207 if (this._startIndex === this._endIndex && this._endOffset) {
208 block = block.subarray(0, block.byteLength - this._endOffset)
209 }
210
211 this.push(block)
212 }
213
214 _read(cb) {
215 this._readp().then(cb, cb)
216 }
217}
218
219class BlobReadStream extends Readable {
220 constructor(core, id, opts = {}) {
221 super(opts)
222 this.id = id
223 this.core = core.session({ wait: opts.wait, timeout: opts.timeout })
224
225 const start = id.blockOffset
226 const end = id.blockOffset + id.blockLength
227 const noPrefetch = opts.wait === false || opts.prefetch === false || !core.core
228
229 this._prefetch = noPrefetch
230 ? null
231 : new Prefetcher(this.core, { max: opts.prefetch, start, end })
232 this._lastPrefetch = null
233
234 this._pos = opts.start !== undefined ? id.byteOffset + opts.start : id.byteOffset
235
236 if (opts.length !== undefined) this._end = this._pos + opts.length
237 else if (opts.end !== undefined) this._end = id.byteOffset + opts.end + 1
238 else this._end = id.byteOffset + id.byteLength
239
240 this._index = 0
241 this._relativeOffset = 0
242 this._bytesRead = 0
243 }
244
245 async _openp() {
246 if (this._pos === this.id.byteOffset) {
247 this._index = this.id.blockOffset
248 this._relativeOffset = 0
249 return
250 }
251
252 const result = await this.core.seek(this._pos, {
253 start: this.id.blockOffset,
254 end: this.id.blockOffset + this.id.blockLength
255 })
256
257 if (!result) throw BLOCK_NOT_AVAILABLE()
258
259 this._index = result[0]
260 this._relativeOffset = result[1]
261 }
262
263 _open(cb) {
264 this._openp().then(cb, cb)
265 }
266
267 _predestroy() {
268 if (this._prefetch) this._prefetch.destroy()
269 this.core.close().then(noop, noop)
270 }
271
272 _destroy(cb) {
273 if (this._prefetch) this._prefetch.destroy()
274 this.core.close().then(cb, cb)
275 }
276
277 async _readp() {
278 if (this._pos >= this._end) {
279 this.push(null)
280 return
281 }
282
283 if (this._prefetch) this._prefetch.update(this._index)
284
285 let block = await this.core.get(this._index)
286 if (!block) throw BLOCK_NOT_AVAILABLE()
287
288 const remainder = this._end - this._pos
289 if (this._relativeOffset || remainder < block.length) {
290 block = block.subarray(this._relativeOffset, this._relativeOffset + remainder)
291 }
292
293 this._index++
294 this._relativeOffset = 0
295 this._pos += block.length
296 this._bytesRead += block.length
297
298 this.push(block)
299 }
300
301 _read(cb) {
302 this._readp().then(cb, cb)
303 }
304}
305
306module.exports = {
307 BlockMapReadStream,
308 BlobReadStream,
309 BlobWriteStream
310}
311
312function noop() {}
313
314function seekBlockMap(map, start, end) {
315 let s = -1
316 let so = -1
317 let e = -1
318 let eo = -1
319
320 for (let i = 0; i < map.blocks.length; i++) {
321 const b = map.blocks[i]
322
323 if (s === -1) {
324 if (start < b.byteLength) {
325 s = i
326 so = start
327 } else {
328 start -= b.byteLength
329 }
330 }
331
332 if (e === -1 && end > -1) {
333 if (end <= b.byteLength) {
334 e = i + 1
335 eo = b.byteLength - end
336 } else {
337 end -= b.byteLength
338 }
339 }
340 }
341
342 return [s, so, e, eo]
343}
node_modules/hyperblobs/package.json +55 -0
……@@ -0,0 +1,55 @@
1{
2 "name": "hyperblobs",
3 "version": "2.9.0",
4 "description": "A blob store for Hypercore",
5 "main": "index.js",
6 "scripts": {
7 "format": "prettier --write .",
8 "lint": "prettier --check . && lunte",
9 "test": "npm run test:node && npm run test:bare",
10 "test:node": "brittle-node test/*.js",
11 "test:bare": "brittle-bare test/*.js"
12 },
13 "repository": {
14 "type": "git",
15 "url": "git+https://github.com/holepunchto/hyperblobs.git"
16 },
17 "keywords": [
18 "hypercore",
19 "blob",
20 "store"
21 ],
22 "author": "Andrew Osheroff <andrewosh@gmail.com>",
23 "license": "Apache-2.0",
24 "bugs": {
25 "url": "https://github.com/holepunchto/hyperblobs/issues"
26 },
27 "homepage": "https://github.com/holepunchto/hyperblobs#readme",
28 "files": [
29 "index.js",
30 "lib/**.js"
31 ],
32 "imports": {
33 "events": {
34 "bare": "bare-events",
35 "default": "events"
36 }
37 },
38 "dependencies": {
39 "b4a": "^1.6.1",
40 "bare-events": "^2.5.0",
41 "compact-encoding": "^2.18.0",
42 "hypercore-crypto": "^3.6.1",
43 "hypercore-errors": "^1.1.1",
44 "mutexify": "^1.4.0",
45 "speedometer": "^1.1.0",
46 "streamx": "^2.13.2"
47 },
48 "devDependencies": {
49 "brittle": "^3.1.0",
50 "hypercore": "^11.0.0",
51 "lunte": "^1.0.0",
52 "prettier": "^3.6.2",
53 "prettier-config-holepunch": "^2.0.0"
54 }
55}
node_modules/hypercore-crypto/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2018 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/hypercore-crypto/README.md +68 -0
……@@ -0,0 +1,68 @@
1# hypercore-crypto
2
3The crypto primitives used in hypercore, extracted into a separate module
4
5```
6npm install hypercore-crypto
7```
8
9## Usage
10
11``` js
12const crypto = require('hypercore-crypto')
13
14const keyPair = crypto.keyPair()
15console.log(keyPair) // prints a ed25519 keypair
16```
17
18## API
19
20#### `keyPair = crypto.keyPair()`
21
22Returns an `ED25519` keypair that can used for tree signing.
23
24#### `signature = crypto.sign(message, secretKey)`
25
26Signs a message (buffer).
27
28#### `verified = crypto.verify(message, signature, publicKey)`
29
30Verifies a signature for a message.
31
32#### `hash = crypto.data(data)`
33
34Hashes a leaf node in a merkle tree.
35
36#### `hash = crypto.parent(left, right)`
37
38Hash a parent node in a merkle tree. `left` and `right` should look like this:
39
40```js
41{
42 index: treeIndex,
43 hash: hashOfThisNode,
44 size: byteSizeOfThisTree
45}
46```
47
48#### `hash = crypto.tree(peaks)`
49
50Hashes the merkle root of the tree. `peaks` should be an array of the peaks of the tree and should look like above.
51
52#### `buffer = crypto.randomBytes(size)`
53
54Returns a buffer containing random bytes of size `size`.
55
56#### `hash = crypto.discoveryKey(publicKey)`
57
58Return a hash derived from a `publicKey` that can used for discovery
59without disclosing the public key.
60
61#### `list = crypto.namespace(name, count)`
62
63Make a list of namespaces from a specific publicly known name.
64Use this to namespace capabilities or hashes / signatures across algorithms.
65
66## License
67
68MIT
node_modules/hypercore-crypto/index.js +185 -0
……@@ -0,0 +1,185 @@
1const sodium = require('sodium-universal')
2const c = require('compact-encoding')
3const b4a = require('b4a')
4
5// https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack
6const LEAF_TYPE = b4a.from([0])
7const PARENT_TYPE = b4a.from([1])
8const ROOT_TYPE = b4a.from([2])
9
10const HYPERCORE = b4a.from('hypercore')
11
12exports.keyPair = function (seed) {
13 // key pairs might stay around for a while, so better not to use a default slab to avoid retaining it completely
14 const slab = b4a.allocUnsafeSlow(sodium.crypto_sign_PUBLICKEYBYTES + sodium.crypto_sign_SECRETKEYBYTES)
15 const publicKey = slab.subarray(0, sodium.crypto_sign_PUBLICKEYBYTES)
16 const secretKey = slab.subarray(sodium.crypto_sign_PUBLICKEYBYTES)
17
18 if (seed) sodium.crypto_sign_seed_keypair(publicKey, secretKey, seed)
19 else sodium.crypto_sign_keypair(publicKey, secretKey)
20
21 return {
22 publicKey,
23 secretKey
24 }
25}
26
27exports.validateKeyPair = function (keyPair) {
28 const pk = b4a.allocUnsafe(sodium.crypto_sign_PUBLICKEYBYTES)
29 sodium.crypto_sign_ed25519_sk_to_pk(pk, keyPair.secretKey)
30 return b4a.equals(pk, keyPair.publicKey)
31}
32
33exports.sign = function (message, secretKey) {
34 // Dedicated slab for the signature, to avoid retaining unneeded mem and for security
35 const signature = b4a.allocUnsafeSlow(sodium.crypto_sign_BYTES)
36 sodium.crypto_sign_detached(signature, message, secretKey)
37 return signature
38}
39
40exports.verify = function (message, signature, publicKey) {
41 if (signature.byteLength !== sodium.crypto_sign_BYTES) return false
42 if (publicKey.byteLength !== sodium.crypto_sign_PUBLICKEYBYTES) return false
43 return sodium.crypto_sign_verify_detached(signature, message, publicKey)
44}
45
46exports.encrypt = function (message, publicKey) {
47 const ciphertext = b4a.alloc(message.byteLength + sodium.crypto_box_SEALBYTES)
48 sodium.crypto_box_seal(ciphertext, message, publicKey)
49 return ciphertext
50}
51
52exports.decrypt = function (ciphertext, keyPair) {
53 if (ciphertext.byteLength < sodium.crypto_box_SEALBYTES) return null
54
55 const plaintext = b4a.alloc(ciphertext.byteLength - sodium.crypto_box_SEALBYTES)
56
57 if (!sodium.crypto_box_seal_open(plaintext, ciphertext, keyPair.publicKey, keyPair.secretKey)) {
58 return null
59 }
60
61 return plaintext
62}
63
64exports.encryptionKeyPair = function (seed) {
65 const publicKey = b4a.alloc(sodium.crypto_box_PUBLICKEYBYTES)
66 const secretKey = b4a.alloc(sodium.crypto_box_SECRETKEYBYTES)
67
68 if (seed) {
69 sodium.crypto_box_seed_keypair(publicKey, secretKey, seed)
70 } else {
71 sodium.crypto_box_keypair(publicKey, secretKey)
72 }
73
74 return {
75 publicKey,
76 secretKey
77 }
78}
79
80exports.data = function (data) {
81 const out = b4a.allocUnsafe(32)
82
83 sodium.crypto_generichash_batch(out, [
84 LEAF_TYPE,
85 c.encode(c.uint64, data.byteLength),
86 data
87 ])
88
89 return out
90}
91
92exports.parent = function (a, b) {
93 if (a.index > b.index) {
94 const tmp = a
95 a = b
96 b = tmp
97 }
98
99 const out = b4a.allocUnsafe(32)
100
101 sodium.crypto_generichash_batch(out, [
102 PARENT_TYPE,
103 c.encode(c.uint64, a.size + b.size),
104 a.hash,
105 b.hash
106 ])
107
108 return out
109}
110
111exports.tree = function (roots, out) {
112 const buffers = new Array(3 * roots.length + 1)
113 let j = 0
114
115 buffers[j++] = ROOT_TYPE
116
117 for (let i = 0; i < roots.length; i++) {
118 const r = roots[i]
119 buffers[j++] = r.hash
120 buffers[j++] = c.encode(c.uint64, r.index)
121 buffers[j++] = c.encode(c.uint64, r.size)
122 }
123
124 if (!out) out = b4a.allocUnsafe(32)
125 sodium.crypto_generichash_batch(out, buffers)
126 return out
127}
128
129exports.hash = function (data, out) {
130 if (!out) out = b4a.allocUnsafe(32)
131 if (!Array.isArray(data)) data = [data]
132
133 sodium.crypto_generichash_batch(out, data)
134
135 return out
136}
137
138exports.randomBytes = function (n) {
139 const buf = b4a.allocUnsafe(n)
140 sodium.randombytes_buf(buf)
141 return buf
142}
143
144exports.discoveryKey = function (key) {
145 if (!key || key.byteLength !== 32) throw new Error('Must pass a 32 byte buffer')
146 // Discovery keys might stay around for a while, so better not to use slab memory (for better gc)
147 const digest = b4a.allocUnsafeSlow(32)
148 sodium.crypto_generichash(digest, HYPERCORE, key)
149 return digest
150}
151
152if (sodium.sodium_free) {
153 exports.free = function (secureBuf) {
154 if (secureBuf.secure) sodium.sodium_free(secureBuf)
155 }
156} else {
157 exports.free = function () {}
158}
159
160exports.namespace = function (name, count) {
161 const ids = typeof count === 'number' ? range(count) : count
162
163 // Namespaces are long-lived, so better to use a dedicated slab
164 const buf = b4a.allocUnsafeSlow(32 * ids.length)
165
166 const list = new Array(ids.length)
167
168 // ns is emhemeral, so default slab
169 const ns = b4a.allocUnsafe(33)
170 sodium.crypto_generichash(ns.subarray(0, 32), typeof name === 'string' ? b4a.from(name) : name)
171
172 for (let i = 0; i < list.length; i++) {
173 list[i] = buf.subarray(32 * i, 32 * i + 32)
174 ns[32] = ids[i]
175 sodium.crypto_generichash(list[i], ns)
176 }
177
178 return list
179}
180
181function range (count) {
182 const arr = new Array(count)
183 for (let i = 0; i < count; i++) arr[i] = i
184 return arr
185}
node_modules/hypercore-crypto/node_modules/sodium-native/CMakeLists.txt +279 -0
……@@ -0,0 +1,279 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6find_package(cmake-npm REQUIRED PATHS node_modules/cmake-npm)
7
8set(CMAKE_POSITION_INDEPENDENT_CODE ON)
9
10project(sodium_native C ASM CXX)
11
12fetch_package("github:jedisct1/libsodium#e18eee6" SOURCE_DIR sodium)
13
14fetch_package("github:holepunchto/libjstl#098664c")
15
16bare_target(target)
17
18if(target MATCHES "win32")
19 add_compile_options(/MT$<$<CONFIG:Debug>:d>)
20endif()
21
22file(COPY_FILE "${sodium}/builds/msvc/version.h" "${sodium}/src/libsodium/include/sodium/version.h")
23
24file(GLOB_RECURSE sodium_headers CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.h")
25file(GLOB_RECURSE sodium_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.c")
26file(GLOB_RECURSE sodium_asm_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.S")
27
28add_library(sodium OBJECT)
29
30target_sources(
31 sodium
32 INTERFACE
33 ${sodium_headers}
34 PRIVATE
35 ${sodium_sources}
36)
37
38target_include_directories(
39 sodium
40 INTERFACE
41 "${sodium}/src/libsodium/include"
42 PRIVATE
43 "${sodium}/src/libsodium/include/sodium"
44)
45
46if(NOT target MATCHES "win32")
47 target_compile_options(
48 sodium
49 PRIVATE
50 -fvisibility=hidden
51 -fno-strict-aliasing
52 -fwrapv
53 -flax-vector-conversions
54 )
55endif()
56
57target_compile_definitions(
58 sodium
59 PUBLIC
60 SODIUM_STATIC=1
61 PRIVATE
62 _GNU_SOURCE=1
63 CONFIGURED=1
64 DEV_MODE=1
65 HAVE_ATOMIC_OPS=1
66 HAVE_C11_MEMORY_FENCES=1
67 HAVE_CET_H=1
68 HAVE_GCC_MEMORY_FENCES=1
69 HAVE_INLINE_ASM=1
70 HAVE_INTTYPES_H=1
71 HAVE_STDINT_H=1
72 HAVE_TI_MODE=1
73)
74
75if(target MATCHES "darwin|ios")
76 target_compile_definitions(
77 sodium
78 PRIVATE
79 ASM_HIDE_SYMBOL=.private_extern
80 TLS=_Thread_local
81 HAVE_ARC4RANDOM=1
82 HAVE_ARC4RANDOM_BUF=1
83 HAVE_CATCHABLE_ABRT=1
84 HAVE_CATCHABLE_SEGV=1
85 HAVE_CLOCK_GETTIME=1
86 HAVE_GETPID=1
87 HAVE_MADVISE=1
88 HAVE_MEMSET_S=1
89 HAVE_MLOCK=1
90 HAVE_MMAP=1
91 HAVE_MPROTECT=1
92 HAVE_NANOSLEEP=1
93 HAVE_POSIX_MEMALIGN=1
94 HAVE_PTHREAD=1
95 HAVE_PTHREAD_PRIO_INHERIT=1
96 HAVE_RAISE=1
97 HAVE_SYSCONF=1
98 HAVE_SYS_MMAN_H=1
99 HAVE_SYS_PARAM_H=1
100 HAVE_WEAK_SYMBOLS=1
101 )
102
103 if(NOT target MATCHES "ios")
104 target_compile_definitions(
105 sodium
106 PRIVATE
107 HAVE_GETENTROPY=1
108 HAVE_SYS_RANDOM_H=1
109 )
110 endif()
111endif()
112
113if(target MATCHES "linux")
114 target_compile_definitions(
115 sodium
116 PRIVATE
117 ASM_HIDE_SYMBOL=.hidden
118 TLS=_Thread_local
119 HAVE_CATCHABLE_ABRT=1
120 HAVE_CATCHABLE_SEGV=1
121 HAVE_CLOCK_GETTIME=1
122 HAVE_GETPID=1
123 HAVE_MADVISE=1
124 HAVE_MLOCK=1
125 HAVE_MMAP=1
126 HAVE_MPROTECT=1
127 HAVE_NANOSLEEP=1
128 HAVE_POSIX_MEMALIGN=1
129 HAVE_PTHREAD_PRIO_INHERIT=1
130 HAVE_PTHREAD=1
131 HAVE_RAISE=1
132 HAVE_SYSCONF=1
133 HAVE_SYS_AUXV_H=1
134 HAVE_SYS_MMAN_H=1
135 HAVE_SYS_PARAM_H=1
136 HAVE_SYS_RANDOM_H=1
137 HAVE_WEAK_SYMBOLS=1
138 )
139endif()
140
141if(target MATCHES "win32")
142 target_compile_definitions(
143 sodium
144 PRIVATE
145 _CRT_SECURE_NO_WARNINGS=1
146 HAVE_RAISE=1
147 )
148endif()
149
150if(target MATCHES "x64")
151 target_compile_definitions(
152 sodium
153 PRIVATE
154 HAVE_CPUID=1
155 HAVE_RDRAND=1
156 HAVE_EMMINTRIN_H=1 # SSE2
157 HAVE_PMMINTRIN_H=1 # SSE3
158 HAVE_TMMINTRIN_H=1 # SSSE3
159 HAVE_SMMINTRIN_H=1 # SSE4.1
160 HAVE_WMMINTRIN_H=1 # AES
161 HAVE_AVXINTRIN_H=1 # AVX
162 HAVE_AVX2INTRIN_H=1 # AVX2
163 HAVE_AVX512FINTRIN_H # AVX512F
164 )
165
166 if(NOT target MATCHES "win32")
167 target_compile_definitions(
168 sodium
169 PRIVATE
170 HAVE_AMD64_ASM=1
171 HAVE_AVX_ASM=1
172 )
173
174 target_sources(
175 sodium
176 PRIVATE
177 ${sodium_asm_sources}
178 )
179 endif()
180endif()
181
182if(target MATCHES "arm64")
183 target_compile_definitions(
184 sodium
185 PRIVATE
186 HAVE_ARMCRYPTO=1
187 )
188endif()
189
190if(CMAKE_C_BYTE_ORDER MATCHES "BIG_ENDIAN")
191 target_compile_definitions(
192 sodium
193 PRIVATE
194 NATIVE_BIG_ENDIAN=1
195 )
196else()
197 target_compile_definitions(
198 sodium
199 PRIVATE
200 NATIVE_LITTLE_ENDIAN=1
201 )
202endif()
203
204if(target MATCHES "linux|android")
205 target_link_options(
206 sodium
207 PUBLIC
208 -Wl,-z,noexecstack
209 )
210endif()
211
212add_library(sodium_extensions OBJECT)
213
214target_sources(
215 sodium_extensions
216 PRIVATE
217 extensions/tweak/tweak.c
218 extensions/tweak/tweak.h
219 extensions/pbkdf2/pbkdf2.c
220 extensions/pbkdf2/pbkdf2.h
221)
222
223target_link_libraries(
224 sodium_extensions
225 PUBLIC
226 sodium
227)
228
229add_bare_module(sodium_native_bare)
230
231target_sources(
232 ${sodium_native_bare}
233 PRIVATE
234 binding.cc
235)
236
237target_link_libraries(
238 ${sodium_native_bare}
239 PRIVATE
240 $<TARGET_OBJECTS:sodium>
241 $<TARGET_OBJECTS:sodium_extensions>
242 jstl
243 PUBLIC
244 sodium
245 sodium_extensions
246)
247
248add_napi_module(sodium_native_node)
249
250target_sources(
251 ${sodium_native_node}
252 PRIVATE
253 binding.cc
254)
255
256target_compile_definitions(
257 ${sodium_native_node}
258 PRIVATE
259 NAPI_VERSION=9
260)
261
262target_link_libraries(
263 ${sodium_native_node}
264 PRIVATE
265 $<TARGET_OBJECTS:sodium>
266 $<TARGET_OBJECTS:sodium_extensions>
267 jstl
268 PUBLIC
269 sodium
270 sodium_extensions
271)
272
273resolve_node_module(bare-compat-napi compat)
274
275target_include_directories(
276 ${sodium_native_node}
277 PRIVATE
278 "${compat}/include"
279)
node_modules/hypercore-crypto/node_modules/sodium-native/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2016 Mathias Buus and Emil Bay
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/hypercore-crypto/node_modules/sodium-native/README.md +51 -0
……@@ -0,0 +1,51 @@
1# sodium-native
2
3Low level bindings for [libsodium](https://github.com/jedisct1/libsodium).
4
5```
6npm install sodium-native
7```
8
9The goal of this project is to be thin, stable, unopionated wrapper around libsodium.
10
11All methods exposed are more or less a direct translation of the libsodium c-api.
12This means that most data types are buffers and you have to manage allocating return values and passing them in as arguments instead of receiving them as return values.
13
14This makes this API harder to use than other libsodium wrappers out there, but also means that you'll be able to get a lot of perf / memory improvements as you can do stuff like inline encryption / decryption, reuse buffers etc.
15
16This also makes this library useful as a foundation for more high level crypto abstractions that you want to make.
17
18## Usage
19
20```js
21var sodium = require('sodium-native')
22
23var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
24var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) // secure buffer
25var message = Buffer.from('Hello, World!')
26var ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
27
28sodium.randombytes_buf(nonce) // insert random data into nonce
29sodium.randombytes_buf(key) // insert random data into key
30
31// encrypted message is stored in ciphertext.
32sodium.crypto_secretbox_easy(ciphertext, message, nonce, key)
33
34console.log('Encrypted message:', ciphertext)
35
36var plainText = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES)
37
38if (!sodium.crypto_secretbox_open_easy(plainText, ciphertext, nonce, key)) {
39 console.log('Decryption failed!')
40} else {
41 console.log('Decrypted message:', plainText, '(' + plainText.toString() + ')')
42}
43```
44
45## Documentation
46
47Complete documentation may be found on the [sodium-friends website](https://sodium-friends.github.io/docs/docs/getstarted)
48
49## License
50
51MIT
node_modules/hypercore-crypto/node_modules/sodium-native/binding.cc +4094 -0
……@@ -0,0 +1,4094 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4#include <jstl.h>
5#include <sodium.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <string.h>
9#include <uv.h>
10
11#include "extensions/pbkdf2/pbkdf2.h"
12#include "extensions/tweak/tweak.h"
13
14#define assert_bounds(arraybuffer) \
15 assert(arraybuffer##_offset + arraybuffer##_len <= arraybuffer.size())
16
17static inline void
18sn_sodium_memzero(
19 js_env_t *,
20 js_receiver_t,
21 js_typedarray_span_t<> buf
22) {
23 sodium_memzero(buf.data(), buf.size_bytes());
24}
25
26static inline int
27sn_sodium_mlock(
28 js_env_t *,
29 js_receiver_t,
30 js_typedarray_span_t<> buf
31) {
32 return sodium_mlock(buf.data(), buf.size_bytes());
33}
34
35static inline int
36sn_sodium_munlock(
37 js_env_t *,
38 js_receiver_t,
39 js_typedarray_span_t<> buf
40) {
41 return sodium_munlock(buf.data(), buf.size_bytes());
42}
43
44static void
45sn_external_arraybuffer_finalize(js_env_t *env, uint8_t *ptr) {
46 sodium_free(ptr);
47}
48
49static js_arraybuffer_t
50sn_sodium_malloc(js_env_t *env, js_receiver_t, uint32_t len) {
51 int err;
52
53 auto ptr = reinterpret_cast<uint8_t *>(sodium_malloc(len));
54
55 js_arraybuffer_t buffer;
56
57 err = js_create_external_arraybuffer<sn_external_arraybuffer_finalize>(env, ptr, len, buffer);
58 assert(err == 0);
59
60 return buffer;
61}
62
63static void
64sn_sodium_free(js_env_t *env, js_receiver_t, js_arraybuffer_t buf) {
65 int err;
66
67 std::span<uint8_t> view;
68 err = js_get_arraybuffer_info(env, buf, view);
69 assert(err == 0);
70
71 if (view.empty()) return;
72
73 err = js_detach_arraybuffer(env, buf);
74 assert(err == 0);
75}
76
77static inline int
78sn_sodium_mprotect_noaccess(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
79 return sodium_mprotect_noaccess(buf.data());
80}
81
82static inline int
83sn_sodium_mprotect_readonly(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
84 return sodium_mprotect_readonly(buf.data());
85}
86
87static inline int
88sn_sodium_mprotect_readwrite(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
89 return sodium_mprotect_readwrite(buf.data());
90}
91
92static inline uint32_t // TODO: test envless
93sn_randombytes_random(js_env_t *env, js_receiver_t) {
94 return randombytes_random();
95}
96
97static inline uint32_t // TODO: test envless
98sn_randombytes_uniform(js_env_t *env, js_receiver_t, uint32_t upper_bound) {
99 return randombytes_uniform(upper_bound);
100}
101
102static inline void
103sn_randombytes_buf(
104 js_env_t *env,
105 js_receiver_t,
106 js_arraybuffer_span_t buf,
107 uint32_t buf_offset,
108 uint32_t buf_len
109) {
110 assert_bounds(buf);
111
112 randombytes_buf(&buf[buf_offset], buf_len);
113}
114
115static inline void
116sn_randombytes_buf_deterministic(
117 js_env_t *env,
118 js_receiver_t,
119
120 js_arraybuffer_span_t buf,
121 uint32_t buf_offset,
122 uint32_t buf_len,
123
124 js_arraybuffer_span_t seed,
125 uint32_t seed_offset,
126 uint32_t seed_len
127) {
128 assert_bounds(buf);
129 assert_bounds(seed);
130
131 assert(seed_len == randombytes_SEEDBYTES);
132
133 randombytes_buf_deterministic(&buf[buf_offset], buf_len, &seed[seed_offset]);
134}
135
136static inline bool
137sn_sodium_memcmp(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
138 if (a.size_bytes() != b.size_bytes()) return false;
139
140 return sodium_memcmp(a.data(), b.data(), a.size_bytes()) == 0;
141}
142
143static inline void
144sn_sodium_increment(js_env_t *, js_receiver_t, js_typedarray_span_t<> n) {
145 sodium_increment(n.data(), n.size_bytes());
146}
147
148static inline void
149sn_sodium_add(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
150 sodium_add(a.data(), b.data(), a.size_bytes());
151}
152
153static inline void
154sn_sodium_sub(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
155 sodium_sub(a.data(), b.data(), a.size_bytes());
156}
157
158static inline int32_t
159sn_sodium_compare(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
160 return sodium_compare(a.data(), b.data(), a.size_bytes());
161}
162
163static inline bool
164sn_sodium_is_zero(js_env_t *, js_receiver_t, js_typedarray_span_t<> buffer, uint32_t len) {
165 assert(len <= buffer.size_bytes());
166
167 return sodium_is_zero(buffer.data(), len) != 0;
168}
169
170static inline uint32_t
171sn_sodium_pad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t unpadded_buflen, uint32_t blocksize) {
172 size_t padded_buflen;
173
174 sodium_pad(&padded_buflen, buf.data(), unpadded_buflen, blocksize, buf.size_bytes());
175
176 return padded_buflen;
177}
178
179static inline uint32_t
180sn_sodium_unpad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t padded_buflen, uint32_t blocksize) {
181 size_t unpadded_buflen;
182
183 sodium_unpad(&unpadded_buflen, buf.data(), padded_buflen, blocksize);
184
185 return unpadded_buflen;
186}
187
188static inline int
189sn_crypto_sign_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
190 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
191 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
192
193 return crypto_sign_keypair(pk.data(), sk.data());
194}
195
196static inline int
197sn_crypto_sign_seed_keypair(
198 js_env_t *,
199 js_receiver_t,
200 js_typedarray_span_t<> pk,
201 js_typedarray_span_t<> sk,
202 js_typedarray_span_t<> seed
203) {
204 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
205 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
206 assert(seed.size_bytes() == crypto_sign_SEEDBYTES);
207
208 return crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data());
209}
210
211static inline int
212sn_crypto_sign(
213 js_env_t *,
214 js_receiver_t,
215 js_typedarray_span_t<> sm,
216 js_typedarray_span_t<> m,
217 js_typedarray_span_t<> sk
218) {
219 assert(sm.size_bytes() == crypto_sign_BYTES + m.size_bytes());
220 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
221
222 return crypto_sign(sm.data(), NULL, m.data(), m.size_bytes(), sk.data());
223}
224
225static inline bool
226sn_crypto_sign_open(
227 js_env_t *,
228 js_receiver_t,
229 js_typedarray_span_t<> m,
230 js_typedarray_span_t<> sm,
231 js_typedarray_span_t<> pk
232) {
233 assert(m.size_bytes() == sm.size_bytes() - crypto_sign_BYTES);
234 assert(sm.size_bytes() >= crypto_sign_BYTES);
235 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
236
237 return crypto_sign_open(m.data(), NULL, sm.data(), sm.size_bytes(), pk.data()) == 0;
238}
239
240static inline int
241sn_crypto_sign_detached(
242 js_env_t *env,
243 js_receiver_t,
244 js_typedarray_span_t<> sig,
245 js_typedarray_span_t<> m,
246 js_typedarray_span_t<> sk
247) {
248 assert(sig.size_bytes() == crypto_sign_BYTES);
249 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
250
251 return crypto_sign_detached(sig.data(), NULL, m.data(), m.size_bytes(), sk.data());
252}
253
254static inline bool
255sn_crypto_sign_verify_detached(
256 js_env_t *env,
257 js_receiver_t,
258
259 js_arraybuffer_span_t sig,
260 uint32_t sig_offset,
261 uint32_t sig_len,
262
263 js_arraybuffer_span_t m,
264 uint32_t m_offset,
265 uint32_t m_len,
266
267 js_arraybuffer_span_t pk,
268 uint32_t pk_offset,
269 uint32_t pk_len
270) {
271 assert_bounds(sig);
272 assert_bounds(m);
273 assert_bounds(pk);
274
275 assert(sig_len >= crypto_sign_BYTES);
276 assert(pk_len == crypto_sign_PUBLICKEYBYTES);
277
278 return crypto_sign_verify_detached(&sig[sig_offset], &m[m_offset], m_len, &pk[pk_offset]) == 0;
279}
280
281static inline int
282sn_crypto_sign_ed25519_sk_to_pk(
283 js_env_t *,
284 js_receiver_t,
285 js_typedarray_span_t<> pk,
286 js_typedarray_span_t<> sk
287) {
288 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
289 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
290
291 return crypto_sign_ed25519_sk_to_pk(pk.data(), sk.data());
292}
293
294static inline int
295sn_crypto_sign_ed25519_pk_to_curve25519(
296 js_env_t *,
297 js_receiver_t,
298 js_typedarray_span_t<> x25519_pk,
299 js_typedarray_span_t<> ed25519_pk
300) {
301 assert(x25519_pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
302 assert(ed25519_pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
303
304 return crypto_sign_ed25519_pk_to_curve25519(x25519_pk.data(), ed25519_pk.data());
305}
306
307static inline int
308sn_crypto_sign_ed25519_sk_to_curve25519(
309 js_env_t *,
310 js_receiver_t,
311 js_typedarray_span_t<> x25519_sk,
312 js_typedarray_span_t<> ed25519_sk
313) {
314 assert(x25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES);
315 assert(
316 ed25519_sk.size_bytes() == crypto_sign_SECRETKEYBYTES ||
317 ed25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES
318 );
319
320 return crypto_sign_ed25519_sk_to_curve25519(x25519_sk.data(), ed25519_sk.data());
321}
322
323static inline int
324sn_crypto_generichash(
325 js_env_t *env,
326 js_receiver_t,
327
328 js_arraybuffer_span_t out,
329 uint32_t out_offset,
330 uint32_t out_len,
331
332 js_arraybuffer_span_t in,
333 uint32_t in_offset,
334 uint32_t in_len,
335
336 js_arraybuffer_span_t key,
337 uint32_t key_offset,
338 uint32_t key_len
339) {
340 assert_bounds(out);
341 assert(
342 out_len >= crypto_generichash_BYTES_MIN &&
343 out_len <= crypto_generichash_BYTES_MAX
344 );
345
346 assert_bounds(in);
347
348 uint8_t *key_data = NULL;
349 if (key_len) {
350 assert_bounds(key);
351 assert(
352 key_len >= crypto_generichash_KEYBYTES_MIN &&
353 key_len <= crypto_generichash_KEYBYTES_MAX
354 );
355 key_data = &key[key_offset];
356 }
357
358 return crypto_generichash(&out[out_offset], out_len, &in[in_offset], in_len, key_data, key_len);
359}
360
361static inline int
362sn_crypto_generichash_batch(
363 js_env_t *env,
364 js_receiver_t,
365 js_typedarray_t<uint8_t> out,
366 std::vector<js_typedarray_span_t<>> batch,
367 bool use_key,
368 js_typedarray_t<uint8_t> key
369) {
370 int err;
371
372 uint8_t *out_data;
373 size_t out_len;
374 err = js_get_typedarray_info(env, out, out_data, out_len);
375 assert(err == 0);
376 assert(
377 out_len >= crypto_generichash_BYTES_MIN &&
378 out_len <= crypto_generichash_BYTES_MAX
379 );
380
381 uint8_t *key_data = NULL;
382 size_t key_len = 0;
383 if (use_key) {
384 err = js_get_typedarray_info(env, key, key_data, key_len);
385 assert(err == 0);
386 assert(
387 key_len >= crypto_generichash_KEYBYTES_MIN &&
388 key_len <= crypto_generichash_KEYBYTES_MAX
389 );
390 }
391
392 crypto_generichash_state state;
393 err = crypto_generichash_init(&state, key_data, key_len, out_len);
394 if (err != 0) return err;
395
396 for (auto &buf : batch) {
397 err = crypto_generichash_update(&state, buf.data(), buf.size());
398 if (err != 0) return err;
399 }
400
401 return crypto_generichash_final(&state, out_data, out_len);
402}
403
404static inline void
405sn_crypto_generichash_keygen(
406 js_env_t *env,
407 js_receiver_t,
408
409 js_arraybuffer_span_t key,
410 uint32_t key_offset,
411 uint32_t key_len
412) {
413 assert_bounds(key);
414 assert(key_len == crypto_generichash_KEYBYTES);
415
416 crypto_generichash_keygen(&key[key_offset]);
417}
418
419static inline int
420sn_crypto_generichash_init(
421 js_env_t *env,
422 js_receiver_t,
423
424 js_arraybuffer_span_t state,
425 uint32_t state_offset,
426 uint32_t state_len,
427
428 js_arraybuffer_span_t key,
429 uint32_t key_offset,
430 uint32_t key_len,
431
432 uint32_t out_len
433) {
434 assert_bounds(state);
435
436 assert(state_len == sizeof(crypto_generichash_state));
437
438 uint8_t *key_data = NULL;
439 if (key_len) {
440 assert_bounds(key);
441 assert(
442 key_len >= crypto_generichash_KEYBYTES_MIN &&
443 key_len <= crypto_generichash_KEYBYTES_MAX
444 );
445 key_data = &key[key_offset];
446 }
447
448 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
449
450 return crypto_generichash_init(state_data, key_data, key_len, out_len);
451}
452
453static inline int
454sn_crypto_generichash_update(
455 js_env_t *env,
456 js_receiver_t,
457
458 js_arraybuffer_span_t state,
459 uint32_t state_offset,
460 uint32_t state_len,
461
462 js_arraybuffer_span_t in,
463 uint32_t in_offset,
464 uint32_t in_len
465) {
466 assert_bounds(state);
467 assert_bounds(in);
468
469 assert(state_len == sizeof(crypto_generichash_state));
470
471 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
472
473 return crypto_generichash_update(state_data, &in[in_offset], in_len);
474}
475
476static inline int
477sn_crypto_generichash_final(
478 js_env_t *env,
479 js_receiver_t,
480
481 js_arraybuffer_span_t state,
482 uint32_t state_offset,
483 uint32_t state_len,
484
485 js_arraybuffer_span_t out,
486 uint32_t out_offset,
487 uint32_t out_len
488) {
489 assert_bounds(state);
490 assert_bounds(out);
491
492 assert(state_len == sizeof(crypto_generichash_state));
493
494 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
495
496 return crypto_generichash_final(state_data, &out[out_offset], out_len);
497}
498
499static inline int
500sn_crypto_box_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
501 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
502 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
503
504 return crypto_box_keypair(pk.data(), sk.data());
505}
506
507static inline int
508sn_crypto_box_seed_keypair(
509 js_env_t *,
510 js_receiver_t,
511 js_typedarray_span_t<> pk,
512 js_typedarray_span_t<> sk,
513 js_typedarray_span_t<> seed
514) {
515 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
516 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
517 assert(seed.size_bytes() == crypto_box_SEEDBYTES);
518
519 return crypto_box_seed_keypair(pk.data(), sk.data(), seed.data());
520}
521
522static inline int
523sn_crypto_box_easy(
524 js_env_t *,
525 js_receiver_t,
526 js_typedarray_span_t<> c,
527 js_typedarray_span_t<> m,
528 js_typedarray_span_t<> n,
529 js_typedarray_span_t<> pk,
530 js_typedarray_span_t<> sk
531) {
532 assert(c.size_bytes() == m.size_bytes() + crypto_box_MACBYTES);
533 assert(n.size_bytes() == crypto_box_NONCEBYTES);
534 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
535 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
536
537 return crypto_box_easy(c.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
538}
539
540static inline bool
541sn_crypto_box_open_easy(
542 js_env_t *,
543 js_receiver_t,
544 js_typedarray_span_t<> m,
545 js_typedarray_span_t<> c,
546 js_typedarray_span_t<> n,
547 js_typedarray_span_t<> pk,
548 js_typedarray_span_t<> sk
549) {
550 assert(c.size_bytes() >= crypto_box_MACBYTES);
551 assert(m.size_bytes() == c.size_bytes() - crypto_box_MACBYTES);
552 assert(n.size_bytes() == crypto_box_NONCEBYTES);
553 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
554 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
555
556 return crypto_box_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
557}
558
559static inline int
560sn_crypto_box_detached(
561 js_env_t *,
562 js_receiver_t,
563 js_typedarray_span_t<> c,
564 js_typedarray_span_t<> mac,
565 js_typedarray_span_t<> m,
566 js_typedarray_span_t<> n,
567 js_typedarray_span_t<> pk,
568 js_typedarray_span_t<> sk
569) {
570 assert(c.size_bytes() == m.size_bytes());
571 assert(mac.size_bytes() == crypto_box_MACBYTES);
572 assert(n.size_bytes() == crypto_box_NONCEBYTES);
573 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
574 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
575
576 return crypto_box_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
577}
578
579static inline bool
580sn_crypto_box_open_detached(
581 js_env_t *,
582 js_receiver_t,
583 js_typedarray_span_t<> m,
584 js_typedarray_span_t<> c,
585 js_typedarray_span_t<> mac,
586 js_typedarray_span_t<> n,
587 js_typedarray_span_t<> pk,
588 js_typedarray_span_t<> sk
589) {
590 assert(m.size_bytes() == c.size_bytes());
591 assert(mac.size_bytes() == crypto_box_MACBYTES);
592 assert(n.size_bytes() == crypto_box_NONCEBYTES);
593 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
594 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
595
596 return crypto_box_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
597}
598
599static inline int
600sn_crypto_box_seal(
601 js_env_t *,
602 js_receiver_t,
603 js_typedarray_span_t<> c,
604 js_typedarray_span_t<> m,
605 js_typedarray_span_t<> pk
606) {
607 assert(c.size_bytes() == m.size_bytes() + crypto_box_SEALBYTES);
608 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
609
610 return crypto_box_seal(c.data(), m.data(), m.size_bytes(), pk.data());
611}
612
613static inline bool
614sn_crypto_box_seal_open(
615 js_env_t *env,
616 js_receiver_t,
617
618 js_arraybuffer_span_t m,
619 uint32_t m_offset,
620 uint32_t m_len,
621
622 js_arraybuffer_span_t c,
623 uint32_t c_offset,
624 uint32_t c_len,
625
626 js_arraybuffer_span_t pk,
627 uint32_t pk_offset,
628 uint32_t pk_len,
629
630 js_arraybuffer_span_t sk,
631 uint32_t sk_offset,
632 uint32_t sk_len
633) {
634 assert_bounds(m);
635 assert_bounds(c);
636 assert_bounds(pk);
637 assert_bounds(sk);
638
639 assert(m_len == c_len - crypto_box_SEALBYTES);
640 assert(c_len >= crypto_box_SEALBYTES);
641 assert(sk_len == crypto_box_SECRETKEYBYTES);
642 assert(pk_len == crypto_box_PUBLICKEYBYTES);
643
644 return crypto_box_seal_open(&m[m_offset], &c[c_offset], c_len, &pk[pk_offset], &sk[sk_offset]) == 0;
645}
646
647static inline int
648sn_crypto_secretbox_easy(
649 js_env_t *,
650 js_receiver_t,
651 js_typedarray_span_t<> c,
652 js_typedarray_span_t<> m,
653 js_typedarray_span_t<> n,
654 js_typedarray_span_t<> k
655) {
656 assert(c.size_bytes() == m.size_bytes() + crypto_secretbox_MACBYTES);
657 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
658 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
659
660 return crypto_secretbox_easy(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
661}
662
663static inline bool
664sn_crypto_secretbox_open_easy(
665 js_env_t *,
666 js_receiver_t,
667 js_typedarray_span_t<> m,
668 js_typedarray_span_t<> c,
669 js_typedarray_span_t<> n,
670 js_typedarray_span_t<> k
671) {
672 assert(m.size_bytes() == c.size_bytes() - crypto_secretbox_MACBYTES);
673 assert(c.size_bytes() >= crypto_secretbox_MACBYTES);
674 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
675 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
676
677 return crypto_secretbox_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), k.data()) == 0;
678}
679
680static inline int
681sn_crypto_secretbox_detached(
682 js_env_t *,
683 js_receiver_t,
684 js_typedarray_span_t<> c,
685 js_typedarray_span_t<> mac,
686 js_typedarray_span_t<> m,
687 js_typedarray_span_t<> n,
688 js_typedarray_span_t<> k
689) {
690 assert(c.size_bytes() == m.size_bytes());
691 assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
692 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
693 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
694
695 return crypto_secretbox_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), k.data());
696}
697
698static inline bool
699sn_crypto_secretbox_open_detached(
700 js_env_t *,
701 js_receiver_t,
702 js_typedarray_span_t<> m,
703 js_typedarray_span_t<> c,
704 js_typedarray_span_t<> mac,
705 js_typedarray_span_t<> n,
706 js_typedarray_span_t<> k
707) {
708 assert(m.size_bytes() == c.size_bytes());
709 assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
710 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
711 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
712
713 return crypto_secretbox_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), k.data()) == 0;
714}
715
716static inline int
717sn_crypto_stream(
718 js_env_t *,
719 js_receiver_t,
720 js_typedarray_span_t<> c,
721 js_typedarray_span_t<> n,
722 js_typedarray_span_t<> k
723) {
724 assert(n.size_bytes() == crypto_stream_NONCEBYTES);
725 assert(k.size_bytes() == crypto_stream_KEYBYTES);
726
727 return crypto_stream(c.data(), c.size_bytes(), n.data(), k.data());
728}
729
730static inline int
731sn_crypto_stream_xor(
732 js_env_t *env,
733 js_receiver_t,
734
735 js_arraybuffer_span_t c,
736 uint32_t c_offset,
737 uint32_t c_len,
738
739 js_arraybuffer_span_t m,
740 uint32_t m_offset,
741 uint32_t m_len,
742
743 js_arraybuffer_span_t n,
744 uint32_t n_offset,
745 uint32_t n_len,
746
747 js_arraybuffer_span_t k,
748 uint32_t k_offset,
749 uint32_t k_len
750) {
751 assert_bounds(c);
752 assert_bounds(m);
753 assert_bounds(n);
754 assert_bounds(k);
755
756 assert(c_len == m_len);
757 assert(n_len == crypto_stream_NONCEBYTES);
758 assert(k_len == crypto_stream_KEYBYTES);
759
760 return crypto_stream_xor(&c[c_offset], &m[m_offset], m_len, &n[n_offset], &k[k_offset]);
761}
762
763static inline int
764sn_crypto_stream_chacha20(
765 js_env_t *,
766 js_receiver_t,
767 js_typedarray_span_t<> c,
768 js_typedarray_span_t<> n,
769 js_typedarray_span_t<> k
770) {
771 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
772 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
773
774 return crypto_stream_chacha20(c.data(), c.size_bytes(), n.data(), k.data());
775}
776
777static inline int
778sn_crypto_stream_chacha20_xor(
779 js_env_t *,
780 js_receiver_t,
781 js_typedarray_span_t<> c,
782 js_typedarray_span_t<> m,
783 js_typedarray_span_t<> n,
784 js_typedarray_span_t<> k
785) {
786 assert(c.size_bytes() == m.size_bytes());
787 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
788 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
789
790 return crypto_stream_chacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
791}
792
793static inline int
794sn_crypto_stream_chacha20_xor_ic(
795 js_env_t *,
796 js_receiver_t,
797 js_typedarray_span_t<> c,
798 js_typedarray_span_t<> m,
799 js_typedarray_span_t<> n,
800 uint32_t ic,
801 js_typedarray_span_t<> k
802) {
803 assert(c.size_bytes() == m.size_bytes());
804 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
805 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
806
807 return crypto_stream_chacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
808}
809
810static inline int
811sn_crypto_stream_chacha20_ietf(
812 js_env_t *,
813 js_receiver_t,
814 js_typedarray_span_t<> c,
815 js_typedarray_span_t<> n,
816 js_typedarray_span_t<> k
817) {
818 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
819 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
820
821 return crypto_stream_chacha20_ietf(c.data(), c.size_bytes(), n.data(), k.data());
822}
823
824static inline int
825sn_crypto_stream_chacha20_ietf_xor(
826 js_env_t *,
827 js_receiver_t,
828 js_typedarray_span_t<> c,
829 js_typedarray_span_t<> m,
830 js_typedarray_span_t<> n,
831 js_typedarray_span_t<> k
832) {
833 assert(c.size_bytes() == m.size_bytes());
834 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
835 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
836
837 return crypto_stream_chacha20_ietf_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
838}
839
840static inline int
841sn_crypto_stream_chacha20_ietf_xor_ic(
842 js_env_t *,
843 js_receiver_t,
844 js_typedarray_span_t<> c,
845 js_typedarray_span_t<> m,
846 js_typedarray_span_t<> n,
847 uint32_t ic,
848 js_typedarray_span_t<> k
849) {
850 assert(c.size_bytes() == m.size_bytes());
851 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
852 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
853
854 return crypto_stream_chacha20_ietf_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
855}
856
857static inline int
858sn_crypto_stream_xchacha20(
859 js_env_t *,
860 js_receiver_t,
861 js_typedarray_span_t<> c,
862 js_typedarray_span_t<> n,
863 js_typedarray_span_t<> k
864) {
865 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
866 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
867
868 return crypto_stream_xchacha20(c.data(), c.size_bytes(), n.data(), k.data());
869}
870
871static inline int
872sn_crypto_stream_xchacha20_xor(
873 js_env_t *,
874 js_receiver_t,
875 js_typedarray_span_t<> c,
876 js_typedarray_span_t<> m,
877 js_typedarray_span_t<> n,
878 js_typedarray_span_t<> k
879) {
880 assert(c.size_bytes() == m.size_bytes());
881 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
882 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
883
884 return crypto_stream_xchacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
885}
886
887static inline int
888sn_crypto_stream_xchacha20_xor_ic(
889 js_env_t *,
890 js_receiver_t,
891 js_typedarray_span_t<> c,
892 js_typedarray_span_t<> m,
893 js_typedarray_span_t<> n,
894 uint32_t ic,
895 js_typedarray_span_t<> k
896) {
897 assert(c.size_bytes() == m.size_bytes());
898 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
899 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
900
901 return crypto_stream_xchacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
902}
903
904static inline int
905sn_crypto_stream_salsa20(
906 js_env_t *,
907 js_receiver_t,
908 js_typedarray_span_t<> c,
909 js_typedarray_span_t<> n,
910 js_typedarray_span_t<> k
911) {
912 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
913 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
914
915 return crypto_stream_salsa20(c.data(), c.size_bytes(), n.data(), k.data());
916}
917
918static inline int
919sn_crypto_stream_salsa20_xor(
920 js_env_t *,
921 js_receiver_t,
922 js_typedarray_span_t<> c,
923 js_typedarray_span_t<> m,
924 js_typedarray_span_t<> n,
925 js_typedarray_span_t<> k
926) {
927 assert(c.size_bytes() == m.size_bytes());
928 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
929 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
930
931 return crypto_stream_salsa20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
932}
933
934static inline int
935sn_crypto_stream_salsa20_xor_ic(
936 js_env_t *,
937 js_receiver_t,
938 js_typedarray_span_t<> c,
939 js_typedarray_span_t<> m,
940 js_typedarray_span_t<> n,
941 uint32_t ic,
942 js_typedarray_span_t<> k
943) {
944 assert(c.size_bytes() == m.size_bytes());
945 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
946 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
947
948 return crypto_stream_salsa20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
949}
950
951static inline int
952sn_crypto_auth(
953 js_env_t *,
954 js_receiver_t,
955 js_typedarray_span_t<> out,
956 js_typedarray_span_t<> in,
957 js_typedarray_span_t<> k
958) {
959 assert(out.size_bytes() == crypto_auth_BYTES);
960 assert(k.size_bytes() == crypto_auth_KEYBYTES);
961
962 return crypto_auth(out.data(), in.data(), in.size_bytes(), k.data());
963}
964
965static inline bool
966sn_crypto_auth_verify(
967 js_env_t *,
968 js_receiver_t,
969 js_typedarray_span_t<> h,
970 js_typedarray_span_t<> in,
971 js_typedarray_span_t<> k
972) {
973 assert(h.size_bytes() == crypto_auth_BYTES);
974 assert(k.size_bytes() == crypto_auth_KEYBYTES);
975
976 return crypto_auth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
977}
978
979static inline int
980sn_crypto_onetimeauth(
981 js_env_t *,
982 js_receiver_t,
983 js_typedarray_span_t<> out,
984 js_typedarray_span_t<> in,
985 js_typedarray_span_t<> k
986) {
987 assert(out.size_bytes() == crypto_onetimeauth_BYTES);
988 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
989
990 return crypto_onetimeauth(out.data(), in.data(), in.size_bytes(), k.data());
991}
992
993static inline int
994sn_crypto_onetimeauth_init(
995 js_env_t *,
996 js_receiver_t,
997 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
998 js_typedarray_span_t<> k
999) {
1000 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
1001
1002 return crypto_onetimeauth_init(&*state, k.data());
1003}
1004
1005static inline int
1006sn_crypto_onetimeauth_update(
1007 js_env_t *,
1008 js_receiver_t,
1009 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
1010 js_typedarray_span_t<> in
1011) {
1012 return crypto_onetimeauth_update(&*state, in.data(), in.size_bytes());
1013}
1014
1015static inline int
1016sn_crypto_onetimeauth_final(
1017 js_env_t *,
1018 js_receiver_t,
1019 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
1020 js_typedarray_span_t<> out
1021) {
1022 assert(out.size_bytes() == crypto_onetimeauth_BYTES);
1023
1024 return crypto_onetimeauth_final(&*state, out.data());
1025}
1026
1027static inline bool
1028sn_crypto_onetimeauth_verify(
1029 js_env_t *,
1030 js_receiver_t,
1031 js_typedarray_span_t<> h,
1032 js_typedarray_span_t<> in,
1033 js_typedarray_span_t<> k
1034) {
1035 assert(h.size_bytes() == crypto_onetimeauth_BYTES);
1036 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
1037
1038 return crypto_onetimeauth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
1039}
1040
1041// CHECK: memlimit can be >32bit
1042static inline int
1043sn_crypto_pwhash(
1044 js_env_t *,
1045 js_receiver_t,
1046 js_typedarray_span_t<> out,
1047 js_typedarray_span_of_t<char> passwd,
1048 js_typedarray_span_t<> salt,
1049 uint64_t opslimit,
1050 uint64_t memlimit,
1051 int32_t alg
1052) {
1053 assert(out.size_bytes() >= crypto_pwhash_BYTES_MIN);
1054 assert(out.size_bytes() <= crypto_pwhash_BYTES_MAX);
1055 assert(salt.size_bytes() == crypto_pwhash_SALTBYTES);
1056 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1057 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1058 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1059 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1060 assert(alg == 1 || alg == 2); // Argon2i or Argon2id
1061
1062 return crypto_pwhash(
1063 out.data(),
1064 out.size_bytes(),
1065 passwd.data(),
1066 passwd.size_bytes(),
1067 salt.data(),
1068 opslimit,
1069 memlimit,
1070 alg
1071 );
1072}
1073
1074static inline int
1075sn_crypto_pwhash_str(
1076 js_env_t *,
1077 js_receiver_t,
1078 js_typedarray_span_of_t<char> out,
1079 js_typedarray_span_of_t<char> passwd,
1080 uint64_t opslimit,
1081 uint64_t memlimit
1082) {
1083 assert(out.size_bytes() == crypto_pwhash_STRBYTES);
1084 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1085 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1086 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1087 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1088
1089 return crypto_pwhash_str(
1090 out.data(),
1091 passwd.data(),
1092 passwd.size_bytes(),
1093 opslimit,
1094 memlimit
1095 );
1096}
1097
1098static inline bool
1099sn_crypto_pwhash_str_verify(
1100 js_env_t *,
1101 js_receiver_t,
1102 js_typedarray_span_of_t<char> str,
1103 js_typedarray_span_of_t<char> passwd
1104) {
1105 assert(str.size_bytes() == crypto_pwhash_STRBYTES);
1106
1107 return crypto_pwhash_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
1108}
1109
1110// CHECK: returns 1, 0, -1
1111static inline bool
1112sn_crypto_pwhash_str_needs_rehash(
1113 js_env_t *,
1114 js_receiver_t,
1115 js_typedarray_span_of_t<char> str,
1116 uint64_t opslimit,
1117 uint64_t memlimit
1118) {
1119 assert(str.size_bytes() == crypto_pwhash_STRBYTES);
1120 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1121 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1122 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1123 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1124
1125 return crypto_pwhash_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
1126}
1127
1128// CHECK: memlimit can be >32bit
1129static inline int
1130sn_crypto_pwhash_scryptsalsa208sha256(
1131 js_env_t *,
1132 js_receiver_t,
1133 js_typedarray_span_t<> out,
1134 js_typedarray_span_of_t<char> passwd,
1135 js_typedarray_span_t<> salt,
1136 uint64_t opslimit,
1137 uint64_t memlimit
1138) {
1139 assert(out.size_bytes() >= crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
1140 assert(out.size_bytes() <= crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
1141 assert(salt.size_bytes() == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
1142 assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
1143 assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
1144 assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
1145 assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
1146
1147 return crypto_pwhash_scryptsalsa208sha256(
1148 out.data(),
1149 out.size_bytes(),
1150 passwd.data(),
1151 passwd.size_bytes(),
1152 salt.data(),
1153 opslimit,
1154 memlimit
1155 );
1156}
1157
1158static inline int
1159sn_crypto_pwhash_scryptsalsa208sha256_str(
1160 js_env_t *,
1161 js_receiver_t,
1162 js_typedarray_span_of_t<char> out,
1163 js_typedarray_span_of_t<char> passwd,
1164 uint64_t opslimit,
1165 uint64_t memlimit
1166) {
1167 assert(out.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1168 assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
1169 assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
1170 assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
1171 assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
1172
1173 return crypto_pwhash_scryptsalsa208sha256_str(
1174 out.data(),
1175 passwd.data(),
1176 passwd.size_bytes(),
1177 opslimit,
1178 memlimit
1179 );
1180}
1181
1182static inline bool
1183sn_crypto_pwhash_scryptsalsa208sha256_str_verify(
1184 js_env_t *,
1185 js_receiver_t,
1186 js_typedarray_span_of_t<char> str,
1187 js_typedarray_span_of_t<char> passwd
1188) {
1189 assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1190
1191 return crypto_pwhash_scryptsalsa208sha256_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
1192}
1193
1194static inline bool
1195sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
1196 js_env_t *,
1197 js_receiver_t,
1198 js_typedarray_span_of_t<char> str,
1199 uint64_t opslimit,
1200 uint64_t memlimit
1201) {
1202 assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1203 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1204 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1205 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1206 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1207
1208 return crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
1209}
1210
1211static inline int
1212sn_crypto_kx_keypair(
1213 js_env_t *,
1214 js_receiver_t,
1215 js_typedarray_span_t<> pk,
1216 js_typedarray_span_t<> sk
1217) {
1218 assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1219 assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1220
1221 return crypto_kx_keypair(pk.data(), sk.data());
1222}
1223
1224static inline int
1225sn_crypto_kx_seed_keypair(
1226 js_env_t *,
1227 js_receiver_t,
1228 js_typedarray_span_t<> pk,
1229 js_typedarray_span_t<> sk,
1230 js_typedarray_span_t<> seed
1231) {
1232 assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1233 assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1234 assert(seed.size_bytes() == crypto_kx_SEEDBYTES);
1235
1236 return crypto_kx_seed_keypair(pk.data(), sk.data(), seed.data());
1237}
1238
1239static inline int
1240sn_crypto_kx_client_session_keys(
1241 js_env_t *,
1242 js_receiver_t,
1243 std::optional<js_typedarray_span_t<>> rx,
1244 std::optional<js_typedarray_span_t<>> tx,
1245 js_typedarray_span_t<> client_pk,
1246 js_typedarray_span_t<> client_sk,
1247 js_typedarray_span_t<> server_pk
1248) {
1249 assert(rx.has_value() || tx.has_value());
1250
1251 if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1252 if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1253
1254 assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1255 assert(client_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1256 assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1257
1258 return crypto_kx_client_session_keys(
1259 rx ? rx->data() : nullptr,
1260 tx ? tx->data() : nullptr,
1261 client_pk.data(),
1262 client_sk.data(),
1263 server_pk.data()
1264 );
1265}
1266
1267static inline int
1268sn_crypto_kx_server_session_keys(
1269 js_env_t *,
1270 js_receiver_t,
1271 std::optional<js_typedarray_span_t<>> rx,
1272 std::optional<js_typedarray_span_t<>> tx,
1273 js_typedarray_span_t<> server_pk,
1274 js_typedarray_span_t<> server_sk,
1275 js_typedarray_span_t<> client_pk
1276) {
1277 assert(rx.has_value() || tx.has_value());
1278
1279 if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1280 if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1281
1282 assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1283 assert(server_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1284 assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1285
1286 return crypto_kx_server_session_keys(
1287 rx ? rx->data() : nullptr,
1288 tx ? tx->data() : nullptr,
1289 server_pk.data(),
1290 server_sk.data(),
1291 client_pk.data()
1292 );
1293}
1294
1295static inline int
1296sn_crypto_scalarmult_base(
1297 js_env_t *,
1298 js_receiver_t,
1299 js_typedarray_span_t<> q,
1300 js_typedarray_span_t<> n
1301) {
1302 assert(q.size_bytes() == crypto_scalarmult_BYTES);
1303 assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
1304
1305 return crypto_scalarmult_base(q.data(), n.data());
1306}
1307
1308static inline int
1309sn_crypto_scalarmult(
1310 js_env_t *,
1311 js_receiver_t,
1312 js_typedarray_span_t<> q,
1313 js_typedarray_span_t<> n,
1314 js_typedarray_span_t<> p
1315) {
1316 assert(q.size_bytes() == crypto_scalarmult_BYTES);
1317 assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
1318 assert(p.size_bytes() == crypto_scalarmult_BYTES);
1319
1320 return crypto_scalarmult(q.data(), n.data(), p.data());
1321}
1322
1323static inline int
1324sn_crypto_scalarmult_ed25519_base(
1325 js_env_t *,
1326 js_receiver_t,
1327 js_typedarray_span_t<> q,
1328 js_typedarray_span_t<> n
1329) {
1330 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1331 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1332
1333 return crypto_scalarmult_ed25519_base(q.data(), n.data());
1334}
1335
1336static inline int
1337sn_crypto_scalarmult_ed25519(
1338 js_env_t *,
1339 js_receiver_t,
1340 js_typedarray_span_t<> q,
1341 js_typedarray_span_t<> n,
1342 js_typedarray_span_t<> p
1343) {
1344 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1345 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1346 assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1347
1348 return crypto_scalarmult_ed25519(q.data(), n.data(), p.data());
1349}
1350
1351static inline bool
1352sn_crypto_core_ed25519_is_valid_point(
1353 js_env_t *,
1354 js_receiver_t,
1355 js_typedarray_span_t<> p
1356) {
1357 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1358
1359 return crypto_core_ed25519_is_valid_point(p.data()) != 0;
1360}
1361
1362static inline int
1363sn_crypto_core_ed25519_from_uniform(
1364 js_env_t *,
1365 js_receiver_t,
1366 js_typedarray_span_t<> p,
1367 js_typedarray_span_t<> r
1368) {
1369 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1370 assert(r.size_bytes() == crypto_core_ed25519_UNIFORMBYTES);
1371
1372 return crypto_core_ed25519_from_uniform(p.data(), r.data());
1373}
1374
1375static inline int
1376sn_crypto_scalarmult_ed25519_base_noclamp(
1377 js_env_t *,
1378 js_receiver_t,
1379 js_typedarray_span_t<> q,
1380 js_typedarray_span_t<> n
1381) {
1382 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1383 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1384
1385 return crypto_scalarmult_ed25519_base_noclamp(q.data(), n.data());
1386}
1387
1388static inline int
1389sn_crypto_scalarmult_ed25519_noclamp(
1390 js_env_t *,
1391 js_receiver_t,
1392 js_typedarray_span_t<> q,
1393 js_typedarray_span_t<> n,
1394 js_typedarray_span_t<> p
1395) {
1396 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1397 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1398 assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1399
1400 return crypto_scalarmult_ed25519_noclamp(q.data(), n.data(), p.data());
1401}
1402
1403static inline int
1404sn_crypto_core_ed25519_add(
1405 js_env_t *,
1406 js_receiver_t,
1407 js_typedarray_span_t<> r,
1408 js_typedarray_span_t<> p,
1409 js_typedarray_span_t<> q
1410) {
1411 assert(r.size_bytes() == crypto_core_ed25519_BYTES);
1412 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1413 assert(q.size_bytes() == crypto_core_ed25519_BYTES);
1414
1415 return crypto_core_ed25519_add(r.data(), p.data(), q.data());
1416}
1417
1418static inline int
1419sn_crypto_core_ed25519_sub(
1420 js_env_t *,
1421 js_receiver_t,
1422 js_typedarray_span_t<> r,
1423 js_typedarray_span_t<> p,
1424 js_typedarray_span_t<> q
1425) {
1426 assert(r.size_bytes() == crypto_core_ed25519_BYTES);
1427 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1428 assert(q.size_bytes() == crypto_core_ed25519_BYTES);
1429
1430 return crypto_core_ed25519_sub(r.data(), p.data(), q.data());
1431}
1432
1433static inline void
1434sn_crypto_core_ed25519_scalar_random(
1435 js_env_t *,
1436 js_receiver_t,
1437 js_typedarray_span_t<> r
1438) {
1439 assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1440
1441 crypto_core_ed25519_scalar_random(r.data());
1442}
1443
1444static inline void
1445sn_crypto_core_ed25519_scalar_reduce(
1446 js_env_t *,
1447 js_receiver_t,
1448 js_typedarray_span_t<> r,
1449 js_typedarray_span_t<> s
1450) {
1451 assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1452 assert(s.size_bytes() == crypto_core_ed25519_NONREDUCEDSCALARBYTES);
1453
1454 crypto_core_ed25519_scalar_reduce(r.data(), s.data());
1455}
1456
1457static inline void
1458sn_crypto_core_ed25519_scalar_invert(
1459 js_env_t *,
1460 js_receiver_t,
1461 js_typedarray_span_t<> recip,
1462 js_typedarray_span_t<> s
1463) {
1464 assert(recip.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1465 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1466
1467 crypto_core_ed25519_scalar_invert(recip.data(), s.data());
1468}
1469
1470static inline void
1471sn_crypto_core_ed25519_scalar_negate(
1472 js_env_t *,
1473 js_receiver_t,
1474 js_typedarray_span_t<> neg,
1475 js_typedarray_span_t<> s
1476) {
1477 assert(neg.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1478 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1479
1480 crypto_core_ed25519_scalar_negate(neg.data(), s.data());
1481}
1482
1483static inline void
1484sn_crypto_core_ed25519_scalar_complement(
1485 js_env_t *,
1486 js_receiver_t,
1487 js_typedarray_span_t<> comp,
1488 js_typedarray_span_t<> s
1489) {
1490 assert(comp.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1491 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1492
1493 crypto_core_ed25519_scalar_complement(comp.data(), s.data());
1494}
1495
1496static inline void
1497sn_crypto_core_ed25519_scalar_add(
1498 js_env_t *,
1499 js_receiver_t,
1500 js_typedarray_span_t<> z,
1501 js_typedarray_span_t<> x,
1502 js_typedarray_span_t<> y
1503) {
1504 assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1505 assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1506 assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1507
1508 crypto_core_ed25519_scalar_add(z.data(), x.data(), y.data());
1509}
1510
1511static inline void
1512sn_crypto_core_ed25519_scalar_sub(
1513 js_env_t *,
1514 js_receiver_t,
1515 js_typedarray_span_t<> z,
1516 js_typedarray_span_t<> x,
1517 js_typedarray_span_t<> y
1518) {
1519 assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1520 assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1521 assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1522
1523 crypto_core_ed25519_scalar_sub(z.data(), x.data(), y.data());
1524}
1525
1526static inline int
1527sn_crypto_shorthash(
1528 js_env_t *,
1529 js_receiver_t,
1530 js_typedarray_span_t<> out,
1531 js_typedarray_span_t<> in,
1532 js_typedarray_span_t<> k
1533) {
1534 assert(out.size_bytes() == crypto_shorthash_BYTES);
1535 assert(k.size_bytes() == crypto_shorthash_KEYBYTES);
1536
1537 return crypto_shorthash(out.data(), in.data(), in.size_bytes(), k.data());
1538}
1539
1540static inline void
1541sn_crypto_kdf_keygen(
1542 js_env_t *,
1543 js_receiver_t,
1544 js_typedarray_span_t<> key
1545) {
1546 assert(key.size_bytes() == crypto_kdf_KEYBYTES);
1547
1548 crypto_kdf_keygen(key.data());
1549}
1550
1551static inline int
1552sn_crypto_kdf_derive_from_key(
1553 js_env_t *,
1554 js_receiver_t,
1555 js_typedarray_span_t<> subkey,
1556 uint64_t subkey_id,
1557 js_typedarray_span_of_t<char> ctx,
1558 js_typedarray_span_t<> key
1559) {
1560 assert(subkey.size_bytes() >= crypto_kdf_BYTES_MIN);
1561 assert(subkey.size_bytes() <= crypto_kdf_BYTES_MAX);
1562 assert(ctx.size_bytes() == crypto_kdf_CONTEXTBYTES);
1563 assert(key.size_bytes() == crypto_kdf_KEYBYTES);
1564
1565 return crypto_kdf_derive_from_key(
1566 subkey.data(),
1567 subkey.size_bytes(),
1568 subkey_id,
1569 ctx.data(),
1570 key.data()
1571 );
1572}
1573
1574static inline int
1575sn_crypto_hash(
1576 js_env_t *,
1577 js_receiver_t,
1578 js_typedarray_span_t<> out,
1579 js_typedarray_span_t<> in
1580) {
1581 assert(out.size_bytes() == crypto_hash_BYTES);
1582
1583 return crypto_hash(out.data(), in.data(), in.size_bytes());
1584}
1585
1586static inline int
1587sn_crypto_hash_sha256(
1588 js_env_t *,
1589 js_receiver_t,
1590 js_typedarray_span_t<> out,
1591 js_typedarray_span_t<> in
1592) {
1593 assert(out.size_bytes() == crypto_hash_sha256_BYTES);
1594
1595 return crypto_hash_sha256(out.data(), in.data(), in.size_bytes());
1596}
1597
1598static inline int
1599sn_crypto_hash_sha256_init(
1600 js_env_t *,
1601 js_receiver_t,
1602 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state
1603) {
1604 return crypto_hash_sha256_init(&*state);
1605}
1606
1607static inline int
1608sn_crypto_hash_sha256_update(
1609 js_env_t *,
1610 js_receiver_t,
1611 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
1612 js_typedarray_span_t<> in
1613) {
1614 return crypto_hash_sha256_update(&*state, in.data(), in.size_bytes());
1615}
1616
1617static inline int
1618sn_crypto_hash_sha256_final(
1619 js_env_t *,
1620 js_receiver_t,
1621 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
1622 js_typedarray_span_t<> out
1623) {
1624 assert(out.size_bytes() == crypto_hash_sha256_BYTES);
1625
1626 return crypto_hash_sha256_final(&*state, out.data());
1627}
1628
1629static inline int
1630sn_crypto_hash_sha512(
1631 js_env_t *,
1632 js_receiver_t,
1633 js_typedarray_span_t<> out,
1634 js_typedarray_span_t<> in
1635) {
1636 assert(out.size_bytes() == crypto_hash_sha512_BYTES);
1637
1638 return crypto_hash_sha512(out.data(), in.data(), in.size_bytes());
1639}
1640
1641static inline int
1642sn_crypto_hash_sha512_init(
1643 js_env_t *,
1644 js_receiver_t,
1645 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state
1646) {
1647 return crypto_hash_sha512_init(&*state);
1648}
1649
1650static inline int
1651sn_crypto_hash_sha512_update(
1652 js_env_t *,
1653 js_receiver_t,
1654 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
1655 js_typedarray_span_t<> in
1656) {
1657 return crypto_hash_sha512_update(&*state, in.data(), in.size_bytes());
1658}
1659
1660static inline int
1661sn_crypto_hash_sha512_final(
1662 js_env_t *,
1663 js_receiver_t,
1664 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
1665 js_typedarray_span_t<> out
1666) {
1667 assert(out.size_bytes() == crypto_hash_sha512_BYTES);
1668
1669 return crypto_hash_sha512_final(&*state, out.data());
1670}
1671
1672static inline void
1673sn_crypto_aead_xchacha20poly1305_ietf_keygen(
1674 js_env_t *,
1675 js_receiver_t,
1676 js_typedarray_span_t<> k
1677) {
1678 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1679
1680 crypto_aead_xchacha20poly1305_ietf_keygen(k.data());
1681}
1682
1683static inline uint64_t
1684sn_crypto_aead_xchacha20poly1305_ietf_encrypt(
1685 js_env_t *,
1686 js_receiver_t,
1687 js_typedarray_span_t<> c,
1688 js_typedarray_span_t<> m,
1689 std::optional<js_typedarray_span_t<>> ad,
1690 js_typedarray_span_t<> npub,
1691 js_typedarray_span_t<> k
1692) {
1693 assert(c.size_bytes() == m.size_bytes() + crypto_aead_xchacha20poly1305_ietf_ABYTES);
1694 assert(c.size_bytes() <= 0xffffffff);
1695 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1696 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1697
1698 uint8_t *ad_data = nullptr;
1699 size_t ad_size = 0;
1700 if (ad) {
1701 ad_data = ad->data();
1702 ad_size = ad->size_bytes();
1703 }
1704
1705 unsigned long long clen = 0;
1706 int status = crypto_aead_xchacha20poly1305_ietf_encrypt(
1707 c.data(),
1708 &clen,
1709 m.data(),
1710 m.size_bytes(),
1711 ad_data,
1712 ad_size,
1713 nullptr,
1714 npub.data(),
1715 k.data()
1716 );
1717
1718 if (status < 0) return status;
1719
1720 return clen;
1721}
1722
1723static inline uint64_t
1724sn_crypto_aead_xchacha20poly1305_ietf_decrypt(
1725 js_env_t *,
1726 js_receiver_t,
1727 js_typedarray_span_t<> m,
1728 js_typedarray_span_t<> c,
1729 std::optional<js_typedarray_span_t<>> ad,
1730 js_typedarray_span_t<> npub,
1731 js_typedarray_span_t<> k
1732) {
1733 assert(m.size_bytes() == c.size_bytes() - crypto_aead_xchacha20poly1305_ietf_ABYTES);
1734 assert(m.size_bytes() <= 0xffffffff);
1735 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1736 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1737
1738 uint8_t *ad_data = nullptr;
1739 size_t ad_size = 0;
1740 if (ad) {
1741 ad_data = ad->data();
1742 ad_size = ad->size_bytes();
1743 }
1744
1745 unsigned long long mlen = 0;
1746 int status = crypto_aead_xchacha20poly1305_ietf_decrypt(
1747 m.data(),
1748 &mlen,
1749 nullptr,
1750 c.data(),
1751 c.size_bytes(),
1752 ad_data,
1753 ad_size,
1754 npub.data(),
1755 k.data()
1756 );
1757
1758 if (status < 0) return status;
1759
1760 return mlen;
1761}
1762
1763static inline uint64_t
1764sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
1765 js_env_t *,
1766 js_receiver_t,
1767 js_typedarray_span_t<> c,
1768 js_typedarray_span_t<> mac,
1769 js_typedarray_span_t<> m,
1770 std::optional<js_typedarray_span_t<>> ad,
1771 js_typedarray_span_t<> npub,
1772 js_typedarray_span_t<> k
1773) {
1774 assert(c.size_bytes() == m.size_bytes());
1775 assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
1776 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1777 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1778
1779 uint8_t *ad_data = nullptr;
1780 size_t ad_size = 0;
1781 if (ad) {
1782 ad_data = ad->data();
1783 ad_size = ad->size_bytes();
1784 }
1785
1786 unsigned long long maclen = 0;
1787 int status = crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
1788 c.data(),
1789 mac.data(),
1790 &maclen,
1791 m.data(),
1792 m.size_bytes(),
1793 ad_data,
1794 ad_size,
1795 nullptr,
1796 npub.data(),
1797 k.data()
1798 );
1799
1800 if (status < 0) return status;
1801
1802 return maclen;
1803}
1804
1805static inline int
1806sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
1807 js_env_t *,
1808 js_receiver_t,
1809 js_typedarray_span_t<> m,
1810 js_typedarray_span_t<> c,
1811 js_typedarray_span_t<> mac,
1812 std::optional<js_typedarray_span_t<>> ad,
1813 js_typedarray_span_t<> npub,
1814 js_typedarray_span_t<> k
1815) {
1816 assert(m.size_bytes() == c.size_bytes());
1817 assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
1818 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1819 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1820
1821 uint8_t *ad_data = nullptr;
1822 size_t ad_size = 0;
1823 if (ad) {
1824 ad_data = ad->data();
1825 ad_size = ad->size_bytes();
1826 }
1827
1828 return crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
1829 m.data(),
1830 nullptr,
1831 c.data(),
1832 c.size_bytes(),
1833 mac.data(),
1834 ad_data,
1835 ad_size,
1836 npub.data(),
1837 k.data()
1838 );
1839}
1840
1841static inline void
1842sn_crypto_aead_chacha20poly1305_ietf_keygen(
1843 js_env_t *,
1844 js_receiver_t,
1845 js_typedarray_span_t<> k
1846) {
1847 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1848
1849 crypto_aead_chacha20poly1305_ietf_keygen(k.data());
1850}
1851
1852static inline uint64_t
1853sn_crypto_aead_chacha20poly1305_ietf_encrypt(
1854 js_env_t *,
1855 js_receiver_t,
1856 js_typedarray_span_t<> c,
1857 js_typedarray_span_t<> m,
1858 std::optional<js_typedarray_span_t<>> ad,
1859 js_typedarray_span_t<> npub,
1860 js_typedarray_span_t<> k
1861) {
1862 assert(c.size_bytes() == m.size_bytes() + crypto_aead_chacha20poly1305_ietf_ABYTES);
1863 assert(c.size_bytes() <= 0xffffffff);
1864 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1865 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1866
1867 uint8_t *ad_data = nullptr;
1868 size_t ad_size = 0;
1869 if (ad) {
1870 ad_data = ad->data();
1871 ad_size = ad->size_bytes();
1872 }
1873
1874 unsigned long long clen = 0;
1875 int status = crypto_aead_chacha20poly1305_ietf_encrypt(
1876 c.data(),
1877 &clen,
1878 m.data(),
1879 m.size_bytes(),
1880 ad_data,
1881 ad_size,
1882 nullptr,
1883 npub.data(),
1884 k.data()
1885 );
1886
1887 if (status < 0) return status;
1888
1889 return clen;
1890}
1891
1892static inline uint64_t
1893sn_crypto_aead_chacha20poly1305_ietf_decrypt(
1894 js_env_t *,
1895 js_receiver_t,
1896 js_typedarray_span_t<> m,
1897 js_typedarray_span_t<> c,
1898 std::optional<js_typedarray_span_t<>> ad,
1899 js_typedarray_span_t<> npub,
1900 js_typedarray_span_t<> k
1901) {
1902 assert(m.size_bytes() == c.size_bytes() - crypto_aead_chacha20poly1305_ietf_ABYTES);
1903 assert(m.size_bytes() <= 0xffffffff);
1904 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1905 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1906
1907 uint8_t *ad_data = nullptr;
1908 size_t ad_size = 0;
1909 if (ad) {
1910 ad_data = ad->data();
1911 ad_size = ad->size_bytes();
1912 }
1913
1914 unsigned long long mlen = 0;
1915 int status = crypto_aead_chacha20poly1305_ietf_decrypt(
1916 m.data(),
1917 &mlen,
1918 nullptr,
1919 c.data(),
1920 c.size_bytes(),
1921 ad_data,
1922 ad_size,
1923 npub.data(),
1924 k.data()
1925 );
1926
1927 if (status < 0) return status;
1928
1929 return mlen;
1930}
1931
1932static inline uint64_t
1933sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached(
1934 js_env_t *,
1935 js_receiver_t,
1936 js_typedarray_span_t<> c,
1937 js_typedarray_span_t<> mac,
1938 js_typedarray_span_t<> m,
1939 std::optional<js_typedarray_span_t<>> ad,
1940 js_typedarray_span_t<> npub,
1941 js_typedarray_span_t<> k
1942) {
1943 assert(c.size_bytes() == m.size_bytes());
1944 assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
1945 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1946 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1947
1948 uint8_t *ad_data = nullptr;
1949 size_t ad_size = 0;
1950 if (ad) {
1951 ad_data = ad->data();
1952 ad_size = ad->size_bytes();
1953 }
1954
1955 unsigned long long maclen = 0;
1956 int status = crypto_aead_chacha20poly1305_ietf_encrypt_detached(
1957 c.data(),
1958 mac.data(),
1959 &maclen,
1960 m.data(),
1961 m.size_bytes(),
1962 ad_data,
1963 ad_size,
1964 nullptr,
1965 npub.data(),
1966 k.data()
1967 );
1968
1969 if (status < 0) return status;
1970
1971 return maclen;
1972}
1973
1974static inline int
1975sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached(
1976 js_env_t *,
1977 js_receiver_t,
1978 js_typedarray_span_t<> m,
1979 js_typedarray_span_t<> c,
1980 js_typedarray_span_t<> mac,
1981 std::optional<js_typedarray_span_t<>> ad,
1982 js_typedarray_span_t<> npub,
1983 js_typedarray_span_t<> k
1984) {
1985 assert(m.size_bytes() == c.size_bytes());
1986 assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
1987 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1988 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1989
1990 uint8_t *ad_data = nullptr;
1991 size_t ad_size = 0;
1992 if (ad) {
1993 ad_data = ad->data();
1994 ad_size = ad->size_bytes();
1995 }
1996
1997 return crypto_aead_chacha20poly1305_ietf_decrypt_detached(
1998 m.data(),
1999 nullptr,
2000 c.data(),
2001 c.size_bytes(),
2002 mac.data(),
2003 ad_data,
2004 ad_size,
2005 npub.data(),
2006 k.data()
2007 );
2008}
2009
2010static inline void
2011sn_crypto_secretstream_xchacha20poly1305_keygen(
2012 js_env_t *env,
2013 js_receiver_t,
2014
2015 js_arraybuffer_span_t k,
2016 uint32_t k_offset,
2017 uint32_t k_len
2018) {
2019 assert_bounds(k);
2020 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2021
2022 crypto_secretstream_xchacha20poly1305_keygen(&k[k_offset]);
2023}
2024
2025static inline int
2026sn_crypto_secretstream_xchacha20poly1305_init_push(
2027 js_env_t *env,
2028 js_receiver_t,
2029
2030 js_arraybuffer_span_t state,
2031 uint32_t state_offset,
2032 uint32_t state_len,
2033
2034 js_arraybuffer_span_t header,
2035 uint32_t header_offset,
2036 uint32_t header_len,
2037
2038 js_arraybuffer_span_t k,
2039 uint32_t k_offset,
2040 uint32_t k_len
2041) {
2042 assert_bounds(state);
2043 assert_bounds(header);
2044 assert_bounds(k);
2045
2046 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2047 assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
2048 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2049
2050 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2051
2052 return crypto_secretstream_xchacha20poly1305_init_push(state_data, &header[header_offset], &k[k_offset]);
2053}
2054
2055static inline uint64_t
2056sn_crypto_secretstream_xchacha20poly1305_push(
2057 js_env_t *env,
2058 js_receiver_t,
2059
2060 js_arraybuffer_span_t state,
2061 uint32_t state_offset,
2062 uint32_t state_len,
2063
2064 js_arraybuffer_span_t c,
2065 uint32_t c_offset,
2066 uint32_t c_len,
2067
2068 js_arraybuffer_span_t m,
2069 uint32_t m_offset,
2070 uint32_t m_len,
2071
2072 js_arraybuffer_span_t ad,
2073 uint32_t ad_offset,
2074 uint32_t ad_len,
2075
2076 uint32_t tag
2077) {
2078 assert_bounds(state);
2079 assert_bounds(c);
2080 assert_bounds(m);
2081
2082 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2083 assert(c_len == m_len + crypto_secretstream_xchacha20poly1305_ABYTES);
2084 assert(c_len <= 0xffffffff && "32bit integer");
2085
2086 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2087
2088 uint8_t *ad_data = NULL;
2089 if (ad_len) {
2090 assert_bounds(ad);
2091 ad_data = &ad[ad_offset];
2092 }
2093
2094 unsigned long long clen = 0;
2095 int status = crypto_secretstream_xchacha20poly1305_push(
2096 state_data,
2097 &c[c_offset],
2098 &clen,
2099 &m[m_offset],
2100 m_len,
2101 ad_data,
2102 ad_len,
2103 tag
2104 );
2105
2106 if (status < 0) return status;
2107
2108 return clen;
2109}
2110
2111static inline int
2112sn_crypto_secretstream_xchacha20poly1305_init_pull(
2113 js_env_t *,
2114 js_receiver_t,
2115
2116 js_arraybuffer_span_t state,
2117 uint32_t state_offset,
2118 uint32_t state_len,
2119
2120 js_arraybuffer_span_t header,
2121 uint32_t header_offset,
2122 uint32_t header_len,
2123
2124 js_arraybuffer_span_t k,
2125 uint32_t k_offset,
2126 uint32_t k_len
2127) {
2128 assert_bounds(state);
2129 assert_bounds(header);
2130 assert_bounds(k);
2131
2132 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2133 assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
2134 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2135
2136 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2137
2138 return crypto_secretstream_xchacha20poly1305_init_pull(state_data, &header[header_offset], &k[k_offset]);
2139}
2140
2141static inline uint64_t
2142sn_crypto_secretstream_xchacha20poly1305_pull(
2143 js_env_t *env,
2144 js_receiver_t,
2145
2146 js_arraybuffer_span_t state,
2147 uint32_t state_offset,
2148 uint32_t state_len,
2149
2150 js_arraybuffer_span_t m,
2151 uint32_t m_offset,
2152 uint32_t m_len,
2153
2154 js_arraybuffer_span_t tag,
2155 uint32_t tag_offset,
2156 uint32_t tag_len,
2157
2158 js_arraybuffer_span_t c,
2159 uint32_t c_offset,
2160 uint32_t c_len,
2161
2162 js_arraybuffer_span_t ad,
2163 uint32_t ad_offset,
2164 uint32_t ad_len
2165) {
2166 assert_bounds(state);
2167 assert_bounds(m);
2168 assert_bounds(tag);
2169 assert_bounds(c);
2170
2171 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2172 assert(c_len >= crypto_secretstream_xchacha20poly1305_ABYTES);
2173 assert(tag_len == 1);
2174 assert(m_len == c_len - crypto_secretstream_xchacha20poly1305_ABYTES);
2175 assert(m_len <= 0xffffffff);
2176
2177 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2178
2179 uint8_t *ad_data = NULL;
2180 if (ad_len) {
2181 assert_bounds(ad);
2182 ad_data = &ad[ad_offset];
2183 }
2184
2185 unsigned long long mlen = 0;
2186 int status = crypto_secretstream_xchacha20poly1305_pull(
2187 state_data,
2188 &m[m_offset],
2189 &mlen,
2190 &tag[tag_offset],
2191 &c[c_offset],
2192 c_len,
2193 ad_data,
2194 ad_len
2195 );
2196
2197 if (status < 0) return status;
2198
2199 return mlen;
2200}
2201
2202static inline void
2203sn_crypto_secretstream_xchacha20poly1305_rekey(
2204 js_env_t *,
2205 js_receiver_t,
2206
2207 js_arraybuffer_span_t state,
2208 uint32_t state_offset,
2209 uint32_t state_len
2210) {
2211 assert_bounds(state);
2212
2213 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2214
2215 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2216
2217 crypto_secretstream_xchacha20poly1305_rekey(state_data);
2218}
2219
2220struct sn_async_task {
2221 uv_work_t task;
2222 js_env_t *env;
2223 js_persistent_t<js_function_t<void, int>> cb;
2224 js_deferred_teardown_t *teardown;
2225 int code = 0;
2226 bool exiting = false;
2227
2228 sn_async_task(js_env_t *env) : env(env) {
2229 int err;
2230 err = js_add_teardown_callback<on_teardown, sn_async_task>(env, this, teardown);
2231 assert(err == 0);
2232 }
2233
2234 ~sn_async_task() {
2235 int err;
2236 err = js_finish_teardown_callback(teardown);
2237 assert(err == 0);
2238 }
2239
2240private:
2241 static void
2242 on_teardown(js_deferred_teardown_t *teardown, sn_async_task *req) {
2243 req->exiting = true;
2244 }
2245};
2246
2247struct sn_async_pwhash_request : sn_async_task {
2248 js_persistent_t<js_arraybuffer_t> out_ref;
2249 std::span<uint8_t> out;
2250
2251 js_persistent_t<js_arraybuffer_t> pwd_ref;
2252 std::span<char> pwd;
2253
2254 js_persistent_t<js_arraybuffer_t> salt_ref;
2255 std::span<uint8_t> salt;
2256
2257 uint64_t opslimit;
2258 size_t memlimit;
2259 int alg;
2260
2261 sn_async_pwhash_request(js_env_t *env) : sn_async_task(env) {}
2262};
2263
2264static void
2265async_pwhash_execute(uv_work_t *uv_req) {
2266 auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
2267
2268 req->code = crypto_pwhash(
2269 req->out.data(),
2270 req->out.size(),
2271 req->pwd.data(),
2272 req->pwd.size(),
2273 req->salt.data(),
2274 req->opslimit,
2275 req->memlimit,
2276 req->alg
2277 );
2278}
2279
2280static void
2281async_pwhash_complete(uv_work_t *uv_req, int status) {
2282 int err;
2283
2284 auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
2285
2286 if (req->exiting) return delete req;
2287
2288 js_handle_scope_t *scope;
2289 err = js_open_handle_scope(req->env, &scope);
2290 assert(err == 0);
2291
2292 js_function_t<void, int> callback;
2293 err = js_get_reference_value(req->env, req->cb, callback);
2294 assert(err == 0);
2295
2296 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2297 assert(err != js_pending_exception);
2298
2299 err = js_close_handle_scope(req->env, scope);
2300 assert(err == 0);
2301
2302 delete req;
2303}
2304
2305static inline void
2306sn_crypto_pwhash_async(
2307 js_env_t *env,
2308 js_receiver_t,
2309
2310 js_arraybuffer_t out,
2311 uint32_t out_offset,
2312 uint32_t out_len,
2313
2314 js_arraybuffer_t pwd,
2315 uint32_t pwd_offset,
2316 uint32_t pwd_len,
2317
2318 js_arraybuffer_t salt,
2319 uint32_t salt_offset,
2320 uint32_t salt_len,
2321
2322 uint64_t opslimit,
2323 uint64_t memlimit,
2324 uint32_t alg,
2325
2326 js_function_t<void, int> callback
2327) {
2328 int err;
2329
2330 auto *req = new sn_async_pwhash_request(env);
2331
2332 std::span<uint8_t> out_view;
2333 err = js_get_arraybuffer_info(env, out, out_view);
2334 assert(err == 0);
2335 assert(out_offset + out_len <= out_view.size());
2336
2337 req->out = {&out_view[out_offset], out_len};
2338
2339 std::span<char> pwd_view;
2340 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2341 assert(err == 0);
2342 assert(pwd_offset + pwd_len <= pwd_view.size());
2343
2344 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2345
2346 std::span<uint8_t> salt_view;
2347 err = js_get_arraybuffer_info(env, salt, salt_view);
2348 assert(err == 0);
2349 assert(salt_offset + salt_len <= salt_view.size());
2350
2351 req->salt = {&salt_view[salt_offset], salt_len};
2352
2353 req->opslimit = opslimit;
2354 req->memlimit = memlimit;
2355 req->alg = alg;
2356
2357 err = js_create_reference(env, out, req->out_ref);
2358 assert(err == 0);
2359
2360 err = js_create_reference(env, pwd, req->pwd_ref);
2361 assert(err == 0);
2362
2363 err = js_create_reference(env, salt, req->salt_ref);
2364 assert(err == 0);
2365
2366 err = js_create_reference(env, callback, req->cb);
2367 assert(err == 0);
2368
2369 uv_loop_t *loop;
2370 err = js_get_env_loop(env, &loop);
2371 assert(err == 0);
2372
2373 err = uv_queue_work(loop, &req->task, async_pwhash_execute, async_pwhash_complete);
2374 assert(err == 0);
2375}
2376
2377struct sn_async_pwhash_str_request : sn_async_task {
2378 js_persistent_t<js_arraybuffer_t> out_ref;
2379 std::span<char> out;
2380
2381 js_persistent_t<js_arraybuffer_t> pwd_ref;
2382 std::span<char> pwd;
2383
2384 uint64_t opslimit;
2385 size_t memlimit;
2386
2387 sn_async_pwhash_str_request(js_env_t *env) : sn_async_task(env) {}
2388};
2389
2390static void
2391async_pwhash_str_execute(uv_work_t *uv_req) {
2392 auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
2393
2394 req->code = crypto_pwhash_str(
2395 req->out.data(),
2396 req->pwd.data(),
2397 req->pwd.size(),
2398 req->opslimit,
2399 req->memlimit
2400 );
2401}
2402
2403static void
2404async_pwhash_str_complete(uv_work_t *uv_req, int status) {
2405 int err;
2406
2407 auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
2408
2409 if (req->exiting) return delete req;
2410
2411 js_handle_scope_t *scope;
2412 err = js_open_handle_scope(req->env, &scope);
2413 assert(err == 0);
2414
2415 js_function_t<void, int> callback;
2416 err = js_get_reference_value(req->env, req->cb, callback);
2417 assert(err == 0);
2418
2419 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2420 assert(err != js_pending_exception);
2421
2422 err = js_close_handle_scope(req->env, scope);
2423 assert(err == 0);
2424
2425 delete req;
2426}
2427
2428static inline void
2429sn_crypto_pwhash_str_async(
2430 js_env_t *env,
2431 js_receiver_t,
2432
2433 js_arraybuffer_t out,
2434 uint32_t out_offset,
2435 uint32_t out_len,
2436
2437 js_arraybuffer_t pwd,
2438 uint32_t pwd_offset,
2439 uint32_t pwd_len,
2440
2441 uint64_t opslimit,
2442 uint64_t memlimit,
2443 js_function_t<void, int> callback
2444) {
2445 int err;
2446
2447 auto *req = new sn_async_pwhash_str_request(env);
2448
2449 std::span<char> out_view;
2450 err = js_get_arraybuffer_info(env, out, out_view);
2451 assert(err == 0);
2452 assert(out_offset + out_len <= out_view.size());
2453
2454 req->out = {&out_view[out_offset], out_len};
2455
2456 std::span<char> pwd_view;
2457 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2458 assert(err == 0);
2459 assert(pwd_offset + pwd_len <= pwd_view.size());
2460
2461 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2462
2463 req->opslimit = opslimit;
2464 req->memlimit = memlimit;
2465
2466 err = js_create_reference(env, out, req->out_ref);
2467 assert(err == 0);
2468
2469 err = js_create_reference(env, pwd, req->pwd_ref);
2470 assert(err == 0);
2471
2472 err = js_create_reference(env, callback, req->cb);
2473 assert(err == 0);
2474
2475 uv_loop_t *loop;
2476 err = js_get_env_loop(env, &loop);
2477 assert(err == 0);
2478
2479 err = uv_queue_work(loop, &req->task, async_pwhash_str_execute, async_pwhash_str_complete);
2480 assert(err == 0);
2481}
2482
2483struct sn_async_pwhash_str_verify_request : sn_async_task {
2484 js_persistent_t<js_arraybuffer_t> str_ref;
2485 std::span<char> str;
2486
2487 js_persistent_t<js_arraybuffer_t> pwd_ref;
2488 std::span<char> pwd;
2489
2490 sn_async_pwhash_str_verify_request(js_env_t *env) : sn_async_task(env) {}
2491};
2492
2493static void
2494async_pwhash_str_verify_execute(uv_work_t *uv_req) {
2495 auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
2496
2497 req->code = crypto_pwhash_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
2498}
2499
2500static void
2501async_pwhash_str_verify_complete(uv_work_t *uv_req, int status) {
2502 int err;
2503
2504 auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
2505
2506 if (req->exiting) return delete req;
2507
2508 js_handle_scope_t *scope;
2509 err = js_open_handle_scope(req->env, &scope);
2510 assert(err == 0);
2511
2512 js_function_t<void, int> callback;
2513 err = js_get_reference_value(req->env, req->cb, callback);
2514 assert(err == 0);
2515
2516 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2517 assert(err != js_pending_exception);
2518
2519 err = js_close_handle_scope(req->env, scope);
2520 assert(err == 0);
2521
2522 delete req;
2523}
2524
2525static inline void
2526sn_crypto_pwhash_str_verify_async(
2527 js_env_t *env,
2528 js_receiver_t,
2529
2530 js_arraybuffer_t str,
2531 uint32_t str_offset,
2532 uint32_t str_len,
2533
2534 js_arraybuffer_t pwd,
2535 uint32_t pwd_offset,
2536 uint32_t pwd_len,
2537
2538 js_function_t<void, int> callback
2539) {
2540 int err;
2541
2542 auto *req = new sn_async_pwhash_str_verify_request(env);
2543
2544 std::span<char> str_view;
2545 err = js_get_arraybuffer_info(env, str, str_view);
2546 assert(err == 0);
2547 assert(str_offset + str_len <= str_view.size());
2548
2549 req->str = {&str_view[str_offset], str_len};
2550
2551 std::span<char> pwd_view;
2552 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2553 assert(err == 0);
2554 assert(pwd_offset + pwd_len <= pwd_view.size());
2555
2556 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2557
2558 err = js_create_reference(env, str, req->str_ref);
2559 assert(err == 0);
2560
2561 err = js_create_reference(env, pwd, req->pwd_ref);
2562 assert(err == 0);
2563
2564 err = js_create_reference(env, callback, req->cb);
2565 assert(err == 0);
2566
2567 uv_loop_t *loop;
2568 err = js_get_env_loop(env, &loop);
2569 assert(err == 0);
2570
2571 err = uv_queue_work(loop, &req->task, async_pwhash_str_verify_execute, async_pwhash_str_verify_complete);
2572 assert(err == 0);
2573}
2574
2575struct sn_async_pwhash_scryptsalsa208sha256_request : sn_async_task {
2576 js_persistent_t<js_arraybuffer_t> out_ref;
2577 std::span<uint8_t> out;
2578
2579 js_persistent_t<js_arraybuffer_t> pwd_ref;
2580 std::span<char> pwd;
2581
2582 js_persistent_t<js_arraybuffer_t> salt_ref;
2583 std::span<uint8_t> salt;
2584
2585 uint64_t opslimit;
2586 size_t memlimit;
2587
2588 sn_async_pwhash_scryptsalsa208sha256_request(js_env_t *env) : sn_async_task(env) {}
2589};
2590
2591static void
2592async_pwhash_scryptsalsa208sha256_execute(uv_work_t *uv_req) {
2593 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
2594
2595 req->code = crypto_pwhash_scryptsalsa208sha256(
2596 req->out.data(),
2597 req->out.size(),
2598 req->pwd.data(),
2599 req->pwd.size(),
2600 req->salt.data(),
2601 req->opslimit,
2602 req->memlimit
2603 );
2604}
2605
2606static void
2607async_pwhash_scryptsalsa208sha256_complete(uv_work_t *uv_req, int status) {
2608 int err;
2609
2610 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
2611
2612 if (req->exiting) return delete req;
2613
2614 js_handle_scope_t *scope;
2615 err = js_open_handle_scope(req->env, &scope);
2616 assert(err == 0);
2617
2618 js_function_t<void, int> callback;
2619 err = js_get_reference_value(req->env, req->cb, callback);
2620 assert(err == 0);
2621
2622 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2623 assert(err != js_pending_exception);
2624
2625 err = js_close_handle_scope(req->env, scope);
2626 assert(err == 0);
2627
2628 delete req;
2629}
2630
2631static inline void
2632sn_crypto_pwhash_scryptsalsa208sha256_async(
2633 js_env_t *env,
2634 js_receiver_t,
2635
2636 js_arraybuffer_t out,
2637 uint32_t out_offset,
2638 uint32_t out_len,
2639
2640 js_arraybuffer_t pwd,
2641 uint32_t pwd_offset,
2642 uint32_t pwd_len,
2643
2644 js_arraybuffer_t salt,
2645 uint32_t salt_offset,
2646 uint32_t salt_len,
2647
2648 uint64_t opslimit,
2649 uint64_t memlimit,
2650
2651 js_function_t<void, int> callback
2652) {
2653 int err;
2654
2655 auto *req = new sn_async_pwhash_scryptsalsa208sha256_request(env);
2656
2657 std::span<uint8_t> out_view;
2658 err = js_get_arraybuffer_info(env, out, out_view);
2659 assert(err == 0);
2660 assert(out_offset + out_len <= out_view.size());
2661
2662 req->out = {&out_view[out_offset], out_len};
2663
2664 std::span<char> pwd_view;
2665 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2666 assert(err == 0);
2667 assert(pwd_offset + pwd_len <= pwd_view.size());
2668
2669 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2670
2671 std::span<uint8_t> salt_view;
2672 err = js_get_arraybuffer_info(env, salt, salt_view);
2673 assert(err == 0);
2674 assert(salt_offset + salt_len <= salt_view.size());
2675 assert(salt_len == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
2676
2677 req->salt = {&salt_view[salt_offset], salt_len};
2678
2679 req->opslimit = opslimit;
2680 req->memlimit = memlimit;
2681
2682 err = js_create_reference(env, out, req->out_ref);
2683 assert(err == 0);
2684
2685 err = js_create_reference(env, pwd, req->pwd_ref);
2686 assert(err == 0);
2687
2688 err = js_create_reference(env, salt, req->salt_ref);
2689 assert(err == 0);
2690
2691 err = js_create_reference(env, callback, req->cb);
2692 assert(err == 0);
2693
2694 uv_loop_t *loop;
2695 err = js_get_env_loop(env, &loop);
2696 assert(err == 0);
2697
2698 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_execute, async_pwhash_scryptsalsa208sha256_complete);
2699 assert(err == 0);
2700}
2701
2702struct sn_async_pwhash_scryptsalsa208sha256_str_request : sn_async_task {
2703 js_persistent_t<js_arraybuffer_t> out_ref;
2704 std::span<char> out;
2705
2706 js_persistent_t<js_arraybuffer_t> pwd_ref;
2707 std::span<char> pwd;
2708
2709 uint64_t opslimit;
2710 size_t memlimit;
2711
2712 sn_async_pwhash_scryptsalsa208sha256_str_request(js_env_t *env) : sn_async_task(env) {}
2713};
2714
2715static void
2716async_pwhash_scryptsalsa208sha256_str_execute(uv_work_t *uv_req) {
2717 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
2718
2719 req->code = crypto_pwhash_scryptsalsa208sha256_str(
2720 req->out.data(),
2721 req->pwd.data(),
2722 req->pwd.size(),
2723 req->opslimit,
2724 req->memlimit
2725 );
2726}
2727
2728static void
2729async_pwhash_scryptsalsa208sha256_str_complete(uv_work_t *uv_req, int status) {
2730 int err;
2731
2732 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
2733
2734 if (req->exiting) return delete req;
2735
2736 js_handle_scope_t *scope;
2737 err = js_open_handle_scope(req->env, &scope);
2738 assert(err == 0);
2739
2740 js_function_t<void, int> callback;
2741 err = js_get_reference_value(req->env, req->cb, callback);
2742 assert(err == 0);
2743
2744 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2745 assert(err != js_pending_exception);
2746
2747 err = js_close_handle_scope(req->env, scope);
2748 assert(err == 0);
2749
2750 delete req;
2751}
2752
2753static inline void
2754sn_crypto_pwhash_scryptsalsa208sha256_str_async(
2755 js_env_t *env,
2756 js_receiver_t,
2757
2758 js_arraybuffer_t out,
2759 uint32_t out_offset,
2760 uint32_t out_len,
2761
2762 js_arraybuffer_t pwd,
2763 uint32_t pwd_offset,
2764 uint32_t pwd_len,
2765
2766 uint64_t opslimit,
2767 uint64_t memlimit,
2768
2769 js_function_t<void, int> callback
2770) {
2771 int err;
2772
2773 auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_request(env);
2774
2775 std::span<char> out_view;
2776 err = js_get_arraybuffer_info(env, out, out_view);
2777 assert(err == 0);
2778 assert(out_offset + out_len <= out_view.size());
2779
2780 req->out = {&out_view[out_offset], out_len};
2781
2782 std::span<char> pwd_view;
2783 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2784 assert(err == 0);
2785 assert(pwd_offset + pwd_len <= pwd_view.size());
2786
2787 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2788
2789 req->opslimit = opslimit;
2790 req->memlimit = memlimit;
2791
2792 err = js_create_reference(env, out, req->out_ref);
2793 assert(err == 0);
2794
2795 err = js_create_reference(env, pwd, req->pwd_ref);
2796 assert(err == 0);
2797
2798 err = js_create_reference(env, callback, req->cb);
2799 assert(err == 0);
2800
2801 uv_loop_t *loop;
2802 err = js_get_env_loop(env, &loop);
2803 assert(err == 0);
2804
2805 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_execute, async_pwhash_scryptsalsa208sha256_str_complete);
2806 assert(err == 0);
2807}
2808
2809struct sn_async_pwhash_scryptsalsa208sha256_str_verify_request : sn_async_task {
2810 js_persistent_t<js_arraybuffer_t> str_ref;
2811 std::span<char> str;
2812
2813 js_persistent_t<js_arraybuffer_t> pwd_ref;
2814 std::span<char> pwd;
2815
2816 sn_async_pwhash_scryptsalsa208sha256_str_verify_request(js_env_t *env) : sn_async_task(env) {}
2817};
2818
2819static void
2820async_pwhash_scryptsalsa208sha256_str_verify_execute(uv_work_t *uv_req) {
2821 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
2822
2823 req->code = crypto_pwhash_scryptsalsa208sha256_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
2824}
2825
2826static void
2827async_pwhash_scryptsalsa208sha256_str_verify_complete(uv_work_t *uv_req, int status) {
2828 int err;
2829
2830 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
2831
2832 if (req->exiting) return delete req;
2833
2834 js_handle_scope_t *scope;
2835 err = js_open_handle_scope(req->env, &scope);
2836 assert(err == 0);
2837
2838 js_function_t<void, int> callback;
2839 err = js_get_reference_value(req->env, req->cb, callback);
2840 assert(err == 0);
2841
2842 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2843 assert(err != js_pending_exception);
2844
2845 err = js_close_handle_scope(req->env, scope);
2846 assert(err == 0);
2847
2848 delete req;
2849}
2850
2851static inline void
2852sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async(
2853 js_env_t *env,
2854 js_receiver_t,
2855
2856 js_arraybuffer_t str,
2857 uint32_t str_offset,
2858 uint32_t str_len,
2859
2860 js_arraybuffer_t pwd,
2861 uint32_t pwd_offset,
2862 uint32_t pwd_len,
2863
2864 js_function_t<void, int> callback
2865) {
2866 int err;
2867
2868 auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_verify_request(env);
2869
2870 std::span<char> str_view;
2871 err = js_get_arraybuffer_info(env, str, str_view);
2872 assert(err == 0);
2873 assert(str_offset + str_len <= str_view.size());
2874
2875 req->str = {&str_view[str_offset], str_len};
2876
2877 std::span<char> pwd_view;
2878 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2879 assert(err == 0);
2880 assert(pwd_offset + pwd_len <= pwd_view.size());
2881
2882 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2883
2884 err = js_create_reference(env, str, req->str_ref);
2885 assert(err == 0);
2886
2887 err = js_create_reference(env, pwd, req->pwd_ref);
2888 assert(err == 0);
2889
2890 err = js_create_reference(env, callback, req->cb);
2891 assert(err == 0);
2892
2893 uv_loop_t *loop;
2894 err = js_get_env_loop(env, &loop);
2895 assert(err == 0);
2896
2897 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_verify_execute, async_pwhash_scryptsalsa208sha256_str_verify_complete);
2898 assert(err == 0);
2899}
2900
2901struct sn_crypto_stream_xor_state {
2902 unsigned char n[crypto_stream_NONCEBYTES];
2903 unsigned char k[crypto_stream_KEYBYTES];
2904 unsigned char next_block[64];
2905 int remainder;
2906 uint64_t block_counter;
2907};
2908
2909static inline void
2910sn_crypto_stream_xor_wrap_init(
2911 js_env_t *,
2912 js_receiver_t,
2913 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
2914 js_typedarray_span_t<> n,
2915 js_typedarray_span_t<> k
2916) {
2917 assert(n.size_bytes() == crypto_stream_NONCEBYTES);
2918 assert(k.size_bytes() == crypto_stream_KEYBYTES);
2919
2920 state->remainder = 0;
2921 state->block_counter = 0;
2922 memcpy(state->n, n.data(), crypto_stream_NONCEBYTES);
2923 memcpy(state->k, k.data(), crypto_stream_KEYBYTES);
2924}
2925
2926static inline void
2927sn_crypto_stream_xor_wrap_update(
2928 js_env_t *,
2929 js_receiver_t,
2930 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
2931 js_typedarray_span_t<> c,
2932 js_typedarray_span_t<> m
2933) {
2934 assert(c.size_bytes() == m.size_bytes());
2935
2936 auto next_block = state->next_block;
2937
2938 size_t m_size = m.size_bytes();
2939 auto *c_ptr = c.data();
2940 auto *m_ptr = m.data();
2941
2942 if (state->remainder) {
2943 uint64_t offset = 0;
2944 int rem = state->remainder;
2945
2946 while (rem < 64 && offset < m_size) {
2947 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
2948 ++offset;
2949 ++rem;
2950 }
2951
2952 c_ptr += offset;
2953 m_ptr += offset;
2954 m_size -= offset;
2955 state->remainder = (rem == 64) ? 0 : rem;
2956
2957 if (m_size == 0) return;
2958 }
2959
2960 state->remainder = m_size & 63;
2961 size_t main_len = m_size - state->remainder;
2962
2963 crypto_stream_xsalsa20_xor_ic(c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k);
2964 state->block_counter += main_len / 64;
2965
2966 if (state->remainder) {
2967 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
2968 memcpy(next_block, m_ptr + main_len, state->remainder);
2969
2970 crypto_stream_xsalsa20_xor_ic(
2971 next_block, next_block, 64, state->n, state->block_counter, state->k
2972 );
2973 memcpy(c_ptr + main_len, next_block, state->remainder);
2974
2975 state->block_counter++;
2976 }
2977}
2978
2979static inline void
2980sn_crypto_stream_xor_wrap_final(
2981 js_env_t *,
2982 js_receiver_t,
2983 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state
2984) {
2985 sodium_memzero(state->n, sizeof(state->n));
2986 sodium_memzero(state->k, sizeof(state->k));
2987 sodium_memzero(state->next_block, sizeof(state->next_block));
2988 state->remainder = 0;
2989}
2990
2991struct sn_crypto_stream_chacha20_xor_state {
2992 unsigned char n[crypto_stream_chacha20_NONCEBYTES];
2993 unsigned char k[crypto_stream_chacha20_KEYBYTES];
2994 unsigned char next_block[64];
2995 int remainder;
2996 uint64_t block_counter;
2997};
2998
2999static inline void
3000sn_crypto_stream_chacha20_xor_wrap_init(
3001 js_env_t *,
3002 js_receiver_t,
3003 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
3004 js_typedarray_span_t<> n,
3005 js_typedarray_span_t<> k
3006) {
3007 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
3008 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
3009
3010 state->remainder = 0;
3011 state->block_counter = 0;
3012 memcpy(state->n, n.data(), crypto_stream_chacha20_NONCEBYTES);
3013 memcpy(state->k, k.data(), crypto_stream_chacha20_KEYBYTES);
3014}
3015
3016static inline void
3017sn_crypto_stream_chacha20_xor_wrap_update(
3018 js_env_t *,
3019 js_receiver_t,
3020 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
3021 js_typedarray_span_t<> c,
3022 js_typedarray_span_t<> m
3023) {
3024 assert(c.size_bytes() == m.size_bytes());
3025
3026 auto *next_block = state->next_block;
3027
3028 size_t m_size = m.size_bytes();
3029 auto *c_ptr = c.data();
3030 auto *m_ptr = m.data();
3031
3032 if (state->remainder) {
3033 uint64_t offset = 0;
3034 int rem = state->remainder;
3035
3036 while (rem < 64 && offset < m_size) {
3037 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3038 offset++;
3039 rem++;
3040 }
3041
3042 c_ptr += offset;
3043 m_ptr += offset;
3044 m_size -= offset;
3045 state->remainder = (rem == 64) ? 0 : rem;
3046
3047 if (m_size == 0) return;
3048 }
3049
3050 state->remainder = m_size & 63;
3051 size_t main_len = m_size - state->remainder;
3052
3053 crypto_stream_chacha20_xor_ic(
3054 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3055 );
3056
3057 state->block_counter += main_len / 64;
3058
3059 if (state->remainder) {
3060 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3061 memcpy(next_block, m_ptr + main_len, state->remainder);
3062
3063 crypto_stream_chacha20_xor_ic(
3064 next_block, next_block, 64, state->n, state->block_counter, state->k
3065 );
3066 memcpy(c_ptr + main_len, next_block, state->remainder);
3067
3068 state->block_counter++;
3069 }
3070}
3071
3072static inline void
3073sn_crypto_stream_chacha20_xor_wrap_final(
3074 js_env_t *,
3075 js_receiver_t,
3076 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state
3077) {
3078 sodium_memzero(state->n, sizeof(state->n));
3079 sodium_memzero(state->k, sizeof(state->k));
3080 sodium_memzero(state->next_block, sizeof(state->next_block));
3081 state->remainder = 0;
3082}
3083
3084struct sn_crypto_stream_chacha20_ietf_xor_state {
3085 unsigned char n[crypto_stream_chacha20_ietf_NONCEBYTES];
3086 unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES];
3087 unsigned char next_block[64];
3088 int remainder;
3089 uint64_t block_counter;
3090};
3091
3092static inline void
3093sn_crypto_stream_chacha20_ietf_xor_wrap_init(
3094 js_env_t *,
3095 js_receiver_t,
3096 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
3097 js_typedarray_span_t<> n,
3098 js_typedarray_span_t<> k
3099) {
3100 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
3101 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
3102
3103 state->remainder = 0;
3104 state->block_counter = 0;
3105 memcpy(state->n, n.data(), crypto_stream_chacha20_ietf_NONCEBYTES);
3106 memcpy(state->k, k.data(), crypto_stream_chacha20_ietf_KEYBYTES);
3107}
3108
3109static inline void
3110sn_crypto_stream_chacha20_ietf_xor_wrap_update(
3111 js_env_t *,
3112 js_receiver_t,
3113 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
3114 js_typedarray_span_t<> c,
3115 js_typedarray_span_t<> m
3116) {
3117 assert(c.size_bytes() == m.size_bytes());
3118
3119 auto *next_block = state->next_block;
3120
3121 size_t m_size = m.size_bytes();
3122 auto *c_ptr = c.data();
3123 auto *m_ptr = m.data();
3124
3125 if (state->remainder) {
3126 uint64_t offset = 0;
3127 int rem = state->remainder;
3128
3129 while (rem < 64 && offset < m_size) {
3130 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3131 offset++;
3132 rem++;
3133 }
3134
3135 c_ptr += offset;
3136 m_ptr += offset;
3137 m_size -= offset;
3138 state->remainder = (rem == 64) ? 0 : rem;
3139
3140 if (m_size == 0) return;
3141 }
3142
3143 state->remainder = m_size & 63;
3144 size_t main_len = m_size - state->remainder;
3145
3146 crypto_stream_chacha20_ietf_xor_ic(
3147 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3148 );
3149
3150 state->block_counter += main_len / 64;
3151
3152 if (state->remainder) {
3153 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3154 memcpy(next_block, m_ptr + main_len, state->remainder);
3155
3156 crypto_stream_chacha20_ietf_xor_ic(
3157 next_block, next_block, 64, state->n, state->block_counter, state->k
3158 );
3159 memcpy(c_ptr + main_len, next_block, state->remainder);
3160
3161 state->block_counter++;
3162 }
3163}
3164
3165static inline void
3166sn_crypto_stream_chacha20_ietf_xor_wrap_final(
3167 js_env_t *,
3168 js_receiver_t,
3169 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state
3170) {
3171 sodium_memzero(state->n, sizeof(state->n));
3172 sodium_memzero(state->k, sizeof(state->k));
3173 sodium_memzero(state->next_block, sizeof(state->next_block));
3174 state->remainder = 0;
3175}
3176
3177struct sn_crypto_stream_xchacha20_xor_state {
3178 unsigned char n[crypto_stream_xchacha20_NONCEBYTES];
3179 unsigned char k[crypto_stream_xchacha20_KEYBYTES];
3180 unsigned char next_block[64];
3181 int remainder;
3182 uint64_t block_counter;
3183};
3184
3185static inline void
3186sn_crypto_stream_xchacha20_xor_wrap_init(
3187 js_env_t *,
3188 js_receiver_t,
3189 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
3190 js_typedarray_span_t<> n,
3191 js_typedarray_span_t<> k
3192) {
3193 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
3194 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
3195
3196 state->remainder = 0;
3197 state->block_counter = 0;
3198 memcpy(state->n, n.data(), crypto_stream_xchacha20_NONCEBYTES);
3199 memcpy(state->k, k.data(), crypto_stream_xchacha20_KEYBYTES);
3200}
3201
3202static inline void
3203sn_crypto_stream_xchacha20_xor_wrap_update(
3204 js_env_t *,
3205 js_receiver_t,
3206 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
3207 js_typedarray_span_t<> c,
3208 js_typedarray_span_t<> m
3209) {
3210 assert(c.size_bytes() == m.size_bytes());
3211
3212 auto *next_block = state->next_block;
3213
3214 size_t m_size = m.size_bytes();
3215 auto *c_ptr = c.data();
3216 auto *m_ptr = m.data();
3217
3218 if (state->remainder) {
3219 uint64_t offset = 0;
3220 int rem = state->remainder;
3221
3222 while (rem < 64 && offset < m_size) {
3223 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3224 ++offset;
3225 ++rem;
3226 }
3227
3228 c_ptr += offset;
3229 m_ptr += offset;
3230 m_size -= offset;
3231 state->remainder = (rem == 64) ? 0 : rem;
3232
3233 if (m_size == 0) return;
3234 }
3235
3236 state->remainder = m_size & 63;
3237 size_t main_len = m_size - state->remainder;
3238
3239 crypto_stream_xchacha20_xor_ic(
3240 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3241 );
3242
3243 state->block_counter += main_len / 64;
3244
3245 if (state->remainder) {
3246 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3247 memcpy(next_block, m_ptr + main_len, state->remainder);
3248
3249 crypto_stream_xchacha20_xor_ic(
3250 next_block, next_block, 64, state->n, state->block_counter, state->k
3251 );
3252 memcpy(c_ptr + main_len, next_block, state->remainder);
3253
3254 state->block_counter++;
3255 }
3256}
3257
3258static inline void
3259sn_crypto_stream_xchacha20_xor_wrap_final(
3260 js_env_t *,
3261 js_receiver_t,
3262 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state
3263) {
3264 sodium_memzero(state->n, sizeof(state->n));
3265 sodium_memzero(state->k, sizeof(state->k));
3266 sodium_memzero(state->next_block, sizeof(state->next_block));
3267 state->remainder = 0;
3268}
3269
3270struct sn_crypto_stream_salsa20_xor_state {
3271 unsigned char n[crypto_stream_salsa20_NONCEBYTES];
3272 unsigned char k[crypto_stream_salsa20_KEYBYTES];
3273 unsigned char next_block[64];
3274 int remainder;
3275 uint64_t block_counter;
3276};
3277
3278static inline void
3279sn_crypto_stream_salsa20_xor_wrap_init(
3280 js_env_t *,
3281 js_receiver_t,
3282 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
3283 js_typedarray_span_t<> n,
3284 js_typedarray_span_t<> k
3285) {
3286 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
3287 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
3288
3289 state->remainder = 0;
3290 state->block_counter = 0;
3291 memcpy(state->n, n.data(), crypto_stream_salsa20_NONCEBYTES);
3292 memcpy(state->k, k.data(), crypto_stream_salsa20_KEYBYTES);
3293}
3294
3295static inline void
3296sn_crypto_stream_salsa20_xor_wrap_update(
3297 js_env_t *,
3298 js_receiver_t,
3299 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
3300 js_typedarray_span_t<> c,
3301 js_typedarray_span_t<> m
3302) {
3303 assert(c.size_bytes() == m.size_bytes());
3304
3305 auto *next_block = state->next_block;
3306
3307 size_t m_size = m.size_bytes();
3308 auto *c_ptr = c.data();
3309 auto *m_ptr = m.data();
3310
3311 if (state->remainder) {
3312 uint64_t offset = 0;
3313 int rem = state->remainder;
3314
3315 while (rem < 64 && offset < m_size) {
3316 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3317 ++offset;
3318 ++rem;
3319 }
3320
3321 c_ptr += offset;
3322 m_ptr += offset;
3323 m_size -= offset;
3324 state->remainder = (rem == 64) ? 0 : rem;
3325
3326 if (m_size == 0) return;
3327 }
3328
3329 state->remainder = m_size & 63;
3330 size_t main_len = m_size - state->remainder;
3331
3332 crypto_stream_salsa20_xor_ic(
3333 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3334 );
3335
3336 state->block_counter += main_len / 64;
3337
3338 if (state->remainder) {
3339 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3340 memcpy(next_block, m_ptr + main_len, state->remainder);
3341
3342 crypto_stream_salsa20_xor_ic(
3343 next_block, next_block, 64, state->n, state->block_counter, state->k
3344 );
3345 memcpy(c_ptr + main_len, next_block, state->remainder);
3346
3347 state->block_counter++;
3348 }
3349}
3350
3351static inline void
3352sn_crypto_stream_salsa20_xor_wrap_final(
3353 js_env_t *,
3354 js_receiver_t,
3355 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state
3356) {
3357 sodium_memzero(state->n, sizeof(state->n));
3358 sodium_memzero(state->k, sizeof(state->k));
3359 sodium_memzero(state->next_block, sizeof(state->next_block));
3360 state->remainder = 0;
3361}
3362
3363// Experimental API
3364
3365static inline void
3366sn_extension_tweak_ed25519_base(
3367 js_env_t *,
3368 js_receiver_t,
3369 js_typedarray_span_t<> n,
3370 js_typedarray_span_t<> p,
3371 js_typedarray_span_t<> ns
3372) {
3373 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3374 assert(p.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3375
3376 sn__extension_tweak_ed25519_base(p.data(), n.data(), ns.data(), ns.size_bytes());
3377}
3378
3379static inline int
3380sn_extension_tweak_ed25519_sign_detached(
3381 js_env_t *,
3382 js_receiver_t,
3383 js_typedarray_span_t<> sig,
3384 js_typedarray_span_t<> m,
3385 js_typedarray_span_t<> scalar,
3386 std::optional<js_typedarray_span_t<>> pk
3387) {
3388 assert(sig.size_bytes() == crypto_sign_BYTES);
3389 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3390
3391 uint8_t *pk_data = nullptr;
3392 if (pk) {
3393 assert(pk->size_bytes() == crypto_sign_PUBLICKEYBYTES);
3394 pk_data = pk->data();
3395 }
3396
3397 return sn__extension_tweak_ed25519_sign_detached(
3398 sig.data(),
3399 nullptr,
3400 m.data(),
3401 m.size_bytes(),
3402 scalar.data(),
3403 pk_data
3404 );
3405}
3406
3407static inline void
3408sn_extension_tweak_ed25519_sk_to_scalar(
3409 js_env_t *,
3410 js_receiver_t,
3411 js_typedarray_span_t<> n,
3412 js_typedarray_span_t<> sk
3413) {
3414 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3415 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
3416
3417 sn__extension_tweak_ed25519_sk_to_scalar(n.data(), sk.data());
3418}
3419
3420static inline void
3421sn_extension_tweak_ed25519_scalar(
3422 js_env_t *,
3423 js_receiver_t,
3424 js_typedarray_span_t<> scalar_out,
3425 js_typedarray_span_t<> scalar,
3426 js_typedarray_span_t<> ns
3427) {
3428 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3429 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3430
3431 sn__extension_tweak_ed25519_scalar(scalar_out.data(), scalar.data(), ns.data(), ns.size_bytes());
3432}
3433
3434static inline int
3435sn_extension_tweak_ed25519_pk(
3436 js_env_t *,
3437 js_receiver_t,
3438 js_typedarray_span_t<> tpk,
3439 js_typedarray_span_t<> pk,
3440 js_typedarray_span_t<> ns
3441) {
3442 assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3443 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3444
3445 return sn__extension_tweak_ed25519_pk(tpk.data(), pk.data(), ns.data(), ns.size_bytes());
3446}
3447
3448static inline void
3449sn_extension_tweak_ed25519_keypair(
3450 js_env_t *,
3451 js_receiver_t,
3452 js_typedarray_span_t<> pk,
3453 js_typedarray_span_t<> scalar_out,
3454 js_typedarray_span_t<> scalar_in,
3455 js_typedarray_span_t<> ns
3456) {
3457 assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3458 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3459 assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3460
3461 sn__extension_tweak_ed25519_keypair(
3462 pk.data(),
3463 scalar_out.data(),
3464 scalar_in.data(),
3465 ns.data(),
3466 ns.size_bytes()
3467 );
3468}
3469
3470static inline void
3471sn_extension_tweak_ed25519_scalar_add(
3472 js_env_t *,
3473 js_receiver_t,
3474 js_typedarray_span_t<> scalar_out,
3475 js_typedarray_span_t<> scalar,
3476 js_typedarray_span_t<> n
3477) {
3478 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3479 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3480 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3481
3482 sn__extension_tweak_ed25519_scalar_add(scalar_out.data(), scalar.data(), n.data());
3483}
3484
3485static inline int
3486sn_extension_tweak_ed25519_pk_add(
3487 js_env_t *,
3488 js_receiver_t,
3489 js_typedarray_span_t<> tpk,
3490 js_typedarray_span_t<> pk,
3491 js_typedarray_span_t<> p
3492) {
3493 assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3494 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3495 assert(p.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3496
3497 return sn__extension_tweak_ed25519_pk_add(tpk.data(), pk.data(), p.data());
3498}
3499
3500static inline int
3501sn_extension_tweak_ed25519_keypair_add(
3502 js_env_t *,
3503 js_receiver_t,
3504 js_typedarray_span_t<> pk,
3505 js_typedarray_span_t<> scalar_out,
3506 js_typedarray_span_t<> scalar_in,
3507 js_typedarray_span_t<> tweak
3508) {
3509 assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3510 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3511 assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3512 assert(tweak.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3513
3514 return sn__extension_tweak_ed25519_keypair_add(
3515 pk.data(),
3516 scalar_out.data(),
3517 scalar_in.data(),
3518 tweak.data()
3519 );
3520}
3521
3522static inline int
3523sn_extension_pbkdf2_sha512(
3524 js_env_t *,
3525 js_receiver_t,
3526 js_typedarray_span_t<> out,
3527 js_typedarray_span_t<> passwd,
3528 js_typedarray_span_t<> salt,
3529 uint64_t iter,
3530 uint64_t outlen
3531) {
3532
3533 assert(iter >= sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
3534 assert(outlen <= sn__extension_pbkdf2_sha512_BYTES_MAX);
3535 assert(out.size_bytes() >= static_cast<size_t>(outlen));
3536
3537 return sn__extension_pbkdf2_sha512(
3538 passwd.data(),
3539 passwd.size_bytes(),
3540 salt.data(),
3541 salt.size_bytes(),
3542 iter,
3543 out.data(),
3544 outlen
3545 );
3546}
3547
3548struct sn_async_pbkdf2_sha512_request : sn_async_task {
3549 js_persistent_t<js_arraybuffer_t> out_ref;
3550 std::span<uint8_t> out;
3551
3552 size_t outlen;
3553
3554 js_persistent_t<js_arraybuffer_t> pwd_ref;
3555 std::span<uint8_t> pwd;
3556
3557 js_persistent_t<js_arraybuffer_t> salt_ref;
3558 std::span<uint8_t> salt;
3559
3560 uint64_t iter;
3561
3562 sn_async_pbkdf2_sha512_request(js_env_t *env) : sn_async_task(env) {}
3563};
3564
3565static void
3566async_pbkdf2_sha512_execute(uv_work_t *uv_req) {
3567 auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
3568
3569 req->code = sn__extension_pbkdf2_sha512(
3570 req->pwd.data(),
3571 req->pwd.size(),
3572 req->salt.data(),
3573 req->salt.size(),
3574 req->iter,
3575 req->out.data(),
3576 req->outlen
3577 );
3578}
3579
3580static void
3581async_pbkdf2_sha512_complete(uv_work_t *uv_req, int status) {
3582 int err;
3583
3584 auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
3585
3586 if (req->exiting) return delete req;
3587
3588 js_handle_scope_t *scope;
3589 err = js_open_handle_scope(req->env, &scope);
3590 assert(err == 0);
3591
3592 js_function_t<void, int> callback;
3593 err = js_get_reference_value(req->env, req->cb, callback);
3594 assert(err == 0);
3595
3596 err = js_call_function_with_checkpoint(req->env, callback, req->code);
3597 assert(err != js_pending_exception);
3598
3599 err = js_close_handle_scope(req->env, scope);
3600 assert(err == 0);
3601
3602 delete req;
3603}
3604
3605static inline void
3606sn_extension_pbkdf2_sha512_async(
3607 js_env_t *env,
3608 js_receiver_t,
3609
3610 js_arraybuffer_t out,
3611 uint32_t out_offset,
3612 uint32_t out_len,
3613
3614 js_arraybuffer_t pwd,
3615 uint32_t pwd_offset,
3616 uint32_t pwd_len,
3617
3618 js_arraybuffer_t salt,
3619 uint32_t salt_offset,
3620 uint32_t salt_len,
3621
3622 uint64_t iter,
3623 uint64_t outlen,
3624
3625 js_function_t<void, int> callback
3626) {
3627 int err;
3628
3629 auto *req = new sn_async_pbkdf2_sha512_request(env);
3630
3631 std::span<uint8_t> out_view;
3632 err = js_get_arraybuffer_info(env, out, out_view);
3633 assert(err == 0);
3634 assert(out_offset + out_len <= out_view.size());
3635
3636 req->out = {&out_view[out_offset], out_len};
3637
3638 std::span<uint8_t> pwd_view;
3639 err = js_get_arraybuffer_info(env, pwd, pwd_view);
3640 assert(err == 0);
3641 assert(pwd_offset + pwd_len <= pwd_view.size());
3642
3643 req->pwd = {&pwd_view[pwd_offset], pwd_len};
3644
3645 std::span<uint8_t> salt_view;
3646 err = js_get_arraybuffer_info(env, salt, salt_view);
3647 assert(err == 0);
3648 assert(salt_offset + salt_len <= salt_view.size());
3649
3650 req->salt = {&salt_view[salt_offset], salt_len};
3651
3652 req->iter = iter;
3653 req->outlen = outlen;
3654
3655 err = js_create_reference(env, out, req->out_ref);
3656 assert(err == 0);
3657
3658 err = js_create_reference(env, pwd, req->pwd_ref);
3659 assert(err == 0);
3660
3661 err = js_create_reference(env, salt, req->salt_ref);
3662 assert(err == 0);
3663
3664 err = js_create_reference(env, callback, req->cb);
3665 assert(err == 0);
3666
3667 uv_loop_t *loop;
3668 err = js_get_env_loop(env, &loop);
3669 assert(err == 0);
3670
3671 err = uv_queue_work(loop, &req->task, async_pbkdf2_sha512_execute, async_pbkdf2_sha512_complete);
3672 assert(err == 0);
3673}
3674
3675static js_value_t *
3676sodium_native_exports(js_env_t *env, js_value_t *exports) {
3677 int err;
3678
3679 err = sodium_init();
3680 assert(err >= 0);
3681
3682#define V_FUNCTION(name, fn) \
3683 err = js_set_property<fn>(env, exports, name); \
3684 assert(err == 0);
3685
3686#define V_FUNCTION_NOSCOPE(name, fn) \
3687 err = js_set_property<fn, js_function_options_t{.scoped = false}>(env, exports, name); \
3688 assert(err == 0);
3689
3690#define V_UINT32(name, constant) \
3691 err = js_set_property(env, exports, name, static_cast<uint32_t>(constant)); \
3692 assert(err == 0);
3693
3694#define V_UINT64(name, constant) \
3695 err = js_set_property(env, exports, name, static_cast<int64_t>(std::min<uint64_t>(constant, js_max_safe_integer))); \
3696 assert(err == 0);
3697
3698#define V_STRING(name, str) \
3699 err = js_set_property(env, exports, name, str); \
3700 assert(err == 0);
3701
3702 // memory
3703
3704 V_FUNCTION("sodium_memzero", sn_sodium_memzero);
3705 V_FUNCTION("sodium_mlock", sn_sodium_mlock);
3706 V_FUNCTION("sodium_munlock", sn_sodium_munlock);
3707 V_FUNCTION("sodium_malloc", sn_sodium_malloc);
3708 V_FUNCTION("sodium_free", sn_sodium_free);
3709 V_FUNCTION("sodium_mprotect_noaccess", sn_sodium_mprotect_noaccess);
3710 V_FUNCTION("sodium_mprotect_readonly", sn_sodium_mprotect_readonly);
3711 V_FUNCTION("sodium_mprotect_readwrite", sn_sodium_mprotect_readwrite);
3712
3713 // randombytes
3714
3715 V_FUNCTION_NOSCOPE("randombytes_buf", sn_randombytes_buf);
3716 V_FUNCTION_NOSCOPE("randombytes_buf_deterministic", sn_randombytes_buf_deterministic);
3717 V_FUNCTION_NOSCOPE("randombytes_random", sn_randombytes_random);
3718 V_FUNCTION_NOSCOPE("randombytes_uniform", sn_randombytes_uniform);
3719
3720 V_UINT32("randombytes_SEEDBYTES", randombytes_SEEDBYTES);
3721
3722 // sodium helpers
3723
3724 V_FUNCTION("sodium_memcmp", sn_sodium_memcmp);
3725 V_FUNCTION("sodium_increment", sn_sodium_increment);
3726 V_FUNCTION("sodium_add", sn_sodium_add);
3727 V_FUNCTION("sodium_sub", sn_sodium_sub);
3728 V_FUNCTION("sodium_compare", sn_sodium_compare);
3729 V_FUNCTION("sodium_is_zero", sn_sodium_is_zero);
3730 V_FUNCTION("sodium_pad", sn_sodium_pad);
3731 V_FUNCTION("sodium_unpad", sn_sodium_unpad);
3732
3733 // crypto_aead
3734
3735 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_keygen", sn_crypto_aead_xchacha20poly1305_ietf_keygen);
3736 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt", sn_crypto_aead_xchacha20poly1305_ietf_encrypt);
3737 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt", sn_crypto_aead_xchacha20poly1305_ietf_decrypt);
3738 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached);
3739 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached);
3740 V_UINT32("crypto_aead_xchacha20poly1305_ietf_ABYTES", crypto_aead_xchacha20poly1305_ietf_ABYTES);
3741 V_UINT32("crypto_aead_xchacha20poly1305_ietf_KEYBYTES", crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
3742 V_UINT32("crypto_aead_xchacha20poly1305_ietf_NPUBBYTES", crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
3743 V_UINT32("crypto_aead_xchacha20poly1305_ietf_NSECBYTES", crypto_aead_xchacha20poly1305_ietf_NSECBYTES);
3744 V_UINT64("crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX);
3745
3746 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_keygen", sn_crypto_aead_chacha20poly1305_ietf_keygen);
3747 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt", sn_crypto_aead_chacha20poly1305_ietf_encrypt);
3748 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt", sn_crypto_aead_chacha20poly1305_ietf_decrypt);
3749 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached);
3750 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached);
3751 V_UINT32("crypto_aead_chacha20poly1305_ietf_ABYTES", crypto_aead_chacha20poly1305_ietf_ABYTES);
3752 V_UINT32("crypto_aead_chacha20poly1305_ietf_KEYBYTES", crypto_aead_chacha20poly1305_ietf_KEYBYTES);
3753 V_UINT32("crypto_aead_chacha20poly1305_ietf_NPUBBYTES", crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
3754 V_UINT32("crypto_aead_chacha20poly1305_ietf_NSECBYTES", crypto_aead_chacha20poly1305_ietf_NSECBYTES);
3755 V_UINT64("crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
3756
3757 // crypto_auth
3758
3759 V_FUNCTION("crypto_auth", sn_crypto_auth);
3760 V_FUNCTION("crypto_auth_verify", sn_crypto_auth_verify);
3761 V_UINT32("crypto_auth_BYTES", crypto_auth_BYTES);
3762 V_UINT32("crypto_auth_KEYBYTES", crypto_auth_KEYBYTES);
3763 V_STRING("crypto_auth_PRIMITIVE", crypto_auth_PRIMITIVE);
3764
3765 // crypto_box
3766
3767 V_FUNCTION("crypto_box_keypair", sn_crypto_box_keypair);
3768 V_FUNCTION("crypto_box_seed_keypair", sn_crypto_box_seed_keypair);
3769 V_FUNCTION("crypto_box_easy", sn_crypto_box_easy);
3770 V_FUNCTION("crypto_box_open_easy", sn_crypto_box_open_easy);
3771 V_FUNCTION("crypto_box_detached", sn_crypto_box_detached);
3772 V_FUNCTION("crypto_box_open_detached", sn_crypto_box_open_detached);
3773 V_FUNCTION("crypto_box_seal", sn_crypto_box_seal);
3774 V_FUNCTION_NOSCOPE("crypto_box_seal_open", sn_crypto_box_seal_open);
3775
3776 V_UINT32("crypto_box_SEEDBYTES", crypto_box_SEEDBYTES);
3777 V_UINT32("crypto_box_PUBLICKEYBYTES", crypto_box_PUBLICKEYBYTES);
3778 V_UINT32("crypto_box_SECRETKEYBYTES", crypto_box_SECRETKEYBYTES);
3779 V_UINT32("crypto_box_NONCEBYTES", crypto_box_NONCEBYTES);
3780 V_UINT32("crypto_box_MACBYTES", crypto_box_MACBYTES);
3781 V_UINT32("crypto_box_SEALBYTES", crypto_box_SEALBYTES);
3782 V_STRING("crypto_box_PRIMITIVE", crypto_box_PRIMITIVE);
3783
3784 // crypto_core
3785
3786 V_FUNCTION("crypto_core_ed25519_is_valid_point", sn_crypto_core_ed25519_is_valid_point);
3787 V_FUNCTION("crypto_core_ed25519_from_uniform", sn_crypto_core_ed25519_from_uniform);
3788 V_FUNCTION("crypto_core_ed25519_add", sn_crypto_core_ed25519_add);
3789 V_FUNCTION("crypto_core_ed25519_sub", sn_crypto_core_ed25519_sub);
3790 V_FUNCTION("crypto_core_ed25519_scalar_random", sn_crypto_core_ed25519_scalar_random);
3791 V_FUNCTION("crypto_core_ed25519_scalar_reduce", sn_crypto_core_ed25519_scalar_reduce);
3792 V_FUNCTION("crypto_core_ed25519_scalar_invert", sn_crypto_core_ed25519_scalar_invert);
3793 V_FUNCTION("crypto_core_ed25519_scalar_negate", sn_crypto_core_ed25519_scalar_negate);
3794 V_FUNCTION("crypto_core_ed25519_scalar_complement", sn_crypto_core_ed25519_scalar_complement);
3795 V_FUNCTION("crypto_core_ed25519_scalar_add", sn_crypto_core_ed25519_scalar_add);
3796 V_FUNCTION("crypto_core_ed25519_scalar_sub", sn_crypto_core_ed25519_scalar_sub);
3797 V_UINT32("crypto_core_ed25519_BYTES", crypto_core_ed25519_BYTES);
3798 V_UINT32("crypto_core_ed25519_UNIFORMBYTES", crypto_core_ed25519_UNIFORMBYTES);
3799 V_UINT32("crypto_core_ed25519_SCALARBYTES", crypto_core_ed25519_SCALARBYTES);
3800 V_UINT32("crypto_core_ed25519_NONREDUCEDSCALARBYTES", crypto_core_ed25519_NONREDUCEDSCALARBYTES);
3801
3802 // crypto_kdf
3803
3804 V_FUNCTION("crypto_kdf_keygen", sn_crypto_kdf_keygen);
3805 V_FUNCTION("crypto_kdf_derive_from_key", sn_crypto_kdf_derive_from_key);
3806 V_UINT32("crypto_kdf_BYTES_MIN", crypto_kdf_BYTES_MIN);
3807 V_UINT32("crypto_kdf_BYTES_MAX", crypto_kdf_BYTES_MAX);
3808 V_UINT32("crypto_kdf_CONTEXTBYTES", crypto_kdf_CONTEXTBYTES);
3809 V_UINT32("crypto_kdf_KEYBYTES", crypto_kdf_KEYBYTES);
3810 V_STRING("crypto_kdf_PRIMITIVE", crypto_kdf_PRIMITIVE);
3811
3812 // crypto_kx
3813
3814 V_FUNCTION("crypto_kx_keypair", sn_crypto_kx_keypair);
3815 V_FUNCTION("crypto_kx_seed_keypair", sn_crypto_kx_seed_keypair);
3816 V_FUNCTION("crypto_kx_client_session_keys", sn_crypto_kx_client_session_keys);
3817 V_FUNCTION("crypto_kx_server_session_keys", sn_crypto_kx_server_session_keys);
3818 V_UINT32("crypto_kx_PUBLICKEYBYTES", crypto_kx_PUBLICKEYBYTES);
3819 V_UINT32("crypto_kx_SECRETKEYBYTES", crypto_kx_SECRETKEYBYTES);
3820 V_UINT32("crypto_kx_SEEDBYTES", crypto_kx_SEEDBYTES);
3821 V_UINT32("crypto_kx_SESSIONKEYBYTES", crypto_kx_SESSIONKEYBYTES);
3822 V_STRING("crypto_kx_PRIMITIVE", crypto_kx_PRIMITIVE);
3823
3824 // crypto_generichash
3825
3826 V_FUNCTION_NOSCOPE("crypto_generichash", sn_crypto_generichash);
3827 V_FUNCTION("crypto_generichash_batch", sn_crypto_generichash_batch);
3828 V_FUNCTION_NOSCOPE("crypto_generichash_keygen", sn_crypto_generichash_keygen);
3829 V_FUNCTION_NOSCOPE("crypto_generichash_init", sn_crypto_generichash_init);
3830 V_FUNCTION_NOSCOPE("crypto_generichash_update", sn_crypto_generichash_update);
3831 V_FUNCTION_NOSCOPE("crypto_generichash_final", sn_crypto_generichash_final);
3832
3833 V_UINT32("crypto_generichash_STATEBYTES", sizeof(crypto_generichash_state));
3834 V_STRING("crypto_generichash_PRIMITIVE", crypto_generichash_PRIMITIVE);
3835 V_UINT32("crypto_generichash_BYTES_MIN", crypto_generichash_BYTES_MIN);
3836 V_UINT32("crypto_generichash_BYTES_MAX", crypto_generichash_BYTES_MAX);
3837 V_UINT32("crypto_generichash_BYTES", crypto_generichash_BYTES);
3838 V_UINT32("crypto_generichash_KEYBYTES_MIN", crypto_generichash_KEYBYTES_MIN);
3839 V_UINT32("crypto_generichash_KEYBYTES_MAX", crypto_generichash_KEYBYTES_MAX);
3840 V_UINT32("crypto_generichash_KEYBYTES", crypto_generichash_KEYBYTES);
3841
3842 // crypto_hash
3843
3844 V_FUNCTION("crypto_hash", sn_crypto_hash);
3845 V_UINT32("crypto_hash_BYTES", crypto_hash_BYTES);
3846 V_STRING("crypto_hash_PRIMITIVE", crypto_hash_PRIMITIVE);
3847
3848 V_FUNCTION("crypto_hash_sha256", sn_crypto_hash_sha256);
3849 V_FUNCTION("crypto_hash_sha256_init", sn_crypto_hash_sha256_init);
3850 V_FUNCTION("crypto_hash_sha256_update", sn_crypto_hash_sha256_update);
3851 V_FUNCTION("crypto_hash_sha256_final", sn_crypto_hash_sha256_final);
3852 V_UINT32("crypto_hash_sha256_STATEBYTES", sizeof(crypto_hash_sha256_state));
3853 V_UINT32("crypto_hash_sha256_BYTES", crypto_hash_sha256_BYTES);
3854
3855 V_FUNCTION("crypto_hash_sha512", sn_crypto_hash_sha512);
3856 V_FUNCTION("crypto_hash_sha512_init", sn_crypto_hash_sha512_init);
3857 V_FUNCTION("crypto_hash_sha512_update", sn_crypto_hash_sha512_update);
3858 V_FUNCTION("crypto_hash_sha512_final", sn_crypto_hash_sha512_final);
3859 V_UINT32("crypto_hash_sha512_STATEBYTES", sizeof(crypto_hash_sha512_state));
3860 V_UINT32("crypto_hash_sha512_BYTES", crypto_hash_sha512_BYTES);
3861
3862 // crypto_onetimeauth
3863
3864 V_FUNCTION("crypto_onetimeauth", sn_crypto_onetimeauth);
3865 V_FUNCTION("crypto_onetimeauth_verify", sn_crypto_onetimeauth_verify);
3866 V_FUNCTION("crypto_onetimeauth_init", sn_crypto_onetimeauth_init);
3867 V_FUNCTION("crypto_onetimeauth_update", sn_crypto_onetimeauth_update);
3868 V_FUNCTION("crypto_onetimeauth_final", sn_crypto_onetimeauth_final);
3869 V_UINT32("crypto_onetimeauth_STATEBYTES", sizeof(crypto_onetimeauth_state));
3870 V_UINT32("crypto_onetimeauth_BYTES", crypto_onetimeauth_BYTES);
3871 V_UINT32("crypto_onetimeauth_KEYBYTES", crypto_onetimeauth_KEYBYTES);
3872 V_STRING("crypto_onetimeauth_PRIMITIVE", crypto_onetimeauth_PRIMITIVE);
3873
3874 // crypto_pwhash
3875
3876 V_FUNCTION("crypto_pwhash", sn_crypto_pwhash);
3877 V_FUNCTION("crypto_pwhash_str", sn_crypto_pwhash_str);
3878 V_FUNCTION("crypto_pwhash_str_verify", sn_crypto_pwhash_str_verify);
3879 V_FUNCTION("crypto_pwhash_str_needs_rehash", sn_crypto_pwhash_str_needs_rehash);
3880 V_FUNCTION("crypto_pwhash_async", sn_crypto_pwhash_async);
3881 V_FUNCTION("crypto_pwhash_str_async", sn_crypto_pwhash_str_async);
3882 V_FUNCTION("crypto_pwhash_str_verify_async", sn_crypto_pwhash_str_verify_async);
3883 V_UINT32("crypto_pwhash_ALG_ARGON2I13", crypto_pwhash_ALG_ARGON2I13);
3884 V_UINT32("crypto_pwhash_ALG_ARGON2ID13", crypto_pwhash_ALG_ARGON2ID13);
3885 V_UINT32("crypto_pwhash_ALG_DEFAULT", crypto_pwhash_ALG_DEFAULT);
3886 V_UINT32("crypto_pwhash_BYTES_MIN", crypto_pwhash_BYTES_MIN);
3887 V_UINT32("crypto_pwhash_BYTES_MAX", crypto_pwhash_BYTES_MAX);
3888 V_UINT32("crypto_pwhash_PASSWD_MIN", crypto_pwhash_PASSWD_MIN);
3889 V_UINT32("crypto_pwhash_PASSWD_MAX", crypto_pwhash_PASSWD_MAX);
3890 V_UINT32("crypto_pwhash_SALTBYTES", crypto_pwhash_SALTBYTES);
3891 V_UINT32("crypto_pwhash_STRBYTES", crypto_pwhash_STRBYTES);
3892 V_STRING("crypto_pwhash_STRPREFIX", crypto_pwhash_STRPREFIX);
3893 V_UINT32("crypto_pwhash_OPSLIMIT_MIN", crypto_pwhash_OPSLIMIT_MIN);
3894 V_UINT32("crypto_pwhash_OPSLIMIT_MAX", crypto_pwhash_OPSLIMIT_MAX);
3895 V_UINT64("crypto_pwhash_MEMLIMIT_MIN", crypto_pwhash_MEMLIMIT_MIN);
3896 V_UINT64("crypto_pwhash_MEMLIMIT_MAX", crypto_pwhash_MEMLIMIT_MAX);
3897 V_UINT32("crypto_pwhash_OPSLIMIT_INTERACTIVE", crypto_pwhash_OPSLIMIT_INTERACTIVE);
3898 V_UINT64("crypto_pwhash_MEMLIMIT_INTERACTIVE", crypto_pwhash_MEMLIMIT_INTERACTIVE);
3899 V_UINT32("crypto_pwhash_OPSLIMIT_MODERATE", crypto_pwhash_OPSLIMIT_MODERATE);
3900 V_UINT64("crypto_pwhash_MEMLIMIT_MODERATE", crypto_pwhash_MEMLIMIT_MODERATE);
3901 V_UINT32("crypto_pwhash_OPSLIMIT_SENSITIVE", crypto_pwhash_OPSLIMIT_SENSITIVE);
3902 V_UINT64("crypto_pwhash_MEMLIMIT_SENSITIVE", crypto_pwhash_MEMLIMIT_SENSITIVE);
3903 V_STRING("crypto_pwhash_PRIMITIVE", crypto_pwhash_PRIMITIVE);
3904
3905 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256", sn_crypto_pwhash_scryptsalsa208sha256);
3906 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str", sn_crypto_pwhash_scryptsalsa208sha256_str);
3907 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify", sn_crypto_pwhash_scryptsalsa208sha256_str_verify);
3908 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_needs_rehash", sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash);
3909 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_async", sn_crypto_pwhash_scryptsalsa208sha256_async);
3910 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_async", sn_crypto_pwhash_scryptsalsa208sha256_str_async)
3911 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify_async", sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async);
3912 V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MIN", crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
3913 V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MAX", crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
3914 V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN", crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN);
3915 V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX", crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX);
3916 V_UINT64("crypto_pwhash_scryptsalsa208sha256_SALTBYTES", crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
3917 V_UINT64("crypto_pwhash_scryptsalsa208sha256_STRBYTES", crypto_pwhash_scryptsalsa208sha256_STRBYTES);
3918 V_STRING("crypto_pwhash_scryptsalsa208sha256_STRPREFIX", crypto_pwhash_scryptsalsa208sha256_STRPREFIX);
3919 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
3920 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
3921 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
3922 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
3923 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
3924 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
3925 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE);
3926 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE);
3927
3928 // crypto_scalarmult
3929
3930 V_FUNCTION("crypto_scalarmult_base", sn_crypto_scalarmult_base);
3931 V_FUNCTION("crypto_scalarmult", sn_crypto_scalarmult);
3932 V_STRING("crypto_scalarmult_PRIMITIVE", crypto_scalarmult_PRIMITIVE);
3933 V_UINT32("crypto_scalarmult_BYTES", crypto_scalarmult_BYTES);
3934 V_UINT32("crypto_scalarmult_SCALARBYTES", crypto_scalarmult_SCALARBYTES);
3935
3936 V_FUNCTION("crypto_scalarmult_ed25519_base", sn_crypto_scalarmult_ed25519_base);
3937 V_FUNCTION("crypto_scalarmult_ed25519", sn_crypto_scalarmult_ed25519);
3938 V_FUNCTION("crypto_scalarmult_ed25519_base_noclamp", sn_crypto_scalarmult_ed25519_base_noclamp);
3939 V_FUNCTION("crypto_scalarmult_ed25519_noclamp", sn_crypto_scalarmult_ed25519_noclamp);
3940 V_UINT32("crypto_scalarmult_ed25519_BYTES", crypto_scalarmult_ed25519_BYTES);
3941 V_UINT32("crypto_scalarmult_ed25519_SCALARBYTES", crypto_scalarmult_ed25519_SCALARBYTES);
3942
3943 // crypto_secretbox
3944
3945 V_FUNCTION("crypto_secretbox_easy", sn_crypto_secretbox_easy);
3946 V_FUNCTION("crypto_secretbox_open_easy", sn_crypto_secretbox_open_easy);
3947 V_FUNCTION("crypto_secretbox_detached", sn_crypto_secretbox_detached);
3948 V_FUNCTION("crypto_secretbox_open_detached", sn_crypto_secretbox_open_detached);
3949 V_UINT32("crypto_secretbox_KEYBYTES", crypto_secretbox_KEYBYTES);
3950 V_UINT32("crypto_secretbox_NONCEBYTES", crypto_secretbox_NONCEBYTES);
3951 V_UINT32("crypto_secretbox_MACBYTES", crypto_secretbox_MACBYTES);
3952 V_STRING("crypto_secretbox_PRIMITIVE", crypto_secretbox_PRIMITIVE);
3953
3954 // crypto_secretstream
3955
3956 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_keygen", sn_crypto_secretstream_xchacha20poly1305_keygen);
3957 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_push", sn_crypto_secretstream_xchacha20poly1305_init_push);
3958 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_pull", sn_crypto_secretstream_xchacha20poly1305_init_pull);
3959 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_push", sn_crypto_secretstream_xchacha20poly1305_push);
3960 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_pull", sn_crypto_secretstream_xchacha20poly1305_pull);
3961 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_rekey", sn_crypto_secretstream_xchacha20poly1305_rekey);
3962
3963 V_UINT32("crypto_secretstream_xchacha20poly1305_STATEBYTES", sizeof(crypto_secretstream_xchacha20poly1305_state));
3964 V_UINT32("crypto_secretstream_xchacha20poly1305_ABYTES", crypto_secretstream_xchacha20poly1305_ABYTES);
3965 V_UINT32("crypto_secretstream_xchacha20poly1305_HEADERBYTES", crypto_secretstream_xchacha20poly1305_HEADERBYTES);
3966 V_UINT32("crypto_secretstream_xchacha20poly1305_KEYBYTES", crypto_secretstream_xchacha20poly1305_KEYBYTES);
3967 V_UINT32("crypto_secretstream_xchacha20poly1305_TAGBYTES", 1);
3968 V_UINT64("crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX", crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX);
3969 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_MESSAGE", crypto_secretstream_xchacha20poly1305_TAG_MESSAGE);
3970 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_PUSH", crypto_secretstream_xchacha20poly1305_TAG_PUSH);
3971 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_REKEY", crypto_secretstream_xchacha20poly1305_TAG_REKEY);
3972 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_FINAL", crypto_secretstream_xchacha20poly1305_TAG_FINAL);
3973
3974 // crypto_shorthash
3975
3976 V_FUNCTION("crypto_shorthash", sn_crypto_shorthash);
3977 V_UINT32("crypto_shorthash_BYTES", crypto_shorthash_BYTES);
3978 V_UINT32("crypto_shorthash_KEYBYTES", crypto_shorthash_KEYBYTES);
3979 V_STRING("crypto_shorthash_PRIMITIVE", crypto_shorthash_PRIMITIVE);
3980
3981 // crypto_sign
3982
3983 V_FUNCTION("crypto_sign_keypair", sn_crypto_sign_keypair);
3984 V_FUNCTION("crypto_sign_seed_keypair", sn_crypto_sign_seed_keypair);
3985 V_FUNCTION("crypto_sign", sn_crypto_sign);
3986 V_FUNCTION("crypto_sign_open", sn_crypto_sign_open);
3987 V_FUNCTION("crypto_sign_detached", sn_crypto_sign_detached);
3988 V_FUNCTION_NOSCOPE("crypto_sign_verify_detached", sn_crypto_sign_verify_detached);
3989 V_FUNCTION("crypto_sign_ed25519_sk_to_pk", sn_crypto_sign_ed25519_sk_to_pk);
3990 V_FUNCTION("crypto_sign_ed25519_pk_to_curve25519", sn_crypto_sign_ed25519_pk_to_curve25519);
3991 V_FUNCTION("crypto_sign_ed25519_sk_to_curve25519", sn_crypto_sign_ed25519_sk_to_curve25519);
3992
3993 V_UINT32("crypto_sign_SEEDBYTES", crypto_sign_SEEDBYTES);
3994 V_UINT32("crypto_sign_PUBLICKEYBYTES", crypto_sign_PUBLICKEYBYTES);
3995 V_UINT32("crypto_sign_SECRETKEYBYTES", crypto_sign_SECRETKEYBYTES);
3996 V_UINT32("crypto_sign_BYTES", crypto_sign_BYTES);
3997
3998 // crypto_stream
3999
4000 V_FUNCTION("crypto_stream", sn_crypto_stream);
4001 V_UINT32("crypto_stream_KEYBYTES", crypto_stream_KEYBYTES);
4002 V_UINT32("crypto_stream_NONCEBYTES", crypto_stream_NONCEBYTES);
4003 V_STRING("crypto_stream_PRIMITIVE", crypto_stream_PRIMITIVE);
4004
4005 V_FUNCTION_NOSCOPE("crypto_stream_xor", sn_crypto_stream_xor);
4006 V_FUNCTION("crypto_stream_xor_init", sn_crypto_stream_xor_wrap_init);
4007 V_FUNCTION("crypto_stream_xor_update", sn_crypto_stream_xor_wrap_update);
4008 V_FUNCTION("crypto_stream_xor_final", sn_crypto_stream_xor_wrap_final);
4009 V_UINT32("crypto_stream_xor_STATEBYTES", sizeof(sn_crypto_stream_xor_state));
4010
4011 V_FUNCTION("crypto_stream_chacha20", sn_crypto_stream_chacha20);
4012 V_UINT32("crypto_stream_chacha20_KEYBYTES", crypto_stream_chacha20_KEYBYTES);
4013 V_UINT32("crypto_stream_chacha20_NONCEBYTES", crypto_stream_chacha20_NONCEBYTES);
4014 V_UINT64("crypto_stream_chacha20_MESSAGEBYTES_MAX", crypto_stream_chacha20_MESSAGEBYTES_MAX);
4015
4016 V_FUNCTION("crypto_stream_chacha20_xor", sn_crypto_stream_chacha20_xor);
4017 V_FUNCTION("crypto_stream_chacha20_xor_ic", sn_crypto_stream_chacha20_xor_ic);
4018 V_FUNCTION("crypto_stream_chacha20_xor_init", sn_crypto_stream_chacha20_xor_wrap_init);
4019 V_FUNCTION("crypto_stream_chacha20_xor_update", sn_crypto_stream_chacha20_xor_wrap_update);
4020 V_FUNCTION("crypto_stream_chacha20_xor_final", sn_crypto_stream_chacha20_xor_wrap_final);
4021 V_UINT32("crypto_stream_chacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_xor_state));
4022
4023 V_FUNCTION("crypto_stream_chacha20_ietf", sn_crypto_stream_chacha20_ietf);
4024 V_UINT32("crypto_stream_chacha20_ietf_KEYBYTES", crypto_stream_chacha20_ietf_KEYBYTES);
4025 V_UINT32("crypto_stream_chacha20_ietf_NONCEBYTES", crypto_stream_chacha20_ietf_NONCEBYTES);
4026 V_UINT64("crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX", crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX);
4027 V_UINT32("crypto_stream_chacha20_ietf_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_ietf_xor_state));
4028
4029 V_FUNCTION("crypto_stream_chacha20_ietf_xor", sn_crypto_stream_chacha20_ietf_xor);
4030 V_FUNCTION("crypto_stream_chacha20_ietf_xor_ic", sn_crypto_stream_chacha20_ietf_xor_ic);
4031 V_FUNCTION("crypto_stream_chacha20_ietf_xor_init", sn_crypto_stream_chacha20_ietf_xor_wrap_init);
4032 V_FUNCTION("crypto_stream_chacha20_ietf_xor_update", sn_crypto_stream_chacha20_ietf_xor_wrap_update);
4033 V_FUNCTION("crypto_stream_chacha20_ietf_xor_final", sn_crypto_stream_chacha20_ietf_xor_wrap_final);
4034
4035 V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
4036 V_UINT32("crypto_stream_xchacha20_KEYBYTES", crypto_stream_xchacha20_KEYBYTES);
4037 V_UINT32("crypto_stream_xchacha20_NONCEBYTES", crypto_stream_xchacha20_NONCEBYTES);
4038 V_UINT64("crypto_stream_xchacha20_MESSAGEBYTES_MAX", crypto_stream_xchacha20_MESSAGEBYTES_MAX);
4039
4040 V_FUNCTION("crypto_stream_xchacha20_xor", sn_crypto_stream_xchacha20_xor);
4041 V_FUNCTION("crypto_stream_xchacha20_xor_ic", sn_crypto_stream_xchacha20_xor_ic);
4042 V_FUNCTION("crypto_stream_xchacha20_xor_init", sn_crypto_stream_xchacha20_xor_wrap_init);
4043 V_FUNCTION("crypto_stream_xchacha20_xor_update", sn_crypto_stream_xchacha20_xor_wrap_update);
4044 V_FUNCTION("crypto_stream_xchacha20_xor_final", sn_crypto_stream_xchacha20_xor_wrap_final);
4045 V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
4046 V_UINT32("crypto_stream_xchacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_xchacha20_xor_state));
4047
4048 V_FUNCTION("crypto_stream_salsa20", sn_crypto_stream_salsa20);
4049 V_UINT32("crypto_stream_salsa20_KEYBYTES", crypto_stream_salsa20_KEYBYTES);
4050 V_UINT32("crypto_stream_salsa20_NONCEBYTES", crypto_stream_salsa20_NONCEBYTES);
4051 V_UINT64("crypto_stream_salsa20_MESSAGEBYTES_MAX", crypto_stream_salsa20_MESSAGEBYTES_MAX);
4052
4053 V_FUNCTION("crypto_stream_salsa20_xor", sn_crypto_stream_salsa20_xor);
4054 V_FUNCTION("crypto_stream_salsa20_xor_ic", sn_crypto_stream_salsa20_xor_ic);
4055 V_FUNCTION("crypto_stream_salsa20_xor_init", sn_crypto_stream_salsa20_xor_wrap_init);
4056 V_FUNCTION("crypto_stream_salsa20_xor_update", sn_crypto_stream_salsa20_xor_wrap_update);
4057 V_FUNCTION("crypto_stream_salsa20_xor_final", sn_crypto_stream_salsa20_xor_wrap_final);
4058 V_UINT32("crypto_stream_salsa20_xor_STATEBYTES", sizeof(sn_crypto_stream_salsa20_xor_state));
4059
4060 // extensions
4061
4062 // tweak
4063
4064 V_FUNCTION("extension_tweak_ed25519_base", sn_extension_tweak_ed25519_base);
4065 V_FUNCTION("extension_tweak_ed25519_sign_detached", sn_extension_tweak_ed25519_sign_detached);
4066 V_FUNCTION("extension_tweak_ed25519_sk_to_scalar", sn_extension_tweak_ed25519_sk_to_scalar);
4067 V_FUNCTION("extension_tweak_ed25519_scalar", sn_extension_tweak_ed25519_scalar);
4068 V_FUNCTION("extension_tweak_ed25519_pk", sn_extension_tweak_ed25519_pk);
4069 V_FUNCTION("extension_tweak_ed25519_keypair", sn_extension_tweak_ed25519_keypair);
4070 V_FUNCTION("extension_tweak_ed25519_scalar_add", sn_extension_tweak_ed25519_scalar_add);
4071 V_FUNCTION("extension_tweak_ed25519_pk_add", sn_extension_tweak_ed25519_pk_add);
4072 V_FUNCTION("extension_tweak_ed25519_keypair_add", sn_extension_tweak_ed25519_keypair_add);
4073 V_UINT32("extension_tweak_ed25519_BYTES", sn__extension_tweak_ed25519_BYTES);
4074 V_UINT32("extension_tweak_ed25519_SCALARBYTES", sn__extension_tweak_ed25519_SCALARBYTES);
4075
4076 // pbkdf2
4077
4078 V_FUNCTION("extension_pbkdf2_sha512", sn_extension_pbkdf2_sha512);
4079 V_FUNCTION("extension_pbkdf2_sha512_async", sn_extension_pbkdf2_sha512_async);
4080 V_UINT32("extension_pbkdf2_sha512_SALTBYTES", sn__extension_pbkdf2_sha512_SALTBYTES);
4081 V_UINT32("extension_pbkdf2_sha512_HASHBYTES", sn__extension_pbkdf2_sha512_HASHBYTES);
4082 V_UINT32("extension_pbkdf2_sha512_ITERATIONS_MIN", sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
4083 V_UINT64("extension_pbkdf2_sha512_BYTES_MAX", sn__extension_pbkdf2_sha512_BYTES_MAX);
4084
4085#undef V_FUNCTION
4086#undef V_FUNCTION_NOSCOPE
4087#undef V_UINT32
4088#undef V_UINT64
4089#undef V_STRING
4090
4091 return exports;
4092}
4093
4094BARE_MODULE(sodium_native, sodium_native_exports)
node_modules/hypercore-crypto/node_modules/sodium-native/binding.js +2 -0
……@@ -0,0 +1,2 @@
1require.addon = require('require-addon')
2module.exports = require.addon('.', __filename)
node_modules/hypercore-crypto/node_modules/sodium-native/extensions/pbkdf2/pbkdf2.c +90 -0
……@@ -0,0 +1,90 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
29 */
30
31#include <string.h>
32#include <sodium.h>
33
34#include "pbkdf2.h"
35
36/**
37 * pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
38 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
39 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
40 */
41int
42sn__extension_pbkdf2_sha512(const unsigned char *passwd, size_t passwdlen,
43 const unsigned char *salt, size_t saltlen, uint64_t c,
44 unsigned char *buf, size_t dkLen)
45{
46 crypto_auth_hmacsha512_state PShctx, hctx;
47 size_t i;
48 unsigned char ivec[4];
49 unsigned char U[64];
50 unsigned char T[64];
51 uint64_t j;
52 unsigned int k;
53 size_t clen;
54
55 if (dkLen > sn__extension_pbkdf2_sha512_BYTES_MAX) {
56 return -1;
57 }
58
59 crypto_auth_hmacsha512_init(&PShctx, passwd, passwdlen);
60 crypto_auth_hmacsha512_update(&PShctx, salt, saltlen);
61
62 for (i = 0; i * crypto_auth_hmacsha512_BYTES < dkLen; i++) {
63 SN_PBKDF2_STORE32_BE(ivec, (uint32_t)(i + 1));
64 memcpy(&hctx, &PShctx, sizeof(crypto_auth_hmacsha512_state));
65 crypto_auth_hmacsha512_update(&hctx, ivec, 4);
66 crypto_auth_hmacsha512_final(&hctx, U);
67
68 memcpy(T, U, crypto_auth_hmacsha512_BYTES);
69 /* LCOV_EXCL_START */
70 for (j = 2; j <= c; j++) {
71 crypto_auth_hmacsha512_init(&hctx, passwd, passwdlen);
72 crypto_auth_hmacsha512_update(&hctx, U, crypto_auth_hmacsha512_BYTES);
73 crypto_auth_hmacsha512_final(&hctx, U);
74
75 for (k = 0; k < crypto_auth_hmacsha512_BYTES; k++) {
76 T[k] ^= U[k];
77 }
78 }
79 /* LCOV_EXCL_STOP */
80
81 clen = dkLen - i * crypto_auth_hmacsha512_BYTES;
82 if (clen > crypto_auth_hmacsha512_BYTES) {
83 clen = crypto_auth_hmacsha512_BYTES;
84 }
85 memcpy(&buf[i * crypto_auth_hmacsha512_BYTES], T, clen);
86 }
87 sodium_memzero((void *) &PShctx, sizeof PShctx);
88
89 return 0;
90}
node_modules/hypercore-crypto/node_modules/sodium-native/extensions/pbkdf2/pbkdf2.h +60 -0
……@@ -0,0 +1,60 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28/*
29 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
30 */
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35#include <sodium.h>
36
37#define SN_PBKDF2_STORE32_BE(buf, n32) \
38 buf[0] = n32 >> 24 & 0xff; \
39 buf[1] = n32 >> 16 & 0xff; \
40 buf[2] = n32 >> 8 & 0xff; \
41 buf[3] = n32 >> 0 & 0xff;
42
43#define sn__extension_pbkdf2_sha512_SALTBYTES 16U
44
45#define sn__extension_pbkdf2_sha512_HASHBYTES crypto_hash_sha512_BYTES
46
47#define sn__extension_pbkdf2_sha512_ITERATIONS_MIN 1U
48
49#define sn__extension_pbkdf2_sha512_BYTES_MAX 0x3fffffffc0ULL
50
51/**
52 * extension_pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
53 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
54 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
55 */
56int sn__extension_pbkdf2_sha512(const unsigned char *, size_t, const unsigned char *, size_t,
57 uint64_t, unsigned char *, size_t);
58#ifdef __cplusplus
59};
60#endif
node_modules/hypercore-crypto/node_modules/sodium-native/extensions/tweak/tweak.c +206 -0
……@@ -0,0 +1,206 @@
1#include "tweak.h"
2
3/*
4 *EXPERIMENTAL API*
5
6 This module is an experimental implementation of a key tweaking protocol
7 over ed25519 keys. The signature algorithm has been reimplemented from
8 libsodium, but the nonce generation algorithm is *non-standard*.
9
10 Use at your own risk
11*/
12
13static void _extension_tweak_nonce (unsigned char *nonce, const unsigned char *n,
14 const unsigned char *m, unsigned long long mlen)
15{
16 // dom2(x, y) with x = 0 (not prehashed) and y = "crypto_tweak_ed25519"
17 static const unsigned char TWEAK_PREFIX[32 + 2 + 20] = {
18 'S', 'i', 'g', 'E', 'd', '2', '5', '5', '1', '9', ' ',
19 'n', 'o', ' ', 'E', 'd', '2', '5', '5', '1', '9', ' ',
20 'c', 'o', 'l', 'l', 'i', 's', 'i', 'o', 'n', 's', 0,
21 20, 'c', 'r', 'y', 'p', 't', 'o', '_', 't', 'w', 'e',
22 'a', 'k', '_', 'e', 'd', '2', '5', '5', '1', '9'
23 };
24
25 crypto_hash_sha512_state hs;
26
27 crypto_hash_sha512_init(&hs);
28 crypto_hash_sha512_update(&hs, TWEAK_PREFIX, sizeof TWEAK_PREFIX);
29 crypto_hash_sha512_update(&hs, n, 32);
30 crypto_hash_sha512_update(&hs, m, mlen);
31 crypto_hash_sha512_final(&hs, nonce);
32}
33
34static inline void
35_crypto_sign_ed25519_clamp(unsigned char k[32])
36{
37 k[0] &= 248;
38 k[31] &= 127;
39 k[31] |= 64;
40}
41
42static void _extension_tweak_ed25519(unsigned char *q, unsigned char *n,
43 const unsigned char *ns, unsigned long long nslen)
44{
45 sodium_memzero(q, sizeof q);
46
47 crypto_hash(n, ns, nslen);
48 n[31] &= 127; // clear highest bit
49
50 crypto_scalarmult_ed25519_base_noclamp(q, n);
51
52 // hash tweak until we get a valid tweaked q
53 while (crypto_core_ed25519_is_valid_point(q) != 1) {
54 crypto_hash(n, n, 32);
55 n[31] &= 127; // clear highest bit
56
57 crypto_scalarmult_ed25519_base_noclamp(q, n);
58 }
59}
60
61void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
62 const unsigned char *ns, unsigned long long nslen)
63{
64 unsigned char n64[64];
65
66 _extension_tweak_ed25519(pk, n64, ns, nslen);
67
68 SN_TWEAK_COPY_32(scalar, n64)
69}
70
71int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
72 const unsigned char *m, unsigned long long mlen,
73 const unsigned char *n, unsigned char *pk)
74{
75 crypto_hash_sha512_state hs;
76
77 unsigned char nonce[64];
78 unsigned char R[32];
79 unsigned char hram[64];
80 unsigned char _pk[32];
81
82 // check if pk was passed
83 if (pk == NULL) {
84 pk = _pk;
85
86 // derive pk from scalar
87 if (crypto_scalarmult_ed25519_base_noclamp(pk, n) != 0) {
88 return -1;
89 }
90 }
91
92 _extension_tweak_nonce(nonce, n, m, mlen);
93 crypto_core_ed25519_scalar_reduce(nonce, nonce);
94
95 // R = G ^ nonce : curve point from nonce
96 if (crypto_scalarmult_ed25519_base_noclamp(R, nonce) != 0) {
97 return -1;
98 }
99
100 // generate challenge as h(ram) = hash(R, pk, message)
101 crypto_hash_sha512_init(&hs);
102 crypto_hash_sha512_update(&hs, R, 32);
103 crypto_hash_sha512_update(&hs, pk, 32);
104 crypto_hash_sha512_update(&hs, m, mlen);
105
106 crypto_hash_sha512_final(&hs, hram);
107
108 crypto_core_ed25519_scalar_reduce(hram, hram);
109
110 // sig = nonce + n * h(ram)
111 crypto_core_ed25519_scalar_mul(sig, hram, n);
112 crypto_core_ed25519_scalar_add(sig + 32, nonce, sig);
113
114 SN_TWEAK_COPY_32(sig, R)
115
116 if (siglen_p != NULL) {
117 *siglen_p = 64U;
118 }
119
120 return 0;
121}
122
123// tweak a secret key
124void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *n, const unsigned char *sk)
125{
126 unsigned char n64[64];
127
128 // get sk scalar from seed, cf. crypto_sign_keypair_seed
129 crypto_hash(n64, sk, 32);
130 _crypto_sign_ed25519_clamp(n64);
131
132 SN_TWEAK_COPY_32(n, n64)
133}
134
135// tweak a secret key
136void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
137 const unsigned char *scalar,
138 const unsigned char *ns,
139 unsigned long long nslen)
140{
141 unsigned char n[64];
142 unsigned char q[32];
143
144 _extension_tweak_ed25519(q, n, ns, nslen);
145 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
146}
147
148// tweak a public key
149int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
150 const unsigned char *pk,
151 const unsigned char *ns,
152 unsigned long long nslen)
153{
154 unsigned char n[64];
155 unsigned char q[32];
156
157 _extension_tweak_ed25519(q, n, ns, nslen);
158 return crypto_core_ed25519_add(tpk, q, pk);
159}
160
161
162void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
163 unsigned char *scalar, const unsigned char *ns,
164 unsigned long long nslen)
165{
166 unsigned char n64[64];
167
168 crypto_hash(n64, ns, nslen);
169 n64[31] &= 127; // clear highest bit
170
171 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
172 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
173
174 // hash tweak until we get a valid tweaked point
175 while (crypto_core_ed25519_is_valid_point(pk) != 1) {
176 crypto_hash(n64, n64, 32);
177 n64[31] &= 127; // clear highest bit
178
179 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
180 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
181 }
182}
183
184// add tweak to scalar
185void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
186 const unsigned char *scalar,
187 const unsigned char *n)
188{
189 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
190}
191
192// add tweak point to public key
193int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
194 const unsigned char *pk,
195 const unsigned char *q)
196{
197 return crypto_core_ed25519_add(tpk, pk, q);
198}
199
200
201int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
202 unsigned char *scalar, const unsigned char *tweak)
203{
204 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, tweak);
205 return crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
206}
node_modules/hypercore-crypto/node_modules/sodium-native/extensions/tweak/tweak.h +62 -0
……@@ -0,0 +1,62 @@
1#ifdef __cplusplus
2extern "C" {
3#endif
4
5#include <sodium.h>
6
7// copy 32 bytes using int64_t pointers
8#define SN_TWEAK_COPY_32(a, b) \
9 { \
10 long long *dst = (long long *) a; \
11 long long *src = (long long *) b; \
12 dst[0] = src[0]; \
13 dst[1] = src[1]; \
14 dst[2] = src[2]; \
15 dst[3] = src[3]; \
16 }
17
18#define sn__extension_tweak_ed25519_BYTES crypto_sign_ed25519_PUBLICKEYBYTES
19
20#define sn__extension_tweak_ed25519_SCALARBYTES crypto_scalarmult_ed25519_SCALARBYTES
21
22int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
23 const unsigned char *m, unsigned long long mlen,
24 const unsigned char *n, unsigned char *pk);
25
26void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
27 const unsigned char *ns, unsigned long long nslen);
28
29void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *scalar, const unsigned char *sk);
30
31// tweak a secret key
32void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
33 const unsigned char *scalar,
34 const unsigned char *ns,
35 unsigned long long nslen);
36
37// tweak a public key
38int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
39 const unsigned char *pk,
40 const unsigned char *ns,
41 unsigned long long nslen);
42
43void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
44 unsigned char *scalar, const unsigned char *ns,
45 unsigned long long nslen);
46
47// add tweak scalar to private key
48void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
49 const unsigned char *scalar,
50 const unsigned char *n);
51
52// add tweak point to public key
53int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
54 const unsigned char *pk,
55 const unsigned char *q);
56
57int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
58 unsigned char *scalar, const unsigned char *tweak);
59
60#ifdef __cplusplus
61};
62#endif
node_modules/hypercore-crypto/node_modules/sodium-native/index.js +3231 -0
……@@ -0,0 +1,3231 @@
1const assert = require('assert')
2const binding = require('./binding')
3const { isNode } = require('which-runtime')
4
5const OPTIONAL = Buffer.from(new ArrayBuffer(0))
6
7module.exports = exports = { ...binding }
8
9// memory
10
11exports.sodium_memzero = function (buf) {
12 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
13
14 binding.sodium_memzero(buf)
15}
16
17exports.sodium_mlock = function (buf) {
18 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
19
20 const res = binding.sodium_mlock(buf)
21
22 if (res !== 0) throw new Error('memory lock failed')
23}
24
25exports.sodium_munlock = function (buf) {
26 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
27
28 const res = binding.sodium_munlock(buf)
29
30 if (res !== 0) throw new Error('memory unlock failed')
31}
32
33exports.sodium_malloc = function (size) {
34 assert(size >= 0, 'invalid size')
35
36 const buf = Buffer.from(binding.sodium_malloc(size))
37 buf.secure = true
38 return buf
39}
40
41exports.sodium_free = function (buf) {
42 if (!buf || !buf.secure) return
43
44 binding.sodium_free(buf.buffer)
45}
46
47exports.sodium_mprotect_noaccess = function (buf) {
48 const res = binding.sodium_mprotect_noaccess(buf.buffer)
49
50 if (res !== 0) throw new Error('failed to lock buffer')
51}
52
53exports.sodium_mprotect_readonly = function (buf) {
54 const res = binding.sodium_mprotect_readonly(buf.buffer)
55
56 if (res !== 0) throw new Error('failed to unlock buffer')
57}
58
59exports.sodium_mprotect_readwrite = function (buf) {
60 const res = binding.sodium_mprotect_readwrite(buf.buffer)
61
62 if (res !== 0) throw new Error('failed to unlock buffer')
63}
64
65// crypto_randombytes
66
67exports.randombytes_buf = function (buffer) {
68 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
69
70 binding.randombytes_buf(buffer.buffer, buffer.byteOffset, buffer.byteLength)
71}
72
73exports.randombytes_buf_deterministic = function (buffer, seed) {
74 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
75 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
76 assert(
77 seed.byteLength === binding.randombytes_SEEDBYTES,
78 "seed must be 'randombytes_SEEDBYTES' bytes"
79 )
80
81 binding.randombytes_buf_deterministic(
82 buffer.buffer,
83 buffer.byteOffset,
84 buffer.byteLength,
85
86 seed.buffer,
87 seed.byteOffset,
88 seed.byteLength
89 )
90}
91
92// sodium_helpers
93
94exports.sodium_memcmp = function (a, b) {
95 assert(ArrayBuffer.isView(a), 'a must be a typed array')
96 assert(ArrayBuffer.isView(b), 'b must be a typed array')
97 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
98
99 return binding.sodium_memcmp(a, b)
100}
101
102exports.sodium_add = function (a, b) {
103 assert(ArrayBuffer.isView(a), 'a must be a typed array')
104 assert(ArrayBuffer.isView(b), 'b must be a typed array')
105 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
106
107 binding.sodium_add(a, b)
108}
109
110exports.sodium_sub = function (a, b) {
111 assert(ArrayBuffer.isView(a), 'a must be a typed array')
112 assert(ArrayBuffer.isView(b), 'b must be a typed array')
113 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
114
115 binding.sodium_sub(a, b)
116}
117
118exports.sodium_compare = function (a, b) {
119 assert(ArrayBuffer.isView(a), 'a must be a typed array')
120 assert(ArrayBuffer.isView(b), 'b must be a typed array')
121 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
122
123 return binding.sodium_compare(a, b)
124}
125
126exports.sodium_is_zero = function (buffer, length) {
127 if (length === undefined) length = buffer.byteLength
128
129 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
130 assert(length >= 0 && length <= buffer.byteLength, 'invalid length')
131
132 return binding.sodium_is_zero(buffer, length)
133}
134
135exports.sodium_pad = function (buffer, unpaddedBuflen, blockSize) {
136 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
137 assert(unpaddedBuflen <= buffer.byteLength, 'unpadded length cannot exceed buffer length')
138 assert(blockSize <= buffer.byteLength, 'block size cannot exceed buffer length')
139 assert(blockSize >= 1, 'block size must be at least 1 byte')
140 assert(
141 buffer.byteLength >= unpaddedBuflen + (blockSize - (unpaddedBuflen % blockSize)),
142 'buf not long enough'
143 )
144
145 return binding.sodium_pad(buffer, unpaddedBuflen, blockSize)
146}
147
148exports.sodium_unpad = function (buffer, paddedBuflen, blockSize) {
149 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
150 assert(paddedBuflen <= buffer.byteLength, 'unpadded length cannot exceed buffer length')
151 assert(blockSize <= buffer.byteLength, 'block size cannot exceed buffer length')
152 assert(blockSize >= 1, 'block size must be at least 1 byte')
153
154 return binding.sodium_unpad(buffer, paddedBuflen, blockSize)
155}
156
157// crypto_sign
158
159exports.crypto_sign_keypair = function (pk, sk) {
160 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
161 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
162 assert(
163 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
164 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
165 )
166 assert(
167 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
168 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
169 )
170
171 const res = binding.crypto_sign_keypair(pk, sk)
172
173 if (res !== 0) throw new Error('status: ' + res)
174}
175
176exports.crypto_sign_seed_keypair = function (pk, sk, seed) {
177 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
178 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
179 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
180 assert(
181 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
182 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
183 )
184 assert(
185 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
186 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
187 )
188 assert(
189 seed.byteLength === binding.crypto_sign_SEEDBYTES,
190 "seed must be 'crypto_sign_SEEDBYTES' bytes"
191 )
192
193 const res = binding.crypto_sign_seed_keypair(pk, sk, seed)
194
195 if (res !== 0) throw new Error('status: ' + res)
196}
197
198exports.crypto_sign = function (sm, m, sk) {
199 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
200 assert(ArrayBuffer.isView(m), 'm must be a typed array')
201 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
202 assert(
203 sm.byteLength === binding.crypto_sign_BYTES + m.byteLength,
204 "sm must be 'm.byteLength + crypto_sign_BYTES' bytes"
205 )
206 assert(
207 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
208 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
209 )
210
211 const res = binding.crypto_sign(sm, m, sk)
212
213 if (res !== 0) throw new Error('status: ' + res)
214}
215
216exports.crypto_sign_open = function (m, sm, pk) {
217 assert(ArrayBuffer.isView(m), 'm must be a typed array')
218 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
219 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
220 assert(
221 sm.byteLength >= binding.crypto_sign_BYTES,
222 "sm must be at least 'crypto_sign_BYTES' bytes"
223 )
224 assert(
225 m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
226 "m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
227 )
228 assert(
229 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
230 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
231 )
232
233 const res = binding.crypto_sign_open(m, sm, pk)
234
235 if (res !== 0) throw new Error('status: ' + res)
236}
237
238exports.crypto_sign_open = function (m, sm, pk) {
239 assert(ArrayBuffer.isView(m), 'm must be a typed array')
240 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
241 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
242 assert(
243 sm.byteLength >= binding.crypto_sign_BYTES,
244 "sm must be at least 'crypto_sign_BYTES' bytes"
245 )
246 assert(
247 m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
248 "m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
249 )
250 assert(
251 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
252 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
253 )
254
255 return binding.crypto_sign_open(m, sm, pk)
256}
257
258exports.crypto_sign_detached = function (sig, m, sk) {
259 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
260 assert(ArrayBuffer.isView(m), 'm must be a typed array')
261 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
262 assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes")
263 assert(
264 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
265 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
266 )
267
268 const res = binding.crypto_sign_detached(sig, m, sk)
269
270 if (res !== 0) throw new Error('status: ' + res)
271}
272
273exports.crypto_sign_verify_detached = function (sig, m, pk) {
274 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
275 assert(ArrayBuffer.isView(m), 'm must be a typed array')
276 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
277 assert(
278 sig.byteLength >= binding.crypto_sign_BYTES,
279 "sig must be at least 'crypto_sign_BYTES' bytes"
280 )
281 assert(
282 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
283 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
284 )
285
286 return binding.crypto_sign_verify_detached(
287 sig.buffer,
288 sig.byteOffset,
289 sig.byteLength,
290
291 m.buffer,
292 m.byteOffset,
293 m.byteLength,
294
295 pk.buffer,
296 pk.byteOffset,
297 pk.byteLength
298 )
299}
300
301exports.crypto_sign_ed25519_sk_to_pk = function (pk, sk) {
302 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
303 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
304 assert(
305 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
306 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
307 )
308 assert(
309 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
310 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
311 )
312
313 const res = binding.crypto_sign_ed25519_sk_to_pk(pk, sk)
314
315 if (res !== 0) throw new Error('status: ' + res)
316}
317
318exports.crypto_sign_ed25519_pk_to_curve25519 = function (x25519pk, ed25519pk) {
319 assert(ArrayBuffer.isView(x25519pk), 'x25519pk must be a typed array')
320 assert(ArrayBuffer.isView(ed25519pk), 'ed25519pk must be a typed array')
321 assert(
322 x25519pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
323 "x25519pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
324 )
325 assert(
326 ed25519pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
327 "ed25519pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
328 )
329
330 const res = binding.crypto_sign_ed25519_pk_to_curve25519(x25519pk, ed25519pk)
331
332 if (res !== 0) throw new Error('status: ' + res)
333}
334
335exports.crypto_sign_ed25519_sk_to_curve25519 = function (x25519sk, ed25519sk) {
336 assert(ArrayBuffer.isView(x25519sk), 'x25519sk must be a typed array')
337 assert(ArrayBuffer.isView(ed25519sk), 'ed25519sk must be a typed array')
338 assert(
339 x25519sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
340 "x25519sk must be 'crypto_box_SECRETKEYBYTES' bytes"
341 )
342
343 const edLen = ed25519sk.byteLength
344
345 assert(
346 edLen === binding.crypto_sign_SECRETKEYBYTES || edLen === binding.crypto_box_SECRETKEYBYTES,
347 "ed25519sk must be 'crypto_sign_SECRETKEYBYTES' or 'crypto_sign_SECRETKEYBYTES - crypto_sign_PUBLICKEYBYTES' bytes"
348 )
349
350 const res = binding.crypto_sign_ed25519_sk_to_curve25519(x25519sk, ed25519sk)
351
352 if (res !== 0) throw new Error('status: ' + res)
353}
354
355// crypto_box
356
357exports.crypto_box_keypair = function (pk, sk) {
358 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
359 assert(
360 pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
361 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
362 )
363 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
364 assert(
365 sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
366 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
367 )
368
369 const res = binding.crypto_box_keypair(pk, sk)
370
371 if (res !== 0) throw new Error('status: ' + res)
372}
373
374exports.crypto_box_seed_keypair = function (pk, sk, seed) {
375 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
376 assert(
377 pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
378 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
379 )
380 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
381 assert(
382 sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
383 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
384 )
385 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
386 assert(
387 seed.byteLength === binding.crypto_box_SEEDBYTES,
388 "seed must be 'crypto_box_SEEDBYTES' bytes"
389 )
390
391 const res = binding.crypto_box_seed_keypair(pk, sk, seed)
392
393 if (res !== 0) throw new Error('status: ' + res)
394}
395
396exports.crypto_box_easy = function (c, m, n, pk, sk) {
397 assert(ArrayBuffer.isView(c), 'c must be a typed array')
398 assert(ArrayBuffer.isView(m), 'm must be a typed array')
399 assert(ArrayBuffer.isView(n), 'n must be a typed array')
400 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
401 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
402 assert(
403 c.byteLength === m.byteLength + exports.crypto_box_MACBYTES,
404 "c must be 'm.byteLength + crypto_box_MACBYTES' bytes"
405 )
406 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
407 assert(
408 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
409 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
410 )
411 assert(
412 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
413 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
414 )
415
416 const res = binding.crypto_box_easy(c, m, n, pk, sk)
417
418 if (res !== 0) throw new Error('status: ' + res)
419}
420
421exports.crypto_box_detached = function (c, mac, m, n, pk, sk) {
422 assert(ArrayBuffer.isView(c), 'c must be a typed array')
423 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
424 assert(ArrayBuffer.isView(m), 'm must be a typed array')
425 assert(ArrayBuffer.isView(n), 'n must be a typed array')
426 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
427 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
428 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
429 assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes")
430 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
431 assert(
432 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
433 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
434 )
435 assert(
436 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
437 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
438 )
439
440 const res = binding.crypto_box_detached(c, mac, m, n, pk, sk)
441
442 if (res !== 0) throw new Error('status: ' + res)
443}
444
445exports.crypto_box_open_easy = function (m, c, n, pk, sk) {
446 assert(ArrayBuffer.isView(m), 'm must be a typed array')
447 assert(ArrayBuffer.isView(c), 'c must be a typed array')
448 assert(ArrayBuffer.isView(n), 'n must be a typed array')
449 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
450 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
451 assert(
452 c.byteLength >= exports.crypto_box_MACBYTES,
453 "c must be at least 'crypto_box_MACBYTES' bytes"
454 )
455 assert(
456 m.byteLength === c.byteLength - exports.crypto_box_MACBYTES,
457 "m must be 'c.byteLength - crypto_box_MACBYTES' bytes"
458 )
459 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
460 assert(
461 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
462 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
463 )
464 assert(
465 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
466 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
467 )
468
469 return binding.crypto_box_open_easy(m, c, n, pk, sk)
470}
471
472exports.crypto_box_open_detached = function (m, c, mac, n, pk, sk) {
473 assert(ArrayBuffer.isView(m), 'm must be a typed array')
474 assert(ArrayBuffer.isView(c), 'c must be a typed array')
475 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
476 assert(ArrayBuffer.isView(n), 'n must be a typed array')
477 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
478 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
479 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
480 assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes")
481 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
482 assert(
483 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
484 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
485 )
486 assert(
487 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
488 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
489 )
490
491 return binding.crypto_box_open_detached(m, c, mac, n, pk, sk)
492}
493
494exports.crypto_box_seal = function (c, m, pk) {
495 assert(ArrayBuffer.isView(c), 'c must be a typed array')
496 assert(ArrayBuffer.isView(m), 'm must be a typed array')
497 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
498 assert(
499 c.byteLength === m.byteLength + exports.crypto_box_SEALBYTES,
500 "c must be 'm.byteLength + crypto_box_SEALBYTES' bytes"
501 )
502 assert(
503 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
504 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
505 )
506
507 const res = binding.crypto_box_seal(c, m, pk)
508
509 if (res !== 0) throw new Error('status: ' + res)
510}
511
512exports.crypto_box_seal_open = function (m, c, pk, sk) {
513 assert(ArrayBuffer.isView(m), 'm must be a typed array')
514 assert(ArrayBuffer.isView(c), 'c must be a typed array')
515 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
516 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
517 assert(
518 c.byteLength >= exports.crypto_box_SEALBYTES,
519 "c must be at least 'crypto_box_SEALBYTES' bytes"
520 )
521 assert(
522 m.byteLength === c.byteLength - exports.crypto_box_SEALBYTES,
523 "m must be 'c.byteLength - crypto_box_SEALBYTES' bytes"
524 )
525 assert(
526 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
527 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
528 )
529 assert(
530 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
531 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
532 )
533
534 return binding.crypto_box_seal_open(
535 m.buffer,
536 m.byteOffset,
537 m.byteLength,
538
539 c.buffer,
540 c.byteOffset,
541 c.byteLength,
542
543 pk.buffer,
544 pk.byteOffset,
545 pk.byteLength,
546
547 sk.buffer,
548 sk.byteOffset,
549 sk.byteLength
550 )
551}
552
553// crypto_secretbox
554
555exports.crypto_secretbox_easy = function (c, m, n, k) {
556 assert(ArrayBuffer.isView(c), 'c must be a typed array')
557 assert(ArrayBuffer.isView(m), 'm must be a typed array')
558 assert(ArrayBuffer.isView(n), 'n must be a typed array')
559 assert(ArrayBuffer.isView(k), 'k must be a typed array')
560 assert(
561 c.byteLength === m.byteLength + binding.crypto_secretbox_MACBYTES,
562 "c must be 'm.byteLength + crypto_secretbox_MACBYTES' bytes"
563 )
564 assert(
565 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
566 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
567 )
568 assert(
569 k.byteLength === binding.crypto_secretbox_KEYBYTES,
570 "k must be 'crypto_secretbox_KEYBYTES' bytes"
571 )
572
573 const res = binding.crypto_secretbox_easy(c, m, n, k)
574
575 if (res !== 0) throw new Error('status: ' + res)
576}
577
578exports.crypto_secretbox_open_easy = function (m, c, n, k) {
579 assert(ArrayBuffer.isView(m), 'm must be a typed array')
580 assert(ArrayBuffer.isView(c), 'c must be a typed array')
581 assert(ArrayBuffer.isView(n), 'n must be a typed array')
582 assert(ArrayBuffer.isView(k), 'k must be a typed array')
583 assert(
584 c.byteLength >= binding.crypto_secretbox_MACBYTES,
585 "c must be at least 'crypto_secretbox_MACBYTES' bytes"
586 )
587 assert(
588 m.byteLength === c.byteLength - binding.crypto_secretbox_MACBYTES,
589 "m must be 'c.byteLength - crypto_secretbox_MACBYTES' bytes"
590 )
591 assert(
592 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
593 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
594 )
595 assert(
596 k.byteLength === binding.crypto_secretbox_KEYBYTES,
597 "k must be 'crypto_secretbox_KEYBYTES' bytes"
598 )
599
600 return binding.crypto_secretbox_open_easy(m, c, n, k)
601}
602
603exports.crypto_secretbox_detached = function (c, mac, m, n, k) {
604 assert(ArrayBuffer.isView(c), 'c must be a typed array')
605 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
606 assert(ArrayBuffer.isView(m), 'm must be a typed array')
607 assert(ArrayBuffer.isView(n), 'n must be a typed array')
608 assert(ArrayBuffer.isView(k), 'k must be a typed array')
609 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
610 assert(
611 mac.byteLength === binding.crypto_secretbox_MACBYTES,
612 "mac must be 'crypto_secretbox_MACBYTES' bytes"
613 )
614 assert(
615 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
616 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
617 )
618 assert(
619 k.byteLength === binding.crypto_secretbox_KEYBYTES,
620 "k must be 'crypto_secretbox_KEYBYTES' bytes"
621 )
622
623 const res = binding.crypto_secretbox_detached(c, mac, m, n, k)
624
625 if (res !== 0) throw new Error('status: ' + res)
626}
627
628exports.crypto_secretbox_open_detached = function (m, c, mac, n, k) {
629 assert(ArrayBuffer.isView(m), 'm must be a typed array')
630 assert(ArrayBuffer.isView(c), 'c must be a typed array')
631 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
632 assert(ArrayBuffer.isView(n), 'n must be a typed array')
633 assert(ArrayBuffer.isView(k), 'k must be a typed array')
634 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
635 assert(
636 mac.byteLength === binding.crypto_secretbox_MACBYTES,
637 "mac must be 'crypto_secretbox_MACBYTES' bytes"
638 )
639 assert(
640 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
641 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
642 )
643 assert(
644 k.byteLength === binding.crypto_secretbox_KEYBYTES,
645 "k must be 'crypto_secretbox_KEYBYTES' bytes"
646 )
647
648 return binding.crypto_secretbox_open_detached(m, c, mac, n, k)
649}
650
651// crypto_generichash
652
653exports.crypto_generichash = function (output, input, key) {
654 if (!key) key = OPTIONAL
655
656 assert(ArrayBuffer.isView(output), 'output must be a typed array')
657 assert(ArrayBuffer.isView(input), 'input must be a typed array')
658 assert(
659 output.byteLength >= binding.crypto_generichash_BYTES_MIN &&
660 output.byteLength <= binding.crypto_generichash_BYTES_MAX,
661 'output must be between crypto_generichash_BYTES_MIN and crypto_generichash_BYTES_MAX bytes'
662 )
663
664 if (key !== OPTIONAL) {
665 assert(ArrayBuffer.isView(key), 'key must be a typed array')
666 assert(
667 key.byteLength >= binding.crypto_generichash_KEYBYTES_MIN &&
668 key.byteLength <= binding.crypto_generichash_KEYBYTES_MAX,
669 'key must be between crypto_generichash_KEYBYTES_MIN and crypto_generichash_KEYBYTES_MAX bytes'
670 )
671 }
672
673 const res = binding.crypto_generichash(
674 output.buffer,
675 output.byteOffset,
676 output.byteLength,
677
678 input.buffer,
679 input.byteOffset,
680 input.byteLength,
681
682 key.buffer,
683 key.byteOffset,
684 key.byteLength
685 )
686
687 if (res !== 0) throw new Error('status: ' + res)
688}
689
690exports.crypto_generichash_batch = function (output, batch, key) {
691 assert(ArrayBuffer.isView(output), 'output must be a typed array')
692
693 if (isNode || batch.length < 4) {
694 const res = binding.crypto_generichash_batch(output, batch, !!key, key || OPTIONAL)
695 if (res !== 0) throw new Error('status: ' + res)
696 } else {
697 const state = Buffer.alloc(binding.crypto_generichash_STATEBYTES)
698
699 exports.crypto_generichash_init(state, key, output.byteLength)
700
701 for (const buf of batch) {
702 exports.crypto_generichash_update(state, buf)
703 }
704
705 exports.crypto_generichash_final(state, output)
706 }
707}
708
709exports.crypto_generichash_keygen = function (key) {
710 assert(ArrayBuffer.isView(key), 'key must be a typed array')
711 assert(
712 key.byteLength === binding.crypto_generichash_KEYBYTES,
713 "key must be 'crypto_generichash_KEYBYTES' bytes"
714 )
715
716 const res = binding.crypto_generichash_keygen(key.buffer, key.byteOffset, key.byteLength)
717
718 if (res !== 0) throw new Error('status: ' + res)
719}
720
721exports.crypto_generichash_init = function (state, key, outputLength) {
722 if (!key) key = OPTIONAL
723
724 assert(ArrayBuffer.isView(state), 'state must be a typed array')
725 assert(
726 state.byteLength === binding.crypto_generichash_STATEBYTES,
727 "state must be 'crypto_generichash_STATEBYTES' bytes"
728 )
729
730 const res = binding.crypto_generichash_init(
731 state.buffer,
732 state.byteOffset,
733 state.byteLength,
734
735 key.buffer,
736 key.byteOffset,
737 key.byteLength,
738
739 outputLength
740 )
741
742 if (res !== 0) throw new Error('status: ' + res)
743}
744
745exports.crypto_generichash_update = function (state, input) {
746 assert(ArrayBuffer.isView(state), 'state must be a typed array')
747 assert(ArrayBuffer.isView(input), 'input must be a typed array')
748 assert(
749 state.byteLength === binding.crypto_generichash_STATEBYTES,
750 "state must be 'crypto_generichash_STATEBYTES' bytes"
751 )
752
753 const res = binding.crypto_generichash_update(
754 state.buffer,
755 state.byteOffset,
756 state.byteLength,
757
758 input.buffer,
759 input.byteOffset,
760 input.byteLength
761 )
762
763 if (res !== 0) throw new Error('status: ' + res)
764}
765
766exports.crypto_generichash_final = function (state, output) {
767 assert(ArrayBuffer.isView(state), 'state must be a typed array')
768 assert(ArrayBuffer.isView(output), 'output must be a typed array')
769 assert(
770 state.byteLength === binding.crypto_generichash_STATEBYTES,
771 "state must be 'crypto_generichash_STATEBYTES' bytes"
772 )
773
774 const res = binding.crypto_generichash_final(
775 state.buffer,
776 state.byteOffset,
777 state.byteLength,
778
779 output.buffer,
780 output.byteOffset,
781 output.byteLength
782 )
783
784 if (res !== 0) throw new Error('status: ' + res)
785}
786
787// secretstream
788
789exports.crypto_secretstream_xchacha20poly1305_keygen = function (k) {
790 assert(ArrayBuffer.isView(k), 'k must be a typed array')
791 assert(
792 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
793 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
794 )
795
796 binding.crypto_secretstream_xchacha20poly1305_keygen(k.buffer, k.byteOffset, k.byteLength)
797}
798
799exports.crypto_secretstream_xchacha20poly1305_init_push = function (state, header, k) {
800 assert(ArrayBuffer.isView(state), 'state must be a typed array')
801 assert(ArrayBuffer.isView(header), 'header must be a typed array')
802 assert(ArrayBuffer.isView(k), 'k must be a typed array')
803 assert(
804 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
805 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
806 )
807 assert(
808 header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
809 "header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
810 )
811 assert(
812 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
813 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
814 )
815
816 const res = binding.crypto_secretstream_xchacha20poly1305_init_push(
817 state.buffer,
818 state.byteOffset,
819 state.byteLength,
820
821 header.buffer,
822 header.byteOffset,
823 header.byteLength,
824
825 k.buffer,
826 k.byteOffset,
827 k.byteLength
828 )
829
830 if (res !== 0) throw new Error('status: ' + res)
831}
832
833exports.crypto_secretstream_xchacha20poly1305_init_pull = function (state, header, k) {
834 assert(ArrayBuffer.isView(state), 'state must be a typed array')
835 assert(ArrayBuffer.isView(header), 'header must be a typed array')
836 assert(ArrayBuffer.isView(k), 'k must be a typed array')
837 assert(
838 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
839 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
840 )
841 assert(
842 header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
843 "header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
844 )
845 assert(
846 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
847 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
848 )
849
850 const res = binding.crypto_secretstream_xchacha20poly1305_init_pull(
851 state.buffer,
852 state.byteOffset,
853 state.byteLength,
854
855 header.buffer,
856 header.byteOffset,
857 header.byteLength,
858
859 k.buffer,
860 k.byteOffset,
861 k.byteLength
862 )
863
864 if (res !== 0) throw new Error('status: ' + res)
865}
866
867exports.crypto_secretstream_xchacha20poly1305_push = function (state, c, m, ad, tag) {
868 if (!ad) ad = OPTIONAL
869
870 assert(ArrayBuffer.isView(state), 'state must be a typed array')
871 assert(ArrayBuffer.isView(c), 'c must be a typed array')
872 assert(ArrayBuffer.isView(m), 'm must be a typed array')
873 assert(
874 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
875 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
876 )
877 assert(
878 c.byteLength === m.byteLength + binding.crypto_secretstream_xchacha20poly1305_ABYTES,
879 "c must be 'm.byteLength + crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
880 )
881
882 const res = binding.crypto_secretstream_xchacha20poly1305_push(
883 state.buffer,
884 state.byteOffset,
885 state.byteLength,
886
887 c.buffer,
888 c.byteOffset,
889 c.byteLength,
890
891 m.buffer,
892 m.byteOffset,
893 m.byteLength,
894
895 ad.buffer,
896 ad.byteOffset,
897 ad.byteLength,
898
899 tag
900 )
901
902 if (res < 0) throw new Error('push failed')
903
904 return res
905}
906
907exports.crypto_secretstream_xchacha20poly1305_pull = function (state, m, tag, c, ad) {
908 if (!ad) ad = OPTIONAL
909
910 assert(ArrayBuffer.isView(state), 'state must be a typed array')
911 assert(
912 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
913 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
914 )
915 assert(ArrayBuffer.isView(tag), 'tag must be a typed array')
916 assert(tag.byteLength === 1, 'tag must be 1 byte')
917
918 assert(ArrayBuffer.isView(c), 'c must be a typed array')
919 assert(
920 c.byteLength >= binding.crypto_secretstream_xchacha20poly1305_ABYTES,
921 "c must be at least 'crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
922 )
923 assert(ArrayBuffer.isView(m), 'm must be a typed array')
924 assert(
925 m.byteLength === c.byteLength - binding.crypto_secretstream_xchacha20poly1305_ABYTES,
926 "m must be 'c.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
927 )
928
929 const res = binding.crypto_secretstream_xchacha20poly1305_pull(
930 state.buffer,
931 state.byteOffset,
932 state.byteLength,
933
934 m.buffer,
935 m.byteOffset,
936 m.byteLength,
937
938 tag.buffer,
939 tag.byteOffset,
940 tag.byteLength,
941
942 c.buffer,
943 c.byteOffset,
944 c.byteLength,
945
946 ad.buffer,
947 ad.byteOffset,
948 ad.byteLength
949 )
950
951 if (res < 0) throw new Error('pull failed')
952
953 return res
954}
955
956exports.crypto_secretstream_xchacha20poly1305_rekey = function (state) {
957 assert(ArrayBuffer.isView(state), 'state must be a typed array')
958 assert(
959 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
960 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
961 )
962
963 binding.crypto_secretstream_xchacha20poly1305_rekey(
964 state.buffer,
965 state.byteOffset,
966 state.byteLength
967 )
968}
969
970// crypto_stream
971
972exports.crypto_stream = function (c, n, k) {
973 assert(ArrayBuffer.isView(c), 'c must be a typed array')
974 assert(ArrayBuffer.isView(n), 'n must be a typed array')
975 assert(ArrayBuffer.isView(k), 'k must be a typed array')
976 assert(
977 n.byteLength === binding.crypto_stream_NONCEBYTES,
978 "n must be 'crypto_stream_NONCEBYTES' bytes"
979 )
980 assert(
981 k.byteLength === binding.crypto_stream_KEYBYTES,
982 "k must be 'crypto_stream_KEYBYTES' bytes"
983 )
984
985 const res = binding.crypto_stream(c, n, k)
986
987 if (res !== 0) throw new Error('status: ' + res)
988}
989
990exports.crypto_stream_xor = function (c, m, n, k) {
991 assert(ArrayBuffer.isView(c), 'c must be a typed array')
992 assert(ArrayBuffer.isView(m), 'm must be a typed array')
993 assert(ArrayBuffer.isView(n), 'n must be a typed array')
994 assert(ArrayBuffer.isView(k), 'k must be a typed array')
995 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
996 assert(
997 n.byteLength === binding.crypto_stream_NONCEBYTES,
998 "n must be 'crypto_stream_NONCEBYTES' bytes"
999 )
1000 assert(
1001 k.byteLength === binding.crypto_stream_KEYBYTES,
1002 "k must be 'crypto_stream_KEYBYTES' bytes"
1003 )
1004
1005 const res = binding.crypto_stream_xor(
1006 c.buffer,
1007 c.byteOffset,
1008 c.byteLength,
1009
1010 m.buffer,
1011 m.byteOffset,
1012 m.byteLength,
1013
1014 n.buffer,
1015 n.byteOffset,
1016 n.byteLength,
1017
1018 k.buffer,
1019 k.byteOffset,
1020 k.byteLength
1021 )
1022
1023 if (res !== 0) throw new Error('status: ' + res)
1024}
1025
1026exports.crypto_stream_chacha20 = function (c, n, k) {
1027 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1028 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1029 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1030 assert(
1031 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1032 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1033 )
1034 assert(
1035 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1036 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1037 )
1038
1039 const res = binding.crypto_stream_chacha20(c, n, k)
1040
1041 if (res !== 0) throw new Error('status: ' + res)
1042}
1043
1044exports.crypto_stream_chacha20_xor = function (c, m, n, k) {
1045 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1046 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1047 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1048 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1049 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1050 assert(
1051 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1052 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1053 )
1054 assert(
1055 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1056 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1057 )
1058
1059 const res = binding.crypto_stream_chacha20_xor(c, m, n, k)
1060
1061 if (res !== 0) throw new Error('status: ' + res)
1062}
1063
1064exports.crypto_stream_chacha20_xor_ic = function (c, m, n, ic, k) {
1065 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1066 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1067 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1068 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1069 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1070 assert(
1071 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1072 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1073 )
1074 assert(
1075 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1076 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1077 )
1078
1079 const res = binding.crypto_stream_chacha20_xor_ic(c, m, n, ic, k)
1080
1081 if (res !== 0) throw new Error('status: ' + res)
1082}
1083
1084exports.crypto_stream_chacha20_ietf = function (c, n, k) {
1085 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1086 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1087 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1088 assert(
1089 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1090 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1091 )
1092 assert(
1093 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1094 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1095 )
1096
1097 const res = binding.crypto_stream_chacha20_ietf(c, n, k)
1098
1099 if (res !== 0) throw new Error('status: ' + res)
1100}
1101
1102exports.crypto_stream_chacha20_ietf_xor = function (c, m, n, k) {
1103 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1104 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1105 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1106 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1107 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1108 assert(
1109 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1110 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1111 )
1112 assert(
1113 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1114 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1115 )
1116
1117 const res = binding.crypto_stream_chacha20_ietf_xor(c, m, n, k)
1118
1119 if (res !== 0) throw new Error('status: ' + res)
1120}
1121
1122exports.crypto_stream_chacha20_ietf_xor_ic = function (c, m, n, ic, k) {
1123 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1124 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1125 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1126 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1127 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1128 assert(
1129 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1130 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1131 )
1132 assert(
1133 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1134 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1135 )
1136
1137 const res = binding.crypto_stream_chacha20_ietf_xor_ic(c, m, n, ic, k)
1138
1139 if (res !== 0) throw new Error('status: ' + res)
1140}
1141
1142exports.crypto_stream_xchacha20 = function (c, n, k) {
1143 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1144 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1145 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1146 assert(
1147 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1148 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1149 )
1150 assert(
1151 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1152 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1153 )
1154
1155 const res = binding.crypto_stream_xchacha20(c, n, k)
1156
1157 if (res !== 0) throw new Error('status: ' + res)
1158}
1159
1160exports.crypto_stream_xchacha20_xor = function (c, m, n, k) {
1161 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1162 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1163 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1164 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1165 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1166 assert(
1167 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1168 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1169 )
1170 assert(
1171 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1172 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1173 )
1174
1175 const res = binding.crypto_stream_xchacha20_xor(c, m, n, k)
1176
1177 if (res !== 0) throw new Error('status: ' + res)
1178}
1179
1180exports.crypto_stream_xchacha20_xor_ic = function (c, m, n, ic, k) {
1181 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1182 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1183 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1184 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1185 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1186 assert(
1187 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1188 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1189 )
1190 assert(
1191 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1192 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1193 )
1194
1195 const res = binding.crypto_stream_xchacha20_xor_ic(c, m, n, ic, k)
1196
1197 if (res !== 0) throw new Error('status: ' + res)
1198}
1199
1200exports.crypto_stream_salsa20 = function (c, n, k) {
1201 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1202 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1203 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1204 assert(
1205 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1206 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1207 )
1208 assert(
1209 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1210 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1211 )
1212
1213 const res = binding.crypto_stream_salsa20(c, n, k)
1214
1215 if (res !== 0) throw new Error('status: ' + res)
1216}
1217
1218exports.crypto_stream_salsa20_xor = function (c, m, n, k) {
1219 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1220 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1221 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1222 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1223 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1224 assert(
1225 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1226 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1227 )
1228 assert(
1229 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1230 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1231 )
1232
1233 const res = binding.crypto_stream_salsa20_xor(c, m, n, k)
1234
1235 if (res !== 0) throw new Error('status: ' + res)
1236}
1237
1238exports.crypto_stream_salsa20_xor_ic = function (c, m, n, ic, k) {
1239 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1240 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1241 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1242 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1243 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1244 assert(
1245 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1246 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1247 )
1248 assert(
1249 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1250 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1251 )
1252
1253 const res = binding.crypto_stream_salsa20_xor_ic(c, m, n, ic, k)
1254
1255 if (res !== 0) throw new Error('status: ' + res)
1256}
1257
1258// crypto_auth
1259
1260exports.crypto_auth = function (out, input, k) {
1261 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1262 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1263 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1264 assert(out.byteLength === binding.crypto_auth_BYTES, "out must be 'crypto_auth_BYTES' bytes")
1265 assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes")
1266
1267 const res = binding.crypto_auth(out, input, k)
1268
1269 if (res !== 0) throw new Error('status: ' + res)
1270}
1271
1272exports.crypto_auth_verify = function (h, input, k) {
1273 assert(ArrayBuffer.isView(h), 'h must be a typed array')
1274 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1275 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1276 assert(h.byteLength === binding.crypto_auth_BYTES, "h must be 'crypto_auth_BYTES' bytes")
1277 assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes")
1278
1279 return binding.crypto_auth_verify(h, input, k)
1280}
1281
1282// crypto_onetimeauth
1283
1284exports.crypto_onetimeauth = function (out, input, k) {
1285 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1286 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1287 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1288 assert(
1289 out.byteLength === binding.crypto_onetimeauth_BYTES,
1290 "out must be 'crypto_onetimeauth_BYTES' bytes"
1291 )
1292 assert(
1293 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1294 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1295 )
1296
1297 const res = binding.crypto_onetimeauth(out, input, k)
1298
1299 if (res !== 0) throw new Error('status: ' + res)
1300}
1301
1302exports.crypto_onetimeauth_init = function (state, k) {
1303 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1304 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1305 assert(
1306 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1307 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1308 )
1309 assert(
1310 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1311 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1312 )
1313
1314 const res = binding.crypto_onetimeauth_init(state, k)
1315
1316 if (res !== 0) throw new Error('status: ' + res)
1317}
1318
1319exports.crypto_onetimeauth_update = function (state, input) {
1320 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1321 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1322 assert(
1323 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1324 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1325 )
1326
1327 const res = binding.crypto_onetimeauth_update(state, input)
1328
1329 if (res !== 0) throw new Error('status: ' + res)
1330}
1331
1332exports.crypto_onetimeauth_final = function (state, out) {
1333 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1334 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1335 assert(
1336 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1337 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1338 )
1339 assert(
1340 out.byteLength === binding.crypto_onetimeauth_BYTES,
1341 "out must be 'crypto_onetimeauth_BYTES' bytes"
1342 )
1343
1344 const res = binding.crypto_onetimeauth_final(state, out)
1345
1346 if (res !== 0) throw new Error('status: ' + res)
1347}
1348
1349exports.crypto_onetimeauth_verify = function (h, input, k) {
1350 assert(ArrayBuffer.isView(h), 'h must be a typed array')
1351 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1352 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1353 assert(
1354 h.byteLength === binding.crypto_onetimeauth_BYTES,
1355 "h must be 'crypto_onetimeauth_BYTES' bytes"
1356 )
1357 assert(
1358 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1359 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1360 )
1361
1362 return binding.crypto_onetimeauth_verify(h, input, k)
1363}
1364
1365// crypto_pwhash
1366
1367exports.crypto_pwhash = function (out, passwd, salt, opslimit, memlimit, alg) {
1368 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1369 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1370 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1371 assert(
1372 out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
1373 "out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
1374 )
1375 assert(
1376 out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
1377 "out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
1378 )
1379 assert(
1380 salt.byteLength === binding.crypto_pwhash_SALTBYTES,
1381 "salt must be 'crypto_pwhash_SALTBYTES' bytes"
1382 )
1383 assert(
1384 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1385 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1386 )
1387 assert(
1388 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1389 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1390 )
1391 assert(
1392 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1393 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1394 )
1395 assert(
1396 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1397 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1398 )
1399 assert(alg >= 1 && alg <= 2, 'alg must be either Argon2i 1.3 or Argon2id 1.3')
1400
1401 const res = binding.crypto_pwhash(out, passwd, salt, opslimit, memlimit, alg)
1402
1403 if (res !== 0) throw new Error('status: ' + res)
1404}
1405
1406exports.crypto_pwhash_async = function (
1407 out,
1408 passwd,
1409 salt,
1410 opslimit,
1411 memlimit,
1412 alg,
1413 callback = undefined
1414) {
1415 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1416 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1417 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1418 assert(
1419 out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
1420 "out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
1421 )
1422 assert(
1423 out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
1424 "out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
1425 )
1426 assert(
1427 salt.byteLength === binding.crypto_pwhash_SALTBYTES,
1428 "salt must be 'crypto_pwhash_SALTBYTES' bytes"
1429 )
1430 assert(
1431 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1432 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1433 )
1434 assert(
1435 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1436 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1437 )
1438 assert(
1439 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1440 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1441 )
1442 assert(
1443 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1444 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1445 )
1446 assert(alg >= 1 && alg <= 2, 'alg must be either Argon2i 1.3 or Argon2id 1.3')
1447
1448 const [done, promise] = checkStatus(callback)
1449
1450 binding.crypto_pwhash_async(
1451 out.buffer,
1452 out.byteOffset,
1453 out.byteLength,
1454
1455 passwd.buffer,
1456 passwd.byteOffset,
1457 passwd.byteLength,
1458
1459 salt.buffer,
1460 salt.byteOffset,
1461 salt.byteLength,
1462
1463 opslimit,
1464 memlimit,
1465 alg,
1466
1467 done
1468 )
1469
1470 return promise
1471}
1472
1473exports.crypto_pwhash_str = function (out, passwd, opslimit, memlimit) {
1474 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1475 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1476 assert(
1477 out.byteLength === binding.crypto_pwhash_STRBYTES,
1478 "out must be 'crypto_pwhash_STRBYTES' bytes"
1479 )
1480 assert(typeof opslimit === 'number', 'opslimit must be a number')
1481 assert(
1482 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1483 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1484 )
1485 assert(
1486 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1487 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1488 )
1489 assert(typeof memlimit === 'number', 'memlimit must be a number')
1490 assert(
1491 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1492 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1493 )
1494 assert(
1495 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1496 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1497 )
1498
1499 const res = binding.crypto_pwhash_str(out, passwd, opslimit, memlimit)
1500
1501 if (res !== 0) throw new Error('status: ' + res)
1502}
1503
1504exports.crypto_pwhash_str_async = function (out, passwd, opslimit, memlimit, callback = undefined) {
1505 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1506 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1507 assert(
1508 out.byteLength === binding.crypto_pwhash_STRBYTES,
1509 "out must be 'crypto_pwhash_STRBYTES' bytes"
1510 )
1511 assert(passwd.byteLength > 0, 'passwd must not be empty')
1512 assert(typeof opslimit === 'number', 'opslimit must be a number')
1513 assert(
1514 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1515 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1516 )
1517 assert(
1518 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1519 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1520 )
1521 assert(typeof memlimit === 'number', 'memlimit must be a number')
1522 assert(
1523 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1524 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1525 )
1526 assert(
1527 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1528 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1529 )
1530
1531 const [done, promise] = checkStatus(callback)
1532
1533 binding.crypto_pwhash_str_async(
1534 out.buffer,
1535 out.byteOffset,
1536 out.byteLength,
1537
1538 passwd.buffer,
1539 passwd.byteOffset,
1540 passwd.byteLength,
1541
1542 opslimit,
1543 memlimit,
1544
1545 done
1546 )
1547
1548 return promise
1549}
1550
1551exports.crypto_pwhash_str_verify = function (str, passwd) {
1552 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1553 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1554 assert(
1555 str.byteLength === binding.crypto_pwhash_STRBYTES,
1556 "str must be 'crypto_pwhash_STRBYTES' bytes"
1557 )
1558
1559 return binding.crypto_pwhash_str_verify(str, passwd)
1560}
1561
1562exports.crypto_pwhash_str_verify_async = function (str, passwd, callback = undefined) {
1563 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1564 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1565 assert(
1566 str.byteLength === binding.crypto_pwhash_STRBYTES,
1567 "str must be 'crypto_pwhash_STRBYTES' bytes"
1568 )
1569 assert(passwd.byteLength > 0, 'passwd must not be empty')
1570
1571 const [done, promise] = checkStatus(callback, true)
1572
1573 binding.crypto_pwhash_str_verify_async(
1574 str.buffer,
1575 str.byteOffset,
1576 str.byteLength,
1577
1578 passwd.buffer,
1579 passwd.byteOffset,
1580 passwd.byteLength,
1581
1582 done
1583 )
1584
1585 return promise
1586}
1587
1588exports.crypto_pwhash_str_needs_rehash = function (str, opslimit, memlimit) {
1589 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1590 assert(
1591 str.byteLength === binding.crypto_pwhash_STRBYTES,
1592 "str must be 'crypto_pwhash_STRBYTES' bytes"
1593 )
1594 assert(
1595 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1596 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1597 )
1598 assert(
1599 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1600 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1601 )
1602 assert(
1603 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1604 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1605 )
1606 assert(
1607 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1608 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1609 )
1610
1611 return binding.crypto_pwhash_str_needs_rehash(str, opslimit, memlimit)
1612}
1613
1614exports.crypto_pwhash_scryptsalsa208sha256 = function (out, passwd, salt, opslimit, memlimit) {
1615 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1616 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1617 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1618 assert(
1619 out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
1620 "out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
1621 )
1622 assert(
1623 out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
1624 "out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
1625 )
1626 assert(
1627 salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
1628 "salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
1629 )
1630 assert(
1631 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1632 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1633 )
1634 assert(
1635 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1636 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1637 )
1638 assert(
1639 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1640 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1641 )
1642 assert(
1643 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1644 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1645 )
1646
1647 const res = binding.crypto_pwhash_scryptsalsa208sha256(out, passwd, salt, opslimit, memlimit)
1648
1649 if (res !== 0) throw new Error('status: ' + res)
1650}
1651
1652exports.crypto_pwhash_scryptsalsa208sha256_async = function (
1653 out,
1654 passwd,
1655 salt,
1656 opslimit,
1657 memlimit,
1658 callback = undefined
1659) {
1660 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1661 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1662 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1663 assert(
1664 out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
1665 "out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
1666 )
1667 assert(
1668 out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
1669 "out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
1670 )
1671 assert(passwd.byteLength > 0, 'passwd must not be empty')
1672 assert(
1673 salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
1674 "salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
1675 )
1676 assert(
1677 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1678 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1679 )
1680 assert(
1681 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1682 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1683 )
1684 assert(
1685 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1686 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1687 )
1688 assert(
1689 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1690 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1691 )
1692
1693 const [done, promise] = checkStatus(callback)
1694
1695 binding.crypto_pwhash_scryptsalsa208sha256_async(
1696 out.buffer,
1697 out.byteOffset,
1698 out.byteLength,
1699
1700 passwd.buffer,
1701 passwd.byteOffset,
1702 passwd.byteLength,
1703
1704 salt.buffer,
1705 salt.byteOffset,
1706 salt.byteLength,
1707
1708 opslimit,
1709 memlimit,
1710
1711 done
1712 )
1713
1714 return promise
1715}
1716
1717exports.crypto_pwhash_scryptsalsa208sha256_str_async = function (
1718 out,
1719 passwd,
1720 opslimit,
1721 memlimit,
1722 callback = undefined
1723) {
1724 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1725 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1726 assert(
1727 out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1728 "out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1729 )
1730 assert(passwd.byteLength > 0, 'passwd must not be empty')
1731 assert(
1732 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1733 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1734 )
1735 assert(
1736 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1737 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1738 )
1739 assert(
1740 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1741 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1742 )
1743 assert(
1744 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1745 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1746 )
1747
1748 const [done, promise] = checkStatus(callback)
1749
1750 binding.crypto_pwhash_scryptsalsa208sha256_str_async(
1751 out.buffer,
1752 out.byteOffset,
1753 out.byteLength,
1754
1755 passwd.buffer,
1756 passwd.byteOffset,
1757 passwd.byteLength,
1758
1759 opslimit,
1760 memlimit,
1761
1762 done
1763 )
1764
1765 return promise
1766}
1767
1768exports.crypto_pwhash_scryptsalsa208sha256_str = function (out, passwd, opslimit, memlimit) {
1769 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1770 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1771 assert(
1772 out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1773 "out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1774 )
1775 assert(passwd.byteLength > 0, 'passwd must not be empty')
1776 assert(
1777 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1778 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1779 )
1780 assert(
1781 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1782 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1783 )
1784 assert(
1785 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1786 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1787 )
1788 assert(
1789 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1790 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1791 )
1792
1793 const res = binding.crypto_pwhash_scryptsalsa208sha256_str(out, passwd, opslimit, memlimit)
1794
1795 if (res !== 0) throw new Error('status: ' + res)
1796}
1797
1798exports.crypto_pwhash_scryptsalsa208sha256_str_verify_async = function (
1799 str,
1800 passwd,
1801 callback = undefined
1802) {
1803 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1804 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1805 assert(
1806 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1807 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1808 )
1809 assert(passwd.byteLength > 0, 'passwd must not be empty')
1810
1811 const [done, promise] = checkStatus(callback, true)
1812
1813 binding.crypto_pwhash_scryptsalsa208sha256_str_verify_async(
1814 str.buffer,
1815 str.byteOffset,
1816 str.byteLength,
1817
1818 passwd.buffer,
1819 passwd.byteOffset,
1820 passwd.byteLength,
1821
1822 done
1823 )
1824
1825 return promise
1826}
1827
1828exports.crypto_pwhash_scryptsalsa208sha256_str_verify = function (str, passwd) {
1829 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1830 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1831 assert(
1832 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1833 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1834 )
1835 assert(passwd.byteLength > 0, 'passwd must not be empty')
1836
1837 return binding.crypto_pwhash_scryptsalsa208sha256_str_verify(str, passwd)
1838}
1839
1840exports.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash = function (str, opslimit, memlimit) {
1841 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1842 assert(
1843 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1844 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1845 )
1846 assert(
1847 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1848 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1849 )
1850 assert(
1851 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1852 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1853 )
1854 assert(
1855 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1856 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1857 )
1858 assert(
1859 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1860 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1861 )
1862
1863 return binding.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str, opslimit, memlimit)
1864}
1865
1866// crypto_kx
1867
1868exports.crypto_kx_keypair = function (pk, sk) {
1869 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
1870 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
1871 assert(
1872 pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1873 "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1874 )
1875 assert(
1876 sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1877 "sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1878 )
1879
1880 const res = binding.crypto_kx_keypair(pk, sk)
1881
1882 if (res !== 0) throw new Error('status: ' + res)
1883}
1884
1885exports.crypto_kx_seed_keypair = function (pk, sk, seed) {
1886 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
1887 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
1888 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
1889 assert(
1890 pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1891 "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1892 )
1893 assert(
1894 sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1895 "sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1896 )
1897 assert(
1898 seed.byteLength === binding.crypto_kx_SEEDBYTES,
1899 "seed must be 'crypto_kx_SEEDBYTES' bytes"
1900 )
1901
1902 const res = binding.crypto_kx_seed_keypair(pk, sk, seed)
1903
1904 if (res !== 0) throw new Error('status: ' + res)
1905}
1906
1907exports.crypto_kx_client_session_keys = function (rx, tx, clientPk, clientSk, serverPk) {
1908 if (!rx) rx = undefined
1909 if (!tx) tx = undefined
1910
1911 assert(rx || tx, 'at least one session key must be specified')
1912
1913 if (rx) {
1914 assert(ArrayBuffer.isView(rx), 'rx must be a typed array')
1915 assert(
1916 rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1917 "rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1918 )
1919 }
1920
1921 if (tx) {
1922 assert(ArrayBuffer.isView(tx), 'tx must be a typed array')
1923 assert(
1924 tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1925 "tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1926 )
1927 }
1928
1929 assert(ArrayBuffer.isView(clientPk), 'clientPk must be a typed array')
1930 assert(ArrayBuffer.isView(clientSk), 'clientSk must be a typed array')
1931 assert(ArrayBuffer.isView(serverPk), 'serverPk must be a typed array')
1932 assert(
1933 clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1934 "clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1935 )
1936 assert(
1937 clientSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1938 "clientSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1939 )
1940 assert(
1941 serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1942 "serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1943 )
1944
1945 const res = binding.crypto_kx_client_session_keys(rx, tx, clientPk, clientSk, serverPk)
1946
1947 if (res !== 0) throw new Error('status: ' + res)
1948}
1949
1950exports.crypto_kx_server_session_keys = function (rx, tx, serverPk, serverSk, clientPk) {
1951 if (!rx) rx = undefined
1952 if (!tx) tx = undefined
1953
1954 assert(rx || tx, 'at least one session key must be specified')
1955
1956 if (rx) {
1957 assert(ArrayBuffer.isView(rx), 'rx must be a typed array')
1958 assert(
1959 rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1960 "rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1961 )
1962 }
1963
1964 if (tx) {
1965 assert(ArrayBuffer.isView(tx), 'tx must be a typed array')
1966 assert(
1967 tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1968 "tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1969 )
1970 }
1971
1972 assert(ArrayBuffer.isView(serverPk), 'serverPk must be a typed array')
1973 assert(ArrayBuffer.isView(serverSk), 'serverSk must be a typed array')
1974 assert(ArrayBuffer.isView(clientPk), 'clientPk must be a typed array')
1975 assert(
1976 serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1977 "serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1978 )
1979 assert(
1980 serverSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1981 "serverSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1982 )
1983 assert(
1984 clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1985 "clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1986 )
1987
1988 const res = binding.crypto_kx_server_session_keys(rx, tx, serverPk, serverSk, clientPk)
1989
1990 if (res !== 0) throw new Error('status: ' + res)
1991}
1992
1993// crypto_scalarmult
1994
1995exports.crypto_scalarmult_base = function (q, n) {
1996 assert(ArrayBuffer.isView(q), 'q must be a typed array')
1997 assert(
1998 q.byteLength === binding.crypto_scalarmult_BYTES,
1999 "q must be 'crypto_scalarmult_BYTES' bytes"
2000 )
2001 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2002 assert(
2003 n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
2004 "n must be 'crypto_scalarmult_SCALARBYTES' bytes"
2005 )
2006
2007 const res = binding.crypto_scalarmult_base(q, n)
2008
2009 if (res !== 0) throw new Error('status: ' + res)
2010}
2011
2012exports.crypto_scalarmult = function (q, n, p) {
2013 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2014 assert(
2015 q.byteLength === binding.crypto_scalarmult_BYTES,
2016 "q must be 'crypto_scalarmult_BYTES' bytes"
2017 )
2018 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2019 assert(
2020 n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
2021 "n must be 'crypto_scalarmult_SCALARBYTES' bytes"
2022 )
2023 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2024 assert(
2025 p.byteLength === binding.crypto_scalarmult_BYTES,
2026 "p must be 'crypto_scalarmult_BYTES' bytes"
2027 )
2028
2029 const res = binding.crypto_scalarmult(q, n, p)
2030
2031 if (res !== 0) throw new Error('status: ' + res)
2032}
2033
2034exports.crypto_scalarmult_ed25519_base = function (q, n) {
2035 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2036 assert(
2037 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2038 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2039 )
2040 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2041 assert(
2042 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2043 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2044 )
2045
2046 const res = binding.crypto_scalarmult_ed25519_base(q, n)
2047
2048 if (res !== 0) throw new Error('status: ' + res)
2049}
2050
2051exports.crypto_scalarmult_ed25519 = function (q, n, p) {
2052 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2053 assert(
2054 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2055 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2056 )
2057 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2058 assert(
2059 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2060 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2061 )
2062 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2063 assert(
2064 p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2065 "p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2066 )
2067
2068 const res = binding.crypto_scalarmult_ed25519(q, n, p)
2069
2070 if (res !== 0) throw new Error('status: ' + res)
2071}
2072
2073exports.crypto_core_ed25519_is_valid_point = function (p) {
2074 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2075 assert(
2076 p.byteLength === binding.crypto_core_ed25519_BYTES,
2077 "p must be 'crypto_core_ed25519_BYTES' bytes"
2078 )
2079
2080 return binding.crypto_core_ed25519_is_valid_point(p)
2081}
2082
2083exports.crypto_core_ed25519_from_uniform = function (p, r) {
2084 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2085 assert(
2086 p.byteLength === binding.crypto_core_ed25519_BYTES,
2087 "p must be 'crypto_core_ed25519_BYTES' bytes"
2088 )
2089 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2090 assert(
2091 r.byteLength === binding.crypto_core_ed25519_UNIFORMBYTES,
2092 "r must be 'crypto_core_ed25519_UNIFORMBYTES' bytes"
2093 )
2094
2095 const res = binding.crypto_core_ed25519_from_uniform(p, r)
2096
2097 if (res !== 0) throw new Error('status: ' + res)
2098}
2099
2100exports.crypto_scalarmult_ed25519_base_noclamp = function (q, n) {
2101 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2102 assert(
2103 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2104 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2105 )
2106 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2107 assert(
2108 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2109 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2110 )
2111
2112 const res = binding.crypto_scalarmult_ed25519_base_noclamp(q, n)
2113
2114 if (res !== 0) throw new Error('status: ' + res)
2115}
2116
2117exports.crypto_scalarmult_ed25519_noclamp = function (q, n, p) {
2118 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2119 assert(
2120 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2121 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2122 )
2123 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2124 assert(
2125 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2126 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2127 )
2128 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2129 assert(
2130 p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2131 "p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2132 )
2133
2134 const res = binding.crypto_scalarmult_ed25519_noclamp(q, n, p)
2135
2136 if (res !== 0) throw new Error('status: ' + res)
2137}
2138
2139// crypto_core
2140
2141exports.crypto_core_ed25519_add = function (r, p, q) {
2142 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2143 assert(
2144 r.byteLength === binding.crypto_core_ed25519_BYTES,
2145 "r must be 'crypto_core_ed25519_BYTES' bytes"
2146 )
2147 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2148 assert(
2149 p.byteLength === binding.crypto_core_ed25519_BYTES,
2150 "p must be 'crypto_core_ed25519_BYTES' bytes"
2151 )
2152 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2153 assert(
2154 q.byteLength === binding.crypto_core_ed25519_BYTES,
2155 "q must be 'crypto_core_ed25519_BYTES' bytes"
2156 )
2157
2158 const res = binding.crypto_core_ed25519_add(r, p, q)
2159
2160 if (res !== 0) throw new Error('status: ' + res)
2161}
2162
2163exports.crypto_core_ed25519_sub = function (r, p, q) {
2164 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2165 assert(
2166 r.byteLength === binding.crypto_core_ed25519_BYTES,
2167 "r must be 'crypto_core_ed25519_BYTES' bytes"
2168 )
2169 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2170 assert(
2171 p.byteLength === binding.crypto_core_ed25519_BYTES,
2172 "p must be 'crypto_core_ed25519_BYTES' bytes"
2173 )
2174 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2175 assert(
2176 q.byteLength === binding.crypto_core_ed25519_BYTES,
2177 "q must be 'crypto_core_ed25519_BYTES' bytes"
2178 )
2179
2180 const res = binding.crypto_core_ed25519_sub(r, p, q)
2181
2182 if (res !== 0) throw new Error('status: ' + res)
2183}
2184
2185exports.crypto_core_ed25519_scalar_random = function (r) {
2186 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2187 assert(
2188 r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2189 "r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2190 )
2191
2192 binding.crypto_core_ed25519_scalar_random(r)
2193}
2194
2195exports.crypto_core_ed25519_scalar_reduce = function (r, s) {
2196 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2197 assert(
2198 r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2199 "r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2200 )
2201 assert(ArrayBuffer.isView(s), 's must be a typed array')
2202 assert(
2203 s.byteLength === binding.crypto_core_ed25519_NONREDUCEDSCALARBYTES,
2204 "s must be 'crypto_core_ed25519_NONREDUCEDSCALARBYTES' bytes"
2205 )
2206
2207 binding.crypto_core_ed25519_scalar_reduce(r, s)
2208}
2209
2210exports.crypto_core_ed25519_scalar_invert = function (recip, s) {
2211 assert(ArrayBuffer.isView(recip), 'recip must be a typed array')
2212 assert(
2213 recip.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2214 "recip must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2215 )
2216 assert(ArrayBuffer.isView(s), 's must be a typed array')
2217 assert(
2218 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2219 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2220 )
2221
2222 binding.crypto_core_ed25519_scalar_invert(recip, s)
2223}
2224
2225exports.crypto_core_ed25519_scalar_negate = function (neg, s) {
2226 assert(ArrayBuffer.isView(neg), 'neg must be a typed array')
2227 assert(
2228 neg.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2229 "neg must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2230 )
2231 assert(ArrayBuffer.isView(s), 's must be a typed array')
2232 assert(
2233 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2234 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2235 )
2236
2237 binding.crypto_core_ed25519_scalar_negate(neg, s)
2238}
2239
2240exports.crypto_core_ed25519_scalar_complement = function (comp, s) {
2241 assert(ArrayBuffer.isView(comp), 'comp must be a typed array')
2242 assert(
2243 comp.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2244 "comp must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2245 )
2246 assert(ArrayBuffer.isView(s), 's must be a typed array')
2247 assert(
2248 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2249 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2250 )
2251
2252 binding.crypto_core_ed25519_scalar_complement(comp, s)
2253}
2254
2255exports.crypto_core_ed25519_scalar_add = function (z, x, y) {
2256 assert(ArrayBuffer.isView(z), 'z must be a typed array')
2257 assert(
2258 z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2259 "z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2260 )
2261 assert(ArrayBuffer.isView(x), 'x must be a typed array')
2262 assert(
2263 x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2264 "x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2265 )
2266 assert(ArrayBuffer.isView(y), 'y must be a typed array')
2267 assert(
2268 y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2269 "y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2270 )
2271
2272 binding.crypto_core_ed25519_scalar_add(z, x, y)
2273}
2274
2275exports.crypto_core_ed25519_scalar_sub = function (z, x, y) {
2276 assert(ArrayBuffer.isView(z), 'z must be a typed array')
2277 assert(
2278 z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2279 "z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2280 )
2281 assert(ArrayBuffer.isView(x), 'x must be a typed array')
2282 assert(
2283 x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2284 "x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2285 )
2286 assert(ArrayBuffer.isView(y), 'y must be a typed array')
2287 assert(
2288 y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2289 "y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2290 )
2291
2292 binding.crypto_core_ed25519_scalar_sub(z, x, y)
2293}
2294
2295// crypto_shorthash
2296
2297exports.crypto_shorthash = function (out, input, k) {
2298 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2299 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2300 assert(
2301 out.byteLength === binding.crypto_shorthash_BYTES,
2302 "out must be 'crypto_shorthash_BYTES' bytes"
2303 )
2304 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2305 assert(
2306 k.byteLength === binding.crypto_shorthash_KEYBYTES,
2307 "k must be 'crypto_shorthash_KEYBYTES' bytes"
2308 )
2309
2310 const res = binding.crypto_shorthash(out, input, k)
2311
2312 if (res !== 0) throw new Error('status: ' + res)
2313}
2314
2315// crypto_kdf
2316
2317exports.crypto_kdf_keygen = function (key) {
2318 assert(ArrayBuffer.isView(key), 'key must be a typed array')
2319 assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes")
2320
2321 binding.crypto_kdf_keygen(key)
2322}
2323
2324exports.crypto_kdf_derive_from_key = function (subkey, subkeyId, ctx, key) {
2325 assert(ArrayBuffer.isView(subkey), 'subkey must be a typed array')
2326 assert(
2327 subkey.byteLength >= binding.crypto_kdf_BYTES_MIN,
2328 "subkey must be at least 'crypto_kdf_BYTES_MIN' bytes"
2329 )
2330 assert(
2331 subkey.byteLength <= binding.crypto_kdf_BYTES_MAX,
2332 "subkey must be at most 'crypto_kdf_BYTES_MAX' bytes"
2333 )
2334 assert(ArrayBuffer.isView(ctx), 'ctx must be a typed array')
2335 assert(
2336 ctx.byteLength === binding.crypto_kdf_CONTEXTBYTES,
2337 "ctx must be 'crypto_kdf_CONTEXTBYTES' bytes"
2338 )
2339 assert(ArrayBuffer.isView(key), 'key must be a typed array')
2340 assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes")
2341
2342 const res = binding.crypto_kdf_derive_from_key(subkey, subkeyId, ctx, key)
2343
2344 if (res !== 0) throw new Error('status: ' + res)
2345}
2346
2347// crypto_hash
2348
2349exports.crypto_hash = function (out, input) {
2350 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2351 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2352 assert(out.byteLength === binding.crypto_hash_BYTES, "out must be 'crypto_hash_BYTES' bytes")
2353
2354 const res = binding.crypto_hash(out, input)
2355
2356 if (res !== 0) throw new Error('status: ' + res)
2357}
2358
2359exports.crypto_hash_sha256 = function (out, input) {
2360 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2361 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2362 assert(
2363 out.byteLength === binding.crypto_hash_sha256_BYTES,
2364 "out must be 'crypto_hash_sha256_BYTES' bytes"
2365 )
2366
2367 const res = binding.crypto_hash_sha256(out, input)
2368
2369 if (res !== 0) throw new Error('status: ' + res)
2370}
2371
2372exports.crypto_hash_sha256_init = function (state) {
2373 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2374 assert(
2375 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2376 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2377 )
2378
2379 const res = binding.crypto_hash_sha256_init(state)
2380
2381 if (res !== 0) throw new Error('status: ' + res)
2382}
2383
2384exports.crypto_hash_sha256_update = function (state, input) {
2385 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2386 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2387 assert(
2388 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2389 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2390 )
2391
2392 const res = binding.crypto_hash_sha256_update(state, input)
2393
2394 if (res !== 0) throw new Error('status: ' + res)
2395}
2396
2397exports.crypto_hash_sha256_final = function (state, out) {
2398 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2399 assert(
2400 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2401 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2402 )
2403 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2404 assert(
2405 out.byteLength === binding.crypto_hash_sha256_BYTES,
2406 "out must be 'crypto_hash_sha256_BYTES' bytes"
2407 )
2408
2409 const res = binding.crypto_hash_sha256_final(state, out)
2410
2411 if (res !== 0) throw new Error('status: ' + res)
2412}
2413
2414exports.crypto_hash_sha512 = function (out, input) {
2415 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2416 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2417 assert(
2418 out.byteLength === binding.crypto_hash_sha512_BYTES,
2419 "out must be 'crypto_hash_sha512_BYTES' bytes"
2420 )
2421
2422 const res = binding.crypto_hash_sha512(out, input)
2423
2424 if (res !== 0) throw new Error('status: ' + res)
2425}
2426
2427exports.crypto_hash_sha512_init = function (state) {
2428 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2429 assert(
2430 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2431 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2432 )
2433
2434 const res = binding.crypto_hash_sha512_init(state)
2435
2436 if (res !== 0) throw new Error('status: ' + res)
2437}
2438
2439exports.crypto_hash_sha512_update = function (state, input) {
2440 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2441 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2442 assert(
2443 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2444 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2445 )
2446
2447 const res = binding.crypto_hash_sha512_update(state, input)
2448
2449 if (res !== 0) throw new Error('status: ' + res)
2450}
2451
2452exports.crypto_hash_sha512_final = function (state, out) {
2453 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2454 assert(
2455 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2456 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2457 )
2458 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2459 assert(
2460 out.byteLength === binding.crypto_hash_sha512_BYTES,
2461 "out must be 'crypto_hash_sha512_BYTES' bytes"
2462 )
2463
2464 const res = binding.crypto_hash_sha512_final(state, out)
2465
2466 if (res !== 0) throw new Error('status: ' + res)
2467}
2468
2469// crypto_aead
2470
2471exports.crypto_aead_xchacha20poly1305_ietf_keygen = function (k) {
2472 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2473 assert(
2474 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2475 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2476 )
2477
2478 binding.crypto_aead_xchacha20poly1305_ietf_keygen(k)
2479}
2480
2481exports.crypto_aead_xchacha20poly1305_ietf_encrypt = function (c, m, ad, nsec, npub, k) {
2482 if (!ad) ad = undefined
2483
2484 assert(nsec === null, 'nsec must always be set to null')
2485 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2486 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2487 assert(
2488 c.byteLength === m.byteLength + binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2489 "c must be 'm.byteLength + crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2490 )
2491 assert(c.byteLength <= 0xffffffff, 'c.byteLength must be a 32bit integer')
2492 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2493 assert(
2494 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2495 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2496 )
2497 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2498 assert(
2499 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2500 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2501 )
2502
2503 const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt(c, m, ad, npub, k)
2504
2505 if (res < 0) throw new Error('could not encrypt data')
2506
2507 return res
2508}
2509
2510exports.crypto_aead_xchacha20poly1305_ietf_decrypt = function (m, nsec, c, ad, npub, k) {
2511 if (!ad) ad = undefined
2512
2513 assert(nsec === null, 'nsec must always be set to null')
2514 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2515 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2516 assert(
2517 m.byteLength === c.byteLength - binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2518 "m must be 'c.byteLength - crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2519 )
2520 assert(m.byteLength <= 0xffffffff, 'm.byteLength must be a 32bit integer')
2521 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2522 assert(
2523 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2524 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2525 )
2526 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2527 assert(
2528 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2529 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2530 )
2531
2532 const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt(m, c, ad, npub, k)
2533
2534 if (res < 0) throw new Error('could not verify data')
2535
2536 return res
2537}
2538
2539exports.crypto_aead_xchacha20poly1305_ietf_encrypt_detached = function (
2540 c,
2541 mac,
2542 m,
2543 ad,
2544 nsec,
2545 npub,
2546 k
2547) {
2548 if (!ad) ad = undefined
2549
2550 assert(nsec === null, 'nsec must always be set to null')
2551 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2552 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2553 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2554 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2555 assert(
2556 mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2557 "mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2558 )
2559 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2560 assert(
2561 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2562 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2563 )
2564 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2565 assert(
2566 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2567 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2568 )
2569
2570 const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k)
2571
2572 if (res < 0) throw new Error('could not encrypt data')
2573
2574 return res
2575}
2576
2577exports.crypto_aead_xchacha20poly1305_ietf_decrypt_detached = function (
2578 m,
2579 nsec,
2580 c,
2581 mac,
2582 ad,
2583 npub,
2584 k
2585) {
2586 if (!ad) ad = undefined
2587
2588 assert(nsec === null, 'nsec must always be set to null')
2589 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2590 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2591 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
2592 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2593 assert(
2594 mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2595 "mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2596 )
2597 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2598 assert(
2599 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2600 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2601 )
2602 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2603 assert(
2604 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2605 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2606 )
2607
2608 const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k)
2609
2610 if (res !== 0) throw new Error('could not verify data')
2611}
2612
2613exports.crypto_aead_chacha20poly1305_ietf_keygen = function (k) {
2614 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2615 assert(
2616 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2617 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2618 )
2619
2620 binding.crypto_aead_chacha20poly1305_ietf_keygen(k)
2621}
2622
2623exports.crypto_aead_chacha20poly1305_ietf_encrypt = function (c, m, ad, nsec, npub, k) {
2624 if (!ad) ad = undefined
2625
2626 assert(nsec === null, 'nsec must always be set to null')
2627 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2628 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2629 assert(
2630 c.byteLength === m.byteLength + binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2631 "c must be 'm.byteLength + crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2632 )
2633 assert(c.byteLength <= 0xffffffff, 'c.byteLength must be a 32bit integer')
2634 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2635 assert(
2636 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2637 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2638 )
2639 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2640 assert(
2641 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2642 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2643 )
2644
2645 const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, ad, npub, k)
2646
2647 if (res < 0) throw new Error('could not encrypt data')
2648
2649 return res
2650}
2651
2652exports.crypto_aead_chacha20poly1305_ietf_decrypt = function (m, nsec, c, ad, npub, k) {
2653 if (!ad) ad = undefined
2654
2655 assert(nsec === null, 'nsec must always be set to null')
2656 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2657 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2658 assert(
2659 m.byteLength === c.byteLength - binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2660 "m must be 'c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2661 )
2662 assert(m.byteLength <= 0xffffffff, 'm.byteLength must be a 32bit integer')
2663 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2664 assert(
2665 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2666 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2667 )
2668 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2669 assert(
2670 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2671 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2672 )
2673
2674 const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt(m, c, ad, npub, k)
2675
2676 if (res < 0) throw new Error('could not verify data')
2677
2678 return res
2679}
2680
2681exports.crypto_aead_chacha20poly1305_ietf_encrypt_detached = function (
2682 c,
2683 mac,
2684 m,
2685 ad,
2686 nsec,
2687 npub,
2688 k
2689) {
2690 if (!ad) ad = undefined
2691
2692 assert(nsec === null, 'nsec must always be set to null')
2693 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2694 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2695 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2696 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2697 assert(
2698 mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2699 "mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2700 )
2701 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2702 assert(
2703 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2704 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2705 )
2706 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2707 assert(
2708 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2709 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2710 )
2711
2712 const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k)
2713
2714 if (res < 0) throw new Error('could not encrypt data')
2715
2716 return res
2717}
2718
2719exports.crypto_aead_chacha20poly1305_ietf_decrypt_detached = function (
2720 m,
2721 nsec,
2722 c,
2723 mac,
2724 ad,
2725 npub,
2726 k
2727) {
2728 if (!ad) ad = undefined
2729
2730 assert(nsec === null, 'nsec must always be set to null')
2731 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2732 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2733 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
2734 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2735 assert(
2736 mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2737 "mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2738 )
2739 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2740 assert(
2741 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2742 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2743 )
2744 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2745 assert(
2746 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2747 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2748 )
2749
2750 const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k)
2751
2752 if (res !== 0) throw new Error('could not verify data')
2753}
2754
2755// crypto_stream
2756
2757exports.crypto_stream_xor_wrap_init = function (state, n, k) {
2758 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2759 assert(
2760 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2761 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2762 )
2763 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2764 assert(
2765 n.byteLength === binding.crypto_stream_NONCEBYTES,
2766 "n must be 'crypto_stream_NONCEBYTES' bytes"
2767 )
2768 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2769 assert(
2770 k.byteLength === binding.crypto_stream_KEYBYTES,
2771 "k must be 'crypto_stream_KEYBYTES' bytes"
2772 )
2773
2774 binding.crypto_stream_xor_wrap_init(state, n, k)
2775}
2776
2777exports.crypto_stream_xor_wrap_update = function (state, c, m) {
2778 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2779 assert(
2780 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2781 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2782 )
2783 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2784 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2785 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2786
2787 binding.crypto_stream_xor_wrap_update(state, c, m)
2788}
2789
2790exports.crypto_stream_xor_wrap_final = function (state) {
2791 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2792 assert(
2793 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2794 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2795 )
2796
2797 binding.crypto_stream_xor_wrap_final(state)
2798}
2799
2800exports.crypto_stream_chacha20_xor_wrap_init = function (state, n, k) {
2801 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2802 assert(
2803 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2804 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2805 )
2806 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2807 assert(
2808 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
2809 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
2810 )
2811 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2812 assert(
2813 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
2814 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
2815 )
2816
2817 binding.crypto_stream_chacha20_xor_wrap_init(state, n, k)
2818}
2819
2820exports.crypto_stream_chacha20_xor_wrap_update = function (state, c, m) {
2821 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2822 assert(
2823 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2824 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2825 )
2826 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2827 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2828 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2829
2830 binding.crypto_stream_chacha20_xor_wrap_update(state, c, m)
2831}
2832
2833exports.crypto_stream_chacha20_xor_wrap_final = function (state) {
2834 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2835 assert(
2836 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2837 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2838 )
2839
2840 binding.crypto_stream_chacha20_xor_wrap_final(state)
2841}
2842
2843exports.crypto_stream_chacha20_ietf_xor_wrap_init = function (state, n, k) {
2844 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2845 assert(
2846 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2847 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2848 )
2849 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2850 assert(
2851 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
2852 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
2853 )
2854 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2855 assert(
2856 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
2857 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
2858 )
2859
2860 binding.crypto_stream_chacha20_ietf_xor_wrap_init(state, n, k)
2861}
2862
2863exports.crypto_stream_chacha20_ietf_xor_wrap_update = function (state, c, m) {
2864 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2865 assert(
2866 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2867 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2868 )
2869 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2870 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2871 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2872
2873 binding.crypto_stream_chacha20_ietf_xor_wrap_update(state, c, m)
2874}
2875
2876exports.crypto_stream_chacha20_ietf_xor_wrap_final = function (state) {
2877 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2878 assert(
2879 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2880 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2881 )
2882
2883 binding.crypto_stream_chacha20_ietf_xor_wrap_final(state)
2884}
2885
2886exports.crypto_stream_xchacha20_xor_wrap_init = function (state, n, k) {
2887 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2888 assert(
2889 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2890 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2891 )
2892 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2893 assert(
2894 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
2895 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
2896 )
2897 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2898 assert(
2899 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
2900 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
2901 )
2902
2903 binding.crypto_stream_xchacha20_xor_wrap_init(state, n, k)
2904}
2905
2906exports.crypto_stream_xchacha20_xor_wrap_update = function (state, c, m) {
2907 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2908 assert(
2909 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2910 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2911 )
2912 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2913 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2914 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2915
2916 binding.crypto_stream_xchacha20_xor_wrap_update(state, c, m)
2917}
2918
2919exports.crypto_stream_xchacha20_xor_wrap_final = function (state) {
2920 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2921 assert(
2922 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2923 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2924 )
2925
2926 binding.crypto_stream_xchacha20_xor_wrap_final(state)
2927}
2928
2929exports.crypto_stream_salsa20_xor_wrap_init = function (state, n, k) {
2930 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2931 assert(
2932 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2933 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2934 )
2935 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2936 assert(
2937 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
2938 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
2939 )
2940 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2941 assert(
2942 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
2943 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
2944 )
2945
2946 binding.crypto_stream_salsa20_xor_wrap_init(state, n, k)
2947}
2948
2949exports.crypto_stream_salsa20_xor_wrap_update = function (state, c, m) {
2950 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2951 assert(
2952 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2953 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2954 )
2955 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2956 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2957 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2958
2959 binding.crypto_stream_salsa20_xor_wrap_update(state, c, m)
2960}
2961
2962exports.crypto_stream_salsa20_xor_wrap_final = function (state) {
2963 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2964 assert(
2965 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2966 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2967 )
2968
2969 binding.crypto_stream_salsa20_xor_wrap_final(state)
2970}
2971
2972// experimental
2973
2974exports.extension_tweak_ed25519_base = function (n, p, ns) {
2975 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2976 assert(
2977 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
2978 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
2979 )
2980 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2981 assert(
2982 p.byteLength === binding.extension_tweak_ed25519_BYTES,
2983 "p must be 'extension_tweak_ed25519_BYTES' bytes"
2984 )
2985
2986 binding.extension_tweak_ed25519_base(n, p, ns)
2987}
2988
2989exports.extension_tweak_ed25519_sign_detached = function (sig, m, scalar, pk) {
2990 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
2991 assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes")
2992 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2993 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
2994 assert(
2995 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
2996 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
2997 )
2998
2999 if (pk) {
3000 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3001 assert(
3002 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3003 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3004 )
3005 }
3006
3007 const res = binding.extension_tweak_ed25519_sign_detached(sig, m, scalar, pk)
3008
3009 if (res !== 0) throw new Error('failed to compute signature')
3010}
3011
3012exports.extension_tweak_ed25519_sk_to_scalar = function (n, sk) {
3013 assert(ArrayBuffer.isView(n), 'n must be a typed array')
3014 assert(
3015 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3016 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3017 )
3018 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
3019 assert(
3020 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
3021 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
3022 )
3023
3024 binding.extension_tweak_ed25519_sk_to_scalar(n, sk)
3025}
3026
3027exports.extension_tweak_ed25519_scalar = function (scalarOut, scalar, ns) {
3028 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3029 assert(
3030 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3031 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3032 )
3033 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
3034 assert(
3035 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3036 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3037 )
3038
3039 binding.extension_tweak_ed25519_scalar(scalarOut, scalar, ns)
3040}
3041
3042exports.extension_tweak_ed25519_pk = function (tpk, pk, ns) {
3043 assert(ArrayBuffer.isView(tpk), 'tpk must be a typed array')
3044 assert(
3045 tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3046 "tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3047 )
3048 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3049 assert(
3050 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3051 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3052 )
3053
3054 const res = binding.extension_tweak_ed25519_pk(tpk, pk, ns)
3055
3056 if (res !== 0) throw new Error('failed to tweak public key')
3057}
3058
3059exports.extension_tweak_ed25519_keypair = function (pk, scalarOut, scalarIn, ns) {
3060 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3061 assert(
3062 pk.byteLength === binding.extension_tweak_ed25519_BYTES,
3063 "pk must be 'extension_tweak_ed25519_BYTES' bytes"
3064 )
3065 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3066 assert(
3067 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3068 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3069 )
3070 assert(ArrayBuffer.isView(scalarIn), 'scalarIn must be a typed array')
3071 assert(
3072 scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3073 "scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3074 )
3075
3076 binding.extension_tweak_ed25519_keypair(pk, scalarOut, scalarIn, ns)
3077}
3078
3079exports.extension_tweak_ed25519_scalar_add = function (scalarOut, scalar, n) {
3080 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3081 assert(
3082 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3083 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3084 )
3085 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
3086 assert(
3087 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3088 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3089 )
3090 assert(ArrayBuffer.isView(n), 'n must be a typed array')
3091 assert(
3092 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3093 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3094 )
3095
3096 binding.extension_tweak_ed25519_scalar_add(scalarOut, scalar, n)
3097}
3098
3099exports.extension_tweak_ed25519_pk_add = function (tpk, pk, p) {
3100 assert(ArrayBuffer.isView(tpk), 'tpk must be a typed array')
3101 assert(
3102 tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3103 "tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3104 )
3105 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3106 assert(
3107 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3108 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3109 )
3110 assert(ArrayBuffer.isView(p), 'p must be a typed array')
3111 assert(
3112 p.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3113 "p must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3114 )
3115
3116 const res = binding.extension_tweak_ed25519_pk_add(tpk, pk, p)
3117
3118 if (res !== 0) throw new Error('failed to add tweak to public key')
3119}
3120
3121exports.extension_tweak_ed25519_keypair_add = function (pk, scalarOut, scalarIn, tweak) {
3122 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3123 assert(
3124 pk.byteLength === binding.extension_tweak_ed25519_BYTES,
3125 "pk must be 'extension_tweak_ed25519_BYTES' bytes"
3126 )
3127 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3128 assert(
3129 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3130 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3131 )
3132 assert(ArrayBuffer.isView(scalarIn), 'scalarIn must be a typed array')
3133 assert(
3134 scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3135 "scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3136 )
3137 assert(ArrayBuffer.isView(tweak), 'tweak must be a typed array')
3138 assert(
3139 tweak.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3140 "tweak must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3141 )
3142
3143 const res = binding.extension_tweak_ed25519_keypair_add(pk, scalarOut, scalarIn, tweak)
3144
3145 if (res !== 0) throw new Error('failed to add tweak to keypair')
3146}
3147
3148exports.extension_pbkdf2_sha512_async = function (out, passwd, salt, iter, outlen, callback) {
3149 assert(
3150 iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
3151 "iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
3152 )
3153 assert(
3154 outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
3155 "outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
3156 )
3157 assert(ArrayBuffer.isView(out), 'out must be a typed array')
3158 assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes")
3159 assert(out.byteLength > 0, 'out must not be empty')
3160 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
3161 assert(passwd.byteLength > 0, 'passwd must not be empty')
3162 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
3163 assert(salt.byteLength > 0, 'salt must not be empty')
3164
3165 const [done, promise] = checkStatus(callback)
3166
3167 binding.extension_pbkdf2_sha512_async(
3168 out.buffer,
3169 out.byteOffset,
3170 out.byteLength,
3171
3172 passwd.buffer,
3173 passwd.byteOffset,
3174 passwd.byteLength,
3175
3176 salt.buffer,
3177 salt.byteOffset,
3178 salt.byteLength,
3179
3180 iter,
3181 outlen,
3182
3183 done
3184 )
3185
3186 return promise
3187}
3188
3189exports.extension_pbkdf2_sha512 = function (out, passwd, salt, iter, outlen) {
3190 assert(
3191 iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
3192 "iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
3193 )
3194 assert(
3195 outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
3196 "outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
3197 )
3198 assert(ArrayBuffer.isView(out), 'out must be a typed array')
3199 assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes")
3200 assert(out.byteLength > 0, 'out must not be empty')
3201 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
3202 assert(passwd.byteLength > 0, 'passwd must not be empty')
3203 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
3204 assert(salt.byteLength > 0, 'salt must not be empty')
3205
3206 const res = binding.extension_pbkdf2_sha512(out, passwd, salt, iter, outlen)
3207
3208 if (res !== 0) throw new Error('failed to add tweak to public key')
3209}
3210
3211function checkStatus(callback, booleanResult = false) {
3212 let done, promise
3213
3214 if (typeof callback === 'function') {
3215 done = function (status) {
3216 if (booleanResult) callback(null, status === 0)
3217 else if (status === 0) callback(null)
3218 else callback(new Error('status: ' + status))
3219 }
3220 } else {
3221 promise = new Promise(function (resolve, reject) {
3222 done = function (status) {
3223 if (booleanResult) resolve(status === 0)
3224 else if (status === 0) resolve()
3225 else reject(new Error('status: ' + status))
3226 }
3227 })
3228 }
3229
3230 return [done, promise]
3231}
node_modules/hypercore-crypto/node_modules/sodium-native/package.json +62 -0
……@@ -0,0 +1,62 @@
1{
2 "name": "sodium-native",
3 "version": "5.1.0",
4 "description": "Low level bindings for libsodium",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "binding.cc",
9 "binding.js",
10 "extensions",
11 "prebuilds",
12 "CMakeLists.txt"
13 ],
14 "imports": {
15 "assert": {
16 "bare": "bare-assert",
17 "node": "assert"
18 }
19 },
20 "addon": true,
21 "dependencies": {
22 "bare-assert": "^1.2.0",
23 "require-addon": "^1.1.0",
24 "which-runtime": "^1.2.1"
25 },
26 "devDependencies": {
27 "bare-compat-napi": "^1.3.5",
28 "brittle": "^3.16.2",
29 "cmake-bare": "^1.6.1",
30 "cmake-fetch": "^1.4.3",
31 "cmake-napi": "^1.2.1",
32 "prettier": "^3.6.2",
33 "prettier-config-holepunch": "^2.0.0"
34 },
35 "scripts": {
36 "test": "prettier . --check && npm run test:node && npm run test:bare",
37 "test:node": "node test/all.js",
38 "test:bare": "bare test/all.js"
39 },
40 "standard": {
41 "ignore": [
42 "/test/fixtures/*.js"
43 ]
44 },
45 "engines": {
46 "bare": ">=1.16.0"
47 },
48 "repository": {
49 "type": "git",
50 "url": "git+https://github.com/holepunchto/sodium-native.git"
51 },
52 "contributors": [
53 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
54 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
55 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
56 ],
57 "license": "MIT",
58 "bugs": {
59 "url": "https://github.com/holepunchto/sodium-native/issues"
60 },
61 "homepage": "https://github.com/holepunchto/sodium-native"
62}
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/android-arm/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/android-arm/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/android-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/android-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/android-ia32/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/android-ia32/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/android-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/android-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/ios-arm64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/ios-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/ios-x64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/win32-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-native/prebuilds/win32-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/hypercore-crypto/node_modules/sodium-universal/LICENSE.md +7 -0
……@@ -0,0 +1,7 @@
1Copyright 2017 Mathias Buus & Emil Bay
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
node_modules/hypercore-crypto/node_modules/sodium-universal/README.md +288 -0
……@@ -0,0 +1,288 @@
1# sodium-universal
2
3Universal wrapper for `sodium-javascript` and `sodium-native` working in Node.js and the Browser
4
5```sh
6npm install sodium-universal
7```
8
9`sodium-native` ships with prebuilds for macOS, Windows, and Linux.
10
11Note that the module itself is generated on a prepublish hook.
12
13## Usage
14
15```js
16var sodium = require('sodium-universal')
17
18var rnd = Buffer.allocUnsafe(12) // Cryptographically random data
19sodium.randombytes_buf(rnd)
20
21console.log(rnd.toString('hex'))
22
23```
24
25Works seamlessly with Node.js:
26
27```sh
28$ node example.js
29c7dbd46a6cc84ff2e0d1285c
30```
31
32And the browser:
33
34First install the peer dep, `sodium-javascript`.
35
36```sh
37npm install --save sodium-javascript
38```
39
40And then browserify
41
42```sh
43browserify example.js > bundle.js
44```
45
46## Introduction
47
48[`libsodium`](https://download.libsodium.org/doc/) is a collection of cryptographic primitives, providing a low-level foundation to build higher-level cryptographic applications and protocols. It is often put in contrast to RSA based cryptography and OpenSSL, even though they all share overlapping algorithms and target slightly different audiences. Sodium is a collection of modern collection of primitives, fulfilling the same cryptographic tasks, but based on simpler and more efficient algorithms.
49
50This library provides seamless bindings to [`sodium-native`](https://github.com/sodium-friends/sodium-native), which is the original C implementation of `libsodium` exposed as a Node native module. For the browser we expose [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript), using the `package.json` [`browser`](https://github.com/defunctzombie/package-browser-field-spec) field, which is supported by most bundlers.
51
52## API
53
54Please refer to [`sodium-native`](https://github.com/sodium-friends/sodium-native#api) and [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript#api). Note that the two modules do not yet have feature parity, where `sodium-native` is the more featureful of the two.
55
56## Compatibilty
57
58<!-- Generated by build-scripts/symbols.js with
59 sodium-native@3.2.0
60 sodium-javascript@0.6.0 -->
61| C Library Symbol | `sodium-native` | `sodium-javascript` |
62|:--------------------------------------------------------:|:--------------------:|:--------------------:|
63| `crypto_aead_chacha20poly1305_ietf_ABYTES` | :white_check_mark: | :white_check_mark: |
64| `crypto_aead_chacha20poly1305_ietf_decrypt` | :white_check_mark: | :white_check_mark: |
65| `crypto_aead_chacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :white_check_mark: |
66| `crypto_aead_chacha20poly1305_ietf_encrypt` | :white_check_mark: | :white_check_mark: |
67| `crypto_aead_chacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :white_check_mark: |
68| `crypto_aead_chacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
69| `crypto_aead_chacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
70| `crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
71| `crypto_aead_chacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :white_check_mark: |
72| `crypto_aead_chacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :white_check_mark: |
73| `crypto_aead_xchacha20poly1305_ietf_ABYTES` | :white_check_mark: | :small_red_triangle: |
74| `crypto_aead_xchacha20poly1305_ietf_decrypt` | :white_check_mark: | :small_red_triangle: |
75| `crypto_aead_xchacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :small_red_triangle: |
76| `crypto_aead_xchacha20poly1305_ietf_encrypt` | :white_check_mark: | :small_red_triangle: |
77| `crypto_aead_xchacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :small_red_triangle: |
78| `crypto_aead_xchacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
79| `crypto_aead_xchacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
80| `crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
81| `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :small_red_triangle: |
82| `crypto_aead_xchacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :small_red_triangle: |
83| `crypto_auth` | :white_check_mark: | :small_red_triangle: |
84| `crypto_auth_BYTES` | :white_check_mark: | :small_red_triangle: |
85| `crypto_auth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
86| `crypto_auth_verify` | :white_check_mark: | :small_red_triangle: |
87| `crypto_box_BEFORENMBYTES` | :small_red_triangle: | :white_check_mark: |
88| `crypto_box_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
89| `crypto_box_detached` | :white_check_mark: | :small_red_triangle: |
90| `crypto_box_easy` | :white_check_mark: | :small_red_triangle: |
91| `crypto_box_keypair` | :white_check_mark: | :white_check_mark: |
92| `crypto_box_MACBYTES` | :white_check_mark: | :small_red_triangle: |
93| `crypto_box_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
94| `crypto_box_open_detached` | :white_check_mark: | :small_red_triangle: |
95| `crypto_box_open_easy` | :white_check_mark: | :small_red_triangle: |
96| `crypto_box_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
97| `crypto_box_seal` | :white_check_mark: | :white_check_mark: |
98| `crypto_box_seal_open` | :white_check_mark: | :white_check_mark: |
99| `crypto_box_SEALBYTES` | :white_check_mark: | :white_check_mark: |
100| `crypto_box_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
101| `crypto_box_seed_keypair` | :white_check_mark: | :white_check_mark: |
102| `crypto_box_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
103| `crypto_box_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
104| `crypto_core_ed25519_add` | :white_check_mark: | :small_red_triangle: |
105| `crypto_core_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
106| `crypto_core_ed25519_from_uniform` | :white_check_mark: | :small_red_triangle: |
107| `crypto_core_ed25519_is_valid_point` | :white_check_mark: | :small_red_triangle: |
108| `crypto_core_ed25519_NONREDUCEDSCALARBYTES` | :white_check_mark: | :small_red_triangle: |
109| `crypto_core_ed25519_scalar_add` | :white_check_mark: | :small_red_triangle: |
110| `crypto_core_ed25519_scalar_complement` | :white_check_mark: | :small_red_triangle: |
111| `crypto_core_ed25519_scalar_invert` | :white_check_mark: | :small_red_triangle: |
112| `crypto_core_ed25519_scalar_negate` | :white_check_mark: | :small_red_triangle: |
113| `crypto_core_ed25519_scalar_random` | :white_check_mark: | :small_red_triangle: |
114| `crypto_core_ed25519_scalar_reduce` | :white_check_mark: | :small_red_triangle: |
115| `crypto_core_ed25519_scalar_sub` | :white_check_mark: | :small_red_triangle: |
116| `crypto_core_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
117| `crypto_core_ed25519_sub` | :white_check_mark: | :small_red_triangle: |
118| `crypto_core_ed25519_UNIFORMBYTES` | :white_check_mark: | :small_red_triangle: |
119| `crypto_generichash` | :white_check_mark: | :white_check_mark: |
120| `crypto_generichash_BYTES` | :white_check_mark: | :white_check_mark: |
121| `crypto_generichash_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
122| `crypto_generichash_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
123| `crypto_generichash_final` | :white_check_mark: | :small_red_triangle: |
124| `crypto_generichash_init` | :white_check_mark: | :small_red_triangle: |
125| `crypto_generichash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
126| `crypto_generichash_KEYBYTES_MAX` | :white_check_mark: | :white_check_mark: |
127| `crypto_generichash_KEYBYTES_MIN` | :white_check_mark: | :white_check_mark: |
128| `crypto_generichash_keygen` | :white_check_mark: | :small_red_triangle: |
129| `crypto_generichash_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
130| `crypto_generichash_update` | :white_check_mark: | :small_red_triangle: |
131| `crypto_hash` | :white_check_mark: | :white_check_mark: |
132| `crypto_hash_BYTES` | :white_check_mark: | :white_check_mark: |
133| `crypto_hash_sha256` | :white_check_mark: | :white_check_mark: |
134| `crypto_hash_sha256_BYTES` | :white_check_mark: | :white_check_mark: |
135| `crypto_hash_sha256_final` | :white_check_mark: | :small_red_triangle: |
136| `crypto_hash_sha256_init` | :white_check_mark: | :small_red_triangle: |
137| `crypto_hash_sha256_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
138| `crypto_hash_sha256_update` | :white_check_mark: | :small_red_triangle: |
139| `crypto_hash_sha512` | :white_check_mark: | :white_check_mark: |
140| `crypto_hash_sha512_BYTES` | :white_check_mark: | :white_check_mark: |
141| `crypto_hash_sha512_final` | :white_check_mark: | :small_red_triangle: |
142| `crypto_hash_sha512_init` | :white_check_mark: | :small_red_triangle: |
143| `crypto_hash_sha512_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
144| `crypto_hash_sha512_update` | :white_check_mark: | :small_red_triangle: |
145| `crypto_kdf_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
146| `crypto_kdf_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
147| `crypto_kdf_CONTEXTBYTES` | :white_check_mark: | :white_check_mark: |
148| `crypto_kdf_derive_from_key` | :white_check_mark: | :white_check_mark: |
149| `crypto_kdf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
150| `crypto_kdf_keygen` | :white_check_mark: | :white_check_mark: |
151| `crypto_kx_client_session_keys` | :white_check_mark: | :small_red_triangle: |
152| `crypto_kx_keypair` | :white_check_mark: | :white_check_mark: |
153| `crypto_kx_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
154| `crypto_kx_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
155| `crypto_kx_seed_keypair` | :white_check_mark: | :white_check_mark: |
156| `crypto_kx_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
157| `crypto_kx_server_session_keys` | :white_check_mark: | :small_red_triangle: |
158| `crypto_kx_SESSIONKEYBYTES` | :white_check_mark: | :small_red_triangle: |
159| `crypto_onetimeauth` | :white_check_mark: | :white_check_mark: |
160| `crypto_onetimeauth_BYTES` | :white_check_mark: | :small_red_triangle: |
161| `crypto_onetimeauth_final` | :white_check_mark: | :small_red_triangle: |
162| `crypto_onetimeauth_init` | :white_check_mark: | :small_red_triangle: |
163| `crypto_onetimeauth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
164| `crypto_onetimeauth_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
165| `crypto_onetimeauth_update` | :white_check_mark: | :small_red_triangle: |
166| `crypto_onetimeauth_verify` | :white_check_mark: | :white_check_mark: |
167| `crypto_pwhash` | :white_check_mark: | :small_red_triangle: |
168| `crypto_pwhash_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
169| `crypto_pwhash_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
170| `crypto_pwhash_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
171| `crypto_pwhash_scryptsalsa208sha256` | :white_check_mark: | :small_red_triangle: |
172| `crypto_pwhash_scryptsalsa208sha256_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
173| `crypto_pwhash_scryptsalsa208sha256_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
174| `crypto_pwhash_scryptsalsa208sha256_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
175| `crypto_pwhash_scryptsalsa208sha256_str` | :white_check_mark: | :small_red_triangle: |
176| `crypto_pwhash_scryptsalsa208sha256_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
177| `crypto_pwhash_scryptsalsa208sha256_str_verify` | :white_check_mark: | :small_red_triangle: |
178| `crypto_pwhash_scryptsalsa208sha256_STRBYTES` | :white_check_mark: | :small_red_triangle: |
179| `crypto_pwhash_str` | :white_check_mark: | :small_red_triangle: |
180| `crypto_pwhash_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
181| `crypto_pwhash_str_verify` | :white_check_mark: | :small_red_triangle: |
182| `crypto_pwhash_STRBYTES` | :white_check_mark: | :small_red_triangle: |
183| `crypto_scalarmult` | :white_check_mark: | :white_check_mark: |
184| `crypto_scalarmult_base` | :white_check_mark: | :white_check_mark: |
185| `crypto_scalarmult_BYTES` | :white_check_mark: | :white_check_mark: |
186| `crypto_scalarmult_ed25519` | :white_check_mark: | :small_red_triangle: |
187| `crypto_scalarmult_ed25519_base` | :white_check_mark: | :small_red_triangle: |
188| `crypto_scalarmult_ed25519_base_noclamp` | :white_check_mark: | :small_red_triangle: |
189| `crypto_scalarmult_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
190| `crypto_scalarmult_ed25519_noclamp` | :white_check_mark: | :small_red_triangle: |
191| `crypto_scalarmult_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
192| `crypto_scalarmult_SCALARBYTES` | :white_check_mark: | :white_check_mark: |
193| `crypto_secretbox` | :small_red_triangle: | :white_check_mark: |
194| `crypto_secretbox_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
195| `crypto_secretbox_detached` | :white_check_mark: | :white_check_mark: |
196| `crypto_secretbox_easy` | :white_check_mark: | :white_check_mark: |
197| `crypto_secretbox_KEYBYTES` | :white_check_mark: | :white_check_mark: |
198| `crypto_secretbox_MACBYTES` | :white_check_mark: | :white_check_mark: |
199| `crypto_secretbox_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
200| `crypto_secretbox_open` | :small_red_triangle: | :white_check_mark: |
201| `crypto_secretbox_open_detached` | :white_check_mark: | :white_check_mark: |
202| `crypto_secretbox_open_easy` | :white_check_mark: | :white_check_mark: |
203| `crypto_secretbox_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
204| `crypto_secretstream_xchacha20poly1305_ABYTES` | :white_check_mark: | :small_red_triangle: |
205| `crypto_secretstream_xchacha20poly1305_HEADERBYTES` | :white_check_mark: | :small_red_triangle: |
206| `crypto_secretstream_xchacha20poly1305_init_pull` | :white_check_mark: | :small_red_triangle: |
207| `crypto_secretstream_xchacha20poly1305_init_push` | :white_check_mark: | :small_red_triangle: |
208| `crypto_secretstream_xchacha20poly1305_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
209| `crypto_secretstream_xchacha20poly1305_keygen` | :white_check_mark: | :small_red_triangle: |
210| `crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
211| `crypto_secretstream_xchacha20poly1305_pull` | :white_check_mark: | :small_red_triangle: |
212| `crypto_secretstream_xchacha20poly1305_push` | :white_check_mark: | :small_red_triangle: |
213| `crypto_secretstream_xchacha20poly1305_rekey` | :white_check_mark: | :small_red_triangle: |
214| `crypto_secretstream_xchacha20poly1305_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
215| `crypto_shorthash` | :white_check_mark: | :white_check_mark: |
216| `crypto_shorthash_BYTES` | :white_check_mark: | :white_check_mark: |
217| `crypto_shorthash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
218| `crypto_sign` | :white_check_mark: | :white_check_mark: |
219| `crypto_sign_BYTES` | :white_check_mark: | :white_check_mark: |
220| `crypto_sign_detached` | :white_check_mark: | :white_check_mark: |
221| `crypto_sign_ed25519_pk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
222| `crypto_sign_ed25519_sk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
223| `crypto_sign_ed25519_sk_to_pk` | :white_check_mark: | :small_red_triangle: |
224| `crypto_sign_keypair` | :white_check_mark: | :white_check_mark: |
225| `crypto_sign_open` | :white_check_mark: | :white_check_mark: |
226| `crypto_sign_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
227| `crypto_sign_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
228| `crypto_sign_seed_keypair` | :white_check_mark: | :white_check_mark: |
229| `crypto_sign_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
230| `crypto_sign_verify_detached` | :white_check_mark: | :white_check_mark: |
231| `crypto_stream` | :white_check_mark: | :white_check_mark: |
232| `crypto_stream_chacha20` | :white_check_mark: | :white_check_mark: |
233| `crypto_stream_chacha20_ietf` | :white_check_mark: | :white_check_mark: |
234| `crypto_stream_chacha20_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
235| `crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
236| `crypto_stream_chacha20_ietf_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
237| `crypto_stream_chacha20_ietf_xor` | :white_check_mark: | :white_check_mark: |
238| `crypto_stream_chacha20_ietf_xor_ic` | :white_check_mark: | :white_check_mark: |
239| `crypto_stream_chacha20_KEYBYTES` | :white_check_mark: | :white_check_mark: |
240| `crypto_stream_chacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
241| `crypto_stream_chacha20_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
242| `crypto_stream_chacha20_xor` | :white_check_mark: | :white_check_mark: |
243| `crypto_stream_chacha20_xor_ic` | :white_check_mark: | :white_check_mark: |
244| `crypto_stream_KEYBYTES` | :white_check_mark: | :white_check_mark: |
245| `crypto_stream_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
246| `crypto_stream_salsa20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
247| `crypto_stream_salsa20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
248| `crypto_stream_salsa20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
249| `crypto_stream_salsa20_xor` | :white_check_mark: | :small_red_triangle: |
250| `crypto_stream_salsa20_xor_ic` | :white_check_mark: | :small_red_triangle: |
251| `crypto_stream_xchacha20` | :white_check_mark: | :small_red_triangle: |
252| `crypto_stream_xchacha20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
253| `crypto_stream_xchacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
254| `crypto_stream_xchacha20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
255| `crypto_stream_xchacha20_xor` | :white_check_mark: | :small_red_triangle: |
256| `crypto_stream_xchacha20_xor_ic` | :white_check_mark: | :small_red_triangle: |
257| `crypto_stream_xor` | :white_check_mark: | :white_check_mark: |
258| `crypto_verify_16` | :small_red_triangle: | :white_check_mark: |
259| `crypto_verify_32` | :small_red_triangle: | :white_check_mark: |
260| `randombytes_buf` | :white_check_mark: | :white_check_mark: |
261| `randombytes_buf_deterministic` | :white_check_mark: | :small_red_triangle: |
262| `randombytes_random` | :white_check_mark: | :small_red_triangle: |
263| `randombytes_SEEDBYTES` | :white_check_mark: | :small_red_triangle: |
264| `randombytes_uniform` | :white_check_mark: | :small_red_triangle: |
265| `sodium_add` | :white_check_mark: | :small_red_triangle: |
266| `sodium_compare` | :white_check_mark: | :small_red_triangle: |
267| `sodium_free` | :white_check_mark: | :small_red_triangle: |
268| `sodium_increment` | :white_check_mark: | :small_red_triangle: |
269| `sodium_is_zero` | :white_check_mark: | :white_check_mark: |
270| `sodium_malloc` | :white_check_mark: | :white_check_mark: |
271| `sodium_memcmp` | :white_check_mark: | :white_check_mark: |
272| `sodium_memzero` | :white_check_mark: | :white_check_mark: |
273| `sodium_mlock` | :white_check_mark: | :small_red_triangle: |
274| `sodium_mprotect_noaccess` | :white_check_mark: | :small_red_triangle: |
275| `sodium_mprotect_readonly` | :white_check_mark: | :small_red_triangle: |
276| `sodium_mprotect_readwrite` | :white_check_mark: | :small_red_triangle: |
277| `sodium_munlock` | :white_check_mark: | :small_red_triangle: |
278| `sodium_pad` | :white_check_mark: | :small_red_triangle: |
279| `sodium_sub` | :white_check_mark: | :small_red_triangle: |
280| `sodium_unpad` | :white_check_mark: | :small_red_triangle: |
281
282### Missing altogether (Ctrl + F friendly)
283
284`crypto_aead_aes256gcm_ABYTES`, `crypto_aead_aes256gcm_beforenm`, `crypto_aead_aes256gcm_decrypt`, `crypto_aead_aes256gcm_decrypt_afternm`, `crypto_aead_aes256gcm_decrypt_detached`, `crypto_aead_aes256gcm_decrypt_detached_afternm`, `crypto_aead_aes256gcm_encrypt`, `crypto_aead_aes256gcm_encrypt_afternm`, `crypto_aead_aes256gcm_encrypt_detached`, `crypto_aead_aes256gcm_encrypt_detached_afternm`, `crypto_aead_aes256gcm_is_available`, `crypto_aead_aes256gcm_KEYBYTES`, `crypto_aead_aes256gcm_keygen`, `crypto_aead_aes256gcm_MESSAGEBYTES_MAX`, `crypto_aead_aes256gcm_NPUBBYTES`, `crypto_aead_aes256gcm_NSECBYTES`, `crypto_aead_aes256gcm_STATEBYTES`, `crypto_aead_chacha20poly1305_ABYTES`, `crypto_aead_chacha20poly1305_decrypt`, `crypto_aead_chacha20poly1305_decrypt_detached`, `crypto_aead_chacha20poly1305_encrypt`, `crypto_aead_chacha20poly1305_encrypt_detached`, `crypto_aead_chacha20poly1305_KEYBYTES`, `crypto_aead_chacha20poly1305_keygen`, `crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX`, `crypto_aead_chacha20poly1305_NPUBBYTES`, `crypto_aead_chacha20poly1305_NSECBYTES`, `crypto_auth_hmacsha256`, `crypto_auth_hmacsha256_BYTES`, `crypto_auth_hmacsha256_final`, `crypto_auth_hmacsha256_init`, `crypto_auth_hmacsha256_KEYBYTES`, `crypto_auth_hmacsha256_keygen`, `crypto_auth_hmacsha256_STATEBYTES`, `crypto_auth_hmacsha256_update`, `crypto_auth_hmacsha256_verify`, `crypto_auth_hmacsha512`, `crypto_auth_hmacsha512256`, `crypto_auth_hmacsha512256_BYTES`, `crypto_auth_hmacsha512256_final`, `crypto_auth_hmacsha512256_init`, `crypto_auth_hmacsha512256_KEYBYTES`, `crypto_auth_hmacsha512256_keygen`, `crypto_auth_hmacsha512256_STATEBYTES`, `crypto_auth_hmacsha512256_update`, `crypto_auth_hmacsha512256_verify`, `crypto_auth_hmacsha512_BYTES`, `crypto_auth_hmacsha512_final`, `crypto_auth_hmacsha512_init`, `crypto_auth_hmacsha512_KEYBYTES`, `crypto_auth_hmacsha512_keygen`, `crypto_auth_hmacsha512_STATEBYTES`, `crypto_auth_hmacsha512_update`, `crypto_auth_hmacsha512_verify`, `crypto_auth_keygen`, `crypto_auth_primitive`, `crypto_box`, `crypto_box_afternm`, `crypto_box_beforenm`, `crypto_box_curve25519xchacha20poly1305_beforenm`, `crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xchacha20poly1305_detached`, `crypto_box_curve25519xchacha20poly1305_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_easy`, `crypto_box_curve25519xchacha20poly1305_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_keypair`, `crypto_box_curve25519xchacha20poly1305_MACBYTES`, `crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xchacha20poly1305_NONCEBYTES`, `crypto_box_curve25519xchacha20poly1305_open_detached`, `crypto_box_curve25519xchacha20poly1305_open_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_open_easy`, `crypto_box_curve25519xchacha20poly1305_open_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seal`, `crypto_box_curve25519xchacha20poly1305_seal_open`, `crypto_box_curve25519xchacha20poly1305_SEALBYTES`, `crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seed_keypair`, `crypto_box_curve25519xchacha20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305`, `crypto_box_curve25519xsalsa20poly1305_afternm`, `crypto_box_curve25519xsalsa20poly1305_beforenm`, `crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES`, `crypto_box_curve25519xsalsa20poly1305_keypair`, `crypto_box_curve25519xsalsa20poly1305_MACBYTES`, `crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xsalsa20poly1305_NONCEBYTES`, `crypto_box_curve25519xsalsa20poly1305_open`, `crypto_box_curve25519xsalsa20poly1305_open_afternm`, `crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_seed_keypair`, `crypto_box_curve25519xsalsa20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305_ZEROBYTES`, `crypto_box_detached_afternm`, `crypto_box_easy_afternm`, `crypto_box_MESSAGEBYTES_MAX`, `crypto_box_open`, `crypto_box_open_afternm`, `crypto_box_open_detached_afternm`, `crypto_box_open_easy_afternm`, `crypto_box_primitive`, `crypto_core_ed25519_from_hash`, `crypto_core_ed25519_HASHBYTES`, `crypto_core_ed25519_random`, `crypto_core_ed25519_scalar_mul`, `crypto_core_hchacha20`, `crypto_core_hchacha20_CONSTBYTES`, `crypto_core_hchacha20_INPUTBYTES`, `crypto_core_hchacha20_KEYBYTES`, `crypto_core_hchacha20_OUTPUTBYTES`, `crypto_core_hsalsa20`, `crypto_core_hsalsa20_CONSTBYTES`, `crypto_core_hsalsa20_INPUTBYTES`, `crypto_core_hsalsa20_KEYBYTES`, `crypto_core_hsalsa20_OUTPUTBYTES`, `crypto_core_ristretto255_add`, `crypto_core_ristretto255_BYTES`, `crypto_core_ristretto255_from_hash`, `crypto_core_ristretto255_HASHBYTES`, `crypto_core_ristretto255_is_valid_point`, `crypto_core_ristretto255_NONREDUCEDSCALARBYTES`, `crypto_core_ristretto255_random`, `crypto_core_ristretto255_scalar_add`, `crypto_core_ristretto255_scalar_complement`, `crypto_core_ristretto255_scalar_invert`, `crypto_core_ristretto255_scalar_mul`, `crypto_core_ristretto255_scalar_negate`, `crypto_core_ristretto255_scalar_random`, `crypto_core_ristretto255_scalar_reduce`, `crypto_core_ristretto255_scalar_sub`, `crypto_core_ristretto255_SCALARBYTES`, `crypto_core_ristretto255_sub`, `crypto_core_salsa20`, `crypto_core_salsa2012`, `crypto_core_salsa2012_CONSTBYTES`, `crypto_core_salsa2012_INPUTBYTES`, `crypto_core_salsa2012_KEYBYTES`, `crypto_core_salsa2012_OUTPUTBYTES`, `crypto_core_salsa208`, `crypto_core_salsa208_CONSTBYTES`, `crypto_core_salsa208_INPUTBYTES`, `crypto_core_salsa208_KEYBYTES`, `crypto_core_salsa208_OUTPUTBYTES`, `crypto_core_salsa20_CONSTBYTES`, `crypto_core_salsa20_INPUTBYTES`, `crypto_core_salsa20_KEYBYTES`, `crypto_core_salsa20_OUTPUTBYTES`, `crypto_generichash_blake2b`, `crypto_generichash_blake2b_BYTES`, `crypto_generichash_blake2b_BYTES_MAX`, `crypto_generichash_blake2b_BYTES_MIN`, `crypto_generichash_blake2b_final`, `crypto_generichash_blake2b_init`, `crypto_generichash_blake2b_init_salt_personal`, `crypto_generichash_blake2b_KEYBYTES`, `crypto_generichash_blake2b_KEYBYTES_MAX`, `crypto_generichash_blake2b_KEYBYTES_MIN`, `crypto_generichash_blake2b_keygen`, `crypto_generichash_blake2b_PERSONALBYTES`, `crypto_generichash_blake2b_salt_personal`, `crypto_generichash_blake2b_SALTBYTES`, `crypto_generichash_blake2b_STATEBYTES`, `crypto_generichash_blake2b_update`, `crypto_generichash_primitive`, `crypto_hash_primitive`, `crypto_kdf_blake2b_BYTES_MAX`, `crypto_kdf_blake2b_BYTES_MIN`, `crypto_kdf_blake2b_CONTEXTBYTES`, `crypto_kdf_blake2b_derive_from_key`, `crypto_kdf_blake2b_KEYBYTES`, `crypto_kdf_primitive`, `crypto_kx_primitive`, `crypto_onetimeauth_keygen`, `crypto_onetimeauth_poly1305`, `crypto_onetimeauth_poly1305_BYTES`, `crypto_onetimeauth_poly1305_final`, `crypto_onetimeauth_poly1305_init`, `crypto_onetimeauth_poly1305_KEYBYTES`, `crypto_onetimeauth_poly1305_keygen`, `crypto_onetimeauth_poly1305_STATEBYTES`, `crypto_onetimeauth_poly1305_update`, `crypto_onetimeauth_poly1305_verify`, `crypto_onetimeauth_primitive`, `crypto_pwhash_alg_argon2i13`, `crypto_pwhash_alg_argon2id13`, `crypto_pwhash_alg_default`, `crypto_pwhash_argon2i`, `crypto_pwhash_argon2i_alg_argon2i13`, `crypto_pwhash_argon2i_BYTES_MAX`, `crypto_pwhash_argon2i_BYTES_MIN`, `crypto_pwhash_argon2i_memlimit_interactive`, `crypto_pwhash_argon2i_memlimit_max`, `crypto_pwhash_argon2i_memlimit_min`, `crypto_pwhash_argon2i_memlimit_moderate`, `crypto_pwhash_argon2i_memlimit_sensitive`, `crypto_pwhash_argon2i_opslimit_interactive`, `crypto_pwhash_argon2i_opslimit_max`, `crypto_pwhash_argon2i_opslimit_min`, `crypto_pwhash_argon2i_opslimit_moderate`, `crypto_pwhash_argon2i_opslimit_sensitive`, `crypto_pwhash_argon2i_passwd_max`, `crypto_pwhash_argon2i_passwd_min`, `crypto_pwhash_argon2i_SALTBYTES`, `crypto_pwhash_argon2i_str`, `crypto_pwhash_argon2i_str_needs_rehash`, `crypto_pwhash_argon2i_str_verify`, `crypto_pwhash_argon2i_STRBYTES`, `crypto_pwhash_argon2i_strprefix`, `crypto_pwhash_argon2id`, `crypto_pwhash_argon2id_alg_argon2id13`, `crypto_pwhash_argon2id_BYTES_MAX`, `crypto_pwhash_argon2id_BYTES_MIN`, `crypto_pwhash_argon2id_memlimit_interactive`, `crypto_pwhash_argon2id_memlimit_max`, `crypto_pwhash_argon2id_memlimit_min`, `crypto_pwhash_argon2id_memlimit_moderate`, `crypto_pwhash_argon2id_memlimit_sensitive`, `crypto_pwhash_argon2id_opslimit_interactive`, `crypto_pwhash_argon2id_opslimit_max`, `crypto_pwhash_argon2id_opslimit_min`, `crypto_pwhash_argon2id_opslimit_moderate`, `crypto_pwhash_argon2id_opslimit_sensitive`, `crypto_pwhash_argon2id_passwd_max`, `crypto_pwhash_argon2id_passwd_min`, `crypto_pwhash_argon2id_SALTBYTES`, `crypto_pwhash_argon2id_str`, `crypto_pwhash_argon2id_str_needs_rehash`, `crypto_pwhash_argon2id_str_verify`, `crypto_pwhash_argon2id_STRBYTES`, `crypto_pwhash_argon2id_strprefix`, `crypto_pwhash_memlimit_interactive`, `crypto_pwhash_memlimit_max`, `crypto_pwhash_memlimit_min`, `crypto_pwhash_memlimit_moderate`, `crypto_pwhash_memlimit_sensitive`, `crypto_pwhash_opslimit_interactive`, `crypto_pwhash_opslimit_max`, `crypto_pwhash_opslimit_min`, `crypto_pwhash_opslimit_moderate`, `crypto_pwhash_opslimit_sensitive`, `crypto_pwhash_passwd_max`, `crypto_pwhash_passwd_min`, `crypto_pwhash_primitive`, `crypto_pwhash_scryptsalsa208sha256_ll`, `crypto_pwhash_scryptsalsa208sha256_memlimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_memlimit_max`, `crypto_pwhash_scryptsalsa208sha256_memlimit_min`, `crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_max`, `crypto_pwhash_scryptsalsa208sha256_opslimit_min`, `crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_passwd_max`, `crypto_pwhash_scryptsalsa208sha256_passwd_min`, `crypto_pwhash_scryptsalsa208sha256_strprefix`, `crypto_pwhash_str_alg`, `crypto_pwhash_strprefix`, `crypto_scalarmult_curve25519`, `crypto_scalarmult_curve25519_base`, `crypto_scalarmult_curve25519_BYTES`, `crypto_scalarmult_curve25519_SCALARBYTES`, `crypto_scalarmult_primitive`, `crypto_scalarmult_ristretto255`, `crypto_scalarmult_ristretto255_base`, `crypto_scalarmult_ristretto255_BYTES`, `crypto_scalarmult_ristretto255_SCALARBYTES`, `crypto_secretbox_keygen`, `crypto_secretbox_MESSAGEBYTES_MAX`, `crypto_secretbox_primitive`, `crypto_secretbox_xchacha20poly1305_detached`, `crypto_secretbox_xchacha20poly1305_easy`, `crypto_secretbox_xchacha20poly1305_KEYBYTES`, `crypto_secretbox_xchacha20poly1305_MACBYTES`, `crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xchacha20poly1305_NONCEBYTES`, `crypto_secretbox_xchacha20poly1305_open_detached`, `crypto_secretbox_xchacha20poly1305_open_easy`, `crypto_secretbox_xsalsa20poly1305`, `crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES`, `crypto_secretbox_xsalsa20poly1305_KEYBYTES`, `crypto_secretbox_xsalsa20poly1305_keygen`, `crypto_secretbox_xsalsa20poly1305_MACBYTES`, `crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xsalsa20poly1305_NONCEBYTES`, `crypto_secretbox_xsalsa20poly1305_open`, `crypto_secretbox_xsalsa20poly1305_ZEROBYTES`, `crypto_secretstream_xchacha20poly1305_tag_final`, `crypto_secretstream_xchacha20poly1305_tag_message`, `crypto_secretstream_xchacha20poly1305_tag_push`, `crypto_secretstream_xchacha20poly1305_tag_rekey`, `crypto_shorthash_keygen`, `crypto_shorthash_primitive`, `crypto_shorthash_siphash24`, `crypto_shorthash_siphash24_BYTES`, `crypto_shorthash_siphash24_KEYBYTES`, `crypto_shorthash_siphashx24`, `crypto_shorthash_siphashx24_BYTES`, `crypto_shorthash_siphashx24_KEYBYTES`, `crypto_sign_ed25519`, `crypto_sign_ed25519_BYTES`, `crypto_sign_ed25519_detached`, `crypto_sign_ed25519_keypair`, `crypto_sign_ed25519_MESSAGEBYTES_MAX`, `crypto_sign_ed25519_open`, `crypto_sign_ed25519_PUBLICKEYBYTES`, `crypto_sign_ed25519_SECRETKEYBYTES`, `crypto_sign_ed25519_seed_keypair`, `crypto_sign_ed25519_SEEDBYTES`, `crypto_sign_ed25519_sk_to_seed`, `crypto_sign_ed25519_verify_detached`, `crypto_sign_ed25519ph_final_create`, `crypto_sign_ed25519ph_final_verify`, `crypto_sign_ed25519ph_init`, `crypto_sign_ed25519ph_STATEBYTES`, `crypto_sign_ed25519ph_update`, `crypto_sign_edwards25519sha512batch`, `crypto_sign_edwards25519sha512batch_keypair`, `crypto_sign_edwards25519sha512batch_open`, `crypto_sign_final_create`, `crypto_sign_final_verify`, `crypto_sign_init`, `crypto_sign_MESSAGEBYTES_MAX`, `crypto_sign_primitive`, `crypto_sign_STATEBYTES`, `crypto_sign_update`, `crypto_stream_chacha20_ietf_keygen`, `crypto_stream_chacha20_keygen`, `crypto_stream_keygen`, `crypto_stream_MESSAGEBYTES_MAX`, `crypto_stream_primitive`, `crypto_stream_salsa20`, `crypto_stream_salsa2012`, `crypto_stream_salsa2012_KEYBYTES`, `crypto_stream_salsa2012_keygen`, `crypto_stream_salsa2012_MESSAGEBYTES_MAX`, `crypto_stream_salsa2012_NONCEBYTES`, `crypto_stream_salsa2012_xor`, `crypto_stream_salsa208`, `crypto_stream_salsa208_KEYBYTES`, `crypto_stream_salsa208_keygen`, `crypto_stream_salsa208_MESSAGEBYTES_MAX`, `crypto_stream_salsa208_NONCEBYTES`, `crypto_stream_salsa208_xor`, `crypto_stream_salsa20_keygen`, `crypto_stream_xchacha20_keygen`, `crypto_stream_xsalsa20`, `crypto_stream_xsalsa20_KEYBYTES`, `crypto_stream_xsalsa20_keygen`, `crypto_stream_xsalsa20_MESSAGEBYTES_MAX`, `crypto_stream_xsalsa20_NONCEBYTES`, `crypto_stream_xsalsa20_xor`, `crypto_stream_xsalsa20_xor_ic`, `crypto_verify_16_BYTES`, `crypto_verify_32_BYTES`, `crypto_verify_64`, `crypto_verify_64_BYTES`, `randombytes`, `randombytes_close`, `randombytes_implementation_name`, `randombytes_internal_implementation`, `randombytes_set_implementation`, `randombytes_stir`, `randombytes_sysrandom_implementation`, `sodium_allocarray`, `sodium_base642bin`, `sodium_base64_encoded_len`, `sodium_bin2base64`, `sodium_bin2hex`, `sodium_hex2bin`, `sodium_init`, `sodium_library_minimal`, `sodium_library_version_major`, `sodium_library_version_minor`, `sodium_misuse`, `sodium_runtime_has_aesni`, `sodium_runtime_has_avx`, `sodium_runtime_has_avx2`, `sodium_runtime_has_avx512f`, `sodium_runtime_has_neon`, `sodium_runtime_has_pclmul`, `sodium_runtime_has_rdrand`, `sodium_runtime_has_sse2`, `sodium_runtime_has_sse3`, `sodium_runtime_has_sse41`, `sodium_runtime_has_ssse3`, `sodium_set_misuse_handler`, `sodium_stackzero`, `sodium_version_string`
285
286## License
287
288[MIT](LICENSE.md)
node_modules/hypercore-crypto/node_modules/sodium-universal/build-scripts/generate.js +33 -0
……@@ -0,0 +1,33 @@
1#!/usr/bin/env node
2
3const fs = require('fs')
4const path = require('path')
5const root = path.dirname(require.resolve('sodium-javascript/package.json'))
6
7const tmp = "module.exports = require('sodium-native')\n"
8
9function recurse (dir) {
10 const ls = fs.readdirSync(dir)
11 const subdir = path.relative(root, dir)
12 if (subdir) fs.mkdirSync(subdir, { recursive: true })
13
14 for (const file of ls) {
15 if (file === 'internal') recurse(path.join(dir, file))
16 if (!/\.js$/i.test(file)) continue
17 if (file === 'example.js') continue
18 if (file === 'test.js') continue
19
20 fs.writeFileSync(path.join(__dirname, '..', subdir, file), tmp)
21 }
22}
23
24recurse(root)
25
26const pkg = require('sodium-javascript/package.json')
27const myPkg = require('../package.json')
28
29for (const key of Object.keys(pkg.dependencies)) {
30 myPkg.dependencies[key] = pkg.dependencies[key]
31}
32
33fs.writeFileSync(path.join(__dirname, '../package.json'), JSON.stringify(myPkg, null, 2) + '\n')
node_modules/hypercore-crypto/node_modules/sodium-universal/build-scripts/symbols.js +32 -0
……@@ -0,0 +1,32 @@
1var exec = require('child_process').execSync
2var path = require('path')
3
4var symbols = exec(`nm -gU "${path.join(require.resolve('sodium-native'), '../prebuilds/darwin-x64/libsodium.dylib')}"`).toString().trim().split('\n')
5var native = new Set(Object.keys(require('sodium-native')).sort())
6var js = new Set(Object.keys(require('sodium-javascript')).sort())
7
8symbols = symbols.map(l => l.split(' ').pop().replace(/^_/, '').replace(/_[^_]*bytes.*/, (s) => s.toUpperCase()))
9
10var missing = []
11
12console.log(`
13<!-- Generated by build-scripts/symbols.js with
14 sodium-native@${require('sodium-native/package.json').version}
15 sodium-javascript@${require('sodium-javascript/package.json').version} -->\
16`)
17
18const max = symbols.filter(s => native.has(s) || js.has(s)).map(s => s.length).reduce((a, b) => Math.max(a, b))
19const lines = ':-' + ''.padEnd(max, '--') + '-:'
20const center = s => s.padStart(Math.floor((max + s.length) / 2), ' ').padEnd(max, ' ')
21
22console.log(`| ${center('C Library Symbol')} | \`sodium-native\` | \`sodium-javascript\` |`)
23console.log(`|${lines}|:--------------------:|:--------------------:|`)
24
25for (var i = 0; i < symbols.length; i++) {
26 var s = symbols[i]
27 if (!(native.has(s) || js.has(s))) missing.push(s)
28 else console.log(`| \`${(s + '`').padEnd(max + 1, ' ')} | ${native.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} | ${js.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} |`)
29}
30
31console.log('\n### Missing altogether (Ctrl + F friendly)\n')
32console.log(missing.map(s => '`' + s + '`').join(', '))
node_modules/hypercore-crypto/node_modules/sodium-universal/build-scripts/transform.js +26 -0
……@@ -0,0 +1,26 @@
1const fs = require('fs')
2const path = require('path')
3const { Transform, PassThrough } = require('stream')
4
5module.exports = function (file, opts) {
6 const basedir = path.resolve(__dirname, '..')
7 const relname = path.relative(basedir, file)
8
9 if (opts._flags.browserField === false) {
10 return new PassThrough()
11 }
12
13 return new Transform({
14 transform (data, enc, cb) {
15 cb()
16 },
17 flush (cb) {
18 const filename = require.resolve('sodium-javascript/' + relname)
19 fs.readFile(filename, (err, buf) => {
20 if (err) return cb(err)
21 this.push(buf)
22 cb(null)
23 })
24 }
25 })
26}
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_aead.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_auth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_box.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_generichash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_hash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_hash_sha256.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_kdf.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_kx.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_onetimeauth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_scalarmult.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_secretbox.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_secretstream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_shorthash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_sign.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_stream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_stream_chacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/crypto_verify.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/helpers.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/index.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/internal/ed25519.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/internal/hchacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/internal/poly1305.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/memory.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/node_modules/sodium-universal/package.json +49 -0
……@@ -0,0 +1,49 @@
1{
2 "name": "sodium-universal",
3 "version": "5.0.1",
4 "description": "Universal wrapper for sodium-javascript and sodium-native working in Node.js and the Browser",
5 "main": "index.js",
6 "dependencies": {
7 "sodium-native": "^5.0.1"
8 },
9 "peerDependencies": {
10 "sodium-javascript": "~0.8.0"
11 },
12 "peerDependenciesMeta": {
13 "sodium-javascript": {
14 "optional": true
15 }
16 },
17 "scripts": {
18 "prepublish": "./build-scripts/generate.js"
19 },
20 "browser": {
21 "sodium-native": "sodium-javascript"
22 },
23 "browserify": {
24 "transform": [
25 "./build-scripts/transform.js"
26 ]
27 },
28 "repository": {
29 "type": "git",
30 "url": "git+https://github.com/holepunchto/sodium-universal.git"
31 },
32 "keywords": [
33 "libsodium",
34 "sodium",
35 "sodium-native",
36 "sodium-javascript",
37 "browserify"
38 ],
39 "contributors": [
40 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
41 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
42 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
43 ],
44 "license": "MIT",
45 "bugs": {
46 "url": "https://github.com/holepunchto/sodium-universal/issues"
47 },
48 "homepage": "https://github.com/holepunchto/sodium-universal#readme"
49}
node_modules/hypercore-crypto/node_modules/sodium-universal/randombytes.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/hypercore-crypto/package.json +31 -0
……@@ -0,0 +1,31 @@
1{
2 "name": "hypercore-crypto",
3 "version": "3.6.1",
4 "description": "The crypto primitives used in hypercore, extracted into a separate module",
5 "main": "index.js",
6 "files": [
7 "index.js"
8 ],
9 "dependencies": {
10 "b4a": "^1.6.6",
11 "compact-encoding": "^2.15.0",
12 "sodium-universal": "^5.0.0"
13 },
14 "devDependencies": {
15 "brittle": "^3.5.0",
16 "standard": "^17.1.0"
17 },
18 "scripts": {
19 "test": "standard && brittle test.js"
20 },
21 "repository": {
22 "type": "git",
23 "url": "https://github.com/mafintosh/hypercore-crypto.git"
24 },
25 "author": "Mathias Buus (@mafintosh)",
26 "license": "MIT",
27 "bugs": {
28 "url": "https://github.com/mafintosh/hypercore-crypto/issues"
29 },
30 "homepage": "https://github.com/mafintosh/hypercore-crypto"
31}
node_modules/hypercore-errors/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/hypercore-errors/README.md +43 -0
……@@ -0,0 +1,43 @@
1# hypercore-errors
2
3Hypercore errors
4
5```
6npm i hypercore-errors
7```
8
9## Usage
10
11```js
12const { BLOCK_NOT_AVAILABLE } = require('hypercore-errors')
13
14throw BLOCK_NOT_AVAILABLE()
15```
16
17## List
18
19- BAD_ARGUMENT
20- STORAGE_EMPTY
21- STORAGE_CONFLICT
22- INVALID_SIGNATURE
23- INVALID_CAPABILITY
24- INVALID_CHECKSUM
25- INVALID_OPERATION
26- INVALID_PROOF
27- BLOCK_NOT_AVAILABLE
28- SNAPSHOT_NOT_AVAILABLE
29- REQUEST_CANCELLED
30- REQUEST_TIMEOUT
31- SESSION_NOT_WRITABLE
32- SESSION_CLOSED
33- BATCH_UNFLUSHED
34- BATCH_ALREADY_EXISTS
35- BATCH_ALREADY_FLUSHED
36- OPLOG_CORRUPT
37- OPLOG_HEADER_OVERFLOW
38- INVALID_OPLOG_VERSION
39- WRITE_FAILED
40
41## License
42
43Apache-2.0
node_modules/hypercore-errors/index.js +115 -0
……@@ -0,0 +1,115 @@
1const IdEnc = require('hypercore-id-encoding')
2
3module.exports = class HypercoreError extends Error {
4 constructor (msg, code, fn = HypercoreError, discoveryKey = null) {
5 if (discoveryKey) msg = `${msg} (discovery key: ${IdEnc.normalize(discoveryKey)})`
6 super(`${code}: ${msg}`)
7
8 this.code = code
9 this.discoveryKey = discoveryKey
10
11 if (Error.captureStackTrace) {
12 Error.captureStackTrace(this, fn)
13 }
14 }
15
16 get name () {
17 return 'HypercoreError'
18 }
19
20 static ASSERTION (msg, discoveryKey = null) { // ERR_ASSERTION is picked up by safety-catch also
21 return new HypercoreError(msg, 'ERR_ASSERTION', HypercoreError.ASSERT, discoveryKey)
22 }
23
24 static BAD_ARGUMENT (msg, discoveryKey = null) {
25 return new HypercoreError(msg, 'BAD_ARGUMENT', HypercoreError.BAD_ARGUMENT, discoveryKey)
26 }
27
28 static STORAGE_EMPTY (msg, discoveryKey = null) {
29 return new HypercoreError(msg, 'STORAGE_EMPTY', HypercoreError.STORAGE_EMPTY, discoveryKey)
30 }
31
32 static STORAGE_CONFLICT (msg, discoveryKey = null) {
33 return new HypercoreError(msg, 'STORAGE_CONFLICT', HypercoreError.STORAGE_CONFLICT, discoveryKey)
34 }
35
36 static INVALID_SIGNATURE (msg, discoveryKey = null) {
37 return new HypercoreError(msg, 'INVALID_SIGNATURE', HypercoreError.INVALID_SIGNATURE, discoveryKey)
38 }
39
40 static INVALID_CAPABILITY (msg, discoveryKey = null) {
41 return new HypercoreError(msg, 'INVALID_CAPABILITY', HypercoreError.INVALID_CAPABILITY, discoveryKey)
42 }
43
44 static INVALID_CHECKSUM (msg = 'Invalid checksum', discoveryKey = null) {
45 return new HypercoreError(msg, 'INVALID_CHECKSUM', HypercoreError.INVALID_CHECKSUM, discoveryKey)
46 }
47
48 static INVALID_OPERATION (msg, discoveryKey = null) {
49 return new HypercoreError(msg, 'INVALID_OPERATION', HypercoreError.INVALID_OPERATION, discoveryKey)
50 }
51
52 static INVALID_PROOF (msg = 'Proof not verifiable', discoveryKey = null) {
53 return new HypercoreError(msg, 'INVALID_PROOF', HypercoreError.INVALID_PROOF, discoveryKey)
54 }
55
56 static BLOCK_NOT_AVAILABLE (msg = 'Block is not available', discoveryKey = null) {
57 return new HypercoreError(msg, 'BLOCK_NOT_AVAILABLE', HypercoreError.BLOCK_NOT_AVAILABLE, discoveryKey)
58 }
59
60 static SNAPSHOT_NOT_AVAILABLE (msg = 'Snapshot is not available', discoveryKey = null) {
61 return new HypercoreError(msg, 'SNAPSHOT_NOT_AVAILABLE', HypercoreError.SNAPSHOT_NOT_AVAILABLE, discoveryKey)
62 }
63
64 static REQUEST_CANCELLED (msg = 'Request was cancelled', discoveryKey = null) {
65 return new HypercoreError(msg, 'REQUEST_CANCELLED', HypercoreError.REQUEST_CANCELLED, discoveryKey)
66 }
67
68 static REQUEST_TIMEOUT (msg = 'Request timed out', discoveryKey = null) {
69 return new HypercoreError(msg, 'REQUEST_TIMEOUT', HypercoreError.REQUEST_TIMEOUT, discoveryKey)
70 }
71
72 static SESSION_NOT_WRITABLE (msg = 'Session is not writable', discoveryKey = null) {
73 return new HypercoreError(msg, 'SESSION_NOT_WRITABLE', HypercoreError.SESSION_NOT_WRITABLE, discoveryKey)
74 }
75
76 static SESSION_CLOSED (msg = 'Session is closed', discoveryKey = null) {
77 return new HypercoreError(msg, 'SESSION_CLOSED', HypercoreError.SESSION_CLOSED, discoveryKey)
78 }
79
80 static BATCH_UNFLUSHED (msg = 'Batch not yet flushed', discoveryKey = null) {
81 return new HypercoreError(msg, 'BATCH_UNFLUSHED', HypercoreError.BATCH_UNFLUSHED, discoveryKey)
82 }
83
84 static BATCH_ALREADY_EXISTS (msg = 'Batch already exists', discoveryKey = null) {
85 return new HypercoreError(msg, 'BATCH_ALREADY_EXISTS', HypercoreError.BATCH_ALREADY_EXISTS, discoveryKey)
86 }
87
88 static BATCH_ALREADY_FLUSHED (msg = 'Batch has already been flushed', discoveryKey = null) {
89 return new HypercoreError(msg, 'BATCH_ALREADY_FLUSHED', HypercoreError.BATCH_ALREADY_FLUSHED, discoveryKey)
90 }
91
92 static OPLOG_CORRUPT (msg = 'Oplog file appears corrupt or out of date', discoveryKey = null) {
93 return new HypercoreError(msg, 'OPLOG_CORRUPT', HypercoreError.OPLOG_CORRUPT, discoveryKey)
94 }
95
96 static OPLOG_HEADER_OVERFLOW (msg = 'Oplog header exceeds page size', discoveryKey = null) {
97 return new HypercoreError(msg, 'OPLOG_HEADER_OVERFLOW', HypercoreError.OPLOG_HEADER_OVERFLOW, discoveryKey)
98 }
99
100 static INVALID_OPLOG_VERSION (msg = 'Invalid header version', discoveryKey = null) {
101 return new HypercoreError(msg, 'INVALID_OPLOG_VERSION', HypercoreError.INVALID_OPLOG_VERSION, discoveryKey)
102 }
103
104 static WRITE_FAILED (msg = 'Write to storage failed', discoveryKey = null) {
105 return new HypercoreError(msg, 'WRITE_FAILED', HypercoreError.WRITE_FAILED, discoveryKey)
106 }
107
108 static DECODING_ERROR (msg = 'Decoding error', discoveryKey = null) {
109 return new HypercoreError(msg, 'DECODING_ERROR', HypercoreError.DECODING_ERROR, discoveryKey)
110 }
111
112 static SESSION_MOVED (msg = 'Session moved', discoveryKey = null) {
113 return new HypercoreError(msg, 'SESSION_MOVED', HypercoreError.SESSION_MOVED, discoveryKey)
114 }
115}
node_modules/hypercore-errors/package.json +30 -0
……@@ -0,0 +1,30 @@
1{
2 "name": "hypercore-errors",
3 "version": "1.5.0",
4 "description": "Hypercore errors",
5 "main": "index.js",
6 "files": [
7 "index.js"
8 ],
9 "scripts": {
10 "test": "standard && brittle test.js"
11 },
12 "repository": {
13 "type": "git",
14 "url": "https://github.com/holepunchto/hypercore-errors.git"
15 },
16 "author": "Holepunch",
17 "license": "Apache-2.0",
18 "bugs": {
19 "url": "https://github.com/holepunchto/hypercore-errors/issues"
20 },
21 "homepage": "https://github.com/holepunchto/hypercore-errors#readme",
22 "devDependencies": {
23 "b4a": "^1.6.7",
24 "brittle": "^3.1.3",
25 "standard": "^17.0.0"
26 },
27 "dependencies": {
28 "hypercore-id-encoding": "^1.3.0"
29 }
30}
node_modules/hypercore-id-encoding/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/hypercore-id-encoding/README.md +55 -0
……@@ -0,0 +1,55 @@
1# hypercore-id-encoding
2
3Encodes Hypercore keys into z-base32 ids, and decodes both hex/z-base32 strings.
4
5```
6npm install hypercore-id-encoding
7```
8
9## Usage
10
11```js
12const { encode, decode, normalize } = require('hypercore-id-encoding')
13
14const id = encode(core.key) // (z-base32 String)
15const hexEncoded = core.key.toString('hex')
16
17const core = new Hypercore(ram, decode(id))
18const core2 = new Hypercore(ram, decode(hexEncoded)) // Will also work with hex
19
20const id2 = normalize(id)
21const id3 = normalize(hexEncoded)
22```
23
24## API
25
26#### `const id = encode(hypercoreKey)`
27
28Encodes a 32-byte Hypercore key into a z-base32 id.
29
30`hypercoreKey` must be a Buffer or an ArrayBuffer.
31
32#### `const buf = decode(hypercoreId)`
33
34Decodes an id or pear link into a Hypercore key.
35
36If `hypercoreId` is a 52-character String, it will be decoded as z-base32.
37
38If `hypercoreId` is a 64-character String, it will be decoded as hex.
39
40If `hypercoreId` is already a Buffer and is a valid id, it will be returned as-is.
41
42#### `const id = normalize(any)`
43
44Decodes and encodes the input `any` to always return a z-base32 id.
45
46#### `isValid(any)`
47
48Returns a boolean indicating whether the key is a valid hypercore key (meaning that it can be decoded/normalised).
49
50## License
51
52Apache-2.0
53
54
55
node_modules/hypercore-id-encoding/index.js +44 -0
……@@ -0,0 +1,44 @@
1const z32 = require('z32')
2const b4a = require('b4a')
3
4module.exports = {
5 encode,
6 decode,
7 normalize,
8 isValid
9}
10
11function encode (key) {
12 if (!b4a.isBuffer(key)) throw new Error('Key must be a Buffer')
13 if (key.byteLength !== 32) throw new Error('Key must be 32-bytes long')
14 return z32.encode(key)
15}
16
17function decode (id) {
18 if (b4a.isBuffer(id)) {
19 if (id.byteLength !== 32) throw new Error('ID must be 32-bytes long')
20 return id
21 }
22 if (typeof id === 'string') {
23 if (id.startsWith('pear://')) id = id.slice(7).split('/')[0]
24 if (id.length === 52) return z32.decode(id)
25 if (id.length === 64) {
26 const buf = b4a.from(id, 'hex')
27 if (buf.byteLength === 32) return buf
28 }
29 }
30 throw new Error('Invalid Hypercore key')
31}
32
33function normalize (any) {
34 return encode(decode(any))
35}
36
37function isValid (any) {
38 try {
39 decode(any)
40 return true
41 } catch {
42 return false
43 }
44}
node_modules/hypercore-id-encoding/package.json +33 -0
……@@ -0,0 +1,33 @@
1{
2 "name": "hypercore-id-encoding",
3 "version": "1.3.0",
4 "description": "Convert Hypercore keys to/from z-base32 or hex",
5 "main": "index.js",
6 "scripts": {
7 "test": "standard && brittle test.js"
8 },
9 "files": [
10 "index.js"
11 ],
12 "dependencies": {
13 "b4a": "^1.5.3",
14 "z32": "^1.0.0"
15 },
16 "devDependencies": {
17 "brittle": "^3.1.1",
18 "hypercore": "^10.0.0",
19 "random-access-memory": "^6.0.0",
20 "standard": "^17.1.0"
21 },
22 "license": "Apache-2.0",
23 "repository": {
24 "type": "git",
25 "url": "git+https://github.com/holepunchto/hypercore-id-encoding.git"
26 },
27 "keywords": [],
28 "author": "",
29 "bugs": {
30 "url": "https://github.com/holepunchto/hypercore-id-encoding/issues"
31 },
32 "homepage": "https://github.com/holepunchto/hypercore-id-encoding#readme"
33}
node_modules/hypercore/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2016 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/hypercore/README.md +488 -0
……@@ -0,0 +1,488 @@
1# Hypercore
2
3### [See the full API docs at docs.pears.com](https://docs.pears.com/building-blocks/hypercore)
4
5Hypercore is a secure, distributed append-only log.
6
7Built for sharing large datasets and streams of real time data
8
9## Features
10
11* **Sparse replication.** Only download the data you are interested in.
12* **Realtime.** Get the latest updates to the log fast and securely.
13* **Performant.** Uses a simple flat file structure to maximize I/O performance.
14* **Secure.** Uses signed merkle trees to verify log integrity in real time.
15* **Modular.** Hypercore aims to do one thing and one thing well - distributing a stream of data.
16
17Note that the latest release is Hypercore 10, which adds support for truncate and many other things.
18Version 10 is not compatible with earlier versions (9 and earlier), but is considered LTS, meaning the storage format and wire protocol is forward compatible with future versions.
19
20## Install
21
22```sh
23npm install hypercore
24```
25
26## API
27
28#### `const core = new Hypercore(storage, [key], [options])`
29
30Make a new Hypercore instance.
31
32`storage` should be set to a directory where you want to store the data and core metadata.
33
34``` js
35const core = new Hypercore('./directory') // store data in ./directory
36```
37
38Alternatively you can pass a function instead that is called with every filename Hypercore needs to function and return your own [abstract-random-access](https://github.com/random-access-storage/abstract-random-access) instance that is used to store the data.
39
40``` js
41const RAM = require('random-access-memory')
42const core = new Hypercore((filename) => {
43 // filename will be one of: data, bitfield, tree, signatures, key, secret_key
44 // the data file will contain all your data concatenated.
45
46 // just store all files in ram by returning a random-access-memory instance
47 return new RAM()
48})
49```
50
51Per default Hypercore uses [random-access-file](https://github.com/random-access-storage/random-access-file). This is also useful if you want to store specific files in other directories.
52
53Hypercore will produce the following files:
54
55* `oplog` - The internal truncating journal/oplog that tracks mutations, the public key and other metadata.
56* `tree` - The Merkle Tree file.
57* `bitfield` - The bitfield of which data blocks this core has.
58* `data` - The raw data of each block.
59
60Note that `tree`, `data`, and `bitfield` are normally heavily sparse files.
61
62`key` can be set to a Hypercore public key. If you do not set this the public key will be loaded from storage. If no key exists a new key pair will be generated.
63
64`options` include:
65
66``` js
67{
68 createIfMissing: true, // create a new Hypercore key pair if none was present in storage
69 overwrite: false, // overwrite any old Hypercore that might already exist
70 sparse: true, // enable sparse mode, counting unavailable blocks towards core.length and core.byteLength
71 valueEncoding: 'json' | 'utf-8' | 'binary', // defaults to binary
72 encodeBatch: batch => { ... }, // optionally apply an encoding to complete batches
73 keyPair: kp, // optionally pass the public key and secret key as a key pair
74 encryptionKey: k, // optionally pass an encryption key to enable block encryption
75 onwait: () => {}, // hook that is called if gets are waiting for download
76 timeout: 0, // wait at max some milliseconds (0 means no timeout)
77 writable: true, // disable appends and truncates
78 inflightRange: null // Advanced option. Set to [minInflight, maxInflight] to change the min and max inflight blocks per peer when downloading.
79}
80```
81
82You can also set valueEncoding to any [abstract-encoding](https://github.com/mafintosh/abstract-encoding) or [compact-encoding](https://github.com/compact-encoding) instance.
83
84valueEncodings will be applied to individual blocks, even if you append batches. If you want to control encoding at the batch-level, you can use the `encodeBatch` option, which is a function that takes a batch and returns a binary-encoded batch. If you provide a custom valueEncoding, it will not be applied prior to `encodeBatch`.
85
86#### `const { length, byteLength } = await core.append(block)`
87
88Append a block of data (or an array of blocks) to the core.
89Returns the new length and byte length of the core.
90
91``` js
92// simple call append with a new block of data
93await core.append(Buffer.from('I am a block of data'))
94
95// pass an array to append multiple blocks as a batch
96await core.append([Buffer.from('batch block 1'), Buffer.from('batch block 2')])
97```
98
99#### `const block = await core.get(index, [options])`
100
101Get a block of data.
102If the data is not available locally this method will prioritize and wait for the data to be downloaded.
103
104``` js
105// get block #42
106const block = await core.get(42)
107
108// get block #43, but only wait 5s
109const blockIfFast = await core.get(43, { timeout: 5000 })
110
111// get block #44, but only if we have it locally
112const blockLocal = await core.get(44, { wait: false })
113```
114
115`options` include:
116
117``` js
118{
119 wait: true, // wait for block to be downloaded
120 onwait: () => {}, // hook that is called if the get is waiting for download
121 timeout: 0, // wait at max some milliseconds (0 means no timeout)
122 valueEncoding: 'json' | 'utf-8' | 'binary', // defaults to the core's valueEncoding
123 decrypt: true // automatically decrypts the block if encrypted
124}
125```
126
127#### `const has = await core.has(start, [end])`
128
129Check if the core has all blocks between `start` and `end`.
130
131#### `const updated = await core.update([options])`
132
133Waits for initial proof of the new core length until all `findingPeers` calls has finished.
134
135``` js
136const updated = await core.update()
137
138console.log('core was updated?', updated, 'length is', core.length)
139```
140
141`options` include:
142
143``` js
144{
145 wait: false
146}
147```
148
149Use `core.findingPeers()` or `{ wait: true }` to make `await core.update()` blocking.
150
151#### `const [index, relativeOffset] = await core.seek(byteOffset, [options])`
152
153Seek to a byte offset.
154
155Returns `[index, relativeOffset]`, where `index` is the data block the `byteOffset` is contained in and `relativeOffset` is
156the relative byte offset in the data block.
157
158``` js
159await core.append([Buffer.from('abc'), Buffer.from('d'), Buffer.from('efg')])
160
161const first = await core.seek(1) // returns [0, 1]
162const second = await core.seek(3) // returns [1, 0]
163const third = await core.seek(5) // returns [2, 1]
164```
165
166``` js
167{
168 wait: true, // wait for data to be downloaded
169 timeout: 0 // wait at max some milliseconds (0 means no timeout)
170}
171```
172
173#### `const stream = core.createReadStream([options])`
174
175Make a read stream to read a range of data out at once.
176
177``` js
178// read the full core
179const fullStream = core.createReadStream()
180
181// read from block 10-15
182const partialStream = core.createReadStream({ start: 10, end: 15 })
183
184// pipe the stream somewhere using the .pipe method on Node.js or consume it as
185// an async iterator
186
187for await (const data of fullStream) {
188 console.log('data:', data)
189}
190```
191
192`options` include:
193
194``` js
195{
196 start: 0,
197 end: core.length,
198 live: false,
199 snapshot: true // auto set end to core.length on open or update it on every read
200}
201```
202
203#### `const bs = core.createByteStream([options])`
204
205Make a byte stream to read a range of bytes.
206
207``` js
208// Read the full core
209const fullStream = core.createByteStream()
210
211// Read from byte 3, and from there read 50 bytes
212const partialStream = core.createByteStream({ byteOffset: 3, byteLength: 50 })
213
214// Consume it as an async iterator
215for await (const data of fullStream) {
216 console.log('data:', data)
217}
218
219// Or pipe it somewhere like any stream:
220partialStream.pipe(process.stdout)
221```
222
223`options` include:
224
225``` js
226{
227 byteOffset: 0,
228 byteLength: core.byteLength - options.byteOffset,
229 prefetch: 32
230}
231```
232
233#### `const cleared = await core.clear(start, [end], [options])`
234
235Clear stored blocks between `start` and `end`, reclaiming storage when possible.
236
237``` js
238await core.clear(4) // clear block 4 from your local cache
239await core.clear(0, 10) // clear block 0-10 from your local cache
240```
241
242The core will also gossip to peers it is connected to, that is no longer has these blocks.
243
244`options` include:
245```js
246{
247 diff: false // Returned `cleared` bytes object is null unless you enable this
248}
249```
250
251#### `await core.truncate(newLength, [forkId])`
252
253Truncate the core to a smaller length.
254
255Per default this will update the fork id of the core to `+ 1`, but you can set the fork id you prefer with the option.
256Note that the fork id should be monotonely incrementing.
257
258#### `await core.purge()`
259
260Purge the hypercore from your storage, completely removing all data.
261
262#### `const hash = await core.treeHash([length])`
263
264Get the Merkle Tree hash of the core at a given length, defaulting to the current length of the core.
265
266#### `const range = core.download([range])`
267
268Download a range of data.
269
270You can await when the range has been fully downloaded by doing:
271
272```js
273await range.done()
274```
275
276A range can have the following properties:
277
278``` js
279{
280 start: startIndex,
281 end: nonInclusiveEndIndex,
282 blocks: [index1, index2, ...],
283 linear: false // download range linearly and not randomly
284}
285```
286
287To download the full core continuously (often referred to as non sparse mode) do
288
289``` js
290// Note that this will never be considered downloaded as the range
291// will keep waiting for new blocks to be appended.
292core.download({ start: 0, end: -1 })
293```
294
295To download a discrete range of blocks pass a list of indices.
296
297```js
298core.download({ blocks: [4, 9, 7] })
299```
300
301To cancel downloading a range simply destroy the range instance.
302
303``` js
304// will stop downloading now
305range.destroy()
306```
307
308#### `const session = await core.session([options])`
309
310Creates a new Hypercore instance that shares the same underlying core.
311
312You must close any session you make.
313
314Options are inherited from the parent instance, unless they are re-set.
315
316`options` are the same as in the constructor.
317
318#### `const info = await core.info([options])`
319
320Get information about this core, such as its total size in bytes.
321
322The object will look like this:
323
324```js
325Info {
326 key: Buffer(...),
327 discoveryKey: Buffer(...),
328 length: 18,
329 contiguousLength: 16,
330 byteLength: 742,
331 fork: 0,
332 padding: 8,
333 storage: {
334 oplog: 8192,
335 tree: 4096,
336 blocks: 4096,
337 bitfield: 4096
338 }
339}
340```
341
342`options` include:
343
344```js
345{
346 storage: false // get storage estimates in bytes, disabled by default
347}
348```
349
350#### `await core.close()`
351
352Fully close this core.
353
354#### `core.on('close')`
355
356Emitted when the core has been fully closed.
357
358#### `await core.ready()`
359
360Wait for the core to fully open.
361
362After this has called `core.length` and other properties have been set.
363
364In general you do NOT need to wait for `ready`, unless checking a synchronous property,
365as all internals await this themself.
366
367#### `core.on('ready')`
368
369Emitted after the core has initially opened all its internal state.
370
371#### `core.writable`
372
373Can we append to this core?
374
375Populated after `ready` has been emitted. Will be `false` before the event.
376
377#### `core.readable`
378
379Can we read from this core? After closing the core this will be false.
380
381Populated after `ready` has been emitted. Will be `false` before the event.
382
383#### `core.id`
384
385String containing the id (z-base-32 of the public key) identifying this core.
386
387Populated after `ready` has been emitted. Will be `null` before the event.
388
389#### `core.key`
390
391Buffer containing the public key identifying this core.
392
393Populated after `ready` has been emitted. Will be `null` before the event.
394
395#### `core.keyPair`
396
397Object containing buffers of the core's public and secret key
398
399Populated after `ready` has been emitted. Will be `null` before the event.
400
401#### `core.discoveryKey`
402
403Buffer containing a key derived from the core's public key.
404In contrast to `core.key` this key does not allow you to verify the data but can be used to announce or look for peers that are sharing the same core, without leaking the core key.
405
406Populated after `ready` has been emitted. Will be `null` before the event.
407
408#### `core.encryptionKey`
409
410Buffer containing the optional block encryption key of this core. Will be `null` unless block encryption is enabled.
411
412#### `core.length`
413
414How many blocks of data are available on this core? If `sparse: false`, this will equal `core.contiguousLength`.
415
416Populated after `ready` has been emitted. Will be `0` before the event.
417
418#### `core.contiguousLength`
419
420How many blocks are contiguously available starting from the first block of this core?
421
422Populated after `ready` has been emitted. Will be `0` before the event.
423
424#### `core.fork`
425
426What is the current fork id of this core?
427
428Populated after `ready` has been emitted. Will be `0` before the event.
429
430#### `core.padding`
431
432How much padding is applied to each block of this core? Will be `0` unless block encryption is enabled.
433
434#### `const stream = core.replicate(isInitiatorOrReplicationStream)`
435
436Create a replication stream. You should pipe this to another Hypercore instance.
437
438The `isInitiator` argument is a boolean indicating whether you are the initiator of the connection (ie the client)
439or if you are the passive part (ie the server).
440
441If you are using a P2P swarm like [Hyperswarm](https://github.com/hyperswarm/hyperswarm) you can know this by checking if the swarm connection is a client socket or server socket. In Hyperswarm you can check that using the [client property on the peer details object](https://github.com/hyperswarm/hyperswarm#swarmonconnection-socket-details--)
442
443If you want to multiplex the replication over an existing Hypercore replication stream you can pass
444another stream instance instead of the `isInitiator` boolean.
445
446``` js
447// assuming we have two cores, localCore + remoteCore, sharing the same key
448// on a server
449const net = require('net')
450const server = net.createServer(function (socket) {
451 socket.pipe(remoteCore.replicate(false)).pipe(socket)
452})
453
454// on a client
455const socket = net.connect(...)
456socket.pipe(localCore.replicate(true)).pipe(socket)
457```
458
459#### `const done = core.findingPeers()`
460
461Create a hook that tells Hypercore you are finding peers for this core in the background. Call `done` when your current discovery iteration is done.
462If you're using Hyperswarm, you'd normally call this after a `swarm.flush()` finishes.
463
464This allows `core.update` to wait for either the `findingPeers` hook to finish or one peer to appear before deciding whether it should wait for a merkle tree update before returning.
465
466#### `core.on('append')`
467
468Emitted when the core has been appended to (i.e. has a new length / byteLength), either locally or remotely.
469
470#### `core.on('truncate', ancestors, forkId)`
471
472Emitted when the core has been truncated, either locally or remotely.
473
474#### `core.on('peer-add')`
475
476Emitted when a new connection has been established with a peer.
477
478#### `core.on('peer-remove')`
479
480Emitted when a peer's connection has been closed.
481
482#### `core.on('upload', index, byteLength, peer)`
483
484Emitted when a block is uploaded to a peer.
485
486#### `core.on('download', index, byteLength, peer)`
487
488Emitted when a block is downloaded from a peer.
node_modules/hypercore/errors.js +2 -0
……@@ -0,0 +1,2 @@
1// explicitly exposed as hypercore/errors
2module.exports = require('hypercore-errors')
node_modules/hypercore/index.js +1149 -0
……@@ -0,0 +1,1149 @@
1const { EventEmitter } = require('events')
2const RAF = require('random-access-file')
3const isOptions = require('is-options')
4const hypercoreCrypto = require('hypercore-crypto')
5const c = require('compact-encoding')
6const b4a = require('b4a')
7const Xache = require('xache')
8const NoiseSecretStream = require('@hyperswarm/secret-stream')
9const Protomux = require('protomux')
10const z32 = require('z32')
11const id = require('hypercore-id-encoding')
12const safetyCatch = require('safety-catch')
13const unslab = require('unslab')
14
15const Replicator = require('./lib/replicator')
16const Core = require('./lib/core')
17const BlockEncryption = require('./lib/block-encryption')
18const Info = require('./lib/info')
19const Download = require('./lib/download')
20const Batch = require('./lib/batch')
21const { manifestHash, createManifest } = require('./lib/verifier')
22const { ReadStream, WriteStream, ByteStream } = require('./lib/streams')
23const {
24 ASSERTION,
25 BAD_ARGUMENT,
26 SESSION_CLOSED,
27 SESSION_NOT_WRITABLE,
28 SNAPSHOT_NOT_AVAILABLE,
29 DECODING_ERROR
30} = require('hypercore-errors')
31
32const promises = Symbol.for('hypercore.promises')
33const inspect = Symbol.for('nodejs.util.inspect.custom')
34
35// Hypercore actually does not have any notion of max/min block sizes
36// but we enforce 15mb to ensure smooth replication (each block is transmitted atomically)
37const MAX_SUGGESTED_BLOCK_SIZE = 15 * 1024 * 1024
38
39module.exports = class Hypercore extends EventEmitter {
40 constructor (storage, key, opts) {
41 super()
42
43 if (isOptions(storage)) {
44 opts = storage
45 storage = null
46 key = opts.key || null
47 } else if (isOptions(key)) {
48 opts = key
49 key = opts.key || null
50 }
51
52 if (key && typeof key === 'string') key = id.decode(key)
53 if (!opts) opts = {}
54
55 if (!storage) storage = opts.storage
56
57 this[promises] = true
58
59 this.storage = null
60 this.crypto = opts.crypto || hypercoreCrypto
61 this.core = null
62 this.replicator = null
63 this.encryption = null
64 this.extensions = new Map()
65 this.cache = createCache(opts.cache)
66
67 this.valueEncoding = null
68 this.encodeBatch = null
69 this.activeRequests = []
70
71 this.id = null
72 this.key = key || null
73 this.keyPair = opts.keyPair || null
74 this.readable = true
75 this.writable = false
76 this.opened = false
77 this.closed = false
78 this.snapshotted = !!opts.snapshot
79 this.sparse = opts.sparse !== false
80 this.sessions = opts._sessions || [this]
81 this.autoClose = !!opts.autoClose
82 this.onwait = opts.onwait || null
83 this.wait = opts.wait !== false
84 this.timeout = opts.timeout || 0
85 this.closing = null
86 this.opening = null
87
88 this._readonly = opts.writable === false
89 this._preappend = preappend.bind(this)
90 this._snapshot = null
91 this._findingPeers = 0
92 this._active = opts.active !== false
93
94 this.opening = this._openSession(key, storage, opts)
95 this.opening.catch(safetyCatch)
96 }
97
98 [inspect] (depth, opts) {
99 let indent = ''
100 if (typeof opts.indentationLvl === 'number') {
101 while (indent.length < opts.indentationLvl) indent += ' '
102 }
103
104 let peers = ''
105 const min = Math.min(this.peers.length, 5)
106
107 for (let i = 0; i < min; i++) {
108 const peer = this.peers[i]
109
110 peers += indent + ' Peer(\n'
111 peers += indent + ' remotePublicKey: ' + opts.stylize(toHex(peer.remotePublicKey), 'string') + '\n'
112 peers += indent + ' remoteLength: ' + opts.stylize(peer.remoteLength, 'number') + '\n'
113 peers += indent + ' remoteFork: ' + opts.stylize(peer.remoteFork, 'number') + '\n'
114 peers += indent + ' remoteCanUpgrade: ' + opts.stylize(peer.remoteCanUpgrade, 'boolean') + '\n'
115 peers += indent + ' )' + '\n'
116 }
117
118 if (this.peers.length > 5) {
119 peers += indent + ' ... and ' + (this.peers.length - 5) + ' more\n'
120 }
121
122 if (peers) peers = '[\n' + peers + indent + ' ]'
123 else peers = '[ ' + opts.stylize(0, 'number') + ' ]'
124
125 return this.constructor.name + '(\n' +
126 indent + ' id: ' + opts.stylize(this.id, 'string') + '\n' +
127 indent + ' key: ' + opts.stylize(toHex(this.key), 'string') + '\n' +
128 indent + ' discoveryKey: ' + opts.stylize(toHex(this.discoveryKey), 'string') + '\n' +
129 indent + ' opened: ' + opts.stylize(this.opened, 'boolean') + '\n' +
130 indent + ' closed: ' + opts.stylize(this.closed, 'boolean') + '\n' +
131 indent + ' snapshotted: ' + opts.stylize(this.snapshotted, 'boolean') + '\n' +
132 indent + ' sparse: ' + opts.stylize(this.sparse, 'boolean') + '\n' +
133 indent + ' writable: ' + opts.stylize(this.writable, 'boolean') + '\n' +
134 indent + ' length: ' + opts.stylize(this.length, 'number') + '\n' +
135 indent + ' fork: ' + opts.stylize(this.fork, 'number') + '\n' +
136 indent + ' sessions: [ ' + opts.stylize(this.sessions.length, 'number') + ' ]\n' +
137 indent + ' activeRequests: [ ' + opts.stylize(this.activeRequests.length, 'number') + ' ]\n' +
138 indent + ' peers: ' + peers + '\n' +
139 indent + ')'
140 }
141
142 static MAX_SUGGESTED_BLOCK_SIZE = MAX_SUGGESTED_BLOCK_SIZE
143
144 static key (manifest, { compat, version, namespace } = {}) {
145 if (b4a.isBuffer(manifest)) manifest = { version, signers: [{ publicKey: manifest, namespace }] }
146 return compat ? manifest.signers[0].publicKey : manifestHash(createManifest(manifest))
147 }
148
149 static discoveryKey (key) {
150 return hypercoreCrypto.discoveryKey(key)
151 }
152
153 static getProtocolMuxer (stream) {
154 return stream.noiseStream.userData
155 }
156
157 static createProtocolStream (isInitiator, opts = {}) {
158 let outerStream = Protomux.isProtomux(isInitiator)
159 ? isInitiator.stream
160 : isStream(isInitiator)
161 ? isInitiator
162 : opts.stream
163
164 let noiseStream = null
165
166 if (outerStream) {
167 noiseStream = outerStream.noiseStream
168 } else {
169 noiseStream = new NoiseSecretStream(isInitiator, null, opts)
170 outerStream = noiseStream.rawStream
171 }
172 if (!noiseStream) throw BAD_ARGUMENT('Invalid stream')
173
174 if (!noiseStream.userData) {
175 const protocol = Protomux.from(noiseStream)
176
177 if (opts.keepAlive !== false) {
178 noiseStream.setKeepAlive(5000)
179 }
180 noiseStream.userData = protocol
181 }
182
183 if (opts.ondiscoverykey) {
184 noiseStream.userData.pair({ protocol: 'hypercore/alpha' }, opts.ondiscoverykey)
185 }
186
187 return outerStream
188 }
189
190 static defaultStorage (storage, opts = {}) {
191 if (typeof storage !== 'string') {
192 if (!isRandomAccessClass(storage)) return storage
193 const Cls = storage // just to satisfy standard...
194 return name => new Cls(name)
195 }
196
197 const directory = storage
198 const toLock = opts.unlocked ? null : (opts.lock || 'oplog')
199 const pool = opts.pool || (opts.poolSize ? RAF.createPool(opts.poolSize) : null)
200 const rmdir = !!opts.rmdir
201 const writable = opts.writable !== false
202
203 return createFile
204
205 function createFile (name) {
206 const lock = toLock === null ? false : isFile(name, toLock)
207 const sparse = isFile(name, 'data') || isFile(name, 'bitfield') || isFile(name, 'tree')
208 return new RAF(name, { directory, lock, sparse, pool: lock ? null : pool, rmdir, writable })
209 }
210
211 function isFile (name, n) {
212 return name === n || name.endsWith('/' + n)
213 }
214 }
215
216 snapshot (opts) {
217 return this.session({ ...opts, snapshot: true })
218 }
219
220 session (opts = {}) {
221 if (this.closing) {
222 // This makes the closing logic a lot easier. If this turns out to be a problem
223 // in practice, open an issue and we'll try to make a solution for it.
224 throw SESSION_CLOSED('Cannot make sessions on a closing core')
225 }
226
227 const sparse = opts.sparse === false ? false : this.sparse
228 const wait = opts.wait === false ? false : this.wait
229 const writable = opts.writable === false ? false : !this._readonly
230 const onwait = opts.onwait === undefined ? this.onwait : opts.onwait
231 const timeout = opts.timeout === undefined ? this.timeout : opts.timeout
232 const Clz = opts.class || Hypercore
233 const s = new Clz(this.storage, this.key, {
234 ...opts,
235 sparse,
236 wait,
237 onwait,
238 timeout,
239 writable,
240 _opening: this.opening,
241 _sessions: this.sessions
242 })
243
244 s._passCapabilities(this)
245
246 // Configure the cache unless explicitly disabled.
247 if (opts.cache !== false) {
248 s.cache = opts.cache === true || !opts.cache ? this.cache : opts.cache
249 }
250
251 if (this.opened) ensureEncryption(s, opts)
252 this._addSession(s)
253
254 return s
255 }
256
257 _addSession (s) {
258 this.sessions.push(s)
259 if (this.core) this.core.active++
260 }
261
262 async setEncryptionKey (encryptionKey, opts) {
263 if (!this.opened) await this.opening
264 this.encryption = encryptionKey ? new BlockEncryption(encryptionKey, this.key, { compat: this.core.compat, ...opts }) : null
265 }
266
267 setKeyPair (keyPair) {
268 this.keyPair = keyPair
269 this.writable = this._isWritable()
270 }
271
272 setActive (bool) {
273 const active = !!bool
274 if (active === this._active || this.closing) return
275 this._active = active
276 if (!this.opened) return
277 this.replicator.updateActivity(this._active ? 1 : -1)
278 }
279
280 _passCapabilities (o) {
281 if (!this.keyPair) this.keyPair = o.keyPair
282 this.crypto = o.crypto
283 this.id = o.id
284 this.key = o.key
285 this.core = o.core
286 this.replicator = o.replicator
287 this.encryption = o.encryption
288 this.writable = this._isWritable()
289 this.autoClose = o.autoClose
290
291 if (this.snapshotted && this.core && !this._snapshot) this._updateSnapshot()
292 }
293
294 async _openFromExisting (from, opts) {
295 if (!from.opened) await from.opening
296
297 // includes ourself as well, so the loop below also updates us
298 const sessions = this.sessions
299
300 for (const s of sessions) {
301 s.sessions = from.sessions
302 s._passCapabilities(from)
303 s._addSession(s)
304 }
305
306 this.storage = from.storage
307 this.replicator.findingPeers += this._findingPeers
308
309 ensureEncryption(this, opts)
310
311 // we need to manually fwd the encryption cap as the above removes it potentially
312 if (this.encryption && !from.encryption) {
313 for (const s of sessions) s.encryption = this.encryption
314 }
315 }
316
317 async _openSession (key, storage, opts) {
318 const isFirst = !opts._opening
319
320 if (!isFirst) {
321 await opts._opening
322 }
323 if (opts.preload) opts = { ...opts, ...(await this._retryPreload(opts.preload)) }
324 if (this.cache === null && opts.cache) this.cache = createCache(opts.cache)
325
326 if (isFirst) {
327 await this._openCapabilities(key, storage, opts)
328
329 // check we are the actual root and not a opts.from session
330 if (!opts.from) {
331 // Only the root session should pass capabilities to other sessions.
332 for (let i = 0; i < this.sessions.length; i++) {
333 const s = this.sessions[i]
334 if (s !== this) s._passCapabilities(this)
335 }
336 }
337 } else {
338 ensureEncryption(this, opts)
339 }
340
341 if (opts.manifest && !this.core.header.manifest) {
342 await this.core.setManifest(opts.manifest)
343 }
344
345 this.writable = this._isWritable()
346
347 if (opts.valueEncoding) {
348 this.valueEncoding = c.from(opts.valueEncoding)
349 }
350 if (opts.encodeBatch) {
351 this.encodeBatch = opts.encodeBatch
352 }
353
354 // Start continous replication if not in sparse mode.
355 if (!this.sparse) this.download({ start: 0, end: -1 })
356
357 // This is a hidden option that's only used by Corestore.
358 // It's required so that corestore can load a name from userData before 'ready' is emitted.
359 if (opts._preready) await opts._preready(this)
360
361 this.replicator.updateActivity(this._active ? 1 : 0)
362
363 this.opened = true
364 this.emit('ready')
365 }
366
367 async _retryPreload (preload) {
368 while (true) { // TODO: better long term fix is allowing lib/core.js creation from the outside...
369 const result = await preload()
370 const from = result && result.from
371 if (from) {
372 if (!from.opened) await from.ready()
373 if (from.closing) continue
374 }
375 return result
376 }
377 }
378
379 async _openCapabilities (key, storage, opts) {
380 if (opts.from) return this._openFromExisting(opts.from, opts)
381
382 const unlocked = !!opts.unlocked
383 this.storage = Hypercore.defaultStorage(opts.storage || storage, { unlocked, writable: !unlocked })
384
385 this.core = await Core.open(this.storage, {
386 compat: opts.compat,
387 force: opts.force,
388 sessions: this.sessions,
389 createIfMissing: opts.createIfMissing,
390 readonly: unlocked,
391 overwrite: opts.overwrite,
392 key,
393 keyPair: opts.keyPair,
394 crypto: this.crypto,
395 legacy: opts.legacy,
396 manifest: opts.manifest,
397 globalCache: opts.globalCache || null, // This is a temp option, not to be relied on unless you know what you are doing (no semver guarantees)
398 onupdate: this._oncoreupdate.bind(this),
399 onconflict: this._oncoreconflict.bind(this)
400 })
401
402 if (opts.userData) {
403 for (const [key, value] of Object.entries(opts.userData)) {
404 await this.core.userData(key, value)
405 }
406 }
407
408 this.key = this.core.header.key
409 this.keyPair = this.core.header.keyPair
410 this.id = z32.encode(this.key)
411
412 this.replicator = new Replicator(this.core, this.key, {
413 eagerUpgrade: true,
414 notDownloadingLinger: opts.notDownloadingLinger,
415 allowFork: opts.allowFork !== false,
416 inflightRange: opts.inflightRange,
417 onpeerupdate: this._onpeerupdate.bind(this),
418 onupload: this._onupload.bind(this),
419 oninvalid: this._oninvalid.bind(this)
420 })
421
422 this.replicator.findingPeers += this._findingPeers
423
424 if (!this.encryption && opts.encryptionKey) {
425 this.encryption = new BlockEncryption(opts.encryptionKey, this.key, { compat: this.core.compat, isBlockKey: opts.isBlockKey })
426 }
427 }
428
429 _getSnapshot () {
430 if (this.sparse) {
431 return {
432 length: this.core.tree.length,
433 byteLength: this.core.tree.byteLength,
434 fork: this.core.tree.fork,
435 compatLength: this.core.tree.length
436 }
437 }
438
439 return {
440 length: this.core.header.hints.contiguousLength,
441 byteLength: 0,
442 fork: this.core.tree.fork,
443 compatLength: this.core.header.hints.contiguousLength
444 }
445 }
446
447 _updateSnapshot () {
448 const prev = this._snapshot
449 const next = this._snapshot = this._getSnapshot()
450
451 if (!prev) return true
452 return prev.length !== next.length || prev.fork !== next.fork
453 }
454
455 _isWritable () {
456 return !this._readonly && !!(this.keyPair && this.keyPair.secretKey)
457 }
458
459 close (err) {
460 if (this.closing) return this.closing
461 this.closing = this._close(err || null)
462 return this.closing
463 }
464
465 async _close (err) {
466 if (this.opened === false) await this.opening
467
468 const i = this.sessions.indexOf(this)
469 if (i === -1) return
470
471 this.sessions.splice(i, 1)
472 this.core.active--
473 this.readable = false
474 this.writable = false
475 this.closed = true
476 this.opened = false
477
478 const gc = []
479 for (const ext of this.extensions.values()) {
480 if (ext.session === this) gc.push(ext)
481 }
482 for (const ext of gc) ext.destroy()
483
484 if (this.replicator !== null) {
485 this.replicator.findingPeers -= this._findingPeers
486 this.replicator.clearRequests(this.activeRequests, err)
487 this.replicator.updateActivity(this._active ? -1 : 0)
488 }
489
490 this._findingPeers = 0
491
492 if (this.sessions.length || this.core.active > 0) {
493 // if this is the last session and we are auto closing, trigger that first to enforce error handling
494 if (this.sessions.length === 1 && this.core.active === 1 && this.autoClose) await this.sessions[0].close(err)
495 // emit "fake" close as this is a session
496 this.emit('close', false)
497 return
498 }
499
500 if (this.replicator !== null) {
501 await this.replicator.destroy()
502 }
503
504 await this.core.close()
505
506 this.emit('close', true)
507 }
508
509 replicate (isInitiator, opts = {}) {
510 // Only limitation here is that ondiscoverykey doesn't work atm when passing a muxer directly,
511 // because it doesn't really make a lot of sense.
512 if (Protomux.isProtomux(isInitiator)) return this._attachToMuxer(isInitiator, opts)
513
514 // if same stream is passed twice, ignore the 2nd one before we make sessions etc
515 if (isStream(isInitiator) && this._isAttached(isInitiator)) return isInitiator
516
517 const protocolStream = Hypercore.createProtocolStream(isInitiator, opts)
518 const noiseStream = protocolStream.noiseStream
519 const protocol = noiseStream.userData
520 const useSession = !!opts.session
521
522 this._attachToMuxer(protocol, useSession)
523
524 return protocolStream
525 }
526
527 _isAttached (stream) {
528 return stream.userData && this.replicator && this.replicator.attached(stream.userData)
529 }
530
531 _attachToMuxer (mux, useSession) {
532 if (this.opened) {
533 this._attachToMuxerOpened(mux, useSession)
534 } else {
535 this.opening.then(this._attachToMuxerOpened.bind(this, mux, useSession), mux.destroy.bind(mux))
536 }
537
538 return mux
539 }
540
541 _attachToMuxerOpened (mux, useSession) {
542 // If the user wants to, we can make this replication run in a session
543 // that way the core wont close "under them" during replication
544 this.replicator.attachTo(mux, useSession)
545 }
546
547 get discoveryKey () {
548 return this.replicator === null ? null : this.replicator.discoveryKey
549 }
550
551 get manifest () {
552 return this.core === null ? null : this.core.header.manifest
553 }
554
555 get length () {
556 if (this._snapshot) return this._snapshot.length
557 if (this.core === null) return 0
558 if (!this.sparse) return this.contiguousLength
559 return this.core.tree.length
560 }
561
562 get signedLength () {
563 return this.length
564 }
565
566 get indexedLength () {
567 return this.length
568 }
569
570 /**
571 * Deprecated. Use `const { byteLength } = await core.info()`.
572 */
573 get byteLength () {
574 if (this._snapshot) return this._snapshot.byteLength
575 if (this.core === null) return 0
576 if (!this.sparse) return this.contiguousByteLength
577 return this.core.tree.byteLength - (this.core.tree.length * this.padding)
578 }
579
580 get contiguousLength () {
581 return this.core === null ? 0 : Math.min(this.core.tree.length, this.core.header.hints.contiguousLength)
582 }
583
584 get contiguousByteLength () {
585 return 0
586 }
587
588 get fork () {
589 return this.core === null ? 0 : this.core.tree.fork
590 }
591
592 get peers () {
593 return this.replicator === null ? [] : this.replicator.peers
594 }
595
596 get encryptionKey () {
597 return this.encryption && this.encryption.key
598 }
599
600 get padding () {
601 return this.encryption === null ? 0 : this.encryption.padding
602 }
603
604 get globalCache () {
605 return this.core && this.core.globalCache
606 }
607
608 ready () {
609 return this.opening
610 }
611
612 _onupload (index, value, from) {
613 const byteLength = value.byteLength - this.padding
614
615 for (let i = 0; i < this.sessions.length; i++) {
616 this.sessions[i].emit('upload', index, byteLength, from)
617 }
618 }
619
620 _oninvalid (err, req, res, from) {
621 for (let i = 0; i < this.sessions.length; i++) {
622 this.sessions[i].emit('verification-error', err, req, res, from)
623 }
624 }
625
626 async _oncoreconflict (proof, from) {
627 await this.replicator.onconflict(from)
628
629 for (const s of this.sessions) s.emit('conflict', proof.upgrade.length, proof.fork, proof)
630
631 const err = new Error('Two conflicting signatures exist for length ' + proof.upgrade.length)
632 await this._closeAllSessions(err)
633 }
634
635 async _closeAllSessions (err) {
636 // this.sessions modifies itself when a session closes
637 // This way we ensure we indeed iterate over all sessions
638 const sessions = [...this.sessions]
639
640 const all = []
641 for (const s of sessions) all.push(s.close(err))
642 await Promise.allSettled(all)
643 }
644
645 _oncoreupdate (status, bitfield, value, from) {
646 if (status !== 0) {
647 const truncatedNonSparse = (status & 0b1000) !== 0
648 const appendedNonSparse = (status & 0b0100) !== 0
649 const truncated = (status & 0b0010) !== 0
650 const appended = (status & 0b0001) !== 0
651
652 if (truncated) {
653 this.replicator.ontruncate(bitfield.start, bitfield.length)
654 }
655
656 if ((status & 0b10011) !== 0) {
657 this.replicator.onupgrade()
658 }
659
660 if (status & 0b10000) {
661 for (let i = 0; i < this.sessions.length; i++) {
662 const s = this.sessions[i]
663
664 if (s.encryption && s.encryption.compat !== this.core.compat) {
665 s.encryption = new BlockEncryption(s.encryption.key, this.key, { compat: this.core.compat, isBlockKey: s.encryption.isBlockKey })
666 }
667 }
668
669 for (let i = 0; i < this.sessions.length; i++) {
670 this.sessions[i].emit('manifest')
671 }
672 }
673
674 for (let i = 0; i < this.sessions.length; i++) {
675 const s = this.sessions[i]
676
677 if (truncated) {
678 if (s.cache) s.cache.clear()
679
680 // If snapshotted, make sure to update our compat so we can fail gets
681 if (s._snapshot && bitfield.start < s._snapshot.compatLength) s._snapshot.compatLength = bitfield.start
682 }
683
684 if (s.sparse ? truncated : truncatedNonSparse) {
685 s.emit('truncate', bitfield.start, this.core.tree.fork)
686 }
687
688 // For sparse sessions, immediately emit appends. If non-sparse, emit if contig length has updated
689 if (s.sparse ? appended : appendedNonSparse) {
690 s.emit('append')
691 }
692 }
693
694 const contig = this.core.header.hints.contiguousLength
695
696 // When the contig length catches up, broadcast the non-sparse length to peers
697 if (appendedNonSparse && contig === this.core.tree.length) {
698 for (const peer of this.peers) {
699 if (peer.broadcastedNonSparse) continue
700
701 peer.broadcastRange(0, contig)
702 peer.broadcastedNonSparse = true
703 }
704 }
705 }
706
707 if (bitfield) {
708 this.replicator.onhave(bitfield.start, bitfield.length, bitfield.drop)
709 }
710
711 if (value) {
712 const byteLength = value.byteLength - this.padding
713
714 for (let i = 0; i < this.sessions.length; i++) {
715 this.sessions[i].emit('download', bitfield.start, byteLength, from)
716 }
717 }
718 }
719
720 _onpeerupdate (added, peer) {
721 const name = added ? 'peer-add' : 'peer-remove'
722
723 for (let i = 0; i < this.sessions.length; i++) {
724 this.sessions[i].emit(name, peer)
725
726 if (added) {
727 for (const ext of this.sessions[i].extensions.values()) {
728 peer.extensions.set(ext.name, ext)
729 }
730 }
731 }
732 }
733
734 async setUserData (key, value, { flush = false } = {}) {
735 if (this.opened === false) await this.opening
736 return this.core.userData(key, value, flush)
737 }
738
739 async getUserData (key) {
740 if (this.opened === false) await this.opening
741 for (const { key: savedKey, value } of this.core.header.userData) {
742 if (key === savedKey) return value
743 }
744 return null
745 }
746
747 createTreeBatch () {
748 return this.core.tree.batch()
749 }
750
751 findingPeers () {
752 this._findingPeers++
753 if (this.replicator !== null && !this.closing) this.replicator.findingPeers++
754
755 let once = true
756
757 return () => {
758 if (this.closing || !once) return
759 once = false
760 this._findingPeers--
761 if (this.replicator !== null && --this.replicator.findingPeers === 0) {
762 this.replicator.updateAll()
763 }
764 }
765 }
766
767 async info (opts) {
768 if (this.opened === false) await this.opening
769
770 return Info.from(this, opts)
771 }
772
773 async update (opts) {
774 if (this.opened === false) await this.opening
775 if (this.closing !== null) return false
776
777 if (this.writable && (!opts || opts.force !== true)) {
778 if (!this.snapshotted) return false
779 return this._updateSnapshot()
780 }
781
782 const remoteWait = this._shouldWait(opts, this.replicator.findingPeers > 0)
783
784 let upgraded = false
785
786 if (await this.replicator.applyPendingReorg()) {
787 upgraded = true
788 }
789
790 if (!upgraded && remoteWait) {
791 const activeRequests = (opts && opts.activeRequests) || this.activeRequests
792 const req = this.replicator.addUpgrade(activeRequests)
793
794 upgraded = await req.promise
795 }
796
797 if (!upgraded) return false
798 if (this.snapshotted) return this._updateSnapshot()
799 return true
800 }
801
802 batch ({ checkout = -1, autoClose = true, session = true, restore = false, clear = false } = {}) {
803 return new Batch(session ? this.session() : this, checkout, autoClose, restore, clear)
804 }
805
806 async seek (bytes, opts) {
807 if (this.opened === false) await this.opening
808 if (!isValidIndex(bytes)) throw ASSERTION('seek is invalid')
809
810 const tree = (opts && opts.tree) || this.core.tree
811 const s = tree.seek(bytes, this.padding)
812
813 const offset = await s.update()
814 if (offset) return offset
815
816 if (this.closing !== null) throw SESSION_CLOSED()
817
818 if (!this._shouldWait(opts, this.wait)) return null
819
820 const activeRequests = (opts && opts.activeRequests) || this.activeRequests
821 const req = this.replicator.addSeek(activeRequests, s)
822
823 const timeout = opts && opts.timeout !== undefined ? opts.timeout : this.timeout
824 if (timeout) req.context.setTimeout(req, timeout)
825
826 return req.promise
827 }
828
829 async has (start, end = start + 1) {
830 if (this.opened === false) await this.opening
831 if (!isValidIndex(start) || !isValidIndex(end)) throw ASSERTION('has range is invalid')
832
833 if (end === start + 1) return this.core.bitfield.get(start)
834
835 const i = this.core.bitfield.firstUnset(start)
836 return i === -1 || i >= end
837 }
838
839 async get (index, opts) {
840 if (this.opened === false) await this.opening
841 if (!isValidIndex(index)) throw ASSERTION('block index is invalid')
842
843 if (this.closing !== null) throw SESSION_CLOSED()
844 if (this._snapshot !== null && index >= this._snapshot.compatLength) throw SNAPSHOT_NOT_AVAILABLE()
845
846 const encoding = (opts && opts.valueEncoding && c.from(opts.valueEncoding)) || this.valueEncoding
847
848 let req = this.cache && this.cache.get(index)
849 if (!req) req = this._get(index, opts)
850
851 let block = await req
852 if (!block) return null
853
854 if (opts && opts.raw) return block
855
856 if (this.encryption && (!opts || opts.decrypt !== false)) {
857 // Copy the block as it might be shared with other sessions.
858 block = b4a.from(block)
859
860 this.encryption.decrypt(index, block)
861 }
862
863 return this._decode(encoding, block)
864 }
865
866 async clear (start, end = start + 1, opts) {
867 if (this.opened === false) await this.opening
868 if (this.closing !== null) throw SESSION_CLOSED()
869
870 if (typeof end === 'object') {
871 opts = end
872 end = start + 1
873 }
874
875 if (!isValidIndex(start) || !isValidIndex(end)) throw ASSERTION('clear range is invalid')
876
877 const cleared = (opts && opts.diff) ? { blocks: 0 } : null
878
879 if (start >= end) return cleared
880 if (start >= this.length) return cleared
881
882 await this.core.clear(start, end, cleared)
883
884 return cleared
885 }
886
887 async purge () {
888 await this._closeAllSessions(null)
889 await this.core.purge()
890 }
891
892 async _get (index, opts) {
893 let block
894
895 if (this.core.bitfield.get(index)) {
896 const tree = (opts && opts.tree) || this.core.tree
897 block = this.core.blocks.get(index, tree)
898
899 if (this.cache) this.cache.set(index, block)
900 } else {
901 if (!this._shouldWait(opts, this.wait)) return null
902
903 if (opts && opts.onwait) opts.onwait(index, this)
904 if (this.onwait) this.onwait(index, this)
905
906 const activeRequests = (opts && opts.activeRequests) || this.activeRequests
907
908 const req = this.replicator.addBlock(activeRequests, index)
909 req.snapshot = index < this.length
910
911 const timeout = opts && opts.timeout !== undefined ? opts.timeout : this.timeout
912 if (timeout) req.context.setTimeout(req, timeout)
913
914 block = this._cacheOnResolve(index, req.promise, this.core.tree.fork)
915 }
916
917 return block
918 }
919
920 async _cacheOnResolve (index, req, fork) {
921 const resolved = await req
922
923 // Unslab only when it takes up less then half the slab
924 const block = resolved !== null && 2 * resolved.byteLength < resolved.buffer.byteLength
925 ? unslab(resolved)
926 : resolved
927
928 if (this.cache && fork === this.core.tree.fork) {
929 this.cache.set(index, Promise.resolve(block))
930 }
931
932 return block
933 }
934
935 _shouldWait (opts, defaultValue) {
936 if (opts) {
937 if (opts.wait === false) return false
938 if (opts.wait === true) return true
939 }
940 return defaultValue
941 }
942
943 createReadStream (opts) {
944 return new ReadStream(this, opts)
945 }
946
947 createWriteStream (opts) {
948 return new WriteStream(this, opts)
949 }
950
951 createByteStream (opts) {
952 return new ByteStream(this, opts)
953 }
954
955 download (range) {
956 const req = this._download(range)
957
958 // do not crash in the background...
959 req.catch(safetyCatch)
960
961 return new Download(req)
962 }
963
964 async _download (range) {
965 if (this.opened === false) await this.opening
966
967 const activeRequests = (range && range.activeRequests) || this.activeRequests
968 return this.replicator.addRange(activeRequests, range)
969 }
970
971 // TODO: get rid of this / deprecate it?
972 undownload (range) {
973 range.destroy(null)
974 }
975
976 // TODO: get rid of this / deprecate it?
977 cancel (request) {
978 // Do nothing for now
979 }
980
981 async truncate (newLength = 0, opts = {}) {
982 if (this.opened === false) await this.opening
983
984 const {
985 fork = this.core.tree.fork + 1,
986 keyPair = this.keyPair,
987 signature = null
988 } = typeof opts === 'number' ? { fork: opts } : opts
989
990 const writable = !this._readonly && !!(signature || (keyPair && keyPair.secretKey))
991 if (writable === false && (newLength > 0 || fork !== this.core.tree.fork)) throw SESSION_NOT_WRITABLE()
992
993 await this.core.truncate(newLength, fork, { keyPair, signature })
994
995 // TODO: Should propagate from an event triggered by the oplog
996 this.replicator.updateAll()
997 }
998
999 async append (blocks, opts = {}) {
1000 if (this.opened === false) await this.opening
1001
1002 const { keyPair = this.keyPair, signature = null } = opts
1003 const writable = !this._readonly && !!(signature || (keyPair && keyPair.secretKey))
1004
1005 if (writable === false) throw SESSION_NOT_WRITABLE()
1006
1007 blocks = Array.isArray(blocks) ? blocks : [blocks]
1008
1009 const preappend = this.encryption && this._preappend
1010
1011 const buffers = this.encodeBatch !== null ? this.encodeBatch(blocks) : new Array(blocks.length)
1012
1013 if (this.encodeBatch === null) {
1014 for (let i = 0; i < blocks.length; i++) {
1015 buffers[i] = this._encode(this.valueEncoding, blocks[i])
1016 }
1017 }
1018 for (const b of buffers) {
1019 if (b.byteLength > MAX_SUGGESTED_BLOCK_SIZE) {
1020 throw BAD_ARGUMENT('Appended block exceeds the maximum suggested block size')
1021 }
1022 }
1023
1024 return this.core.append(buffers, { keyPair, signature, preappend })
1025 }
1026
1027 async treeHash (length) {
1028 if (length === undefined) {
1029 await this.ready()
1030 length = this.core.tree.length
1031 }
1032
1033 const roots = await this.core.tree.getRoots(length)
1034 return this.crypto.tree(roots)
1035 }
1036
1037 registerExtension (name, handlers = {}) {
1038 if (this.extensions.has(name)) {
1039 const ext = this.extensions.get(name)
1040 ext.handlers = handlers
1041 ext.encoding = c.from(handlers.encoding || c.buffer)
1042 ext.session = this
1043 return ext
1044 }
1045
1046 const ext = {
1047 name,
1048 handlers,
1049 encoding: c.from(handlers.encoding || c.buffer),
1050 session: this,
1051 send (message, peer) {
1052 const buffer = c.encode(this.encoding, message)
1053 peer.extension(name, buffer)
1054 },
1055 broadcast (message) {
1056 const buffer = c.encode(this.encoding, message)
1057 for (const peer of this.session.peers) {
1058 peer.extension(name, buffer)
1059 }
1060 },
1061 destroy () {
1062 for (const peer of this.session.peers) {
1063 if (peer.extensions.get(name) === ext) peer.extensions.delete(name)
1064 }
1065 this.session.extensions.delete(name)
1066 },
1067 _onmessage (state, peer) {
1068 const m = this.encoding.decode(state)
1069 if (this.handlers.onmessage) this.handlers.onmessage(m, peer)
1070 }
1071 }
1072
1073 this.extensions.set(name, ext)
1074 for (const peer of this.peers) {
1075 peer.extensions.set(name, ext)
1076 }
1077
1078 return ext
1079 }
1080
1081 _encode (enc, val) {
1082 const state = { start: this.padding, end: this.padding, buffer: null }
1083
1084 if (b4a.isBuffer(val)) {
1085 if (state.start === 0) return val
1086 state.end += val.byteLength
1087 } else if (enc) {
1088 enc.preencode(state, val)
1089 } else {
1090 val = b4a.from(val)
1091 if (state.start === 0) return val
1092 state.end += val.byteLength
1093 }
1094
1095 state.buffer = b4a.allocUnsafe(state.end)
1096
1097 if (enc) enc.encode(state, val)
1098 else state.buffer.set(val, state.start)
1099
1100 return state.buffer
1101 }
1102
1103 _decode (enc, block) {
1104 if (this.padding) block = block.subarray(this.padding)
1105 try {
1106 if (enc) return c.decode(enc, block)
1107 } catch {
1108 throw DECODING_ERROR()
1109 }
1110 return block
1111 }
1112}
1113
1114function isStream (s) {
1115 return typeof s === 'object' && s && typeof s.pipe === 'function'
1116}
1117
1118function isRandomAccessClass (fn) {
1119 return !!(typeof fn === 'function' && fn.prototype && typeof fn.prototype.open === 'function')
1120}
1121
1122function toHex (buf) {
1123 return buf && b4a.toString(buf, 'hex')
1124}
1125
1126function preappend (blocks) {
1127 const offset = this.core.tree.length
1128 const fork = this.core.tree.fork
1129
1130 for (let i = 0; i < blocks.length; i++) {
1131 this.encryption.encrypt(offset + i, blocks[i], fork)
1132 }
1133}
1134
1135function ensureEncryption (core, opts) {
1136 if (!opts.encryptionKey) return
1137 // Only override the block encryption if it's either not already set or if
1138 // the caller provided a different key.
1139 if (core.encryption && b4a.equals(core.encryption.key, opts.encryptionKey) && core.encryption.compat === core.core.compat) return
1140 core.encryption = new BlockEncryption(opts.encryptionKey, core.key, { compat: core.core ? core.core.compat : true, isBlockKey: opts.isBlockKey })
1141}
1142
1143function createCache (cache) {
1144 return cache === true ? new Xache({ maxSize: 65536, maxAge: 0 }) : (cache || null)
1145}
1146
1147function isValidIndex (index) {
1148 return index === 0 || index > 0
1149}
node_modules/hypercore/lib/audit.js +129 -0
……@@ -0,0 +1,129 @@
1const hypercoreCrypto = require('hypercore-crypto')
2const flat = require('flat-tree')
3const c = require('compact-encoding')
4const b4a = require('b4a')
5
6const empty = b4a.alloc(32)
7
8// this is optimised for speed over mem atm
9// can be tweaked in the future
10
11module.exports = async function auditCore (core) {
12 const corrections = {
13 tree: 0,
14 blocks: 0
15 }
16
17 const length = core.header.tree.length
18
19 const data = await readFullStorage(core.blocks.storage)
20 const tree = await readFullStorage(core.tree.storage)
21
22 const valid = new Uint8Array(Math.ceil(tree.byteLength / 40))
23 const stack = []
24
25 for (const r of core.tree.roots) {
26 valid[r.index] = 1
27 stack.push(r)
28 }
29
30 while (stack.length > 0) {
31 const node = stack.pop()
32 if ((node.index & 1) === 0) continue
33
34 const [left, right] = flat.children(node.index)
35 const leftNode = getNode(left)
36 const rightNode = getNode(right)
37
38 if (!rightNode && !leftNode) continue
39
40 stack.push(leftNode, rightNode)
41
42 if (valid[node.index]) {
43 const hash = hypercoreCrypto.parent(leftNode, rightNode)
44 if (b4a.equals(hash, node.hash) && node.size === (leftNode.size + rightNode.size)) {
45 valid[leftNode.index] = 1
46 valid[rightNode.index] = 1
47 continue
48 }
49 }
50
51 if (leftNode.size) clearNode(leftNode)
52 if (rightNode.size) clearNode(rightNode)
53 }
54
55 if (corrections.tree) {
56 core.tree.cache.clear()
57 }
58
59 let i = 0
60 let nextOffset = -1
61 while (i < length) {
62 const has = core.bitfield.get(i)
63
64 if (!has) {
65 if (i + 1 === length) break
66 i = core.bitfield.findFirst(true, i + 1)
67 if (i < 0) break
68 nextOffset = -1
69 continue
70 }
71
72 if (nextOffset === -1) {
73 try {
74 nextOffset = await core.tree.byteOffset(i * 2)
75 } catch {
76 core._setBitfield(i, false)
77 corrections.blocks++
78 i++
79 continue
80 }
81 }
82
83 const node = getNode(i * 2)
84 const blk = data.subarray(nextOffset, nextOffset + node.size)
85 const hash = hypercoreCrypto.data(blk)
86
87 nextOffset += blk.byteLength
88
89 if (!b4a.equals(hash, node.hash)) {
90 core._setBitfield(i, false)
91 corrections.blocks++
92 }
93
94 i++
95 }
96
97 return corrections
98
99 function getNode (index) {
100 if (index * 40 + 40 > tree.byteLength) return null
101 const state = { start: index * 40, end: index * 40 + 40, buffer: tree }
102 const size = c.uint64.decode(state)
103 const hash = c.fixed32.decode(state)
104 if (size === 0 && hash.equals(empty)) return null
105 return { index, size, hash }
106 }
107
108 function clearNode (node) {
109 valid[node.index] = 0
110
111 if (node.size) {
112 b4a.fill(tree, 0, node.index * 40, node.index * 40 + 40)
113 core.tree.unflushed.set(node.index, core.tree.blankNode(node.index))
114 corrections.tree++
115 }
116 }
117}
118
119function readFullStorage (storage) {
120 return new Promise((resolve, reject) => {
121 storage.stat((_, st) => {
122 if (!st) return resolve(b4a.alloc(0))
123 storage.read(0, st.size, (err, data) => {
124 if (err) reject(err)
125 else resolve(data)
126 })
127 })
128 })
129}
node_modules/hypercore/lib/batch.js +431 -0
……@@ -0,0 +1,431 @@
1const { BLOCK_NOT_AVAILABLE, SESSION_CLOSED } = require('hypercore-errors')
2const EventEmitter = require('events')
3const c = require('compact-encoding')
4const b4a = require('b4a')
5const safetyCatch = require('safety-catch')
6
7module.exports = class HypercoreBatch extends EventEmitter {
8 constructor (session, checkoutLength, autoClose, restore, clear) {
9 super()
10
11 this.session = session
12 this.opened = false
13 this.closed = false
14 this.opening = null
15 this.closing = null
16 this.writable = true // always writable...
17 this.autoClose = autoClose
18 this.restore = restore
19 this.fork = 0
20
21 this._appends = []
22 this._appendsActual = null
23 this._checkoutLength = checkoutLength
24 this._byteLength = 0
25 this._sessionLength = 0
26 this._sessionByteLength = 0
27 this._sessionBatch = null
28 this._cachedBatch = null
29 this._flushing = null
30 this._clear = clear
31
32 this.opening = this._open()
33 this.opening.catch(safetyCatch)
34 }
35
36 get id () {
37 return this.session.id
38 }
39
40 get key () {
41 return this.session.key
42 }
43
44 get discoveryKey () {
45 return this.session.discoveryKey
46 }
47
48 get indexedLength () {
49 return Math.min(this._sessionLength, this.session.core === null ? 0 : this.session.core.tree.length)
50 }
51
52 get flushedLength () {
53 return this._sessionLength
54 }
55
56 get indexedByteLength () {
57 return this._sessionByteLength
58 }
59
60 get length () {
61 return this._sessionLength + this._appends.length
62 }
63
64 get byteLength () {
65 return this._sessionByteLength + this._byteLength
66 }
67
68 get core () {
69 return this.session.core
70 }
71
72 get manifest () {
73 return this.session.manifest
74 }
75
76 ready () {
77 return this.opening
78 }
79
80 async _open () {
81 await this.session.ready()
82
83 if (this._clear) this._checkoutLength = this.core.tree.length
84
85 if (this._checkoutLength !== -1) {
86 const batch = await this.session.core.tree.restoreBatch(this._checkoutLength)
87 batch.treeLength = this._checkoutLength
88 this._sessionLength = batch.length
89 this._sessionByteLength = batch.byteLength
90 this._sessionBatch = batch
91 if (this._clear) await this.core.clearBatch()
92 } else {
93 const last = this.restore ? this.session.core.bitfield.findFirst(false, this.session.length) : 0
94
95 if (last > this.session.length) {
96 const batch = await this.session.core.tree.restoreBatch(last)
97 this._sessionLength = batch.length
98 this._sessionByteLength = batch.byteLength - this.session.padding * batch.length
99 this._sessionBatch = batch
100 } else {
101 this._sessionLength = this.session.length
102 this._sessionByteLength = this.session.byteLength
103 this._sessionBatch = this.session.createTreeBatch()
104 }
105 }
106
107 this._appendsActual = this.session.encryption ? [] : this._appends
108 this.fork = this.session.fork
109 this.opened = true
110 this.emit('ready')
111 }
112
113 async has (index) {
114 if (this.opened === false) await this.ready()
115 if (index >= this._sessionLength) return index < this.length
116 return this.session.has(index)
117 }
118
119 async update (opts) {
120 if (this.opened === false) await this.ready()
121 await this.session.update(opts)
122 }
123
124 treeHash () {
125 return this._sessionBatch.hash()
126 }
127
128 setUserData (key, value, opts) {
129 return this.session.setUserData(key, value, opts)
130 }
131
132 getUserData (key, opts) {
133 return this.session.getUserData(key, opts)
134 }
135
136 async info (opts) {
137 const session = this.session
138 const info = await session.info(opts)
139
140 info.length = this._sessionLength
141
142 if (info.contiguousLength >= info.length) {
143 info.contiguousLength = info.length += this._appends.length
144 } else {
145 info.length += this._appends.length
146 }
147
148 info.byteLength = this._sessionByteLength + this._byteLength
149
150 return info
151 }
152
153 async seek (bytes, opts = {}) {
154 if (this.opened === false) await this.opening
155 if (this.closing) throw SESSION_CLOSED()
156
157 if (bytes < this._sessionByteLength) return await this.session.seek(bytes, { ...opts, tree: this._sessionBatch })
158
159 bytes -= this._sessionByteLength
160
161 let i = 0
162
163 for (const blk of this._appends) {
164 if (bytes < blk.byteLength) return [this._sessionLength + i, bytes]
165 i++
166 bytes -= blk.byteLength
167 }
168
169 if (bytes === 0) return [this._sessionLength + i, 0]
170
171 throw BLOCK_NOT_AVAILABLE()
172 }
173
174 async get (index, opts = {}) {
175 if (this.opened === false) await this.opening
176 if (this.closing) throw SESSION_CLOSED()
177
178 const length = this._sessionLength
179
180 if (index < length) {
181 return this.session.get(index, { ...opts, tree: this._sessionBatch })
182 }
183
184 if (opts && opts.raw) {
185 return this._appendsActual[index - length] || null
186 }
187
188 const buffer = this._appends[index - length] || null
189 if (!buffer) throw BLOCK_NOT_AVAILABLE()
190
191 const encoding = (opts && opts.valueEncoding && c.from(opts.valueEncoding)) || this.session.valueEncoding
192 if (!encoding) return buffer
193
194 return c.decode(encoding, buffer)
195 }
196
197 async _waitForFlush () {
198 // wait for any pending flush...
199 while (this._flushing) {
200 await this._flushing
201 await Promise.resolve() // yield in case a new flush is queued
202 }
203 }
204
205 async restoreBatch (length, blocks) {
206 if (this.opened === false) await this.opening
207 if (length >= this._sessionLength) return this.createTreeBatch(length, blocks)
208 return this.session.core.tree.restoreBatch(length)
209 }
210
211 _catchupBatch (clone) {
212 if (this._cachedBatch === null) this._cachedBatch = this._sessionBatch.clone()
213
214 if (this.length > this._cachedBatch.length) {
215 const offset = this._cachedBatch.length - this._sessionBatch.length
216
217 for (let i = offset; i < this._appendsActual.length; i++) {
218 this._cachedBatch.append(this._appendsActual[i])
219 }
220 }
221
222 return clone ? this._cachedBatch.clone() : this._cachedBatch
223 }
224
225 createTreeBatch (length, opts = {}) {
226 if (Array.isArray(opts)) opts = { blocks: opts }
227
228 const { blocks = [], clone = true } = opts
229 if (!length && length !== 0) length = this.length + blocks.length
230
231 const maxLength = this.length + blocks.length
232 const b = this._catchupBatch(clone || (blocks.length > 0 || length !== this.length))
233 const len = Math.min(length, this.length)
234
235 if (len < this._sessionLength || length > maxLength) return null
236 if (len < b.length) b.checkout(len, this._sessionBatch.roots)
237
238 for (let i = 0; i < length - len; i++) {
239 b.append(this._appendsActual === this._appends ? blocks[i] : this._encrypt(b.length, blocks[i]))
240 }
241
242 return b
243 }
244
245 async truncate (newLength = 0, opts = {}) {
246 if (this.opened === false) await this.opening
247 if (this.closing) throw SESSION_CLOSED()
248
249 // wait for any pending flush... (prop needs a lock)
250 await this._waitForFlush()
251
252 if (typeof opts === 'number') opts = { fork: opts }
253 const { fork = this.fork + 1, force = false } = opts
254
255 this._cachedBatch = null
256
257 const length = this._sessionLength
258 if (newLength < length) {
259 if (!force) throw new Error('Cannot truncate committed blocks')
260 this._appends.length = 0
261 this._byteLength = 0
262 await this.session.truncate(newLength, { fork, force: true, ...opts })
263 this._sessionLength = this.session.length
264 this._sessionByteLength = this.session.byteLength
265 this._sessionBatch = this.session.createTreeBatch()
266 } else {
267 for (let i = newLength - length; i < this._appends.length; i++) this._byteLength -= this._appends[i].byteLength
268 this._appends.length = newLength - length
269 }
270
271 this.fork = fork
272
273 this.emit('truncate', newLength, this.fork)
274 }
275
276 async append (blocks) {
277 const session = this.session
278
279 if (this.opened === false) await this.opening
280 if (this.closing) throw SESSION_CLOSED()
281
282 // wait for any pending flush... (prop needs a lock)
283 await this._waitForFlush()
284
285 blocks = Array.isArray(blocks) ? blocks : [blocks]
286
287 const buffers = session.encodeBatch !== null
288 ? session.encodeBatch(blocks)
289 : new Array(blocks.length)
290
291 if (session.encodeBatch === null) {
292 for (let i = 0; i < blocks.length; i++) {
293 const buffer = this._encode(session.valueEncoding, blocks[i])
294 buffers[i] = buffer
295 this._byteLength += buffer.byteLength
296 }
297 }
298 if (this._appends !== this._appendsActual) {
299 for (let i = 0; i < buffers.length; i++) {
300 this._appendsActual.push(this._encrypt(this._sessionLength + this._appendsActual.length, buffers[i]))
301 }
302 }
303
304 for (const b of buffers) this._appends.push(b)
305
306 const info = { length: this.length, byteLength: this.byteLength }
307 this.emit('append')
308
309 return info
310 }
311
312 _encode (enc, val) {
313 const state = { start: 0, end: 0, buffer: null }
314
315 if (b4a.isBuffer(val)) {
316 if (state.start === 0) return val
317 state.end += val.byteLength
318 } else if (enc) {
319 enc.preencode(state, val)
320 } else {
321 val = b4a.from(val)
322 if (state.start === 0) return val
323 state.end += val.byteLength
324 }
325
326 state.buffer = b4a.allocUnsafe(state.end)
327
328 if (enc) enc.encode(state, val)
329 else state.buffer.set(val, state.start)
330
331 return state.buffer
332 }
333
334 _encrypt (index, buffer) {
335 const block = b4a.allocUnsafe(buffer.byteLength + 8)
336 block.set(buffer, 8)
337 this.session.encryption.encrypt(index, block, this.fork)
338 return block
339 }
340
341 async flush (opts = {}) {
342 if (this.opened === false) await this.opening
343 if (this.closing) throw SESSION_CLOSED()
344
345 const { length = this.length, keyPair = this.session.keyPair, signature = null, pending = !signature && !keyPair } = opts
346
347 while (this._flushing) await this._flushing
348 this._flushing = this._flush(length, keyPair, signature, pending)
349
350 let flushed = false
351
352 try {
353 flushed = await this._flushing
354 } finally {
355 this._flushing = null
356 }
357
358 if (this.autoClose) await this.close()
359
360 return flushed
361 }
362
363 async _flush (length, keyPair, signature, pending) { // TODO: make this safe to interact with a parallel truncate...
364 if (this._sessionBatch.fork !== this.session.fork) return false // no truncs supported atm
365
366 if (this.session.replicator._upgrade) {
367 for (const req of this.session.replicator._upgrade.inflight) {
368 // yield to the remote inflight upgrade, TODO: if the remote upgrade fails, retry flushing...
369 if (req.upgrade && (req.upgrade.start + req.upgrade.length) > length) {
370 return false
371 }
372 }
373 }
374
375 const flushingLength = Math.min(length - this._sessionLength, this._appends.length)
376 if (flushingLength <= 0) {
377 if (this._sessionLength > this.core.tree.length && length > this.core.tree.length && !pending) {
378 const batch = await this.restoreBatch(length)
379 const info = await this.core.insertBatch(batch, [], { keyPair, signature, pending, treeLength: length })
380 return info !== null
381 }
382 return true
383 }
384
385 const batch = this.createTreeBatch(this._sessionLength + flushingLength)
386 if (batch === null) return false
387
388 const info = await this.core.insertBatch(batch, this._appendsActual, { keyPair, signature, pending, treeLength: this._sessionLength })
389 if (info === null) return false
390
391 const delta = info.byteLength - this._sessionByteLength
392 const newBatch = info.length !== this.session.length ? await this.session.core.tree.restoreBatch(info.length) : this.session.createTreeBatch()
393
394 this._sessionLength = info.length
395 this._sessionByteLength = info.byteLength
396 this._sessionBatch = newBatch
397
398 if (this._cachedBatch !== null) this._cachedBatch.prune(info.length)
399
400 const same = this._appends === this._appendsActual
401
402 this._appends = this._appends.slice(flushingLength)
403 this._appendsActual = same ? this._appends : this._appendsActual.slice(flushingLength)
404 this._byteLength -= delta
405
406 this.emit('flush')
407
408 return true
409 }
410
411 close () {
412 if (!this.closing) this.closing = this._close()
413 return this.closing
414 }
415
416 async _close () {
417 this._clearAppends()
418
419 await this.session.close()
420
421 this.closed = true
422 this.emit('close')
423 }
424
425 _clearAppends () {
426 this._appends = []
427 this._appendsActual = []
428 this._byteLength = 0
429 this.fork = 0
430 }
431}
node_modules/hypercore/lib/big-header.js +55 -0
……@@ -0,0 +1,55 @@
1const c = require('compact-encoding')
2const { oplog } = require('./messages')
3
4module.exports = class BigHeader {
5 constructor (storage) {
6 this.storage = storage
7 }
8
9 async load (external) {
10 const buf = await new Promise((resolve, reject) => {
11 this.storage.read(external.start, external.length, (err, buf) => {
12 if (err) return reject(err)
13 resolve(buf)
14 })
15 })
16
17 const header = c.decode(oplog.header, buf)
18 header.external = external
19 return header
20 }
21
22 async flush (header) {
23 const external = header.external || { start: 0, length: 0 }
24 header.external = null
25
26 const buf = c.encode(oplog.header, header)
27
28 let start = 0
29 if (buf.byteLength > external.start) {
30 start = external.start + external.length
31 const rem = start & 4095
32 if (rem > 0) start += (4096 - rem)
33 }
34
35 header.external = { start, length: buf.byteLength }
36
37 await new Promise((resolve, reject) => {
38 this.storage.write(start, buf, (err) => {
39 if (err) return reject(err)
40 resolve()
41 })
42 })
43
44 return header
45 }
46
47 close () {
48 return new Promise((resolve, reject) => {
49 this.storage.close((err) => {
50 if (err) return reject(err)
51 resolve()
52 })
53 })
54 }
55}
node_modules/hypercore/lib/bitfield.js +496 -0
……@@ -0,0 +1,496 @@
1const BigSparseArray = require('big-sparse-array')
2const b4a = require('b4a')
3const quickbit = require('./compat').quickbit
4
5const BITS_PER_PAGE = 32768
6const BYTES_PER_PAGE = BITS_PER_PAGE / 8
7const WORDS_PER_PAGE = BYTES_PER_PAGE / 4
8const BITS_PER_SEGMENT = 2097152
9const BYTES_PER_SEGMENT = BITS_PER_SEGMENT / 8
10const WORDS_PER_SEGMENT = BYTES_PER_SEGMENT / 4
11const INITIAL_WORDS_PER_SEGMENT = 1024
12const PAGES_PER_SEGMENT = BITS_PER_SEGMENT / BITS_PER_PAGE
13const SEGMENT_GROWTH_FACTOR = 4
14
15class BitfieldPage {
16 constructor (index, segment) {
17 this.dirty = false
18 this.index = index
19 this.offset = index * BYTES_PER_PAGE - segment.offset
20 this.bitfield = null
21 this.segment = segment
22
23 segment.add(this)
24 }
25
26 get tree () {
27 return this.segment.tree
28 }
29
30 get (index) {
31 return quickbit.get(this.bitfield, index)
32 }
33
34 set (index, val) {
35 if (quickbit.set(this.bitfield, index, val)) {
36 this.tree.update(this.offset * 8 + index)
37 }
38 }
39
40 setRange (start, length, val) {
41 quickbit.fill(this.bitfield, val, start, start + length)
42
43 let i = Math.floor(start / 128)
44 const n = i + Math.ceil(length / 128)
45
46 while (i <= n) this.tree.update(this.offset * 8 + i++ * 128)
47 }
48
49 findFirst (val, position) {
50 return quickbit.findFirst(this.bitfield, val, position)
51 }
52
53 findLast (val, position) {
54 return quickbit.findLast(this.bitfield, val, position)
55 }
56
57 count (start, length, val) {
58 const end = start + length
59
60 let i = start
61 let c = 0
62
63 while (length > 0) {
64 const l = this.findFirst(val, i)
65 if (l === -1 || l >= end) return c
66
67 const h = this.findFirst(!val, l + 1)
68 if (h === -1 || h >= end) return c + end - l
69
70 c += h - l
71 length -= h - i
72 i = h
73 }
74
75 return c
76 }
77}
78
79class BitfieldSegment {
80 constructor (index, bitfield) {
81 this.index = index
82 this.offset = index * BYTES_PER_SEGMENT
83 this.tree = quickbit.Index.from(bitfield, BYTES_PER_SEGMENT)
84 this.pages = new Array(PAGES_PER_SEGMENT)
85 }
86
87 get bitfield () {
88 return this.tree.field
89 }
90
91 add (page) {
92 const i = page.index - this.index * PAGES_PER_SEGMENT
93 this.pages[i] = page
94
95 const start = i * WORDS_PER_PAGE
96 const end = start + WORDS_PER_PAGE
97
98 if (end >= this.bitfield.length) this.reallocate(end)
99
100 page.bitfield = this.bitfield.subarray(start, end)
101 }
102
103 reallocate (length) {
104 let target = this.bitfield.length
105 while (target < length) target *= SEGMENT_GROWTH_FACTOR
106
107 const bitfield = new Uint32Array(target)
108 bitfield.set(this.bitfield)
109
110 this.tree = quickbit.Index.from(bitfield, BYTES_PER_SEGMENT)
111
112 for (let i = 0; i < this.pages.length; i++) {
113 const page = this.pages[i]
114 if (!page) continue
115
116 const start = i * WORDS_PER_PAGE
117 const end = start + WORDS_PER_PAGE
118
119 page.bitfield = bitfield.subarray(start, end)
120 }
121 }
122
123 findFirst (val, position) {
124 position = this.tree.skipFirst(!val, position)
125
126 let j = position & (BITS_PER_PAGE - 1)
127 let i = (position - j) / BITS_PER_PAGE
128
129 if (i >= PAGES_PER_SEGMENT) return -1
130
131 while (i < this.pages.length) {
132 const p = this.pages[i]
133
134 let index = -1
135
136 if (p) index = p.findFirst(val, j)
137 else if (!val) index = j
138
139 if (index !== -1) return i * BITS_PER_PAGE + index
140
141 j = 0
142 i++
143 }
144
145 return -1
146 }
147
148 findLast (val, position) {
149 position = this.tree.skipLast(!val, position)
150
151 let j = position & (BITS_PER_PAGE - 1)
152 let i = (position - j) / BITS_PER_PAGE
153
154 if (i >= PAGES_PER_SEGMENT) return -1
155
156 while (i >= 0) {
157 const p = this.pages[i]
158
159 let index = -1
160
161 if (p) index = p.findLast(val, j)
162 else if (!val) index = j
163
164 if (index !== -1) return i * BITS_PER_PAGE + index
165
166 j = BITS_PER_PAGE - 1
167 i--
168 }
169
170 return -1
171 }
172}
173
174module.exports = class Bitfield {
175 constructor (storage, buffer) {
176 this.unflushed = []
177 this.storage = storage
178 this.resumed = !!(buffer && buffer.byteLength >= 4)
179
180 this._pages = new BigSparseArray()
181 this._segments = new BigSparseArray()
182
183 const view = this.resumed
184 ? new Uint32Array(
185 buffer.buffer,
186 buffer.byteOffset,
187 Math.floor(buffer.byteLength / 4)
188 )
189 : new Uint32Array(INITIAL_WORDS_PER_SEGMENT)
190
191 for (let i = 0; i < view.length; i += WORDS_PER_SEGMENT) {
192 let bitfield = view.subarray(i, i + (WORDS_PER_SEGMENT))
193 let length = WORDS_PER_SEGMENT
194
195 if (i === 0) {
196 length = INITIAL_WORDS_PER_SEGMENT
197 while (length < bitfield.length) length *= SEGMENT_GROWTH_FACTOR
198 }
199
200 if (bitfield.length !== length) {
201 const copy = new Uint32Array(length)
202 copy.set(bitfield, 0)
203 bitfield = copy
204 }
205
206 const segment = new BitfieldSegment(i / (WORDS_PER_SEGMENT), bitfield)
207 this._segments.set(segment.index, segment)
208
209 for (let j = 0; j < bitfield.length; j += WORDS_PER_PAGE) {
210 const page = new BitfieldPage((i + j) / WORDS_PER_PAGE, segment)
211 this._pages.set(page.index, page)
212 }
213 }
214 }
215
216 toBuffer (length) {
217 const pages = Math.ceil(length / BITS_PER_PAGE)
218 const buffer = b4a.allocUnsafe(pages * BYTES_PER_PAGE)
219
220 for (let i = 0; i < pages; i++) {
221 const page = this._pages.get(i)
222 const offset = i * BYTES_PER_PAGE
223
224 if (page) {
225 const buf = b4a.from(
226 page.bitfield.buffer,
227 page.bitfield.byteOffset,
228 page.bitfield.byteLength
229 )
230
231 buffer.set(buf, offset)
232 } else {
233 buffer.fill(0, offset, offset + BYTES_PER_PAGE)
234 }
235 }
236
237 return buffer
238 }
239
240 getBitfield (index) {
241 const j = index & (BITS_PER_PAGE - 1)
242 const i = (index - j) / BITS_PER_PAGE
243
244 const p = this._pages.get(i)
245 return p || null
246 }
247
248 get (index) {
249 const j = index & (BITS_PER_PAGE - 1)
250 const i = (index - j) / BITS_PER_PAGE
251
252 const p = this._pages.get(i)
253
254 return p ? p.get(j) : false
255 }
256
257 set (index, val) {
258 const j = index & (BITS_PER_PAGE - 1)
259 const i = (index - j) / BITS_PER_PAGE
260
261 let p = this._pages.get(i)
262
263 if (!p && val) {
264 const k = Math.floor(i / PAGES_PER_SEGMENT)
265 const s = this._segments.get(k) || this._segments.set(k, new BitfieldSegment(k, new Uint32Array(k === 0 ? INITIAL_WORDS_PER_SEGMENT : WORDS_PER_SEGMENT)))
266
267 p = this._pages.set(i, new BitfieldPage(i, s))
268 }
269
270 if (p) {
271 p.set(j, val)
272
273 if (!p.dirty) {
274 p.dirty = true
275 this.unflushed.push(p)
276 }
277 }
278 }
279
280 setRange (start, length, val) {
281 let j = start & (BITS_PER_PAGE - 1)
282 let i = (start - j) / BITS_PER_PAGE
283
284 while (length > 0) {
285 let p = this._pages.get(i)
286
287 if (!p && val) {
288 const k = Math.floor(i / PAGES_PER_SEGMENT)
289 const s = this._segments.get(k) || this._segments.set(k, new BitfieldSegment(k, new Uint32Array(k === 0 ? INITIAL_WORDS_PER_SEGMENT : WORDS_PER_SEGMENT)))
290
291 p = this._pages.set(i, new BitfieldPage(i, s))
292 }
293
294 const end = Math.min(j + length, BITS_PER_PAGE)
295 const range = end - j
296
297 if (p) {
298 p.setRange(j, range, val)
299
300 if (!p.dirty) {
301 p.dirty = true
302 this.unflushed.push(p)
303 }
304 }
305
306 j = 0
307 i++
308 length -= range
309 }
310 }
311
312 findFirst (val, position) {
313 let j = position & (BITS_PER_SEGMENT - 1)
314 let i = (position - j) / BITS_PER_SEGMENT
315
316 while (i < this._segments.maxLength) {
317 const s = this._segments.get(i)
318
319 let index = -1
320
321 if (s) index = s.findFirst(val, j)
322 else if (!val) index = j
323
324 if (index !== -1) return i * BITS_PER_SEGMENT + index
325
326 j = 0
327 i++
328 }
329
330 return val ? -1 : this._segments.maxLength * BITS_PER_SEGMENT
331 }
332
333 firstSet (position) {
334 return this.findFirst(true, position)
335 }
336
337 firstUnset (position) {
338 return this.findFirst(false, position)
339 }
340
341 findLast (val, position) {
342 let j = position & (BITS_PER_SEGMENT - 1)
343 let i = (position - j) / BITS_PER_SEGMENT
344
345 while (i >= 0) {
346 const s = this._segments.get(i)
347
348 let index = -1
349
350 if (s) index = s.findLast(val, j)
351 else if (!val) index = j
352
353 if (index !== -1) return i * BITS_PER_SEGMENT + index
354
355 j = BITS_PER_SEGMENT - 1
356 i--
357 }
358
359 return -1
360 }
361
362 lastSet (position) {
363 return this.findLast(true, position)
364 }
365
366 lastUnset (position) {
367 return this.findLast(false, position)
368 }
369
370 count (start, length, val) {
371 let j = start & (BITS_PER_PAGE - 1)
372 let i = (start - j) / BITS_PER_PAGE
373 let c = 0
374
375 while (length > 0) {
376 const p = this._pages.get(i)
377
378 const end = Math.min(j + length, BITS_PER_PAGE)
379 const range = end - j
380
381 if (p) c += p.count(j, range, val)
382 else if (!val) c += range
383
384 j = 0
385 i++
386 length -= range
387 }
388
389 return c
390 }
391
392 countSet (start, length) {
393 return this.count(start, length, true)
394 }
395
396 countUnset (start, length) {
397 return this.count(start, length, false)
398 }
399
400 * want (start, length) {
401 const j = start & (BITS_PER_SEGMENT - 1)
402 let i = (start - j) / BITS_PER_SEGMENT
403
404 while (length > 0) {
405 const s = this._segments.get(i)
406
407 if (s) {
408 // We always send at least 4 KiB worth of bitfield in a want, rounding
409 // to the nearest 4 KiB.
410 const end = ceilTo(clamp(length / 8, 4096, BYTES_PER_SEGMENT), 4096)
411
412 yield {
413 start: i * BITS_PER_SEGMENT,
414 bitfield: s.bitfield.subarray(0, end / 4)
415 }
416 }
417
418 i++
419 length -= BITS_PER_SEGMENT
420 }
421 }
422
423 clear () {
424 return new Promise((resolve, reject) => {
425 this.storage.truncate(0, (err) => {
426 if (err) return reject(err)
427 this._pages = new BigSparseArray()
428 this.unflushed = []
429 resolve()
430 })
431 })
432 }
433
434 close () {
435 return new Promise((resolve, reject) => {
436 this.storage.close((err) => {
437 if (err) reject(err)
438 else resolve()
439 })
440 })
441 }
442
443 flush () {
444 return new Promise((resolve, reject) => {
445 if (!this.unflushed.length) return resolve()
446
447 const self = this
448 let missing = this.unflushed.length
449 let error = null
450
451 for (const page of this.unflushed) {
452 const buf = b4a.from(
453 page.bitfield.buffer,
454 page.bitfield.byteOffset,
455 page.bitfield.byteLength
456 )
457
458 page.dirty = false
459 this.storage.write(page.index * BYTES_PER_PAGE, buf, done)
460 }
461
462 function done (err) {
463 if (err) error = err
464 if (--missing) return
465 if (error) return reject(error)
466 self.unflushed = []
467 resolve()
468 }
469 })
470 }
471
472 static open (storage, tree = null) {
473 return new Promise((resolve, reject) => {
474 storage.stat((err, st) => {
475 if (err) return resolve(new Bitfield(storage, null))
476 let size = st.size - (st.size & 3)
477 if (!size) return resolve(new Bitfield(storage, null))
478 if (tree) size = Math.min(size, ceilTo(tree.length / 8, 4096))
479 storage.read(0, size, (err, data) => {
480 if (err) return reject(err)
481 resolve(new Bitfield(storage, data))
482 })
483 })
484 })
485 }
486}
487
488function clamp (n, min, max) {
489 return Math.min(Math.max(n, min), max)
490}
491
492function ceilTo (n, multiple = 1) {
493 const remainder = n % multiple
494 if (remainder === 0) return n
495 return n + multiple - remainder
496}
node_modules/hypercore/lib/block-encryption.js +75 -0
……@@ -0,0 +1,75 @@
1const sodium = require('sodium-universal')
2const c = require('compact-encoding')
3const b4a = require('b4a')
4const { BLOCK_ENCRYPTION } = require('./caps')
5
6const nonce = b4a.alloc(sodium.crypto_stream_NONCEBYTES)
7
8module.exports = class BlockEncryption {
9 constructor (encryptionKey, hypercoreKey, { isBlockKey = false, compat = true } = {}) {
10 const subKeys = b4a.alloc(2 * sodium.crypto_stream_KEYBYTES)
11
12 this.key = encryptionKey
13 this.blockKey = isBlockKey ? encryptionKey : subKeys.subarray(0, sodium.crypto_stream_KEYBYTES)
14 this.blindingKey = subKeys.subarray(sodium.crypto_stream_KEYBYTES)
15 this.padding = 8
16 this.compat = compat
17 this.isBlockKey = isBlockKey
18
19 if (!isBlockKey) {
20 if (compat) sodium.crypto_generichash_batch(this.blockKey, [encryptionKey], hypercoreKey)
21 else sodium.crypto_generichash_batch(this.blockKey, [BLOCK_ENCRYPTION, hypercoreKey, encryptionKey])
22 }
23
24 sodium.crypto_generichash(this.blindingKey, this.blockKey)
25 }
26
27 encrypt (index, block, fork) {
28 const padding = block.subarray(0, this.padding)
29 block = block.subarray(this.padding)
30
31 c.uint64.encode({ start: 0, end: 8, buffer: padding }, fork)
32 c.uint64.encode({ start: 0, end: 8, buffer: nonce }, index)
33
34 // Zero out any previous padding.
35 nonce.fill(0, 8, 8 + padding.byteLength)
36
37 // Blind the fork ID, possibly risking reusing the nonce on a reorg of the
38 // Hypercore. This is fine as the blinding is best-effort and the latest
39 // fork ID shared on replication anyway.
40 sodium.crypto_stream_xor(
41 padding,
42 padding,
43 nonce,
44 this.blindingKey
45 )
46
47 nonce.set(padding, 8)
48
49 // The combination of a (blinded) fork ID and a block index is unique for a
50 // given Hypercore and is therefore a valid nonce for encrypting the block.
51 sodium.crypto_stream_xor(
52 block,
53 block,
54 nonce,
55 this.blockKey
56 )
57 }
58
59 decrypt (index, block) {
60 const padding = block.subarray(0, this.padding)
61 block = block.subarray(this.padding)
62
63 c.uint64.encode({ start: 0, end: 8, buffer: nonce }, index)
64
65 nonce.set(padding, 8)
66
67 // Decrypt the block using the blinded fork ID.
68 sodium.crypto_stream_xor(
69 block,
70 block,
71 nonce,
72 this.blockKey
73 )
74 }
75}
node_modules/hypercore/lib/block-store.js +63 -0
……@@ -0,0 +1,63 @@
1const b4a = require('b4a')
2const { WRITE_FAILED } = require('hypercore-errors')
3
4module.exports = class BlockStore {
5 constructor (storage, tree) {
6 this.storage = storage
7 this.tree = tree
8 }
9
10 async get (i, tree) {
11 if (!tree) tree = this.tree
12 const [offset, size] = await tree.byteRange(2 * i)
13 return this._read(offset, size)
14 }
15
16 async put (i, data, offset) {
17 return this._write(offset, data)
18 }
19
20 putBatch (i, batch, offset) {
21 if (batch.length === 0) return Promise.resolve()
22 return this.put(i, batch.length === 1 ? batch[0] : b4a.concat(batch), offset)
23 }
24
25 clear (offset = 0, length = -1) {
26 return new Promise((resolve, reject) => {
27 if (length === -1) this.storage.truncate(offset, done)
28 else this.storage.del(offset, length, done)
29
30 function done (err) {
31 if (err) reject(err)
32 else resolve()
33 }
34 })
35 }
36
37 close () {
38 return new Promise((resolve, reject) => {
39 this.storage.close((err) => {
40 if (err) reject(err)
41 else resolve()
42 })
43 })
44 }
45
46 _read (offset, size) {
47 return new Promise((resolve, reject) => {
48 this.storage.read(offset, size, (err, data) => {
49 if (err) reject(err)
50 else resolve(data)
51 })
52 })
53 }
54
55 _write (offset, data) {
56 return new Promise((resolve, reject) => {
57 this.storage.write(offset, data, (err) => {
58 if (err) reject(WRITE_FAILED(err.message))
59 else resolve(offset + data.byteLength)
60 })
61 })
62 }
63}
node_modules/hypercore/lib/caps.js +46 -0
……@@ -0,0 +1,46 @@
1const crypto = require('hypercore-crypto')
2const sodium = require('sodium-universal')
3const b4a = require('b4a')
4const c = require('compact-encoding')
5
6// TODO: rename this to "crypto" and move everything hashing related etc in here
7// Also lets move the tree stuff from hypercore-crypto here
8
9const [
10 TREE,
11 REPLICATE_INITIATOR,
12 REPLICATE_RESPONDER,
13 MANIFEST,
14 DEFAULT_NAMESPACE,
15 BLOCK_ENCRYPTION
16] = crypto.namespace('hypercore', 6)
17
18exports.MANIFEST = MANIFEST
19exports.DEFAULT_NAMESPACE = DEFAULT_NAMESPACE
20exports.BLOCK_ENCRYPTION = BLOCK_ENCRYPTION
21
22exports.replicate = function (isInitiator, key, handshakeHash) {
23 const out = b4a.allocUnsafe(32)
24 sodium.crypto_generichash_batch(out, [isInitiator ? REPLICATE_INITIATOR : REPLICATE_RESPONDER, key], handshakeHash)
25 return out
26}
27
28exports.treeSignable = function (manifestHash, treeHash, length, fork) {
29 const state = { start: 0, end: 112, buffer: b4a.allocUnsafe(112) }
30 c.fixed32.encode(state, TREE)
31 c.fixed32.encode(state, manifestHash)
32 c.fixed32.encode(state, treeHash)
33 c.uint64.encode(state, length)
34 c.uint64.encode(state, fork)
35 return state.buffer
36}
37
38exports.treeSignableCompat = function (hash, length, fork, noHeader) {
39 const end = noHeader ? 48 : 80
40 const state = { start: 0, end, buffer: b4a.allocUnsafe(end) }
41 if (!noHeader) c.fixed32.encode(state, TREE) // ultra legacy mode, kill in future major
42 c.fixed32.encode(state, hash)
43 c.uint64.encode(state, length)
44 c.uint64.encode(state, fork)
45 return state.buffer
46}
node_modules/hypercore/lib/compat.js +12 -0
……@@ -0,0 +1,12 @@
1// Export the appropriate version of `quickbit-universal` as the plain import
2// may resolve to an older version in some environments
3let quickbit = require('quickbit-universal')
4if (
5 typeof quickbit.findFirst !== 'function' ||
6 typeof quickbit.findLast !== 'function' ||
7 typeof quickbit.clear !== 'function'
8) {
9 // This should always load the fallback from the locally installed version
10 quickbit = require('quickbit-universal/fallback')
11}
12exports.quickbit = quickbit
node_modules/hypercore/lib/core.js +1106 -0
……@@ -0,0 +1,1106 @@
1const hypercoreCrypto = require('hypercore-crypto')
2const b4a = require('b4a')
3const unslab = require('unslab')
4const Oplog = require('./oplog')
5const BigHeader = require('./big-header')
6const Mutex = require('./mutex')
7const MerkleTree = require('./merkle-tree')
8const BlockStore = require('./block-store')
9const Bitfield = require('./bitfield')
10const RemoteBitfield = require('./remote-bitfield')
11const Info = require('./info')
12const { BAD_ARGUMENT, STORAGE_EMPTY, STORAGE_CONFLICT, INVALID_OPERATION, INVALID_SIGNATURE, INVALID_CHECKSUM } = require('hypercore-errors')
13const m = require('./messages')
14const Verifier = require('./verifier')
15const audit = require('./audit')
16
17module.exports = class Core {
18 constructor (header, compat, crypto, oplog, bigHeader, tree, blocks, bitfield, verifier, sessions, legacy, globalCache, onupdate, onconflict) {
19 this.onupdate = onupdate
20 this.onconflict = onconflict
21 this.preupdate = null
22 this.header = header
23 this.compat = compat
24 this.crypto = crypto
25 this.oplog = oplog
26 this.bigHeader = bigHeader
27 this.tree = tree
28 this.blocks = blocks
29 this.bitfield = bitfield
30 this.verifier = verifier
31 this.truncating = 0
32 this.updating = false
33 this.closed = false
34 this.skipBitfield = null
35 this.active = sessions.length
36 this.sessions = sessions
37 this.globalCache = globalCache
38
39 this._manifestFlushed = !!header.manifest
40 this._maxOplogSize = 65536
41 this._autoFlush = 1
42 this._verifies = null
43 this._verifiesFlushed = null
44 this._mutex = new Mutex()
45 this._legacy = legacy
46 }
47
48 static async open (storage, opts = {}) {
49 const oplogFile = storage('oplog')
50 const treeFile = storage('tree')
51 const bitfieldFile = storage('bitfield')
52 const dataFile = storage('data')
53 const headerFile = storage('header')
54
55 try {
56 return await this.resume(oplogFile, treeFile, bitfieldFile, dataFile, headerFile, opts)
57 } catch (err) {
58 await closeAll(oplogFile, treeFile, bitfieldFile, dataFile, headerFile)
59 throw err
60 }
61 }
62
63 static async resume (oplogFile, treeFile, bitfieldFile, dataFile, headerFile, opts) {
64 let overwrite = opts.overwrite === true
65
66 const force = opts.force === true
67 const createIfMissing = opts.createIfMissing !== false
68 const crypto = opts.crypto || hypercoreCrypto
69 // kill this flag soon
70 const legacy = !!opts.legacy
71
72 const oplog = new Oplog(oplogFile, {
73 headerEncoding: m.oplog.header,
74 entryEncoding: m.oplog.entry,
75 readonly: opts.readonly
76 })
77
78 // default to true for now if no manifest is provided
79 let compat = opts.compat === true || (opts.compat !== false && !opts.manifest)
80
81 let { header, entries } = await oplog.open()
82
83 if (force && opts.key && header && !b4a.equals(header.key, opts.key)) {
84 overwrite = true
85 }
86
87 const bigHeader = new BigHeader(headerFile)
88
89 if (!header || overwrite) {
90 if (!createIfMissing) {
91 throw STORAGE_EMPTY('No Hypercore is stored here')
92 }
93
94 if (compat) {
95 if (opts.key && opts.keyPair && !b4a.equals(opts.key, opts.keyPair.publicKey)) {
96 throw BAD_ARGUMENT('Key must match publicKey when in compat mode')
97 }
98 }
99
100 const keyPair = opts.keyPair || (opts.key ? null : crypto.keyPair())
101 const defaultManifest = !opts.manifest && (!!opts.compat || !opts.key || !!(keyPair && b4a.equals(opts.key, keyPair.publicKey)))
102 const manifest = defaultManifest ? Verifier.defaultSignerManifest(opts.key || keyPair.publicKey) : Verifier.createManifest(opts.manifest)
103
104 header = {
105 external: null,
106 key: opts.key || (compat ? manifest.signers[0].publicKey : Verifier.manifestHash(manifest)),
107 manifest,
108 keyPair: keyPair ? { publicKey: keyPair.publicKey, secretKey: keyPair.secretKey || null } : null,
109 userData: [],
110 tree: {
111 fork: 0,
112 length: 0,
113 rootHash: null,
114 signature: null
115 },
116 hints: {
117 reorgs: [],
118 contiguousLength: 0
119 }
120 }
121
122 await flushHeader(oplog, bigHeader, header)
123 } else if (header.external) {
124 header = await bigHeader.load(header.external)
125 }
126
127 // unslab the long lived buffers to avoid keeping the slab alive
128 header.key = unslab(header.key)
129 header.tree.rootHash = unslab(header.tree.rootHash)
130 header.tree.signature = unslab(header.tree.signature)
131
132 if (header.keyPair) {
133 header.keyPair.publicKey = unslab(header.keyPair.publicKey)
134 header.keyPair.secretKey = unslab(header.keyPair.secretKey)
135 }
136
137 if (opts.manifest) {
138 // if we provide a manifest and no key, verify that the stored key is the same
139 if (!opts.key && !Verifier.isValidManifest(header.key, Verifier.createManifest(opts.manifest))) {
140 throw STORAGE_CONFLICT('Manifest does not hash to provided key')
141 }
142
143 if (!header.manifest) header.manifest = opts.manifest
144 }
145
146 if (opts.key && !b4a.equals(header.key, opts.key)) {
147 throw STORAGE_CONFLICT('Another Hypercore is stored here')
148 }
149
150 // if we signalled compat, but already now this core isn't disable it
151 if (compat && header.manifest && !Verifier.isCompat(header.key, header.manifest)) {
152 compat = false
153 } else if (!compat && header.manifest && Verifier.isCompat(header.key, header.manifest)) {
154 compat = true
155 }
156
157 const prologue = header.manifest ? header.manifest.prologue : null
158
159 const tree = await MerkleTree.open(treeFile, { crypto, prologue, ...header.tree })
160 const bitfield = await Bitfield.open(bitfieldFile)
161 const blocks = new BlockStore(dataFile, tree)
162
163 if (overwrite) {
164 await tree.clear()
165 await blocks.clear()
166 await bitfield.clear()
167 entries = []
168 }
169
170 // compat from earlier version that do not store contig length
171 if (header.hints.contiguousLength === 0) {
172 while (bitfield.get(header.hints.contiguousLength)) header.hints.contiguousLength++
173 }
174
175 // to unslab
176 if (header.manifest) header.manifest = Verifier.createManifest(header.manifest)
177
178 const verifier = header.manifest ? new Verifier(header.key, header.manifest, { crypto, legacy }) : null
179
180 for (const e of entries) {
181 if (e.userData) {
182 updateUserData(header.userData, e.userData.key, e.userData.value)
183 }
184
185 if (e.treeNodes) {
186 for (const node of e.treeNodes) {
187 tree.addNode(node)
188 }
189 }
190
191 if (e.bitfield) {
192 bitfield.setRange(e.bitfield.start, e.bitfield.length, !e.bitfield.drop)
193 updateContig(header, e.bitfield, bitfield)
194 }
195
196 if (e.treeUpgrade) {
197 const batch = await tree.truncate(e.treeUpgrade.length, e.treeUpgrade.fork)
198 batch.ancestors = e.treeUpgrade.ancestors
199 batch.signature = unslab(e.treeUpgrade.signature)
200 addReorgHint(header.hints.reorgs, tree, batch)
201 batch.commit()
202
203 header.tree.length = tree.length
204 header.tree.fork = tree.fork
205 header.tree.rootHash = tree.hash()
206 header.tree.signature = tree.signature
207 }
208 }
209
210 for (const entry of header.userData) {
211 entry.value = unslab(entry.value)
212 }
213
214 return new this(header, compat, crypto, oplog, bigHeader, tree, blocks, bitfield, verifier, opts.sessions || [], legacy, opts.globalCache || null, opts.onupdate || noop, opts.onconflict || noop)
215 }
216
217 async audit () {
218 await this._mutex.lock()
219
220 try {
221 await this._flushOplog()
222 const corrections = await audit(this)
223 if (corrections.blocks || corrections.tree) await this._flushOplog()
224 return corrections
225 } finally {
226 await this._mutex.unlock()
227 }
228 }
229
230 async setManifest (manifest) {
231 await this._mutex.lock()
232
233 try {
234 if (manifest && this.header.manifest === null) {
235 if (!Verifier.isValidManifest(this.header.key, manifest)) throw INVALID_CHECKSUM('Manifest hash does not match')
236 this._setManifest(Verifier.createManifest(manifest), null)
237 await this._flushOplog()
238 }
239 } finally {
240 this._mutex.unlock()
241 }
242 }
243
244 _setManifest (manifest, keyPair) {
245 if (!manifest && b4a.equals(keyPair.publicKey, this.header.key)) manifest = Verifier.defaultSignerManifest(this.header.key)
246 if (!manifest) return
247
248 const verifier = new Verifier(this.header.key, manifest, { crypto: this.crypto, legacy: this._legacy })
249
250 if (verifier.prologue) this.tree.setPrologue(verifier.prologue)
251
252 this.header.manifest = manifest
253 this.compat = verifier.compat
254 this.verifier = verifier
255 this._manifestFlushed = false
256
257 this.onupdate(0b10000, null, null, null)
258 }
259
260 _shouldFlush () {
261 // TODO: make something more fancy for auto flush mode (like fibonacci etc)
262 if (--this._autoFlush <= 0 || this.oplog.byteLength >= this._maxOplogSize) {
263 this._autoFlush = 4
264 return true
265 }
266
267 if (!this._manifestFlushed && this.header.manifest) {
268 this._manifestFlushed = true
269 return true
270 }
271
272 return false
273 }
274
275 async copyPrologue (src, { additional = [] } = {}) {
276 await this._mutex.lock()
277
278 try {
279 await src._mutex.lock()
280 } catch (err) {
281 this._mutex.unlock()
282 throw err
283 }
284
285 try {
286 const prologue = this.header.manifest && this.header.manifest.prologue
287 if (!prologue) throw INVALID_OPERATION('No prologue present')
288
289 const srcLength = prologue.length - additional.length
290 const srcBatch = srcLength !== src.tree.length ? await src.tree.truncate(srcLength) : src.tree.batch()
291 const srcRoots = srcBatch.roots.slice(0)
292 const srcByteLength = srcBatch.byteLength
293
294 for (const blk of additional) srcBatch.append(blk)
295
296 if (!b4a.equals(srcBatch.hash(), prologue.hash)) throw INVALID_OPERATION('Source tree is conflicting')
297
298 // all hashes are correct, lets copy
299
300 const entry = {
301 userData: null,
302 treeNodes: srcRoots,
303 treeUpgrade: null,
304 bitfield: null
305 }
306
307 if (additional.length) {
308 await this.blocks.putBatch(srcLength, additional, srcByteLength)
309 entry.treeNodes = entry.treeNodes.concat(srcBatch.nodes)
310 entry.bitfield = {
311 drop: false,
312 start: srcLength,
313 length: additional.length
314 }
315 }
316
317 await this.oplog.append([entry], false)
318 this.tree.addNodes(entry.treeNodes)
319
320 if (this.header.tree.length < srcBatch.length) {
321 this.header.tree.length = srcBatch.length
322 this.header.tree.rootHash = srcBatch.hash()
323
324 this.tree.length = srcBatch.length
325 this.tree.byteLength = srcBatch.byteLength
326 this.tree.roots = srcBatch.roots
327 this.onupdate(0b0001, null, null, null)
328 }
329
330 if (entry.bitfield) {
331 this._setBitfieldRange(entry.bitfield.start, entry.bitfield.length, true)
332 this.onupdate(0, entry.bitfield, null, null)
333 }
334
335 await this._flushOplog()
336
337 // no more additional blocks now and we should be consistant on disk
338 // copy over all existing segments...
339
340 let segmentEnd = 0
341
342 while (segmentEnd < srcLength) {
343 const segmentStart = maximumSegmentStart(segmentEnd, src.bitfield, this.bitfield)
344 if (segmentStart >= srcLength || segmentStart < 0) break
345
346 // max segment is 65536 to avoid running out of memory
347 segmentEnd = Math.min(segmentStart + 65536, srcLength, minimumSegmentEnd(segmentStart, src.bitfield, this.bitfield))
348
349 const treeNodes = await src.tree.getNeededNodes(srcLength, segmentStart, segmentEnd)
350 const bitfield = {
351 drop: false,
352 start: segmentStart,
353 length: segmentEnd - segmentStart
354 }
355
356 const segment = []
357 for (let i = segmentStart; i < segmentEnd; i++) {
358 const blk = await src.blocks.get(i)
359 segment.push(blk)
360 }
361
362 const offset = await src.tree.byteOffset(2 * segmentStart)
363 await this.blocks.putBatch(segmentStart, segment, offset)
364
365 const entry = {
366 userData: null,
367 treeNodes,
368 treeUpgrade: null,
369 bitfield
370 }
371
372 await this.oplog.append([entry], false)
373 this.tree.addNodes(treeNodes)
374 this._setBitfieldRange(bitfield.start, bitfield.length, true)
375 this.onupdate(0, bitfield, null, null)
376 await this._flushOplog()
377 }
378
379 this.header.userData = src.header.userData.slice(0)
380 const contig = Math.min(src.header.hints.contiguousLength, srcBatch.length)
381 if (this.header.hints.contiguousLength < contig) this.header.hints.contiguousLength = contig
382
383 await this._flushOplog()
384 } finally {
385 src._mutex.unlock()
386 this._mutex.unlock()
387 }
388 }
389
390 async flush () {
391 await this._mutex.lock()
392 try {
393 this._manifestFlushed = true
394 this._autoFlush = 4
395 await this._flushOplog()
396 } finally {
397 this._mutex.unlock()
398 }
399 }
400
401 async _flushOplog () {
402 // TODO: the apis using this, actually do not need to wait for the bitfields, tree etc to flush
403 // as their mutations are already stored in the oplog. We could potentially just run this in the
404 // background. Might be easier to impl that where it is called instead and keep this one simple.
405 await this.bitfield.flush()
406 await this.tree.flush()
407
408 return flushHeader(this.oplog, this.bigHeader, this.header)
409 }
410
411 _appendBlocks (values) {
412 return this.blocks.putBatch(this.tree.length, values, this.tree.byteLength)
413 }
414
415 async _writeBlock (batch, index, value) {
416 const byteOffset = await batch.byteOffset(index * 2)
417 await this.blocks.put(index, value, byteOffset)
418 }
419
420 async userData (key, value, flush) {
421 // TODO: each oplog append can set user data, so we should have a way
422 // to just hitch a ride on one of the other ongoing appends?
423 await this._mutex.lock()
424
425 try {
426 let empty = true
427
428 for (const u of this.header.userData) {
429 if (u.key !== key) continue
430 if (value && b4a.equals(u.value, value)) return
431 empty = false
432 break
433 }
434
435 if (empty && !value) return
436
437 const entry = {
438 userData: { key, value },
439 treeNodes: null,
440 treeUpgrade: null,
441 bitfield: null
442 }
443
444 await this.oplog.append([entry], false)
445
446 updateUserData(this.header.userData, key, value)
447
448 if (this._shouldFlush() || flush) await this._flushOplog()
449 } finally {
450 this._mutex.unlock()
451 }
452 }
453
454 async truncate (length, fork, { signature, keyPair = this.header.keyPair } = {}) {
455 if (this.tree.prologue && length < this.tree.prologue.length) {
456 throw INVALID_OPERATION('Truncation breaks prologue')
457 }
458
459 this.truncating++
460 await this._mutex.lock()
461
462 // upsert compat manifest
463 if (this.verifier === null && keyPair) this._setManifest(null, keyPair)
464
465 try {
466 const batch = await this.tree.truncate(length, fork)
467 if (length > 0) batch.signature = signature || this.verifier.sign(batch, keyPair)
468 await this._truncate(batch, null)
469 } finally {
470 this.truncating--
471 this._mutex.unlock()
472 }
473 }
474
475 async clearBatch () {
476 await this._mutex.lock()
477
478 try {
479 const len = this.bitfield.findFirst(false, this.tree.length)
480 if (len <= this.tree.length) return
481
482 const batch = await this.tree.truncate(this.tree.length, this.tree.fork)
483
484 batch.signature = this.tree.signature // same sig
485
486 const entry = {
487 userData: null,
488 treeNodes: batch.nodes,
489 treeUpgrade: batch,
490 bitfield: {
491 drop: true,
492 start: batch.ancestors,
493 length: len - batch.ancestors
494 }
495 }
496
497 await this.oplog.append([entry], false)
498
499 this._setBitfieldRange(batch.ancestors, len - batch.ancestors, false)
500 batch.commit()
501
502 // TODO: (see below todo)
503 await this._flushOplog()
504 } finally {
505 this._mutex.unlock()
506 }
507 }
508
509 async clear (start, end, cleared) {
510 await this._mutex.lock()
511
512 try {
513 const entry = {
514 userData: null,
515 treeNodes: null,
516 treeUpgrade: null,
517 bitfield: {
518 start,
519 length: end - start,
520 drop: true
521 }
522 }
523
524 await this.oplog.append([entry], false)
525
526 this._setBitfieldRange(start, end - start, false)
527
528 if (start < this.header.hints.contiguousLength) {
529 this.header.hints.contiguousLength = start
530 }
531
532 start = this.bitfield.lastSet(start) + 1
533 end = this.bitfield.firstSet(end)
534
535 if (end === -1) end = this.tree.length
536 if (start >= end || start >= this.tree.length) return
537
538 const offset = await this.tree.byteOffset(start * 2)
539 const endOffset = await this.tree.byteOffset(end * 2)
540 const length = endOffset - offset
541
542 const before = cleared ? await Info.bytesUsed(this.blocks.storage) : null
543
544 await this.blocks.clear(offset, length)
545
546 const after = cleared ? await Info.bytesUsed(this.blocks.storage) : null
547
548 if (cleared) cleared.blocks = Math.max(before - after, 0)
549
550 this.onupdate(0, entry.bitfield, null, null)
551
552 if (this._shouldFlush()) await this._flushOplog()
553 } finally {
554 this._mutex.unlock()
555 }
556 }
557
558 async purge () {
559 return new Promise((resolve, reject) => {
560 let missing = 4
561 let error = null
562
563 this.oplog.storage.unlink(done)
564 this.tree.storage.unlink(done)
565 this.bitfield.storage.unlink(done)
566 this.blocks.storage.unlink(done)
567
568 function done (err) {
569 if (err) error = err
570 if (--missing) return
571 if (error) reject(error)
572 else resolve()
573 }
574 })
575 }
576
577 async insertBatch (batch, values, { signature, keyPair = this.header.keyPair, pending = false, treeLength = batch.treeLength } = {}) {
578 await this._mutex.lock()
579
580 try {
581 // upsert compat manifest
582 if (this.verifier === null && keyPair) this._setManifest(null, keyPair)
583
584 if (this.tree.fork !== batch.fork) return null
585
586 if (this.tree.length > batch.treeLength) {
587 if (this.tree.length > batch.length) return null // TODO: partial commit in the future if possible
588
589 for (const root of this.tree.roots) {
590 const batchRoot = await batch.get(root.index)
591 if (batchRoot.size !== root.size || !b4a.equals(batchRoot.hash, root.hash)) {
592 return null
593 }
594 }
595 }
596
597 const adding = batch.length - treeLength
598
599 batch.upgraded = !pending && batch.length > this.tree.length
600 batch.treeLength = this.tree.length
601 batch.ancestors = this.tree.length
602 if (batch.upgraded && !pending) batch.signature = signature || this.verifier.sign(batch, keyPair)
603
604 let byteOffset = batch.byteLength
605 for (let i = 0; i < adding; i++) byteOffset -= values[i].byteLength
606
607 if (pending === true) batch.upgraded = false
608
609 const entry = {
610 userData: null,
611 treeNodes: batch.nodes,
612 treeUpgrade: batch.upgraded ? batch : null,
613 bitfield: {
614 drop: false,
615 start: treeLength,
616 length: adding
617 }
618 }
619
620 await this.blocks.putBatch(treeLength, adding < values.length ? values.slice(0, adding) : values, byteOffset)
621 await this.oplog.append([entry], false)
622
623 this._setBitfieldRange(entry.bitfield.start, entry.bitfield.length, true)
624 batch.commit()
625
626 if (batch.upgraded) {
627 this.header.tree.length = batch.length
628 this.header.tree.rootHash = batch.hash()
629 this.header.tree.signature = batch.signature
630 }
631
632 const status = (batch.upgraded ? 0b0001 : 0) | updateContig(this.header, entry.bitfield, this.bitfield)
633 if (!pending) {
634 // we already commit this, and now we signed it, so tell others
635 if (entry.treeUpgrade && treeLength > batch.treeLength) {
636 entry.bitfield.start = batch.treeLength
637 entry.bitfield.length = treeLength - batch.treeLength
638 }
639
640 this.onupdate(status, entry.bitfield, null, null)
641 }
642
643 if (this._shouldFlush()) await this._flushOplog()
644 } finally {
645 this._mutex.unlock()
646 }
647
648 return { length: batch.length, byteLength: batch.byteLength }
649 }
650
651 async append (values, { signature, keyPair = this.header.keyPair, preappend } = {}) {
652 await this._mutex.lock()
653
654 try {
655 // upsert compat manifest
656 if (this.verifier === null && keyPair) this._setManifest(null, keyPair)
657
658 if (preappend) await preappend(values)
659
660 if (!values.length) {
661 return { length: this.tree.length, byteLength: this.tree.byteLength }
662 }
663
664 const batch = this.tree.batch()
665 for (const val of values) batch.append(val)
666
667 // only multisig can have prologue so signature is always present
668 if (this.tree.prologue && batch.length < this.tree.prologue.length) {
669 throw INVALID_OPERATION('Append is not consistent with prologue')
670 }
671
672 batch.signature = signature || this.verifier.sign(batch, keyPair)
673
674 const entry = {
675 userData: null,
676 treeNodes: batch.nodes,
677 treeUpgrade: batch,
678 bitfield: {
679 drop: false,
680 start: batch.ancestors,
681 length: values.length
682 }
683 }
684
685 const byteLength = await this._appendBlocks(values)
686
687 await this.oplog.append([entry], false)
688
689 this._setBitfieldRange(batch.ancestors, batch.length - batch.ancestors, true)
690 batch.commit()
691
692 this.header.tree.length = batch.length
693 this.header.tree.rootHash = batch.hash()
694 this.header.tree.signature = batch.signature
695
696 const status = 0b0001 | updateContig(this.header, entry.bitfield, this.bitfield)
697 this.onupdate(status, entry.bitfield, null, null)
698
699 if (this._shouldFlush()) await this._flushOplog()
700
701 return { length: batch.length, byteLength }
702 } finally {
703 this._mutex.unlock()
704 }
705 }
706
707 _verifyBatchUpgrade (batch, manifest) {
708 if (!this.header.manifest) {
709 if (!manifest && this.compat) manifest = Verifier.defaultSignerManifest(this.header.key)
710
711 if (!manifest || !(Verifier.isValidManifest(this.header.key, manifest) || (this.compat && Verifier.isCompat(this.header.key, manifest)))) {
712 throw INVALID_SIGNATURE('Proof contains an invalid manifest') // TODO: proper error type
713 }
714 }
715
716 manifest = Verifier.createManifest(manifest) // To unslab
717
718 const verifier = this.verifier || new Verifier(this.header.key, manifest, { crypto: this.crypto, legacy: this._legacy })
719
720 if (!verifier.verify(batch, batch.signature)) {
721 throw INVALID_SIGNATURE('Proof contains an invalid signature')
722 }
723
724 if (!this.header.manifest) {
725 this.header.manifest = manifest
726 this.compat = verifier.compat
727 this.verifier = verifier
728 this.onupdate(0b10000, null, null, null)
729 }
730 }
731
732 async _verifyExclusive ({ batch, bitfield, value, manifest, from }) {
733 this._verifyBatchUpgrade(batch, manifest)
734
735 await this._mutex.lock()
736
737 try {
738 if (!batch.commitable()) return false
739 this.updating = true
740
741 const entry = {
742 userData: null,
743 treeNodes: batch.nodes,
744 treeUpgrade: batch,
745 bitfield
746 }
747
748 if (this.preupdate !== null) await this.preupdate(batch, this.header.key)
749 if (bitfield) await this._writeBlock(batch, bitfield.start, value)
750
751 await this.oplog.append([entry], false)
752
753 let status = 0b0001
754
755 if (bitfield) {
756 this._setBitfield(bitfield.start, true)
757 status |= updateContig(this.header, bitfield, this.bitfield)
758 }
759
760 batch.commit()
761
762 this.header.tree.fork = batch.fork
763 this.header.tree.length = batch.length
764 this.header.tree.rootHash = batch.hash()
765 this.header.tree.signature = batch.signature
766
767 this.onupdate(status, bitfield, value, from)
768
769 if (this._shouldFlush()) await this._flushOplog()
770 } finally {
771 this.updating = false
772 this._mutex.unlock()
773 }
774
775 return true
776 }
777
778 async _verifyShared () {
779 if (!this._verifies.length) return false
780
781 await this._mutex.lock()
782
783 const verifies = this._verifies
784 this._verifies = null
785 this._verified = null
786
787 try {
788 const entries = []
789
790 for (const { batch, bitfield, value } of verifies) {
791 if (!batch.commitable()) continue
792
793 if (bitfield) {
794 await this._writeBlock(batch, bitfield.start, value)
795 }
796
797 entries.push({
798 userData: null,
799 treeNodes: batch.nodes,
800 treeUpgrade: null,
801 bitfield
802 })
803 }
804
805 await this.oplog.append(entries, false)
806
807 for (let i = 0; i < verifies.length; i++) {
808 const { batch, bitfield, value, manifest, from } = verifies[i]
809
810 if (!batch.commitable()) {
811 verifies[i] = null // signal that we cannot commit this one
812 continue
813 }
814
815 let status = 0
816
817 if (bitfield) {
818 this._setBitfield(bitfield.start, true)
819 status = updateContig(this.header, bitfield, this.bitfield)
820 }
821
822 // if we got a manifest AND its strictly a non compat one, lets store it
823 if (manifest && this.header.manifest === null) {
824 if (!Verifier.isValidManifest(this.header.key, manifest)) throw INVALID_CHECKSUM('Manifest hash does not match')
825 this._setManifest(manifest, null)
826 }
827
828 batch.commit()
829
830 this.onupdate(status, bitfield, value, from)
831 }
832
833 if (this._shouldFlush()) await this._flushOplog()
834 } finally {
835 this._mutex.unlock()
836 }
837
838 return verifies[0] !== null
839 }
840
841 async checkConflict (proof, from) {
842 if (this.tree.length < proof.upgrade.length || proof.fork !== this.tree.fork) {
843 // out of date this proof - ignore for now
844 return false
845 }
846
847 const batch = this.tree.verifyFullyRemote(proof)
848
849 try {
850 this._verifyBatchUpgrade(batch, proof.manifest)
851 } catch {
852 return true
853 }
854
855 const remoteTreeHash = this.crypto.tree(proof.upgrade.nodes)
856 const localTreeHash = this.crypto.tree(await this.tree.getRoots(proof.upgrade.length))
857
858 if (b4a.equals(localTreeHash, remoteTreeHash)) return false
859
860 await this.onconflict(proof)
861 return true
862 }
863
864 async verifyReorg (proof) {
865 const batch = await this.tree.reorg(proof)
866
867 this._verifyBatchUpgrade(batch, proof.manifest)
868
869 return batch
870 }
871
872 async verify (proof, from) {
873 // We cannot apply "other forks" atm.
874 // We should probably still try and they are likely super similar for non upgrades
875 // but this is easy atm (and the above layer will just retry)
876 if (proof.fork !== this.tree.fork) return false
877
878 const batch = await this.tree.verify(proof)
879 if (!batch.commitable()) return false
880
881 const value = (proof.block && proof.block.value) || null
882 const op = {
883 batch,
884 bitfield: value && { drop: false, start: proof.block.index, length: 1 },
885 value,
886 manifest: proof.manifest,
887 from
888 }
889
890 if (batch.upgraded) return this._verifyExclusive(op)
891
892 if (this._verifies !== null) {
893 const verifies = this._verifies
894 const i = verifies.push(op)
895 await this._verified
896 return verifies[i] !== null
897 }
898
899 this._verifies = [op]
900 this._verified = this._verifyShared()
901 return this._verified
902 }
903
904 async reorg (batch, from) {
905 if (!batch.commitable()) return false
906
907 this.truncating++
908 await this._mutex.lock()
909
910 try {
911 if (!batch.commitable()) return false
912 await this._truncate(batch, from)
913 } finally {
914 this.truncating--
915 this._mutex.unlock()
916 }
917
918 return true
919 }
920
921 async _truncate (batch, from) {
922 const entry = {
923 userData: null,
924 treeNodes: batch.nodes,
925 treeUpgrade: batch,
926 bitfield: {
927 drop: true,
928 start: batch.ancestors,
929 length: this.tree.length - batch.ancestors
930 }
931 }
932
933 await this.oplog.append([entry], false)
934
935 this._setBitfieldRange(batch.ancestors, this.tree.length - batch.ancestors, false)
936 addReorgHint(this.header.hints.reorgs, this.tree, batch)
937 batch.commit()
938
939 const contigStatus = updateContig(this.header, entry.bitfield, this.bitfield)
940 const status = ((batch.length > batch.ancestors) ? 0b0011 : 0b0010) | contigStatus
941
942 this.header.tree.fork = batch.fork
943 this.header.tree.length = batch.length
944 this.header.tree.rootHash = batch.hash()
945 this.header.tree.signature = batch.signature
946
947 this.onupdate(status, entry.bitfield, null, from)
948
949 // TODO: there is a bug in the merkle tree atm where it cannot handle unflushed
950 // truncates if we append or download anything after the truncation point later on
951 // This is because tree.get checks the truncated flag. We should fix this so we can do
952 // the later flush here as well
953 // if (this._shouldFlush()) await this._flushOplog()
954 await this._flushOplog()
955 }
956
957 openSkipBitfield () {
958 if (this.skipBitfield !== null) return this.skipBitfield
959 this.skipBitfield = new RemoteBitfield()
960 const buf = this.bitfield.toBuffer(this.tree.length)
961 const bitfield = new Uint32Array(buf.buffer, buf.byteOffset, buf.byteLength / 4)
962 this.skipBitfield.insert(0, bitfield)
963 return this.skipBitfield
964 }
965
966 _setBitfield (index, value) {
967 this.bitfield.set(index, value)
968 if (this.skipBitfield !== null) this.skipBitfield.set(index, value)
969 }
970
971 _setBitfieldRange (start, length, value) {
972 this.bitfield.setRange(start, length, value)
973 if (this.skipBitfield !== null) this.skipBitfield.setRange(start, length, value)
974 }
975
976 async close () {
977 this.closed = true
978 await this._mutex.destroy()
979 await Promise.allSettled([
980 this.oplog.close(),
981 this.bitfield.close(),
982 this.tree.close(),
983 this.blocks.close(),
984 this.bigHeader.close()
985 ])
986 }
987}
988
989function updateContig (header, upd, bitfield) {
990 const end = upd.start + upd.length
991
992 let c = header.hints.contiguousLength
993
994 if (upd.drop) {
995 // If we dropped a block in the current contig range, "downgrade" it
996 if (c <= end && c > upd.start) {
997 c = upd.start
998 }
999 } else {
1000 if (c <= end && c >= upd.start) {
1001 c = end
1002 while (bitfield.get(c)) c++
1003 }
1004 }
1005
1006 if (c === header.hints.contiguousLength) {
1007 return 0b0000
1008 }
1009
1010 if (c > header.hints.contiguousLength) {
1011 header.hints.contiguousLength = c
1012 return 0b0100
1013 }
1014
1015 header.hints.contiguousLength = c
1016 return 0b1000
1017}
1018
1019function addReorgHint (list, tree, batch) {
1020 if (tree.length === 0 || tree.fork === batch.fork) return
1021
1022 while (list.length >= 4) list.shift() // 4 here is arbitrary, just want it to be small (hints only)
1023 while (list.length > 0) {
1024 if (list[list.length - 1].ancestors > batch.ancestors) list.pop()
1025 else break
1026 }
1027
1028 list.push({ from: tree.fork, to: batch.fork, ancestors: batch.ancestors })
1029}
1030
1031function updateUserData (list, key, value) {
1032 value = unslab(value)
1033
1034 for (let i = 0; i < list.length; i++) {
1035 if (list[i].key === key) {
1036 if (value) list[i].value = value
1037 else list.splice(i, 1)
1038 return
1039 }
1040 }
1041 if (value) list.push({ key, value })
1042}
1043
1044function closeAll (...storages) {
1045 let missing = 1
1046 let error = null
1047
1048 return new Promise((resolve, reject) => {
1049 for (const s of storages) {
1050 missing++
1051 s.close(done)
1052 }
1053
1054 done(null)
1055
1056 function done (err) {
1057 if (err) error = err
1058 if (--missing) return
1059 if (error) reject(error)
1060 else resolve()
1061 }
1062 })
1063}
1064
1065async function flushHeader (oplog, bigHeader, header) {
1066 if (header.external) {
1067 await bigHeader.flush(header)
1068 }
1069
1070 try {
1071 await oplog.flush(header)
1072 } catch (err) {
1073 if (err.code !== 'OPLOG_HEADER_OVERFLOW') throw err
1074 await bigHeader.flush(header)
1075 await oplog.flush(header)
1076 }
1077}
1078
1079function noop () {}
1080
1081function maximumSegmentStart (start, src, dst) {
1082 while (true) {
1083 const a = src.firstSet(start)
1084 const b = dst.firstUnset(start)
1085
1086 if (a === -1) return -1
1087 if (b === -1) return a
1088
1089 // if dst has the segment, restart
1090 if (a < b) {
1091 start = b
1092 continue
1093 }
1094
1095 return a
1096 }
1097}
1098
1099function minimumSegmentEnd (start, src, dst) {
1100 const a = src.firstUnset(start)
1101 const b = dst.firstSet(start)
1102
1103 if (a === -1) return -1
1104 if (b === -1) return a
1105 return a < b ? a : b
1106}
node_modules/hypercore/lib/download.js +22 -0
……@@ -0,0 +1,22 @@
1module.exports = class Download {
2 constructor (req) {
3 this.req = req
4 }
5
6 async done () {
7 return (await this.req).promise
8 }
9
10 /**
11 * Deprecated. Use `range.done()`.
12 */
13 downloaded () {
14 return this.done()
15 }
16
17 destroy () {
18 this.req.then(req => req.context && req.context.detach(req), noop)
19 }
20}
21
22function noop () {}
node_modules/hypercore/lib/hotswap-queue.js +60 -0
……@@ -0,0 +1,60 @@
1const TICKS = 16
2
3module.exports = class HotswapQueue {
4 constructor () {
5 this.priorities = [[], [], []]
6 }
7
8 * pick (peer) {
9 for (let i = 0; i < this.priorities.length; i++) {
10 // try first one more than second one etc etc
11 let ticks = (this.priorities.length - i) * TICKS
12 const queue = this.priorities[i]
13
14 for (let j = 0; j < queue.length; j++) {
15 const r = j + Math.floor(Math.random() * queue.length - j)
16 const a = queue[j]
17 const b = queue[r]
18
19 if (r !== j) {
20 queue[(b.hotswap.index = j)] = b
21 queue[(a.hotswap.index = r)] = a
22 }
23
24 if (hasInflight(b, peer)) continue
25
26 yield b
27
28 if (--ticks <= 0) break
29 }
30 }
31 }
32
33 add (block) {
34 if (block.hotswap !== null) this.remove(block)
35 if (block.inflight.length === 0 || block.inflight.length >= 3) return
36
37 // TODO: also use other stuff to determine queue prio
38 const queue = this.priorities[block.inflight.length - 1]
39
40 const index = queue.push(block) - 1
41 block.hotswap = { ref: this, queue, index }
42 }
43
44 remove (block) {
45 const hotswap = block.hotswap
46 if (hotswap === null) return
47
48 block.hotswap = null
49 const head = hotswap.queue.pop()
50 if (head === block) return
51 hotswap.queue[(head.hotswap.index = hotswap.index)] = head
52 }
53}
54
55function hasInflight (block, peer) {
56 for (let j = 0; j < block.inflight.length; j++) {
57 if (block.inflight[j].peer === peer) return true
58 }
59 return false
60}
node_modules/hypercore/lib/info.js +53 -0
……@@ -0,0 +1,53 @@
1module.exports = class Info {
2 constructor (opts = {}) {
3 this.key = opts.key
4 this.discoveryKey = opts.discoveryKey
5 this.length = opts.length || 0
6 this.contiguousLength = opts.contiguousLength || 0
7 this.byteLength = opts.byteLength || 0
8 this.fork = opts.fork || 0
9 this.padding = opts.padding || 0
10 this.storage = opts.storage || null
11 }
12
13 static async from (session, opts = {}) {
14 return new Info({
15 key: session.key,
16 discoveryKey: session.discoveryKey,
17 length: session.length,
18 contiguousLength: session.contiguousLength,
19 byteLength: session.byteLength,
20 fork: session.fork,
21 padding: session.padding,
22 storage: opts.storage ? await this.storage(session) : null
23 })
24 }
25
26 static async storage (session) {
27 const { oplog, tree, blocks, bitfield } = session.core
28 try {
29 return {
30 oplog: await Info.bytesUsed(oplog.storage),
31 tree: await Info.bytesUsed(tree.storage),
32 blocks: await Info.bytesUsed(blocks.storage),
33 bitfield: await Info.bytesUsed(bitfield.storage)
34 }
35 } catch {
36 return null
37 }
38 }
39
40 static bytesUsed (file) {
41 return new Promise((resolve, reject) => {
42 file.stat((err, st) => {
43 if (err) {
44 resolve(0) // prob just file not found (TODO, improve)
45 } else if (typeof st.blocks !== 'number') {
46 reject(new Error('cannot determine bytes used'))
47 } else {
48 resolve(st.blocks * 512)
49 }
50 })
51 })
52 }
53}
node_modules/hypercore/lib/merkle-tree.js +1402 -0
……@@ -0,0 +1,1402 @@
1const flat = require('flat-tree')
2const crypto = require('hypercore-crypto')
3const c = require('compact-encoding')
4const Xache = require('xache')
5const b4a = require('b4a')
6const unslab = require('unslab')
7const caps = require('./caps')
8const { INVALID_PROOF, INVALID_CHECKSUM, INVALID_OPERATION, BAD_ARGUMENT, ASSERTION } = require('hypercore-errors')
9
10const BLANK_HASH = b4a.alloc(32)
11const OLD_TREE = b4a.from([5, 2, 87, 2, 0, 0, 40, 7, 66, 76, 65, 75, 69, 50, 98])
12const TREE_CACHE = 128 // speeds up linear scans by A LOT
13
14class NodeQueue {
15 constructor (nodes, extra = null) {
16 this.i = 0
17 this.nodes = nodes
18 this.extra = extra
19 this.length = nodes.length + (this.extra === null ? 0 : 1)
20 }
21
22 shift (index) {
23 if (this.extra !== null && this.extra.index === index) {
24 const node = this.extra
25 this.extra = null
26 this.length--
27 return node
28 }
29
30 if (this.i >= this.nodes.length) {
31 throw INVALID_OPERATION('Expected node ' + index + ', got (nil)')
32 }
33
34 const node = this.nodes[this.i++]
35 if (node.index !== index) {
36 throw INVALID_OPERATION('Expected node ' + index + ', got node ' + node.index)
37 }
38
39 this.length--
40 return node
41 }
42}
43
44class MerkleTreeBatch {
45 constructor (tree) {
46 this.fork = tree.fork
47 this.roots = [...tree.roots]
48 this.length = tree.length
49 this.ancestors = tree.length
50 this.byteLength = tree.byteLength
51 this.signature = null
52 this.hashCached = null
53
54 this.treeLength = tree.length
55 this.treeFork = tree.fork
56 this.tree = tree
57 this.nodes = []
58 this.upgraded = false
59 }
60
61 checkout (length, additionalRoots) {
62 const roots = []
63 let r = 0
64
65 const head = 2 * length - 2
66 const gaps = new Set()
67 const all = new Map()
68
69 // additional roots is so the original roots can be passed (we mutate the array in appendRoot)
70 if (additionalRoots) {
71 for (const node of additionalRoots) all.set(node.index, node)
72 }
73
74 for (const node of this.nodes) all.set(node.index, node)
75
76 for (const index of flat.fullRoots(head + 2)) {
77 const left = flat.leftSpan(index)
78 if (left !== 0) gaps.add(left - 1)
79
80 if (r < this.roots.length && this.roots[r].index === index) {
81 roots.push(this.roots[r++])
82 continue
83 }
84 const node = all.get(index)
85 if (!node) throw new BAD_ARGUMENT('root missing for given length')
86 roots.push(node)
87 }
88
89 this.roots = roots
90 this.length = length
91 this.byteLength = totalSize(roots)
92 this.hashCached = null
93 this.signature = null
94
95 for (let i = 0; i < this.nodes.length; i++) {
96 const index = this.nodes[i].index
97 if (index <= head && !gaps.has(index)) continue
98 const last = this.nodes.pop()
99 if (i < this.nodes.length) this.nodes[i--] = last
100 }
101 }
102
103 prune (length) {
104 if (length === 0) return
105
106 const head = 2 * length - 2
107 const gaps = new Set()
108
109 // TODO: make a function for this in flat-tree
110 for (const index of flat.fullRoots(head + 2)) {
111 const left = flat.leftSpan(index)
112 if (left !== 0) gaps.add(left - 1)
113 }
114
115 for (let i = 0; i < this.nodes.length; i++) {
116 const index = this.nodes[i].index
117 if (index > head || gaps.has(index)) continue
118 const last = this.nodes.pop()
119 if (i < this.nodes.length) this.nodes[i--] = last
120 }
121 }
122
123 clone () {
124 const b = new MerkleTreeBatch(this.tree)
125
126 b.fork = this.fork
127 b.roots = [...this.roots]
128 b.length = this.length
129 b.byteLength = this.byteLength
130 b.signature = this.signature
131 b.treeLength = this.treeLength
132 b.treeFork = this.treeFork
133 b.tree = this.tree
134 b.nodes = [...this.nodes]
135 b.upgraded = this.upgraded
136
137 return b
138 }
139
140 hash () {
141 if (this.hashCached === null) this.hashCached = unslab(this.tree.crypto.tree(this.roots))
142 return this.hashCached
143 }
144
145 signable (manifestHash) {
146 return caps.treeSignable(manifestHash, this.hash(), this.length, this.fork)
147 }
148
149 signableCompat (noHeader) {
150 return caps.treeSignableCompat(this.hash(), this.length, this.fork, noHeader)
151 }
152
153 get (index, error) {
154 if (index >= this.length * 2) {
155 return null
156 }
157
158 for (const n of this.nodes) {
159 if (n.index === index) return n
160 }
161
162 return this.tree.get(index, error)
163 }
164
165 proof ({ block, hash, seek, upgrade }) {
166 return generateProof(this, block, hash, seek, upgrade)
167 }
168
169 verifyUpgrade (proof) {
170 const unverified = verifyTree(proof, this.tree.crypto, this.nodes)
171
172 if (!proof.upgrade) throw INVALID_OPERATION('Expected upgrade proof')
173
174 return verifyUpgrade(proof, unverified, this)
175 }
176
177 append (buf) {
178 const head = this.length * 2
179 const ite = flat.iterator(head)
180 const node = blockNode(this.tree.crypto, head, buf)
181
182 this.appendRoot(node, ite)
183 }
184
185 appendRoot (node, ite) {
186 node = unslabNode(node)
187 this.hashCached = null
188 this.upgraded = true
189 this.length += ite.factor / 2
190 this.byteLength += node.size
191 this.roots.push(node)
192 this.nodes.push(node)
193
194 while (this.roots.length > 1) {
195 const a = this.roots[this.roots.length - 1]
196 const b = this.roots[this.roots.length - 2]
197
198 // TODO: just have a peek sibling instead? (pretty sure it's always the left sib as well)
199 if (ite.sibling() !== b.index) {
200 ite.sibling() // unset so it always points to last root
201 break
202 }
203
204 const node = unslabNode(parentNode(this.tree.crypto, ite.parent(), a, b))
205 this.nodes.push(node)
206 this.roots.pop()
207 this.roots.pop()
208 this.roots.push(node)
209 }
210 }
211
212 commitable () {
213 return this.treeFork === this.tree.fork && (
214 this.upgraded
215 ? this.treeLength === this.tree.length
216 : this.treeLength <= this.tree.length
217 )
218 }
219
220 commit () {
221 if (!this.commitable()) throw INVALID_OPERATION('Tree was modified during batch, refusing to commit')
222
223 if (this.upgraded) this._commitUpgrade()
224
225 for (let i = 0; i < this.nodes.length; i++) {
226 const node = this.nodes[i]
227 this.tree.unflushed.set(node.index, node)
228 }
229 }
230
231 _commitUpgrade () {
232 // TODO: If easy to detect, we should refuse an trunc+append here without a fork id
233 // change. Will only happen on user error so mostly to prevent that.
234
235 if (this.ancestors < this.treeLength) {
236 if (this.ancestors > 0) {
237 const head = 2 * this.ancestors
238 const ite = flat.iterator(head - 2)
239
240 while (true) {
241 if (ite.contains(head) && ite.index < head) {
242 this.tree.unflushed.set(ite.index, blankNode(ite.index))
243 }
244 if (ite.offset === 0) break
245 ite.parent()
246 }
247 }
248
249 this.tree.truncateTo = this.tree.truncated
250 ? Math.min(this.tree.truncateTo, this.ancestors)
251 : this.ancestors
252
253 this.tree.truncated = true
254 this.tree.cache = new Xache({ maxSize: this.tree.cache.maxSize })
255 truncateMap(this.tree.unflushed, this.ancestors)
256 if (this.tree.flushing !== null) truncateMap(this.tree.flushing, this.ancestors)
257 }
258
259 this.tree.roots = this.roots
260 this.tree.length = this.length
261 this.tree.byteLength = this.byteLength
262 this.tree.fork = this.fork
263 this.tree.signature = this.signature
264 }
265
266 seek (bytes, padding) {
267 return new ByteSeeker(this, bytes, padding)
268 }
269
270 byteRange (index) {
271 return getByteRange(this, index)
272 }
273
274 byteOffset (index) {
275 if (index === 2 * this.tree.length) return this.tree.byteLength
276 return getByteOffset(this, index)
277 }
278}
279
280class ReorgBatch extends MerkleTreeBatch {
281 constructor (tree) {
282 super(tree)
283 this.roots = []
284 this.length = 0
285 this.byteLength = 0
286 this.diff = null
287 this.ancestors = 0
288 // We set upgraded because reorgs are signed so hit will
289 // hit the same code paths (like the treeLength check in commit)
290 this.upgraded = true
291 this.want = {
292 nodes: 0,
293 start: 0,
294 end: 0
295 }
296 }
297
298 get finished () {
299 return this.want === null
300 }
301
302 update (proof) {
303 if (this.want === null) return true
304
305 const nodes = []
306 const root = verifyTree(proof, this.tree.crypto, nodes)
307
308 if (root === null || !b4a.equals(root.hash, this.diff.hash)) return false
309
310 this.nodes.push(...nodes)
311 return this._update(nodes)
312 }
313
314 async _update (nodes) {
315 const n = new Map()
316 for (const node of nodes) n.set(node.index, node)
317
318 let diff = null
319 const ite = flat.iterator(this.diff.index)
320 const startingDiff = this.diff
321
322 while ((ite.index & 1) !== 0) {
323 const left = n.get(ite.leftChild())
324 if (!left) break
325
326 const existing = await this.tree.get(left.index, false)
327 if (!existing || !b4a.equals(existing.hash, left.hash)) {
328 diff = left
329 } else {
330 diff = n.get(ite.sibling())
331 }
332 }
333
334 if ((this.diff.index & 1) === 0) return true
335 if (diff === null) return false
336 if (startingDiff !== this.diff) return false
337
338 return this._updateDiffRoot(diff)
339 }
340
341 _updateDiffRoot (diff) {
342 if (this.want === null) return true
343
344 const spans = flat.spans(diff.index)
345 const start = spans[0] / 2
346 const end = Math.min(this.treeLength, spans[1] / 2 + 1)
347 const len = end - start
348
349 this.ancestors = start
350 this.diff = diff
351
352 if ((diff.index & 1) === 0 || this.want.start >= this.treeLength || len <= 0) {
353 this.want = null
354 return true
355 }
356
357 this.want.start = start
358 this.want.end = end
359 this.want.nodes = log2(spans[1] - spans[0] + 2) - 1
360
361 return false
362 }
363}
364
365class ByteSeeker {
366 constructor (tree, bytes, padding = 0) {
367 this.tree = tree
368 this.bytes = bytes
369 this.padding = padding
370
371 const size = tree.byteLength - (tree.length * padding)
372
373 this.start = bytes >= size ? tree.length : 0
374 this.end = bytes < size ? tree.length : 0
375 }
376
377 async _seek (bytes) {
378 if (!bytes) return [0, 0]
379
380 for (const node of this.tree.roots) { // all async ticks happen once we find the root so safe
381 const size = getUnpaddedSize(node, this.padding, null)
382
383 if (bytes === size) return [flat.rightSpan(node.index) + 2, 0]
384 if (bytes > size) {
385 bytes -= size
386 continue
387 }
388
389 const ite = flat.iterator(node.index)
390
391 while ((ite.index & 1) !== 0) {
392 const l = await this.tree.get(ite.leftChild(), false)
393
394 if (l) {
395 const size = getUnpaddedSize(l, this.padding, ite)
396
397 if (size === bytes) return [ite.rightSpan() + 2, 0]
398 if (size > bytes) continue
399 bytes -= size
400 ite.sibling()
401 } else {
402 ite.parent()
403 return [ite.index, bytes]
404 }
405 }
406
407 return [ite.index, bytes]
408 }
409
410 return null
411 }
412
413 async update () { // TODO: combine _seek and this, much simpler
414 const res = await this._seek(this.bytes)
415 if (!res) return null
416 if ((res[0] & 1) === 0) return [res[0] / 2, res[1]]
417
418 const span = flat.spans(res[0])
419 this.start = span[0] / 2
420 this.end = span[1] / 2 + 1
421
422 return null
423 }
424}
425
426module.exports = class MerkleTree {
427 constructor (storage, roots, fork, signature, prologue) {
428 this.crypto = crypto
429 this.fork = fork
430 this.roots = roots
431 this.length = roots.length ? totalSpan(roots) / 2 : 0
432 this.byteLength = totalSize(roots)
433 this.signature = signature
434 this.prologue = prologue
435
436 this.storage = storage
437 this.unflushed = new Map()
438 this.cache = new Xache({ maxSize: TREE_CACHE })
439 this.flushing = null
440 this.truncated = false
441 this.truncateTo = 0
442 }
443
444 addNode (node) {
445 if (node.size === 0 && b4a.equals(node.hash, BLANK_HASH)) node = blankNode(node.index)
446 this.unflushed.set(node.index, node)
447 }
448
449 batch () {
450 return new MerkleTreeBatch(this)
451 }
452
453 async restoreBatch (length) {
454 const batch = new MerkleTreeBatch(this)
455 if (length === this.length) return batch
456
457 const roots = unslabNodes(await this.getRoots(length))
458
459 batch.roots = roots
460 batch.length = length
461 batch.byteLength = 0
462 batch.ancestors = length
463
464 for (const node of roots) batch.byteLength += node.size
465
466 return batch
467 }
468
469 seek (bytes, padding) {
470 return new ByteSeeker(this, bytes, padding)
471 }
472
473 hash () {
474 return unslab(this.crypto.tree(this.roots))
475 }
476
477 signable (namespace) {
478 return caps.treeSignable(namespace, this.hash(), this.length, this.fork)
479 }
480
481 getRoots (length) {
482 const indexes = flat.fullRoots(2 * length)
483 const roots = new Array(indexes.length)
484
485 for (let i = 0; i < indexes.length; i++) {
486 roots[i] = this.get(indexes[i], true)
487 }
488
489 return Promise.all(roots)
490 }
491
492 setPrologue ({ hash, length }) {
493 this.prologue = { hash, length }
494 }
495
496 addNodes (nodes) {
497 for (let i = 0; i < nodes.length; i++) {
498 const node = nodes[i]
499 this.unflushed.set(node.index, node)
500 }
501 }
502
503 getNeededNodes (length, start, end) {
504 const nodes = new Map()
505 const head = length * 2
506
507 for (let i = start; i < end; i++) {
508 const ite = flat.iterator(i * 2)
509
510 while (true) {
511 if (nodes.has(ite.index)) break
512 nodes.set(ite.index, this.get(ite.index, true))
513
514 const sibling = ite.sibling()
515
516 ite.parent()
517 if (ite.contains(head)) break
518
519 if (nodes.has(sibling)) break
520 nodes.set(sibling, this.get(sibling, true))
521 }
522 }
523
524 return Promise.all([...nodes.values()])
525 }
526
527 async upgradeable (length) {
528 const indexes = flat.fullRoots(2 * length)
529 const roots = new Array(indexes.length)
530
531 for (let i = 0; i < indexes.length; i++) {
532 roots[i] = this.get(indexes[i], false)
533 }
534
535 for (const node of await Promise.all(roots)) {
536 if (node === null) return false
537 }
538
539 return true
540 }
541
542 blankNode (index) {
543 return blankNode(index)
544 }
545
546 get (index, error = true) {
547 const c = this.cache.get(index)
548 if (c) return c
549
550 let node = this.unflushed.get(index)
551
552 if (this.flushing !== null && node === undefined) {
553 node = this.flushing.get(index)
554 }
555
556 // TODO: test this
557 if (this.truncated && node !== undefined && node.index >= 2 * this.truncateTo) {
558 node = blankNode(index)
559 }
560
561 if (node !== undefined) {
562 if (node.hash === BLANK_HASH) {
563 if (error) throw INVALID_OPERATION('Could not load node: ' + index)
564 return Promise.resolve(null)
565 }
566 return Promise.resolve(node)
567 }
568
569 return getStoredNode(this.storage, index, this.cache, error)
570 }
571
572 async flush () {
573 this.flushing = this.unflushed
574 this.unflushed = new Map()
575
576 try {
577 if (this.truncated) await this._flushTruncation()
578 await this._flushNodes()
579 } catch (err) {
580 for (const node of this.flushing.values()) {
581 if (!this.unflushed.has(node.index)) this.unflushed.set(node.index, node)
582 }
583 throw err
584 } finally {
585 this.flushing = null
586 }
587 }
588
589 _flushTruncation () {
590 return new Promise((resolve, reject) => {
591 const t = this.truncateTo
592 const offset = t === 0 ? 0 : (t - 1) * 80 + 40
593
594 this.storage.truncate(offset, (err) => {
595 if (err) return reject(err)
596
597 if (this.truncateTo === t) {
598 this.truncateTo = 0
599 this.truncated = false
600 }
601
602 resolve()
603 })
604 })
605 }
606
607 _flushNodes () {
608 // TODO: write neighbors together etc etc
609 // TODO: bench loading a full disk page and copy to that instead
610 return new Promise((resolve, reject) => {
611 const slab = b4a.allocUnsafe(40 * this.flushing.size)
612
613 let error = null
614 let missing = this.flushing.size + 1
615 let offset = 0
616
617 for (const node of this.flushing.values()) {
618 const state = {
619 start: 0,
620 end: 40,
621 buffer: slab.subarray(offset, offset += 40)
622 }
623
624 c.uint64.encode(state, node.size)
625 c.raw.encode(state, node.hash)
626
627 this.storage.write(node.index * 40, state.buffer, done)
628 }
629
630 done(null)
631
632 function done (err) {
633 if (err) error = err
634 if (--missing > 0) return
635 if (error) reject(error)
636 else resolve()
637 }
638 })
639 }
640
641 clear () {
642 this.cache = new Xache({ maxSize: this.cache.maxSize })
643 this.truncated = true
644 this.truncateTo = 0
645 this.roots = []
646 this.length = 0
647 this.byteLength = 0
648 this.fork = 0
649 this.signature = null
650 if (this.flushing !== null) this.flushing.clear()
651 this.unflushed.clear()
652 return this.flush()
653 }
654
655 close () {
656 return new Promise((resolve, reject) => {
657 this.storage.close(err => {
658 if (err) reject(err)
659 else resolve()
660 })
661 })
662 }
663
664 async truncate (length, fork = this.fork) {
665 const head = length * 2
666 const batch = new MerkleTreeBatch(this)
667 const fullRoots = flat.fullRoots(head)
668
669 for (let i = 0; i < fullRoots.length; i++) {
670 const root = fullRoots[i]
671 if (i < batch.roots.length && batch.roots[i].index === root) continue
672
673 while (batch.roots.length > i) batch.roots.pop()
674 batch.roots.push(unslabNode(await this.get(root)))
675 }
676
677 while (batch.roots.length > fullRoots.length) {
678 batch.roots.pop()
679 }
680
681 batch.fork = fork
682 batch.length = length
683 batch.ancestors = length
684 batch.byteLength = totalSize(batch.roots)
685 batch.upgraded = true
686
687 return batch
688 }
689
690 async reorg (proof) {
691 const batch = new ReorgBatch(this)
692
693 let unverified = null
694
695 if (proof.block || proof.hash || proof.seek) {
696 unverified = verifyTree(proof, this.crypto, batch.nodes)
697 }
698
699 if (!verifyUpgrade(proof, unverified, batch)) {
700 throw INVALID_PROOF('Fork proof not verifiable')
701 }
702
703 for (const root of batch.roots) {
704 const existing = await this.get(root.index, false)
705 if (existing && b4a.equals(existing.hash, root.hash)) continue
706 batch._updateDiffRoot(root)
707 break
708 }
709
710 if (batch.diff !== null) {
711 await batch._update(batch.nodes)
712 } else {
713 batch.want = null
714 batch.ancestors = batch.length
715 }
716
717 return batch
718 }
719
720 verifyFullyRemote (proof) {
721 // TODO: impl this less hackishly
722 const batch = new MerkleTreeBatch(this)
723
724 batch.fork = proof.fork
725 batch.roots = []
726 batch.length = 0
727 batch.ancestors = 0
728 batch.byteLength = 0
729
730 let unverified = verifyTree(proof, this.crypto, batch.nodes)
731
732 if (proof.upgrade) {
733 if (verifyUpgrade(proof, unverified, batch)) {
734 unverified = null
735 }
736 }
737
738 return batch
739 }
740
741 async verify (proof) {
742 const batch = new MerkleTreeBatch(this)
743
744 let unverified = verifyTree(proof, this.crypto, batch.nodes)
745
746 if (proof.upgrade) {
747 if (verifyUpgrade(proof, unverified, batch)) {
748 unverified = null
749 }
750 }
751
752 if (unverified) {
753 const verified = await this.get(unverified.index)
754 if (!b4a.equals(verified.hash, unverified.hash)) {
755 throw INVALID_CHECKSUM('Invalid checksum at node ' + unverified.index)
756 }
757 }
758
759 return batch
760 }
761
762 proof ({ block, hash, seek, upgrade }) {
763 return generateProof(this, block, hash, seek, upgrade)
764 }
765
766 // Successor to .nodes()
767 async missingNodes (index) {
768 const head = 2 * this.length
769 const ite = flat.iterator(index)
770
771 // See iterator.rightSpan()
772 const iteRightSpan = ite.index + ite.factor / 2 - 1
773 // If the index is not in the current tree, we do not know how many missing nodes there are...
774 if (iteRightSpan >= head) return 0
775
776 let cnt = 0
777 while (!ite.contains(head) && (await this.get(ite.index, false)) === null) {
778 cnt++
779 ite.parent()
780 }
781
782 return cnt
783 }
784
785 // Deprecated
786 async nodes (index) {
787 const head = 2 * this.length
788 const ite = flat.iterator(index)
789
790 let cnt = 0
791 while (!ite.contains(head) && (await this.get(ite.index, false)) === null) {
792 cnt++
793 ite.parent()
794 }
795
796 return cnt
797 }
798
799 byteRange (index) {
800 return getByteRange(this, index)
801 }
802
803 byteOffset (index) {
804 return getByteOffset(this, index)
805 }
806
807 static async open (storage, opts = {}) {
808 await new Promise((resolve, reject) => {
809 storage.read(0, OLD_TREE.length, (err, buf) => {
810 if (err) return resolve()
811 if (b4a.equals(buf, OLD_TREE)) return reject(new Error('Storage contains an incompatible merkle tree'))
812 resolve()
813 })
814 })
815
816 const length = typeof opts.length === 'number'
817 ? opts.length
818 : await autoLength(storage)
819
820 const roots = []
821 for (const index of flat.fullRoots(2 * length)) {
822 roots.push(unslabNode(await getStoredNode(storage, index, null, true)))
823 }
824
825 return new MerkleTree(storage, roots, opts.fork || 0, opts.signature || null, opts.prologue || null)
826 }
827}
828
829async function getByteRange (tree, index) {
830 const head = 2 * tree.length
831 if (((index & 1) === 0 ? index : flat.rightSpan(index)) >= head) {
832 throw BAD_ARGUMENT('Index is out of bounds')
833 }
834 return [await tree.byteOffset(index), (await tree.get(index)).size]
835}
836
837async function getByteOffset (tree, index) {
838 if (index === 2 * tree.length) return tree.byteLength
839 if ((index & 1) === 1) index = flat.leftSpan(index)
840
841 let head = 0
842 let offset = 0
843
844 for (const node of tree.roots) { // all async ticks happen once we find the root so safe
845 head += 2 * ((node.index - head) + 1)
846
847 if (index >= head) {
848 offset += node.size
849 continue
850 }
851
852 const ite = flat.iterator(node.index)
853
854 while (ite.index !== index) {
855 if (index < ite.index) {
856 ite.leftChild()
857 } else {
858 offset += (await tree.get(ite.leftChild())).size
859 ite.sibling()
860 }
861 }
862
863 return offset
864 }
865
866 throw ASSERTION('Failed to find offset')
867}
868
869// All the methods needed for proof verification
870
871function verifyTree ({ block, hash, seek }, crypto, nodes) {
872 const untrustedNode = block
873 ? { index: 2 * block.index, value: block.value, nodes: block.nodes }
874 : hash
875 ? { index: hash.index, value: null, nodes: hash.nodes }
876 : null
877
878 if (untrustedNode === null && (!seek || !seek.nodes.length)) return null
879
880 let root = null
881
882 if (seek && seek.nodes.length) {
883 const ite = flat.iterator(seek.nodes[0].index)
884 const q = new NodeQueue(seek.nodes)
885
886 root = q.shift(ite.index)
887 nodes.push(root)
888
889 while (q.length > 0) {
890 const node = q.shift(ite.sibling())
891
892 root = parentNode(crypto, ite.parent(), root, node)
893 nodes.push(node)
894 nodes.push(root)
895 }
896 }
897
898 if (untrustedNode === null) return root
899
900 const ite = flat.iterator(untrustedNode.index)
901 const blockHash = untrustedNode.value && blockNode(crypto, ite.index, untrustedNode.value)
902
903 const q = new NodeQueue(untrustedNode.nodes, root)
904
905 root = blockHash || q.shift(ite.index)
906 nodes.push(root)
907
908 while (q.length > 0) {
909 const node = q.shift(ite.sibling())
910
911 root = parentNode(crypto, ite.parent(), root, node)
912 nodes.push(node)
913 nodes.push(root)
914 }
915
916 return root
917}
918
919function verifyUpgrade ({ fork, upgrade }, blockRoot, batch) {
920 const prologue = batch.tree.prologue
921
922 if (prologue) {
923 const { start, length } = upgrade
924 if (start < prologue.length && (start !== 0 || length < prologue.length)) {
925 throw INVALID_PROOF('Upgrade does not satisfy prologue')
926 }
927 }
928
929 const q = new NodeQueue(upgrade.nodes, blockRoot)
930
931 let grow = batch.roots.length > 0
932 let i = 0
933
934 const to = 2 * (upgrade.start + upgrade.length)
935 const ite = flat.iterator(0)
936
937 for (; ite.fullRoot(to); ite.nextTree()) {
938 if (i < batch.roots.length && batch.roots[i].index === ite.index) {
939 i++
940 continue
941 }
942
943 if (grow) {
944 grow = false
945 const root = ite.index
946 if (i < batch.roots.length) {
947 ite.seek(batch.roots[batch.roots.length - 1].index)
948 while (ite.index !== root) {
949 batch.appendRoot(q.shift(ite.sibling()), ite)
950 }
951 continue
952 }
953 }
954
955 batch.appendRoot(q.shift(ite.index), ite)
956 }
957
958 if (prologue && batch.length === prologue.length) {
959 if (!b4a.equals(prologue.hash, batch.hash())) {
960 throw INVALID_PROOF('Invalid hash')
961 }
962 }
963
964 const extra = upgrade.additionalNodes
965
966 ite.seek(batch.roots[batch.roots.length - 1].index)
967 i = 0
968
969 while (i < extra.length && extra[i].index === ite.sibling()) {
970 batch.appendRoot(extra[i++], ite)
971 }
972
973 while (i < extra.length) {
974 const node = extra[i++]
975
976 while (node.index !== ite.index) {
977 if (ite.factor === 2) throw INVALID_OPERATION('Unexpected node: ' + node.index)
978 ite.leftChild()
979 }
980
981 batch.appendRoot(node, ite)
982 ite.sibling()
983 }
984
985 batch.signature = unslab(upgrade.signature)
986 batch.fork = fork
987
988 return q.extra === null
989}
990
991async function seekFromHead (tree, head, bytes, padding) {
992 const roots = flat.fullRoots(head)
993
994 for (let i = 0; i < roots.length; i++) {
995 const root = roots[i]
996 const node = await tree.get(root)
997 const size = getUnpaddedSize(node, padding, null)
998
999 if (bytes === size) return root
1000 if (bytes > size) {
1001 bytes -= size
1002 continue
1003 }
1004
1005 return seekTrustedTree(tree, root, bytes, padding)
1006 }
1007
1008 return head
1009}
1010
1011// trust that bytes are within the root tree and find the block at bytes
1012
1013async function seekTrustedTree (tree, root, bytes, padding) {
1014 if (!bytes) return root
1015
1016 const ite = flat.iterator(root)
1017
1018 while ((ite.index & 1) !== 0) {
1019 const l = await tree.get(ite.leftChild(), false)
1020 if (l) {
1021 const size = getUnpaddedSize(l, padding, ite)
1022 if (size === bytes) return ite.index
1023 if (size > bytes) continue
1024 bytes -= size
1025 ite.sibling()
1026 } else {
1027 ite.parent()
1028 return ite.index
1029 }
1030 }
1031
1032 return ite.index
1033}
1034
1035// try to find the block at bytes without trusting that is *is* within the root passed
1036
1037async function seekUntrustedTree (tree, root, bytes, padding) {
1038 const offset = await tree.byteOffset(root) - (padding ? padding * flat.leftSpan(root) / 2 : 0)
1039
1040 if (offset > bytes) throw INVALID_OPERATION('Invalid seek')
1041 if (offset === bytes) return root
1042
1043 bytes -= offset
1044
1045 const node = await tree.get(root)
1046
1047 if (getUnpaddedSize(node, padding, null) <= bytes) throw INVALID_OPERATION('Invalid seek')
1048
1049 return seekTrustedTree(tree, root, bytes, padding)
1050}
1051
1052// Below is proof production, ie, construct proofs to verify a request
1053// Note, that all these methods are sync as we can statically infer which nodes
1054// are needed for the remote to verify given they arguments they passed us
1055
1056function seekProof (tree, seekRoot, root, p) {
1057 const ite = flat.iterator(seekRoot)
1058
1059 p.seek = []
1060 p.seek.push(tree.get(ite.index))
1061
1062 while (ite.index !== root) {
1063 ite.sibling()
1064 p.seek.push(tree.get(ite.index))
1065 ite.parent()
1066 }
1067}
1068
1069function blockAndSeekProof (tree, node, seek, seekRoot, root, p) {
1070 if (!node) return seekProof(tree, seekRoot, root, p)
1071
1072 const ite = flat.iterator(node.index)
1073
1074 p.node = []
1075 if (!node.value) p.node.push(tree.get(ite.index))
1076
1077 while (ite.index !== root) {
1078 ite.sibling()
1079
1080 if (seek && ite.contains(seekRoot) && ite.index !== seekRoot) {
1081 seekProof(tree, seekRoot, ite.index, p)
1082 } else {
1083 p.node.push(tree.get(ite.index))
1084 }
1085
1086 ite.parent()
1087 }
1088}
1089
1090function upgradeProof (tree, node, seek, from, to, subTree, p) {
1091 if (from === 0) p.upgrade = []
1092
1093 for (const ite = flat.iterator(0); ite.fullRoot(to); ite.nextTree()) {
1094 // check if they already have the node
1095 if (ite.index + ite.factor / 2 < from) continue
1096
1097 // connect existing tree
1098 if (p.upgrade === null && ite.contains(from - 2)) {
1099 p.upgrade = []
1100
1101 const root = ite.index
1102 const target = from - 2
1103
1104 ite.seek(target)
1105
1106 while (ite.index !== root) {
1107 ite.sibling()
1108 if (ite.index > target) {
1109 if (p.node === null && p.seek === null && ite.contains(subTree)) {
1110 blockAndSeekProof(tree, node, seek, subTree, ite.index, p)
1111 } else {
1112 p.upgrade.push(tree.get(ite.index))
1113 }
1114 }
1115 ite.parent()
1116 }
1117
1118 continue
1119 }
1120
1121 if (p.upgrade === null) {
1122 p.upgrade = []
1123 }
1124
1125 // if the subtree included is a child of this tree, include that one
1126 // instead of a dup node
1127 if (p.node === null && p.seek === null && ite.contains(subTree)) {
1128 blockAndSeekProof(tree, node, seek, subTree, ite.index, p)
1129 continue
1130 }
1131
1132 // add root (can be optimised since the root might be in tree.roots)
1133 p.upgrade.push(tree.get(ite.index))
1134 }
1135}
1136
1137function additionalUpgradeProof (tree, from, to, p) {
1138 if (from === 0) p.additionalUpgrade = []
1139
1140 for (const ite = flat.iterator(0); ite.fullRoot(to); ite.nextTree()) {
1141 // check if they already have the node
1142 if (ite.index + ite.factor / 2 < from) continue
1143
1144 // connect existing tree
1145 if (p.additionalUpgrade === null && ite.contains(from - 2)) {
1146 p.additionalUpgrade = []
1147
1148 const root = ite.index
1149 const target = from - 2
1150
1151 ite.seek(target)
1152
1153 while (ite.index !== root) {
1154 ite.sibling()
1155 if (ite.index > target) {
1156 p.additionalUpgrade.push(tree.get(ite.index))
1157 }
1158 ite.parent()
1159 }
1160
1161 continue
1162 }
1163
1164 if (p.additionalUpgrade === null) {
1165 p.additionalUpgrade = []
1166 }
1167
1168 // add root (can be optimised since the root is in tree.roots)
1169 p.additionalUpgrade.push(tree.get(ite.index))
1170 }
1171}
1172
1173function nodesToRoot (index, nodes, head) {
1174 const ite = flat.iterator(index)
1175
1176 for (let i = 0; i < nodes; i++) {
1177 ite.parent()
1178 if (ite.contains(head)) throw BAD_ARGUMENT('Nodes is out of bounds')
1179 }
1180
1181 return ite.index
1182}
1183
1184function totalSize (nodes) {
1185 let s = 0
1186 for (const node of nodes) s += node.size
1187 return s
1188}
1189
1190function totalSpan (nodes) {
1191 let s = 0
1192 for (const node of nodes) s += 2 * ((node.index - s) + 1)
1193 return s
1194}
1195
1196function blockNode (crypto, index, value) {
1197 return { index, size: value.byteLength, hash: crypto.data(value) }
1198}
1199
1200function parentNode (crypto, index, a, b) {
1201 return { index, size: a.size + b.size, hash: crypto.parent(a, b) }
1202}
1203
1204function blankNode (index) {
1205 return { index, size: 0, hash: BLANK_HASH }
1206}
1207
1208// Storage methods
1209
1210function getStoredNode (storage, index, cache, error) {
1211 return new Promise((resolve, reject) => {
1212 storage.read(40 * index, 40, (err, data) => {
1213 if (err) {
1214 if (error) return reject(err)
1215 else resolve(null)
1216 return
1217 }
1218
1219 const hash = data.subarray(8)
1220 const size = c.decode(c.uint64, data)
1221
1222 if (size === 0 && b4a.compare(hash, BLANK_HASH) === 0) {
1223 if (error) reject(new Error('Could not load node: ' + index))
1224 else resolve(null)
1225 return
1226 }
1227
1228 const node = { index, size, hash }
1229
1230 if (cache !== null) {
1231 // Copy hash to a new buffer to avoid blocking gc of its original slab
1232 node.hash = unslab(hash)
1233 cache.set(index, node)
1234 }
1235
1236 resolve(node)
1237 })
1238 })
1239}
1240
1241function storedNodes (storage) {
1242 return new Promise((resolve) => {
1243 storage.stat((_, st) => {
1244 if (!st) return resolve(0)
1245 resolve((st.size - (st.size % 40)) / 40)
1246 })
1247 })
1248}
1249
1250async function autoLength (storage) {
1251 const nodes = await storedNodes(storage)
1252 if (!nodes) return 0
1253 const ite = flat.iterator(nodes - 1)
1254 let index = nodes - 1
1255 while (await getStoredNode(storage, ite.parent(), null, false)) index = ite.index
1256 return flat.rightSpan(index) / 2 + 1
1257}
1258
1259function truncateMap (map, len) {
1260 for (const node of map.values()) {
1261 if (node.index >= 2 * len) map.delete(node.index)
1262 }
1263}
1264
1265function log2 (n) {
1266 let res = 1
1267
1268 while (n > 2) {
1269 n /= 2
1270 res++
1271 }
1272
1273 return res
1274}
1275
1276function normalizeIndexed (block, hash) {
1277 if (block) return { value: true, index: block.index * 2, nodes: block.nodes, lastIndex: block.index }
1278 if (hash) return { value: false, index: hash.index, nodes: hash.nodes, lastIndex: flat.rightSpan(hash.index) / 2 }
1279 return null
1280}
1281
1282async function settleProof (p) {
1283 const result = [
1284 p.node && Promise.all(p.node),
1285 p.seek && Promise.all(p.seek),
1286 p.upgrade && Promise.all(p.upgrade),
1287 p.additionalUpgrade && Promise.all(p.additionalUpgrade)
1288 ]
1289
1290 try {
1291 return await Promise.all(result)
1292 } catch (err) {
1293 if (p.node) await Promise.allSettled(p.node)
1294 if (p.seek) await Promise.allSettled(p.seek)
1295 if (p.upgrade) await Promise.allSettled(p.upgrade)
1296 if (p.additionalUpgrade) await Promise.allSettled(p.additionalUpgrade)
1297 throw err
1298 }
1299}
1300
1301// tree can be either the merkle tree or a merkle tree batch
1302async function generateProof (tree, block, hash, seek, upgrade) {
1303 // Important that this does not throw inbetween making the promise arrays
1304 // and finalise being called, otherwise there will be lingering promises in the background
1305
1306 if (tree.prologue && upgrade) {
1307 upgrade.start = upgrade.start < tree.prologue.length ? 0 : upgrade.start
1308 upgrade.length = upgrade.start < tree.prologue.length ? tree.prologue.length : upgrade.length
1309 }
1310
1311 const fork = tree.fork
1312 const signature = tree.signature
1313 const head = 2 * tree.length
1314 const from = upgrade ? upgrade.start * 2 : 0
1315 const to = upgrade ? from + upgrade.length * 2 : head
1316 const node = normalizeIndexed(block, hash)
1317
1318 const result = { fork, block: null, hash: null, seek: null, upgrade: null, manifest: null }
1319
1320 // can't do anything as we have no data...
1321 if (head === 0) return result
1322
1323 if (from >= to || to > head) {
1324 throw INVALID_OPERATION('Invalid upgrade')
1325 }
1326 if (seek && upgrade && node !== null && node.index >= from) {
1327 throw INVALID_OPERATION('Cannot both do a seek and block/hash request when upgrading')
1328 }
1329
1330 let subTree = head
1331
1332 const p = {
1333 node: null,
1334 seek: null,
1335 upgrade: null,
1336 additionalUpgrade: null
1337 }
1338
1339 if (node !== null && (!upgrade || node.lastIndex < upgrade.start)) {
1340 subTree = nodesToRoot(node.index, node.nodes, to)
1341 const seekRoot = seek ? await seekUntrustedTree(tree, subTree, seek.bytes, seek.padding) : head
1342 blockAndSeekProof(tree, node, seek, seekRoot, subTree, p)
1343 } else if ((node || seek) && upgrade) {
1344 subTree = seek ? await seekFromHead(tree, to, seek.bytes, seek.padding) : node.index
1345 }
1346
1347 if (upgrade) {
1348 upgradeProof(tree, node, seek, from, to, subTree, p)
1349 if (head > to) additionalUpgradeProof(tree, to, head, p)
1350 }
1351
1352 const [pNode, pSeek, pUpgrade, pAdditional] = await settleProof(p)
1353
1354 if (block) {
1355 if (pNode === null) throw INVALID_OPERATION('Invalid block request')
1356 result.block = {
1357 index: block.index,
1358 value: null, // populated upstream, alloc it here for simplicity
1359 nodes: pNode
1360 }
1361 } else if (hash) {
1362 if (pNode === null) throw INVALID_OPERATION('Invalid hash request')
1363 result.hash = {
1364 index: hash.index,
1365 nodes: pNode
1366 }
1367 }
1368
1369 if (seek && pSeek !== null) {
1370 result.seek = {
1371 bytes: seek.bytes,
1372 nodes: pSeek
1373 }
1374 }
1375
1376 if (upgrade) {
1377 result.upgrade = {
1378 start: upgrade.start,
1379 length: upgrade.length,
1380 nodes: pUpgrade,
1381 additionalNodes: pAdditional || [],
1382 signature
1383 }
1384 }
1385
1386 return result
1387}
1388
1389function getUnpaddedSize (node, padding, ite) {
1390 return padding === 0 ? node.size : node.size - padding * (ite ? ite.countLeaves() : flat.countLeaves(node.index))
1391}
1392
1393function unslabNodes (nodes) {
1394 for (const node of nodes) unslabNode(node)
1395 return nodes
1396}
1397
1398function unslabNode (node) {
1399 if (node === null) return node
1400 node.hash = unslab(node.hash)
1401 return node
1402}
node_modules/hypercore/lib/messages.js +1069 -0
……@@ -0,0 +1,1069 @@
1const c = require('compact-encoding')
2const b4a = require('b4a')
3const { DEFAULT_NAMESPACE } = require('./caps')
4const { INVALID_OPLOG_VERSION } = require('hypercore-errors')
5const unslab = require('unslab')
6
7const EMPTY = b4a.alloc(0)
8
9const hashes = {
10 preencode (state, m) {
11 state.end++ // small uint
12 },
13 encode (state, m) {
14 if (m === 'blake2b') {
15 c.uint.encode(state, 0)
16 return
17 }
18
19 throw new Error('Unknown hash: ' + m)
20 },
21 decode (state) {
22 const n = c.uint.decode(state)
23 if (n === 0) return 'blake2b'
24 throw new Error('Unknown hash id: ' + n)
25 }
26}
27
28const signatures = {
29 preencode (state, m) {
30 state.end++ // small uint
31 },
32 encode (state, m) {
33 if (m === 'ed25519') {
34 c.uint.encode(state, 0)
35 return
36 }
37
38 throw new Error('Unknown signature: ' + m)
39 },
40 decode (state) {
41 const n = c.uint.decode(state)
42 if (n === 0) return 'ed25519'
43 throw new Error('Unknown signature id: ' + n)
44 }
45}
46
47const signer = {
48 preencode (state, m) {
49 signatures.preencode(state, m.signature)
50 c.fixed32.preencode(state, m.namespace)
51 c.fixed32.preencode(state, m.publicKey)
52 },
53 encode (state, m) {
54 signatures.encode(state, m.signature)
55 c.fixed32.encode(state, m.namespace)
56 c.fixed32.encode(state, m.publicKey)
57 },
58 decode (state) {
59 return {
60 signature: signatures.decode(state),
61 namespace: c.fixed32.decode(state),
62 publicKey: c.fixed32.decode(state)
63 }
64 }
65}
66
67const signerArray = c.array(signer)
68
69const prologue = {
70 preencode (state, p) {
71 c.fixed32.preencode(state, p.hash)
72 c.uint.preencode(state, p.length)
73 },
74 encode (state, p) {
75 c.fixed32.encode(state, p.hash)
76 c.uint.encode(state, p.length)
77 },
78 decode (state) {
79 return {
80 hash: c.fixed32.decode(state),
81 length: c.uint.decode(state)
82 }
83 }
84}
85
86const manifestv0 = {
87 preencode (state, m) {
88 hashes.preencode(state, m.hash)
89 state.end++ // type
90
91 if (m.prologue && m.signers.length === 0) {
92 c.fixed32.preencode(state, m.prologue.hash)
93 return
94 }
95
96 if (m.quorum === 1 && m.signers.length === 1 && !m.allowPatch) {
97 signer.preencode(state, m.signers[0])
98 } else {
99 state.end++ // flags
100 c.uint.preencode(state, m.quorum)
101 signerArray.preencode(state, m.signers)
102 }
103 },
104 encode (state, m) {
105 hashes.encode(state, m.hash)
106
107 if (m.prologue && m.signers.length === 0) {
108 c.uint.encode(state, 0)
109 c.fixed32.encode(state, m.prologue.hash)
110 return
111 }
112
113 if (m.quorum === 1 && m.signers.length === 1 && !m.allowPatch) {
114 c.uint.encode(state, 1)
115 signer.encode(state, m.signers[0])
116 } else {
117 c.uint.encode(state, 2)
118 c.uint.encode(state, m.allowPatch ? 1 : 0)
119 c.uint.encode(state, m.quorum)
120 signerArray.encode(state, m.signers)
121 }
122 },
123 decode (state) {
124 const hash = hashes.decode(state)
125 const type = c.uint.decode(state)
126
127 if (type > 2) throw new Error('Unknown type: ' + type)
128
129 if (type === 0) {
130 return {
131 version: 0,
132 hash,
133 allowPatch: false,
134 quorum: 0,
135 signers: [],
136 prologue: {
137 hash: c.fixed32.decode(state),
138 length: 0
139 }
140 }
141 }
142
143 if (type === 1) {
144 return {
145 version: 0,
146 hash,
147 allowPatch: false,
148 quorum: 1,
149 signers: [signer.decode(state)],
150 prologue: null
151 }
152 }
153
154 const flags = c.uint.decode(state)
155
156 return {
157 version: 0,
158 hash,
159 allowPatch: (flags & 1) !== 0,
160 quorum: c.uint.decode(state),
161 signers: signerArray.decode(state),
162 prologue: null
163 }
164 }
165}
166
167const manifest = exports.manifest = {
168 preencode (state, m) {
169 state.end++ // version
170 if (m.version === 0) return manifestv0.preencode(state, m)
171
172 state.end++ // flags
173 hashes.preencode(state, m.hash)
174
175 c.uint.preencode(state, m.quorum)
176 signerArray.preencode(state, m.signers)
177 if (m.prologue) prologue.preencode(state, m.prologue)
178 },
179 encode (state, m) {
180 c.uint.encode(state, m.version)
181 if (m.version === 0) return manifestv0.encode(state, m)
182
183 c.uint.encode(state, (m.allowPatch ? 1 : 0) | (m.prologue ? 2 : 0))
184 hashes.encode(state, m.hash)
185
186 c.uint.encode(state, m.quorum)
187 signerArray.encode(state, m.signers)
188 if (m.prologue) prologue.encode(state, m.prologue)
189 },
190 decode (state) {
191 const v = c.uint.decode(state)
192 if (v === 0) return manifestv0.decode(state)
193 if (v !== 1) throw new Error('Unknown version: ' + v)
194
195 const flags = c.uint.decode(state)
196 const hash = hashes.decode(state)
197 const quorum = c.uint.decode(state)
198 const signers = signerArray.decode(state)
199
200 return {
201 version: 1,
202 hash,
203 allowPatch: (flags & 1) !== 0,
204 quorum,
205 signers,
206 prologue: (flags & 2) === 0 ? null : prologue.decode(state)
207 }
208 }
209}
210
211const node = {
212 preencode (state, n) {
213 c.uint.preencode(state, n.index)
214 c.uint.preencode(state, n.size)
215 c.fixed32.preencode(state, n.hash)
216 },
217 encode (state, n) {
218 c.uint.encode(state, n.index)
219 c.uint.encode(state, n.size)
220 c.fixed32.encode(state, n.hash)
221 },
222 decode (state) {
223 return {
224 index: c.uint.decode(state),
225 size: c.uint.decode(state),
226 hash: c.fixed32.decode(state)
227 }
228 }
229}
230
231const nodeArray = c.array(node)
232
233const wire = exports.wire = {}
234
235wire.handshake = {
236 preencode (state, m) {
237 c.uint.preencode(state, 1)
238 c.fixed32.preencode(state, m.capability)
239 },
240 encode (state, m) {
241 c.uint.encode(state, m.seeks ? 1 : 0)
242 c.fixed32.encode(state, m.capability)
243 },
244 decode (state) {
245 const flags = c.uint.decode(state)
246 return {
247 seeks: (flags & 1) !== 0,
248 capability: unslab(c.fixed32.decode(state))
249 }
250 }
251}
252
253const requestBlock = {
254 preencode (state, b) {
255 c.uint.preencode(state, b.index)
256 c.uint.preencode(state, b.nodes)
257 },
258 encode (state, b) {
259 c.uint.encode(state, b.index)
260 c.uint.encode(state, b.nodes)
261 },
262 decode (state) {
263 return {
264 index: c.uint.decode(state),
265 nodes: c.uint.decode(state)
266 }
267 }
268}
269
270const requestSeek = {
271 preencode (state, s) {
272 c.uint.preencode(state, s.bytes)
273 c.uint.preencode(state, s.padding)
274 },
275 encode (state, s) {
276 c.uint.encode(state, s.bytes)
277 c.uint.encode(state, s.padding)
278 },
279 decode (state) {
280 return {
281 bytes: c.uint.decode(state),
282 padding: c.uint.decode(state)
283 }
284 }
285}
286
287const requestUpgrade = {
288 preencode (state, u) {
289 c.uint.preencode(state, u.start)
290 c.uint.preencode(state, u.length)
291 },
292 encode (state, u) {
293 c.uint.encode(state, u.start)
294 c.uint.encode(state, u.length)
295 },
296 decode (state) {
297 return {
298 start: c.uint.decode(state),
299 length: c.uint.decode(state)
300 }
301 }
302}
303
304wire.request = {
305 preencode (state, m) {
306 state.end++ // flags
307 c.uint.preencode(state, m.id)
308 c.uint.preencode(state, m.fork)
309
310 if (m.block) requestBlock.preencode(state, m.block)
311 if (m.hash) requestBlock.preencode(state, m.hash)
312 if (m.seek) requestSeek.preencode(state, m.seek)
313 if (m.upgrade) requestUpgrade.preencode(state, m.upgrade)
314 if (m.priority) c.uint.preencode(state, m.priority)
315 },
316 encode (state, m) {
317 const flags = (m.block ? 1 : 0) | (m.hash ? 2 : 0) | (m.seek ? 4 : 0) | (m.upgrade ? 8 : 0) | (m.manifest ? 16 : 0) | (m.priority ? 32 : 0)
318
319 c.uint.encode(state, flags)
320 c.uint.encode(state, m.id)
321 c.uint.encode(state, m.fork)
322
323 if (m.block) requestBlock.encode(state, m.block)
324 if (m.hash) requestBlock.encode(state, m.hash)
325 if (m.seek) requestSeek.encode(state, m.seek)
326 if (m.upgrade) requestUpgrade.encode(state, m.upgrade)
327 if (m.priority) c.uint.encode(state, m.priority)
328 },
329 decode (state) {
330 const flags = c.uint.decode(state)
331
332 return {
333 id: c.uint.decode(state),
334 fork: c.uint.decode(state),
335 block: flags & 1 ? requestBlock.decode(state) : null,
336 hash: flags & 2 ? requestBlock.decode(state) : null,
337 seek: flags & 4 ? requestSeek.decode(state) : null,
338 upgrade: flags & 8 ? requestUpgrade.decode(state) : null,
339 manifest: (flags & 16) !== 0,
340 priority: flags & 32 ? c.uint.decode(state) : 0
341 }
342 }
343}
344
345wire.cancel = {
346 preencode (state, m) {
347 c.uint.preencode(state, m.request)
348 },
349 encode (state, m) {
350 c.uint.encode(state, m.request)
351 },
352 decode (state, m) {
353 return {
354 request: c.uint.decode(state)
355 }
356 }
357}
358
359const dataUpgrade = {
360 preencode (state, u) {
361 c.uint.preencode(state, u.start)
362 c.uint.preencode(state, u.length)
363 nodeArray.preencode(state, u.nodes)
364 nodeArray.preencode(state, u.additionalNodes)
365 c.buffer.preencode(state, u.signature)
366 },
367 encode (state, u) {
368 c.uint.encode(state, u.start)
369 c.uint.encode(state, u.length)
370 nodeArray.encode(state, u.nodes)
371 nodeArray.encode(state, u.additionalNodes)
372 c.buffer.encode(state, u.signature)
373 },
374 decode (state) {
375 return {
376 start: c.uint.decode(state),
377 length: c.uint.decode(state),
378 nodes: nodeArray.decode(state),
379 additionalNodes: nodeArray.decode(state),
380 signature: c.buffer.decode(state)
381 }
382 }
383}
384
385const dataSeek = {
386 preencode (state, s) {
387 c.uint.preencode(state, s.bytes)
388 nodeArray.preencode(state, s.nodes)
389 },
390 encode (state, s) {
391 c.uint.encode(state, s.bytes)
392 nodeArray.encode(state, s.nodes)
393 },
394 decode (state) {
395 return {
396 bytes: c.uint.decode(state),
397 nodes: nodeArray.decode(state)
398 }
399 }
400}
401
402const dataBlock = {
403 preencode (state, b) {
404 c.uint.preencode(state, b.index)
405 c.buffer.preencode(state, b.value)
406 nodeArray.preencode(state, b.nodes)
407 },
408 encode (state, b) {
409 c.uint.encode(state, b.index)
410 c.buffer.encode(state, b.value)
411 nodeArray.encode(state, b.nodes)
412 },
413 decode (state) {
414 return {
415 index: c.uint.decode(state),
416 value: c.buffer.decode(state) || EMPTY,
417 nodes: nodeArray.decode(state)
418 }
419 }
420}
421
422const dataHash = {
423 preencode (state, b) {
424 c.uint.preencode(state, b.index)
425 nodeArray.preencode(state, b.nodes)
426 },
427 encode (state, b) {
428 c.uint.encode(state, b.index)
429 nodeArray.encode(state, b.nodes)
430 },
431 decode (state) {
432 return {
433 index: c.uint.decode(state),
434 nodes: nodeArray.decode(state)
435 }
436 }
437}
438
439wire.data = {
440 preencode (state, m) {
441 state.end++ // flags
442 c.uint.preencode(state, m.request)
443 c.uint.preencode(state, m.fork)
444
445 if (m.block) dataBlock.preencode(state, m.block)
446 if (m.hash) dataHash.preencode(state, m.hash)
447 if (m.seek) dataSeek.preencode(state, m.seek)
448 if (m.upgrade) dataUpgrade.preencode(state, m.upgrade)
449 if (m.manifest) manifest.preencode(state, m.manifest)
450 },
451 encode (state, m) {
452 const flags = (m.block ? 1 : 0) | (m.hash ? 2 : 0) | (m.seek ? 4 : 0) | (m.upgrade ? 8 : 0) | (m.manifest ? 16 : 0)
453
454 c.uint.encode(state, flags)
455 c.uint.encode(state, m.request)
456 c.uint.encode(state, m.fork)
457
458 if (m.block) dataBlock.encode(state, m.block)
459 if (m.hash) dataHash.encode(state, m.hash)
460 if (m.seek) dataSeek.encode(state, m.seek)
461 if (m.upgrade) dataUpgrade.encode(state, m.upgrade)
462 if (m.manifest) manifest.encode(state, m.manifest)
463 },
464 decode (state) {
465 const flags = c.uint.decode(state)
466
467 return {
468 request: c.uint.decode(state),
469 fork: c.uint.decode(state),
470 block: flags & 1 ? dataBlock.decode(state) : null,
471 hash: flags & 2 ? dataHash.decode(state) : null,
472 seek: flags & 4 ? dataSeek.decode(state) : null,
473 upgrade: flags & 8 ? dataUpgrade.decode(state) : null,
474 manifest: flags & 16 ? manifest.decode(state) : null
475 }
476 }
477}
478
479wire.noData = {
480 preencode (state, m) {
481 c.uint.preencode(state, m.request)
482 },
483 encode (state, m) {
484 c.uint.encode(state, m.request)
485 },
486 decode (state, m) {
487 return {
488 request: c.uint.decode(state)
489 }
490 }
491}
492
493wire.want = {
494 preencode (state, m) {
495 c.uint.preencode(state, m.start)
496 c.uint.preencode(state, m.length)
497 },
498 encode (state, m) {
499 c.uint.encode(state, m.start)
500 c.uint.encode(state, m.length)
501 },
502 decode (state) {
503 return {
504 start: c.uint.decode(state),
505 length: c.uint.decode(state)
506 }
507 }
508}
509
510wire.unwant = {
511 preencode (state, m) {
512 c.uint.preencode(state, m.start)
513 c.uint.preencode(state, m.length)
514 },
515 encode (state, m) {
516 c.uint.encode(state, m.start)
517 c.uint.encode(state, m.length)
518 },
519 decode (state, m) {
520 return {
521 start: c.uint.decode(state),
522 length: c.uint.decode(state)
523 }
524 }
525}
526
527wire.range = {
528 preencode (state, m) {
529 state.end++ // flags
530 c.uint.preencode(state, m.start)
531 if (m.length !== 1) c.uint.preencode(state, m.length)
532 },
533 encode (state, m) {
534 c.uint.encode(state, (m.drop ? 1 : 0) | (m.length === 1 ? 2 : 0))
535 c.uint.encode(state, m.start)
536 if (m.length !== 1) c.uint.encode(state, m.length)
537 },
538 decode (state) {
539 const flags = c.uint.decode(state)
540
541 return {
542 drop: (flags & 1) !== 0,
543 start: c.uint.decode(state),
544 length: (flags & 2) !== 0 ? 1 : c.uint.decode(state)
545 }
546 }
547}
548
549wire.bitfield = {
550 preencode (state, m) {
551 c.uint.preencode(state, m.start)
552 c.uint32array.preencode(state, m.bitfield)
553 },
554 encode (state, m) {
555 c.uint.encode(state, m.start)
556 c.uint32array.encode(state, m.bitfield)
557 },
558 decode (state, m) {
559 return {
560 start: c.uint.decode(state),
561 bitfield: c.uint32array.decode(state)
562 }
563 }
564}
565
566wire.sync = {
567 preencode (state, m) {
568 state.end++ // flags
569 c.uint.preencode(state, m.fork)
570 c.uint.preencode(state, m.length)
571 c.uint.preencode(state, m.remoteLength)
572 },
573 encode (state, m) {
574 c.uint.encode(state, (m.canUpgrade ? 1 : 0) | (m.uploading ? 2 : 0) | (m.downloading ? 4 : 0) | (m.hasManifest ? 8 : 0))
575 c.uint.encode(state, m.fork)
576 c.uint.encode(state, m.length)
577 c.uint.encode(state, m.remoteLength)
578 },
579 decode (state) {
580 const flags = c.uint.decode(state)
581
582 return {
583 fork: c.uint.decode(state),
584 length: c.uint.decode(state),
585 remoteLength: c.uint.decode(state),
586 canUpgrade: (flags & 1) !== 0,
587 uploading: (flags & 2) !== 0,
588 downloading: (flags & 4) !== 0,
589 hasManifest: (flags & 8) !== 0
590 }
591 }
592}
593
594wire.reorgHint = {
595 preencode (state, m) {
596 c.uint.preencode(state, m.from)
597 c.uint.preencode(state, m.to)
598 c.uint.preencode(state, m.ancestors)
599 },
600 encode (state, m) {
601 c.uint.encode(state, m.from)
602 c.uint.encode(state, m.to)
603 c.uint.encode(state, m.ancestors)
604 },
605 decode (state) {
606 return {
607 from: c.uint.encode(state),
608 to: c.uint.encode(state),
609 ancestors: c.uint.encode(state)
610 }
611 }
612}
613
614wire.extension = {
615 preencode (state, m) {
616 c.string.preencode(state, m.name)
617 c.raw.preencode(state, m.message)
618 },
619 encode (state, m) {
620 c.string.encode(state, m.name)
621 c.raw.encode(state, m.message)
622 },
623 decode (state) {
624 return {
625 name: c.string.decode(state),
626 message: c.raw.decode(state)
627 }
628 }
629}
630
631const keyValue = {
632 preencode (state, p) {
633 c.string.preencode(state, p.key)
634 c.buffer.preencode(state, p.value)
635 },
636 encode (state, p) {
637 c.string.encode(state, p.key)
638 c.buffer.encode(state, p.value)
639 },
640 decode (state) {
641 return {
642 key: c.string.decode(state),
643 value: c.buffer.decode(state)
644 }
645 }
646}
647
648const treeUpgrade = {
649 preencode (state, u) {
650 c.uint.preencode(state, u.fork)
651 c.uint.preencode(state, u.ancestors)
652 c.uint.preencode(state, u.length)
653 c.buffer.preencode(state, u.signature)
654 },
655 encode (state, u) {
656 c.uint.encode(state, u.fork)
657 c.uint.encode(state, u.ancestors)
658 c.uint.encode(state, u.length)
659 c.buffer.encode(state, u.signature)
660 },
661 decode (state) {
662 return {
663 fork: c.uint.decode(state),
664 ancestors: c.uint.decode(state),
665 length: c.uint.decode(state),
666 signature: c.buffer.decode(state)
667 }
668 }
669}
670
671const bitfieldUpdate = { // TODO: can maybe be folded into a HAVE later on with the most recent spec
672 preencode (state, b) {
673 state.end++ // flags
674 c.uint.preencode(state, b.start)
675 c.uint.preencode(state, b.length)
676 },
677 encode (state, b) {
678 state.buffer[state.start++] = b.drop ? 1 : 0
679 c.uint.encode(state, b.start)
680 c.uint.encode(state, b.length)
681 },
682 decode (state) {
683 const flags = c.uint.decode(state)
684 return {
685 drop: (flags & 1) !== 0,
686 start: c.uint.decode(state),
687 length: c.uint.decode(state)
688 }
689 }
690}
691
692const oplog = exports.oplog = {}
693
694oplog.entry = {
695 preencode (state, m) {
696 state.end++ // flags
697 if (m.userData) keyValue.preencode(state, m.userData)
698 if (m.treeNodes) nodeArray.preencode(state, m.treeNodes)
699 if (m.treeUpgrade) treeUpgrade.preencode(state, m.treeUpgrade)
700 if (m.bitfield) bitfieldUpdate.preencode(state, m.bitfield)
701 },
702 encode (state, m) {
703 const s = state.start++
704 let flags = 0
705
706 if (m.userData) {
707 flags |= 1
708 keyValue.encode(state, m.userData)
709 }
710 if (m.treeNodes) {
711 flags |= 2
712 nodeArray.encode(state, m.treeNodes)
713 }
714 if (m.treeUpgrade) {
715 flags |= 4
716 treeUpgrade.encode(state, m.treeUpgrade)
717 }
718 if (m.bitfield) {
719 flags |= 8
720 bitfieldUpdate.encode(state, m.bitfield)
721 }
722
723 state.buffer[s] = flags
724 },
725 decode (state) {
726 const flags = c.uint.decode(state)
727 return {
728 userData: (flags & 1) !== 0 ? keyValue.decode(state) : null,
729 treeNodes: (flags & 2) !== 0 ? nodeArray.decode(state) : null,
730 treeUpgrade: (flags & 4) !== 0 ? treeUpgrade.decode(state) : null,
731 bitfield: (flags & 8) !== 0 ? bitfieldUpdate.decode(state) : null
732 }
733 }
734}
735
736const keyPair = {
737 preencode (state, kp) {
738 c.buffer.preencode(state, kp.publicKey)
739 c.buffer.preencode(state, kp.secretKey)
740 },
741 encode (state, kp) {
742 c.buffer.encode(state, kp.publicKey)
743 c.buffer.encode(state, kp.secretKey)
744 },
745 decode (state) {
746 return {
747 publicKey: c.buffer.decode(state),
748 secretKey: c.buffer.decode(state)
749 }
750 }
751}
752
753const reorgHint = {
754 preencode (state, r) {
755 c.uint.preencode(state, r.from)
756 c.uint.preencode(state, r.to)
757 c.uint.preencode(state, r.ancestors)
758 },
759 encode (state, r) {
760 c.uint.encode(state, r.from)
761 c.uint.encode(state, r.to)
762 c.uint.encode(state, r.ancestors)
763 },
764 decode (state) {
765 return {
766 from: c.uint.decode(state),
767 to: c.uint.decode(state),
768 ancestors: c.uint.decode(state)
769 }
770 }
771}
772
773const reorgHintArray = c.array(reorgHint)
774
775const hints = {
776 preencode (state, h) {
777 reorgHintArray.preencode(state, h.reorgs)
778 c.uint.preencode(state, h.contiguousLength)
779 },
780 encode (state, h) {
781 reorgHintArray.encode(state, h.reorgs)
782 c.uint.encode(state, h.contiguousLength)
783 },
784 decode (state) {
785 return {
786 reorgs: reorgHintArray.decode(state),
787 contiguousLength: state.start < state.end ? c.uint.decode(state) : 0
788 }
789 }
790}
791
792const treeHeader = {
793 preencode (state, t) {
794 c.uint.preencode(state, t.fork)
795 c.uint.preencode(state, t.length)
796 c.buffer.preencode(state, t.rootHash)
797 c.buffer.preencode(state, t.signature)
798 },
799 encode (state, t) {
800 c.uint.encode(state, t.fork)
801 c.uint.encode(state, t.length)
802 c.buffer.encode(state, t.rootHash)
803 c.buffer.encode(state, t.signature)
804 },
805 decode (state) {
806 return {
807 fork: c.uint.decode(state),
808 length: c.uint.decode(state),
809 rootHash: c.buffer.decode(state),
810 signature: c.buffer.decode(state)
811 }
812 }
813}
814
815const types = {
816 preencode (state, t) {
817 c.string.preencode(state, t.tree)
818 c.string.preencode(state, t.bitfield)
819 c.string.preencode(state, t.signer)
820 },
821 encode (state, t) {
822 c.string.encode(state, t.tree)
823 c.string.encode(state, t.bitfield)
824 c.string.encode(state, t.signer)
825 },
826 decode (state) {
827 return {
828 tree: c.string.decode(state),
829 bitfield: c.string.decode(state),
830 signer: c.string.decode(state)
831 }
832 }
833}
834
835const externalHeader = {
836 preencode (state, m) {
837 c.uint.preencode(state, m.start)
838 c.uint.preencode(state, m.length)
839 },
840 encode (state, m) {
841 c.uint.encode(state, m.start)
842 c.uint.encode(state, m.length)
843 },
844 decode (state) {
845 return {
846 start: c.uint.decode(state),
847 length: c.uint.decode(state)
848 }
849 }
850}
851
852const keyValueArray = c.array(keyValue)
853
854oplog.header = {
855 preencode (state, h) {
856 state.end += 2 // version + flags
857 if (h.external) {
858 externalHeader.preencode(state, h.external)
859 return
860 }
861 c.fixed32.preencode(state, h.key)
862 if (h.manifest) manifest.preencode(state, h.manifest)
863 if (h.keyPair) keyPair.preencode(state, h.keyPair)
864 keyValueArray.preencode(state, h.userData)
865 treeHeader.preencode(state, h.tree)
866 hints.preencode(state, h.hints)
867 },
868 encode (state, h) {
869 c.uint.encode(state, 1)
870 if (h.external) {
871 c.uint.encode(state, 1) // ONLY set the first big for clarity
872 externalHeader.encode(state, h.external)
873 return
874 }
875 c.uint.encode(state, (h.manifest ? 2 : 0) | (h.keyPair ? 4 : 0))
876 c.fixed32.encode(state, h.key)
877 if (h.manifest) manifest.encode(state, h.manifest)
878 if (h.keyPair) keyPair.encode(state, h.keyPair)
879 keyValueArray.encode(state, h.userData)
880 treeHeader.encode(state, h.tree)
881 hints.encode(state, h.hints)
882 },
883 decode (state) {
884 const version = c.uint.decode(state)
885
886 if (version > 1) {
887 throw INVALID_OPLOG_VERSION('Invalid header version. Expected <= 1, got ' + version)
888 }
889
890 if (version === 0) {
891 const old = {
892 types: types.decode(state),
893 userData: keyValueArray.decode(state),
894 tree: treeHeader.decode(state),
895 signer: keyPair.decode(state),
896 hints: hints.decode(state)
897 }
898
899 return {
900 external: null,
901 key: old.signer.publicKey,
902 manifest: {
903 version: 0,
904 hash: old.types.tree,
905 allowPatch: false,
906 quorum: 1,
907 signers: [{
908 signature: old.types.signer,
909 namespace: DEFAULT_NAMESPACE,
910 publicKey: old.signer.publicKey
911 }],
912 prologue: null
913 },
914 keyPair: old.signer.secretKey ? old.signer : null,
915 userData: old.userData,
916 tree: old.tree,
917 hints: old.hints
918 }
919 }
920
921 const flags = c.uint.decode(state)
922
923 if (flags & 1) {
924 return {
925 external: externalHeader.decode(state),
926 key: null,
927 manifest: null,
928 keyPair: null,
929 userData: null,
930 tree: null,
931 hints: null
932 }
933 }
934
935 return {
936 external: null,
937 key: c.fixed32.decode(state),
938 manifest: (flags & 2) !== 0 ? manifest.decode(state) : null,
939 keyPair: (flags & 4) !== 0 ? keyPair.decode(state) : null,
940 userData: keyValueArray.decode(state),
941 tree: treeHeader.decode(state),
942 hints: hints.decode(state)
943 }
944 }
945}
946
947const uintArray = c.array(c.uint)
948
949const multisigInput = {
950 preencode (state, inp) {
951 c.uint.preencode(state, inp.signer)
952 c.fixed64.preencode(state, inp.signature)
953 c.uint.preencode(state, inp.patch)
954 },
955 encode (state, inp) {
956 c.uint.encode(state, inp.signer)
957 c.fixed64.encode(state, inp.signature)
958 c.uint.encode(state, inp.patch)
959 },
960 decode (state) {
961 return {
962 signer: c.uint.decode(state),
963 signature: c.fixed64.decode(state),
964 patch: c.uint.decode(state)
965 }
966 }
967}
968
969const patchEncodingv0 = {
970 preencode (state, n) {
971 c.uint.preencode(state, n.start)
972 c.uint.preencode(state, n.length)
973 uintArray.preencode(state, n.nodes)
974 },
975 encode (state, n) {
976 c.uint.encode(state, n.start)
977 c.uint.encode(state, n.length)
978 uintArray.encode(state, n.nodes)
979 },
980 decode (state) {
981 return {
982 start: c.uint.decode(state),
983 length: c.uint.decode(state),
984 nodes: uintArray.decode(state)
985 }
986 }
987}
988
989const multisigInputv0 = {
990 preencode (state, n) {
991 state.end++
992 c.uint.preencode(state, n.signer)
993 c.fixed64.preencode(state, n.signature)
994 if (n.patch) patchEncodingv0.preencode(state, n.patch)
995 },
996 encode (state, n) {
997 c.uint.encode(state, n.patch ? 1 : 0)
998 c.uint.encode(state, n.signer)
999 c.fixed64.encode(state, n.signature)
1000 if (n.patch) patchEncodingv0.encode(state, n.patch)
1001 },
1002 decode (state) {
1003 const flags = c.uint.decode(state)
1004 return {
1005 signer: c.uint.decode(state),
1006 signature: c.fixed64.decode(state),
1007 patch: (flags & 1) ? patchEncodingv0.decode(state) : null
1008 }
1009 }
1010}
1011
1012const multisigInputArrayv0 = c.array(multisigInputv0)
1013const multisigInputArray = c.array(multisigInput)
1014
1015const compactNode = {
1016 preencode (state, n) {
1017 c.uint.preencode(state, n.index)
1018 c.uint.preencode(state, n.size)
1019 c.fixed32.preencode(state, n.hash)
1020 },
1021 encode (state, n) {
1022 c.uint.encode(state, n.index)
1023 c.uint.encode(state, n.size)
1024 c.fixed32.encode(state, n.hash)
1025 },
1026 decode (state) {
1027 return {
1028 index: c.uint.decode(state),
1029 size: c.uint.decode(state),
1030 hash: c.fixed32.decode(state)
1031 }
1032 }
1033}
1034
1035const compactNodeArray = c.array(compactNode)
1036
1037exports.multiSignaturev0 = {
1038 preencode (state, s) {
1039 multisigInputArrayv0.preencode(state, s.proofs)
1040 compactNodeArray.preencode(state, s.patch)
1041 },
1042 encode (state, s) {
1043 multisigInputArrayv0.encode(state, s.proofs)
1044 compactNodeArray.encode(state, s.patch)
1045 },
1046 decode (state) {
1047 return {
1048 proofs: multisigInputArrayv0.decode(state),
1049 patch: compactNodeArray.decode(state)
1050 }
1051 }
1052}
1053
1054exports.multiSignature = {
1055 preencode (state, s) {
1056 multisigInputArray.preencode(state, s.proofs)
1057 compactNodeArray.preencode(state, s.patch)
1058 },
1059 encode (state, s) {
1060 multisigInputArray.encode(state, s.proofs)
1061 compactNodeArray.encode(state, s.patch)
1062 },
1063 decode (state) {
1064 return {
1065 proofs: multisigInputArray.decode(state),
1066 patch: compactNodeArray.decode(state)
1067 }
1068 }
1069}
node_modules/hypercore/lib/multisig.js +124 -0
……@@ -0,0 +1,124 @@
1const c = require('compact-encoding')
2const b4a = require('b4a')
3const flat = require('flat-tree')
4const { multiSignature, multiSignaturev0 } = require('./messages')
5
6module.exports = {
7 assemblev0,
8 assemble,
9 inflatev0,
10 inflate,
11 partialSignature,
12 signableLength
13}
14
15function inflatev0 (data) {
16 return c.decode(multiSignaturev0, data)
17}
18
19function inflate (data) {
20 return c.decode(multiSignature, data)
21}
22
23async function partialSignature (tree, signer, from, to = tree.length, signature = tree.signature) {
24 if (from > tree.length) return null
25 const nodes = to <= from ? null : await upgradeNodes(tree, from, to)
26
27 if (signature.byteLength !== 64) signature = c.decode(multiSignature, signature).proofs[0].signature
28
29 return {
30 signer,
31 signature,
32 patch: nodes ? to - from : 0,
33 nodes
34 }
35}
36
37async function upgradeNodes (tree, from, to) {
38 const p = await tree.proof({ upgrade: { start: from, length: to - from } })
39 return p.upgrade.nodes
40}
41
42function signableLength (lengths, quorum) {
43 if (quorum <= 0) quorum = 1
44 if (quorum > lengths.length) return 0
45
46 return lengths.sort(cmp)[quorum - 1]
47}
48
49function cmp (a, b) {
50 return b - a
51}
52
53function assemblev0 (inputs) {
54 const proofs = []
55 const patch = []
56
57 for (const u of inputs) {
58 proofs.push(compressProof(u, patch))
59 }
60
61 return c.encode(multiSignaturev0, { proofs, patch })
62}
63
64function assemble (inputs) {
65 const proofs = []
66 const patch = []
67 const seen = new Set()
68
69 for (const u of inputs) {
70 if (u.nodes) {
71 for (const node of u.nodes) {
72 if (seen.has(node.index)) continue
73 seen.add(node.index)
74 patch.push(node)
75 }
76 }
77
78 proofs.push({
79 signer: u.signer,
80 signature: u.signature,
81 patch: u.patch
82 })
83 }
84
85 return c.encode(multiSignature, { proofs, patch })
86}
87
88function compareNode (a, b) {
89 if (a.index !== b.index) return false
90 if (a.size !== b.size) return false
91 return b4a.equals(a.hash, b.hash)
92}
93
94function compressProof (proof, nodes) {
95 return {
96 signer: proof.signer,
97 signature: proof.signature,
98 patch: proof.patch ? compressUpgrade(proof, nodes) : null
99 }
100}
101
102function compressUpgrade (p, nodes) {
103 const u = {
104 start: flat.rightSpan(p.nodes[p.nodes.length - 1].index) / 2 + 1,
105 length: p.patch,
106 nodes: []
107 }
108
109 for (const node of p.nodes) {
110 let present = false
111 for (let i = 0; i < nodes.length; i++) {
112 if (!compareNode(nodes[i], node)) continue
113
114 u.nodes.push(i)
115 present = true
116 break
117 }
118
119 if (present) continue
120 u.nodes.push(nodes.push(node) - 1)
121 }
122
123 return u
124}
node_modules/hypercore/lib/mutex.js +39 -0
……@@ -0,0 +1,39 @@
1module.exports = class Mutex {
2 constructor () {
3 this.locked = false
4 this.destroyed = false
5
6 this._destroying = null
7 this._destroyError = null
8 this._queue = []
9 this._enqueue = (resolve, reject) => this._queue.push([resolve, reject])
10 }
11
12 lock () {
13 if (this.destroyed) return Promise.reject(this._destroyError || new Error('Mutex has been destroyed'))
14 if (this.locked) return new Promise(this._enqueue)
15 this.locked = true
16 return Promise.resolve()
17 }
18
19 unlock () {
20 if (!this._queue.length) {
21 this.locked = false
22 return
23 }
24 this._queue.shift()[0]()
25 }
26
27 destroy (err) {
28 if (!this._destroying) this._destroying = this.locked ? this.lock().catch(() => {}) : Promise.resolve()
29
30 this.destroyed = true
31 if (err) this._destroyError = err
32
33 if (err) {
34 while (this._queue.length) this._queue.shift()[1](err)
35 }
36
37 return this._destroying
38 }
39}
node_modules/hypercore/lib/oplog.js +228 -0
……@@ -0,0 +1,228 @@
1const cenc = require('compact-encoding')
2const b4a = require('b4a')
3const { crc32 } = require('crc-universal')
4const { OPLOG_CORRUPT, OPLOG_HEADER_OVERFLOW, WRITE_FAILED } = require('hypercore-errors')
5
6module.exports = class Oplog {
7 constructor (storage, { pageSize = 4096, headerEncoding = cenc.raw, entryEncoding = cenc.raw, readonly = false } = {}) {
8 this.storage = storage
9 this.headerEncoding = headerEncoding
10 this.entryEncoding = entryEncoding
11 this.readonly = readonly
12 this.flushed = false
13 this.byteLength = 0
14 this.length = 0
15
16 this._headers = [1, 0]
17 this._pageSize = pageSize
18 this._entryOffset = pageSize * 2
19 }
20
21 _addHeader (state, len, headerBit, partialBit) {
22 // add the uint header (frame length and flush info)
23 state.start = state.start - len - 4
24 cenc.uint32.encode(state, (len << 2) | headerBit | partialBit)
25
26 // crc32 the length + header-bit + content and prefix it
27 state.start -= 8
28 cenc.uint32.encode(state, crc32(state.buffer.subarray(state.start + 4, state.start + 8 + len)))
29 state.start += len + 4
30 }
31
32 _decodeEntry (state, enc) {
33 if (state.end - state.start < 8) return null
34 const cksum = cenc.uint32.decode(state)
35 const l = cenc.uint32.decode(state)
36 const length = l >>> 2
37 const headerBit = l & 1
38 const partialBit = l & 2
39
40 if (state.end - state.start < length) return null
41
42 const end = state.start + length
43
44 if (crc32(state.buffer.subarray(state.start - 4, end)) !== cksum) {
45 return null
46 }
47
48 const result = { header: headerBit, partial: partialBit !== 0, byteLength: length + 8, message: null }
49
50 try {
51 result.message = enc.decode({ start: state.start, end, buffer: state.buffer })
52 } catch {
53 return null
54 }
55
56 state.start = end
57
58 return result
59 }
60
61 async open () {
62 const buffer = await this._readAll() // TODO: stream the oplog in on load maybe?
63 const state = { start: 0, end: buffer.byteLength, buffer }
64 const result = { header: null, entries: [] }
65
66 this.byteLength = 0
67 this.length = 0
68
69 const h1 = this._decodeEntry(state, this.headerEncoding)
70 state.start = this._pageSize
71
72 const h2 = this._decodeEntry(state, this.headerEncoding)
73 state.start = this._entryOffset
74
75 if (!h1 && !h2) {
76 // reset state...
77 this.flushed = false
78 this._headers[0] = 1
79 this._headers[1] = 0
80
81 if (buffer.byteLength >= this._entryOffset) {
82 throw OPLOG_CORRUPT()
83 }
84 return result
85 }
86
87 this.flushed = true
88
89 if (h1 && !h2) {
90 this._headers[0] = h1.header
91 this._headers[1] = h1.header
92 } else if (!h1 && h2) {
93 this._headers[0] = (h2.header + 1) & 1
94 this._headers[1] = h2.header
95 } else {
96 this._headers[0] = h1.header
97 this._headers[1] = h2.header
98 }
99
100 const header = (this._headers[0] + this._headers[1]) & 1
101 const decoded = []
102
103 result.header = header ? h2.message : h1.message
104
105 while (true) {
106 const entry = this._decodeEntry(state, this.entryEncoding)
107 if (!entry) break
108 if (entry.header !== header) break
109
110 decoded.push(entry)
111 }
112
113 while (decoded.length > 0 && decoded[decoded.length - 1].partial) decoded.pop()
114
115 for (const e of decoded) {
116 result.entries.push(e.message)
117 this.byteLength += e.byteLength
118 this.length++
119 }
120
121 const size = this.byteLength + this._entryOffset
122
123 if (size === buffer.byteLength) return result
124
125 await new Promise((resolve, reject) => {
126 if (this.readonly) return resolve()
127 this.storage.truncate(size, err => {
128 if (err) return reject(err)
129 resolve()
130 })
131 })
132
133 return result
134 }
135
136 _readAll () {
137 return new Promise((resolve, reject) => {
138 this.storage.open(err => {
139 if (err && err.code !== 'ENOENT') return reject(err)
140 if (err) return resolve(b4a.alloc(0))
141 this.storage.stat((err, stat) => {
142 if (err && err.code !== 'ENOENT') return reject(err)
143 this.storage.read(0, stat.size, (err, buf) => {
144 if (err) return reject(err)
145 resolve(buf)
146 })
147 })
148 })
149 })
150 }
151
152 flush (header) {
153 const state = { start: 8, end: 8, buffer: null }
154 const i = this._headers[0] === this._headers[1] ? 1 : 0
155 const bit = (this._headers[i] + 1) & 1
156
157 this.headerEncoding.preencode(state, header)
158 if (state.end > this._pageSize) throw OPLOG_HEADER_OVERFLOW()
159 state.buffer = b4a.allocUnsafe(state.end)
160 this.headerEncoding.encode(state, header)
161 this._addHeader(state, state.end - 8, bit, 0)
162
163 return this._writeHeaderAndTruncate(i, bit, state.buffer)
164 }
165
166 _writeHeaderAndTruncate (i, bit, buf) {
167 return new Promise((resolve, reject) => {
168 this.storage.write(i === 0 ? 0 : this._pageSize, buf, err => {
169 if (err) return reject(err)
170
171 this.storage.truncate(this._entryOffset, err => {
172 if (err) return reject(err)
173
174 this._headers[i] = bit
175 this.byteLength = 0
176 this.length = 0
177 this.flushed = true
178
179 resolve()
180 })
181 })
182 })
183 }
184
185 append (batch, atomic = true) {
186 if (!Array.isArray(batch)) batch = [batch]
187
188 const state = { start: 0, end: batch.length * 8, buffer: null }
189 const bit = (this._headers[0] + this._headers[1]) & 1
190
191 for (let i = 0; i < batch.length; i++) {
192 this.entryEncoding.preencode(state, batch[i])
193 }
194
195 state.buffer = b4a.allocUnsafe(state.end)
196
197 for (let i = 0; i < batch.length; i++) {
198 const start = state.start += 8 // space for header
199 const partial = (atomic && i < batch.length - 1) ? 2 : 0
200 this.entryEncoding.encode(state, batch[i])
201 this._addHeader(state, state.start - start, bit, partial)
202 }
203
204 return this._append(state.buffer, batch.length)
205 }
206
207 close () {
208 return new Promise((resolve, reject) => {
209 this.storage.close(err => {
210 if (err) return reject(err)
211 resolve()
212 })
213 })
214 }
215
216 _append (buf, count) {
217 return new Promise((resolve, reject) => {
218 this.storage.write(this._entryOffset + this.byteLength, buf, err => {
219 if (err) return reject(WRITE_FAILED(err.message))
220
221 this.byteLength += buf.byteLength
222 this.length += count
223
224 resolve()
225 })
226 })
227 }
228}
node_modules/hypercore/lib/receiver-queue.js +71 -0
……@@ -0,0 +1,71 @@
1const FIFO = require('fast-fifo')
2
3module.exports = class ReceiverQueue {
4 constructor () {
5 this.queue = new FIFO()
6 this.priority = []
7 this.requests = new Map()
8 this.length = 0
9 }
10
11 push (req) {
12 // TODO: use a heap at some point if we wanna support multiple prios
13 if (req.priority > 0) this.priority.push(req)
14 else this.queue.push(req)
15
16 this.requests.set(req.id, req)
17 this.length++
18 }
19
20 shift () {
21 while (this.priority.length > 0) {
22 const msg = this.priority.pop()
23 const req = this._processRequest(msg)
24 if (req !== null) return req
25 }
26
27 while (this.queue.length > 0) {
28 const msg = this.queue.shift()
29 const req = this._processRequest(msg)
30 if (req !== null) return req
31 }
32
33 return null
34 }
35
36 _processRequest (req) {
37 if (req.block || req.hash || req.seek || req.upgrade || req.manifest) {
38 this.requests.delete(req.id)
39 this.length--
40 return req
41 }
42
43 return null
44 }
45
46 clear () {
47 this.queue.clear()
48 this.priority = []
49 this.length = 0
50 this.requests.clear()
51 }
52
53 delete (id) {
54 const req = this.requests.get(id)
55 if (!req) return
56
57 req.block = null
58 req.hash = null
59 req.seek = null
60 req.upgrade = null
61 req.manifest = false
62
63 this.requests.delete(id)
64 this.length--
65
66 if (this.length === 0) {
67 this.queue.clear()
68 this.priority = []
69 }
70 }
71}
node_modules/hypercore/lib/remote-bitfield.js +346 -0
……@@ -0,0 +1,346 @@
1const BigSparseArray = require('big-sparse-array')
2const quickbit = require('./compat').quickbit
3
4const BITS_PER_PAGE = 32768
5const BYTES_PER_PAGE = BITS_PER_PAGE / 8
6const WORDS_PER_PAGE = BYTES_PER_PAGE / 4
7const BITS_PER_SEGMENT = 2097152
8const BYTES_PER_SEGMENT = BITS_PER_SEGMENT / 8
9const PAGES_PER_SEGMENT = BITS_PER_SEGMENT / BITS_PER_PAGE
10
11class RemoteBitfieldPage {
12 constructor (index, bitfield, segment) {
13 this.index = index
14 this.offset = index * BYTES_PER_PAGE - segment.offset
15 this.bitfield = bitfield
16 this.segment = segment
17
18 segment.add(this)
19 }
20
21 get tree () {
22 return this.segment.tree
23 }
24
25 get (index) {
26 return quickbit.get(this.bitfield, index)
27 }
28
29 set (index, val) {
30 if (quickbit.set(this.bitfield, index, val)) {
31 this.tree.update(this.offset * 8 + index)
32 }
33 }
34
35 setRange (start, length, val) {
36 quickbit.fill(this.bitfield, val, start, start + length)
37
38 let i = Math.floor(start / 128)
39 const n = i + Math.ceil(length / 128)
40
41 while (i <= n) this.tree.update(this.offset * 8 + i++ * 128)
42 }
43
44 findFirst (val, position) {
45 return quickbit.findFirst(this.bitfield, val, position)
46 }
47
48 findLast (val, position) {
49 return quickbit.findLast(this.bitfield, val, position)
50 }
51
52 insert (start, bitfield) {
53 this.bitfield.set(bitfield, start / 32)
54 this.segment.refresh()
55 }
56
57 clear (start, bitfield) {
58 quickbit.clear(this.bitfield, { field: bitfield, offset: start })
59 }
60}
61
62class RemoteBitfieldSegment {
63 constructor (index) {
64 this.index = index
65 this.offset = index * BYTES_PER_SEGMENT
66 this.tree = quickbit.Index.from([], BYTES_PER_SEGMENT)
67 this.pages = new Array(PAGES_PER_SEGMENT)
68 this.pagesLength = 0
69 }
70
71 get chunks () {
72 return this.tree.chunks
73 }
74
75 refresh () {
76 this.tree = quickbit.Index.from(this.tree.chunks, BYTES_PER_SEGMENT)
77 }
78
79 add (page) {
80 const pageIndex = page.index - this.index * PAGES_PER_SEGMENT
81 if (pageIndex >= this.pagesLength) this.pagesLength = pageIndex + 1
82
83 this.pages[pageIndex] = page
84
85 const chunk = { field: page.bitfield, offset: page.offset }
86
87 this.chunks.push(chunk)
88
89 for (let i = this.chunks.length - 2; i >= 0; i--) {
90 const prev = this.chunks[i]
91 if (prev.offset <= chunk.offset) break
92 this.chunks[i] = chunk
93 this.chunks[i + 1] = prev
94 }
95 }
96
97 findFirst (val, position) {
98 position = this.tree.skipFirst(!val, position)
99
100 let j = position & (BITS_PER_PAGE - 1)
101 let i = (position - j) / BITS_PER_PAGE
102
103 if (i >= PAGES_PER_SEGMENT) return -1
104
105 while (i < this.pagesLength) {
106 const p = this.pages[i]
107
108 let index = -1
109
110 if (p) index = p.findFirst(val, j)
111 else if (!val) index = j
112
113 if (index !== -1) return i * BITS_PER_PAGE + index
114
115 j = 0
116 i++
117 }
118
119 return (val || this.pagesLength === PAGES_PER_SEGMENT) ? -1 : this.pagesLength * BITS_PER_PAGE
120 }
121
122 findLast (val, position) {
123 position = this.tree.skipLast(!val, position)
124
125 let j = position & (BITS_PER_PAGE - 1)
126 let i = (position - j) / BITS_PER_PAGE
127
128 if (i >= PAGES_PER_SEGMENT) return -1
129
130 while (i >= 0) {
131 const p = this.pages[i]
132
133 let index = -1
134
135 if (p) index = p.findLast(val, j)
136 else if (!val) index = j
137
138 if (index !== -1) return i * BITS_PER_PAGE + index
139
140 j = BITS_PER_PAGE - 1
141 i--
142 }
143
144 return -1
145 }
146}
147
148module.exports = class RemoteBitfield {
149 static BITS_PER_PAGE = BITS_PER_PAGE
150
151 constructor () {
152 this._pages = new BigSparseArray()
153 this._segments = new BigSparseArray()
154 this._maxSegments = 0
155 }
156
157 getBitfield (index) {
158 const j = index & (BITS_PER_PAGE - 1)
159 const i = (index - j) / BITS_PER_PAGE
160
161 const p = this._pages.get(i)
162 return p || null
163 }
164
165 get (index) {
166 const j = index & (BITS_PER_PAGE - 1)
167 const i = (index - j) / BITS_PER_PAGE
168
169 const p = this._pages.get(i)
170
171 return p ? p.get(j) : false
172 }
173
174 set (index, val) {
175 const j = index & (BITS_PER_PAGE - 1)
176 const i = (index - j) / BITS_PER_PAGE
177
178 let p = this._pages.get(i)
179
180 if (!p && val) {
181 const k = Math.floor(i / PAGES_PER_SEGMENT)
182 const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k))
183 if (this._maxSegments <= k) this._maxSegments = k + 1
184
185 p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s))
186 }
187
188 if (p) p.set(j, val)
189 }
190
191 setRange (start, length, val) {
192 let j = start & (BITS_PER_PAGE - 1)
193 let i = (start - j) / BITS_PER_PAGE
194
195 while (length > 0) {
196 let p = this._pages.get(i)
197
198 if (!p && val) {
199 const k = Math.floor(i / PAGES_PER_SEGMENT)
200 const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k))
201 if (this._maxSegments <= k) this._maxSegments = k + 1
202
203 p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s))
204 }
205
206 const end = Math.min(j + length, BITS_PER_PAGE)
207 const range = end - j
208
209 if (p) p.setRange(j, range, val)
210
211 j = 0
212 i++
213 length -= range
214 }
215 }
216
217 findFirst (val, position) {
218 let j = position & (BITS_PER_SEGMENT - 1)
219 let i = (position - j) / BITS_PER_SEGMENT
220
221 while (i < this._maxSegments) {
222 const s = this._segments.get(i)
223
224 let index = -1
225
226 if (s) index = s.findFirst(val, j)
227 else if (!val) index = j
228
229 if (index !== -1) return i * BITS_PER_SEGMENT + index
230
231 j = 0
232 i++
233 }
234
235 // For the val === false case, we always return at least
236 // the 'position', also if nothing was found
237 return val
238 ? -1
239 : Math.max(position, this._maxSegments * BITS_PER_SEGMENT)
240 }
241
242 firstSet (position) {
243 return this.findFirst(true, position)
244 }
245
246 firstUnset (position) {
247 return this.findFirst(false, position)
248 }
249
250 findLast (val, position) {
251 let j = position & (BITS_PER_SEGMENT - 1)
252 let i = (position - j) / BITS_PER_SEGMENT
253
254 while (i >= 0) {
255 const s = this._segments.get(i)
256
257 let index = -1
258
259 if (s) index = s.findLast(val, j)
260 else if (!val) index = j
261
262 if (index !== -1) return i * BITS_PER_SEGMENT + index
263
264 j = BITS_PER_SEGMENT - 1
265 i--
266 }
267
268 return -1
269 }
270
271 lastSet (position) {
272 return this.findLast(true, position)
273 }
274
275 lastUnset (position) {
276 return this.findLast(false, position)
277 }
278
279 insert (start, bitfield) {
280 if (start % 32 !== 0) return false
281
282 let length = bitfield.byteLength * 8
283
284 let j = start & (BITS_PER_PAGE - 1)
285 let i = (start - j) / BITS_PER_PAGE
286
287 while (length > 0) {
288 let p = this._pages.get(i)
289
290 if (!p) {
291 const k = Math.floor(i / PAGES_PER_SEGMENT)
292 const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k))
293 if (this._maxSegments <= k) this._maxSegments = k + 1
294
295 p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s))
296 }
297
298 const end = Math.min(j + length, BITS_PER_PAGE)
299 const range = end - j
300
301 p.insert(j, bitfield.subarray(0, range / 32))
302
303 bitfield = bitfield.subarray(range / 32)
304
305 j = 0
306 i++
307 length -= range
308 }
309
310 return true
311 }
312
313 clear (start, bitfield) {
314 if (start % 32 !== 0) return false
315
316 let length = bitfield.byteLength * 8
317
318 let j = start & (BITS_PER_PAGE - 1)
319 let i = (start - j) / BITS_PER_PAGE
320
321 while (length > 0) {
322 let p = this._pages.get(i)
323
324 if (!p) {
325 const k = Math.floor(i / PAGES_PER_SEGMENT)
326 const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k))
327 if (this._maxSegments <= k) this._maxSegments = k + 1
328
329 p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s))
330 }
331
332 const end = Math.min(j + length, BITS_PER_PAGE)
333 const range = end - j
334
335 p.clear(j, bitfield.subarray(0, range / 32))
336
337 bitfield = bitfield.subarray(range / 32)
338
339 j = 0
340 i++
341 length -= range
342 }
343
344 return true
345 }
346}
node_modules/hypercore/lib/replicator.js +2587 -0
……@@ -0,0 +1,2587 @@
1/* DEV DOCS
2 Every hypercore has one Replicator object managing its connections to other peers.
3 There is one Peer object per peer connected to the Hypercore.
4 Hypercores do not know about other hypercores, so when a peer is connected to multiple cores, there exists one Peer object per core.
5
6 Hypercore indicates block should be downloaded through methods like Replicator.addRange or Replicator.addBlock
7 Hypercore calls Replicator.updateActivity every time a hypercore session opens/closes
8 Replicator.updateActivity ensures the Hypercore is downloading blocks as expected
9 Replicator keeps track of:
10 - Which blocks need to be downloaded (Replicator._blocks)
11 - Which blocks currently have inflight requests (Replicator._inflight)
12
13 Blocks are requested from remote peers by Peer objects. The flow is:
14 - The replicator's updatePeer method gets called
15 - The replicator detects whether the Peer can accept more requests (for example by checking if it's maxed out on inflight blocks)
16 - The replicator then tells the Peer what to request (e.g. Peer_requestRange or Peer._requestBlock methods)
17
18 The Peer object is responsible for tracking
19 - Which blocks does the Peer have available (tracked in remoteBitfield)
20 - Which blocks are you actively looking for from this peer (tracked in missingBlocks)
21 - How many blocks are currently inflight (tracked in inflight)
22 The Peer uses this information to decide which blocks to request form the peer in response to _requestRange requests and the like.
23*/
24
25const b4a = require('b4a')
26const safetyCatch = require('safety-catch')
27const RandomIterator = require('random-array-iterator')
28const flatTree = require('flat-tree')
29const ReceiverQueue = require('./receiver-queue')
30const HotswapQueue = require('./hotswap-queue')
31const RemoteBitfield = require('./remote-bitfield')
32const { REQUEST_CANCELLED, REQUEST_TIMEOUT, INVALID_CAPABILITY, SNAPSHOT_NOT_AVAILABLE } = require('hypercore-errors')
33const m = require('./messages')
34const caps = require('./caps')
35
36const DEFAULT_MAX_INFLIGHT = [16, 512]
37const SCALE_LATENCY = 50
38const DEFAULT_SEGMENT_SIZE = 256 * 1024 * 8 // 256 KiB in bits
39const NOT_DOWNLOADING_SLACK = 20000 + (Math.random() * 20000) | 0
40const MAX_PEERS_UPGRADE = 3
41
42const MAX_RANGES = 64
43
44const PRIORITY = {
45 NORMAL: 0,
46 HIGH: 1,
47 VERY_HIGH: 2,
48 CANCELLED: 255 // reserved to mark cancellation
49}
50
51class Attachable {
52 constructor () {
53 this.resolved = false
54 this.refs = []
55 }
56
57 attach (session) {
58 const r = {
59 context: this,
60 session,
61 sindex: 0,
62 rindex: 0,
63 snapshot: true,
64 resolve: null,
65 reject: null,
66 promise: null,
67 timeout: null
68 }
69
70 r.sindex = session.push(r) - 1
71 r.rindex = this.refs.push(r) - 1
72 r.promise = new Promise((resolve, reject) => {
73 r.resolve = resolve
74 r.reject = reject
75 })
76
77 return r
78 }
79
80 detach (r, err = null) {
81 if (r.context !== this) return false
82
83 this._detach(r)
84 this._cancel(r, err)
85 this.gc()
86
87 return true
88 }
89
90 _detach (r) {
91 const rh = this.refs.pop()
92 const sh = r.session.pop()
93
94 if (r.rindex < this.refs.length) this.refs[rh.rindex = r.rindex] = rh
95 if (r.sindex < r.session.length) r.session[sh.sindex = r.sindex] = sh
96
97 destroyRequestTimeout(r)
98 r.context = null
99
100 return r
101 }
102
103 gc () {
104 if (this.refs.length === 0) this._unref()
105 }
106
107 _cancel (r, err) {
108 r.reject(err || REQUEST_CANCELLED())
109 }
110
111 _unref () {
112 // overwrite me
113 }
114
115 resolve (val) {
116 this.resolved = true
117 while (this.refs.length > 0) {
118 this._detach(this.refs[this.refs.length - 1]).resolve(val)
119 }
120 }
121
122 reject (err) {
123 this.resolved = true
124 while (this.refs.length > 0) {
125 this._detach(this.refs[this.refs.length - 1]).reject(err)
126 }
127 }
128
129 setTimeout (r, ms) {
130 destroyRequestTimeout(r)
131 r.timeout = setTimeout(onrequesttimeout, ms, r)
132 }
133}
134
135class BlockRequest extends Attachable {
136 constructor (tracker, index, priority) {
137 super()
138
139 this.index = index
140 this.priority = priority
141 this.inflight = []
142 this.queued = false
143 this.hotswap = null
144 this.tracker = tracker
145 }
146
147 _unref () {
148 this.queued = false
149
150 for (const req of this.inflight) {
151 req.peer._cancelRequest(req)
152 }
153
154 this.tracker.remove(this.index)
155 removeHotswap(this)
156 }
157}
158
159class RangeRequest extends Attachable {
160 constructor (ranges, start, end, linear, ifAvailable, blocks) {
161 super()
162
163 this.start = start
164 this.end = end
165 this.linear = linear
166 this.ifAvailable = ifAvailable
167 this.blocks = blocks
168 this.ranges = ranges
169
170 // As passed by the user, immut
171 this.userStart = start
172 this.userEnd = end
173 }
174
175 _unref () {
176 const i = this.ranges.indexOf(this)
177 if (i === -1) return
178 const h = this.ranges.pop()
179 if (i < this.ranges.length) this.ranges[i] = h
180 }
181
182 _cancel (r) {
183 r.resolve(false)
184 }
185}
186
187class UpgradeRequest extends Attachable {
188 constructor (replicator, fork, length) {
189 super()
190
191 this.fork = fork
192 this.length = length
193 this.inflight = []
194 this.replicator = replicator
195 }
196
197 _unref () {
198 if (this.replicator.eagerUpgrade === true || this.inflight.length > 0) return
199 this.replicator._upgrade = null
200 }
201
202 _cancel (r) {
203 r.resolve(false)
204 }
205}
206
207class SeekRequest extends Attachable {
208 constructor (seeks, seeker) {
209 super()
210
211 this.seeker = seeker
212 this.inflight = []
213 this.seeks = seeks
214 }
215
216 _unref () {
217 if (this.inflight.length > 0) return
218 const i = this.seeks.indexOf(this)
219 if (i === -1) return
220 const h = this.seeks.pop()
221 if (i < this.seeks.length) this.seeks[i] = h
222 }
223}
224
225class InflightTracker {
226 constructor () {
227 this._requests = []
228 this._free = []
229 }
230
231 get idle () {
232 return this._requests.length === this._free.length
233 }
234
235 * [Symbol.iterator] () {
236 for (const req of this._requests) {
237 if (req !== null) yield req
238 }
239 }
240
241 add (req) {
242 const id = this._free.length ? this._free.pop() : this._requests.push(null)
243 req.id = id
244 this._requests[id - 1] = req
245 return req
246 }
247
248 get (id) {
249 return id <= this._requests.length ? this._requests[id - 1] : null
250 }
251
252 remove (id, roundtrip) {
253 if (id > this._requests.length) return
254 this._requests[id - 1] = null
255 if (roundtrip === true) this._free.push(id)
256 }
257
258 reusable (id) {
259 this._free.push(id)
260 }
261}
262
263class BlockTracker {
264 constructor () {
265 this._map = new Map()
266 }
267
268 [Symbol.iterator] () {
269 return this._map.values()
270 }
271
272 isEmpty () {
273 return this._map.size === 0
274 }
275
276 has (index) {
277 return this._map.has(index)
278 }
279
280 get (index) {
281 return this._map.get(index) || null
282 }
283
284 add (index, priority) {
285 let b = this._map.get(index)
286 if (b) return b
287
288 b = new BlockRequest(this, index, priority)
289 this._map.set(index, b)
290
291 return b
292 }
293
294 remove (index) {
295 const b = this.get(index)
296 this._map.delete(index)
297 return b
298 }
299}
300
301class RoundtripQueue {
302 constructor () {
303 this.queue = []
304 this.tick = 0
305 }
306
307 clear () {
308 const ids = new Array(this.queue.length)
309 for (let i = 0; i < ids.length; i++) {
310 ids[i] = this.queue[i][1]
311 }
312
313 this.queue = []
314
315 return ids
316 }
317
318 add (id) {
319 this.queue.push([++this.tick, id])
320 }
321
322 flush (tick) {
323 let flushed = null
324
325 for (let i = 0; i < this.queue.length; i++) {
326 if (this.queue[i][0] > tick) break
327 if (flushed === null) flushed = []
328 flushed.push(this.queue[i][1])
329 }
330
331 if (flushed !== null) this.queue.splice(0, flushed.length)
332 return flushed
333 }
334}
335
336class Peer {
337 constructor (replicator, protomux, channel, useSession, inflightRange) {
338 this.core = replicator.core
339 this.replicator = replicator
340 this.stream = protomux.stream
341 this.protomux = protomux
342 this.remotePublicKey = this.stream.remotePublicKey
343 this.remoteSupportsSeeks = false
344 this.inflightRange = inflightRange
345
346 this.paused = false
347 this.removed = false
348
349 this.useSession = useSession
350
351 this.channel = channel
352 this.channel.userData = this
353
354 this.wireSync = this.channel.messages[0]
355 this.wireRequest = this.channel.messages[1]
356 this.wireCancel = this.channel.messages[2]
357 this.wireData = this.channel.messages[3]
358 this.wireNoData = this.channel.messages[4]
359 this.wireWant = this.channel.messages[5]
360 this.wireUnwant = this.channel.messages[6]
361 this.wireBitfield = this.channel.messages[7]
362 this.wireRange = this.channel.messages[8]
363 this.wireExtension = this.channel.messages[9]
364
365 // Same stats as replicator, but for this specific peer
366 this.stats = {
367 wireSync: { tx: 0, rx: 0 },
368 wireRequest: { tx: 0, rx: 0 },
369 wireCancel: { tx: 0, rx: 0 },
370 wireData: { tx: 0, rx: 0 },
371 wireWant: { tx: 0, rx: 0 },
372 wireBitfield: { tx: 0, rx: 0 },
373 wireRange: { tx: 0, rx: 0 },
374 wireExtension: { tx: 0, rx: 0 },
375 hotswaps: 0
376 }
377
378 this.receiverQueue = new ReceiverQueue()
379 this.receiverBusy = false
380
381 // most often not used, so made on demand
382 this.roundtripQueue = null
383
384 this.inflight = 0
385 this.dataProcessing = 0
386
387 this.canUpgrade = true
388
389 this.needsSync = false
390 this.syncsProcessing = 0
391
392 this._remoteContiguousLength = 0
393
394 // TODO: tweak pipelining so that data sent BEFORE remoteOpened is not cap verified!
395 // we might wanna tweak that with some crypto, ie use the cap to encrypt it...
396 // or just be aware of that, to only push non leaky data
397
398 this.remoteOpened = false
399 this.remoteBitfield = new RemoteBitfield()
400 this.missingBlocks = new RemoteBitfield()
401
402 this.remoteFork = 0
403 this.remoteLength = 0
404 this.remoteCanUpgrade = false
405 this.remoteUploading = true
406 this.remoteDownloading = true
407 this.remoteSynced = false
408 this.remoteHasManifest = false
409 this.remoteRequests = new Map()
410
411 this.segmentsWanted = new Set()
412 this.broadcastedNonSparse = false
413
414 this.lengthAcked = 0
415
416 this.extensions = new Map()
417 this.lastExtensionSent = ''
418 this.lastExtensionRecv = ''
419
420 replicator._ifAvailable++
421 }
422
423 get remoteContiguousLength () {
424 return this.remoteBitfield.findFirst(false, this._remoteContiguousLength)
425 }
426
427 getMaxInflight () {
428 const stream = this.stream.rawStream
429 if (!stream.udx) return Math.min(this.inflightRange[1], this.inflightRange[0] * 3)
430
431 const scale = stream.rtt <= SCALE_LATENCY ? 1 : stream.rtt / SCALE_LATENCY * Math.min(1, 2 / this.replicator.peers.length)
432 return Math.max(this.inflightRange[0], Math.round(Math.min(this.inflightRange[1], this.inflightRange[0] * scale)))
433 }
434
435 getMaxHotswapInflight () {
436 const inf = this.getMaxInflight()
437 return Math.max(16, inf / 2)
438 }
439
440 signalUpgrade () {
441 if (this._shouldUpdateCanUpgrade() === true) this._updateCanUpgradeAndSync()
442 else this.sendSync()
443 }
444
445 _markInflight (index) {
446 this.missingBlocks.set(index, false)
447 }
448
449 broadcastRange (start, length, drop) {
450 if (drop) this._unclearLocalRange(start, length)
451 else this._clearLocalRange(start, length)
452
453 // TODO: consider also adding early-returns on the drop===true case
454 if (!drop) {
455 // No need to broadcast if the remote already has this range
456
457 if (this._remoteContiguousLength >= start + length) return
458
459 if (length === 1) {
460 if (this.remoteBitfield.get(start)) return
461 } else {
462 if (this.remoteBitfield.firstUnset(start) >= start + length) return
463 }
464 }
465
466 this.wireRange.send({
467 drop,
468 start,
469 length
470 })
471 incrementTx(this.stats.wireRange, this.replicator.stats.wireRange)
472 }
473
474 extension (name, message) {
475 this.wireExtension.send({ name: name === this.lastExtensionSent ? '' : name, message })
476 incrementTx(this.stats.wireExtension, this.replicator.stats.wireExtension)
477 this.lastExtensionSent = name
478 }
479
480 onextension (message) {
481 const name = message.name || this.lastExtensionRecv
482 this.lastExtensionRecv = name
483 const ext = this.extensions.get(name)
484 if (ext) ext._onmessage({ start: 0, end: message.message.byteLength, buffer: message.message }, this)
485 }
486
487 sendSync () {
488 if (this.syncsProcessing !== 0) {
489 this.needsSync = true
490 return
491 }
492
493 if (this.core.tree.fork !== this.remoteFork) {
494 this.canUpgrade = false
495 }
496
497 this.needsSync = false
498
499 this.wireSync.send({
500 fork: this.core.tree.fork,
501 length: this.core.tree.length,
502 remoteLength: this.core.tree.fork === this.remoteFork ? this.remoteLength : 0,
503 canUpgrade: this.canUpgrade,
504 uploading: true,
505 downloading: this.replicator.isDownloading(),
506 hasManifest: !!this.core.header.manifest && this.core.compat === false
507 })
508 incrementTx(this.stats.wireSync, this.replicator.stats.wireSync)
509 }
510
511 onopen ({ seeks, capability }) {
512 const expected = caps.replicate(this.stream.isInitiator === false, this.replicator.key, this.stream.handshakeHash)
513
514 if (b4a.equals(capability, expected) !== true) { // TODO: change this to a rejection instead, less leakage
515 throw INVALID_CAPABILITY('Remote sent an invalid replication capability')
516 }
517
518 if (this.remoteOpened === true) return
519 this.remoteOpened = true
520 this.remoteSupportsSeeks = seeks
521
522 this.protomux.cork()
523
524 this.sendSync()
525
526 const contig = Math.min(this.core.tree.length, this.core.header.hints.contiguousLength)
527 if (contig > 0) {
528 this.broadcastRange(0, contig, false)
529
530 if (contig === this.core.tree.length) {
531 this.broadcastedNonSparse = true
532 }
533 }
534
535 this.replicator._ifAvailable--
536 this.replicator._addPeer(this)
537
538 this.protomux.uncork()
539 }
540
541 onclose (isRemote) {
542 // we might have signalled to the remote that we are done (ie not downloading) and the remote might agree on that
543 // if that happens, the channel might be closed by the remote. if so just renegotiate it.
544 // TODO: add a CLOSE_REASON to mux to we can make this cleaner...
545 const reopen = isRemote === true && this.remoteOpened === true && this.remoteDownloading === false &&
546 this.remoteUploading === true && this.replicator.downloading === true
547
548 if (this.remoteOpened === false) {
549 if (this.useSession) {
550 this.replicator._peerSessions--
551 this.replicator._closeSessionMaybe()
552 }
553 this.replicator._ifAvailable--
554 this.replicator.updateAll()
555 return
556 }
557
558 this.remoteOpened = false
559 this.removed = true
560 this.remoteRequests.clear() // cancel all
561 this.receiverQueue.clear()
562
563 if (this.roundtripQueue !== null) {
564 for (const id of this.roundtripQueue.clear()) this.replicator._inflight.reusable(id)
565 }
566
567 this.replicator._removePeer(this)
568
569 if (reopen) {
570 this.replicator._makePeer(this.protomux, this.useSession)
571 }
572
573 if (this.useSession) {
574 this.replicator._peerSessions--
575 this.replicator._closeSessionMaybe()
576 }
577 }
578
579 closeIfIdle () {
580 if (this.remoteDownloading === false && this.replicator.isDownloading() === false) {
581 // idling, shut it down...
582 this.channel.close()
583 return true
584 }
585
586 return false
587 }
588
589 async onsync ({ fork, length, remoteLength, canUpgrade, uploading, downloading, hasManifest }) {
590 const lengthChanged = length !== this.remoteLength
591 const sameFork = fork === this.core.tree.fork
592
593 this.remoteSynced = true
594 this.remoteFork = fork
595 this.remoteLength = length
596 this.remoteCanUpgrade = canUpgrade
597 this.remoteUploading = uploading
598 this.remoteDownloading = downloading
599 this.remoteHasManifest = hasManifest
600
601 if (this.closeIfIdle()) return
602
603 this.lengthAcked = sameFork ? remoteLength : 0
604 this.syncsProcessing++
605
606 this.replicator._updateFork(this)
607
608 if (this.remoteLength > this.core.tree.length && this.lengthAcked === this.core.tree.length) {
609 if (this.replicator._addUpgradeMaybe() !== null) this._update()
610 }
611
612 const upgrade = (lengthChanged === false || sameFork === false)
613 ? this.canUpgrade && sameFork
614 : await this._canUpgrade(length, fork)
615
616 if (length === this.remoteLength && fork === this.core.tree.fork) {
617 this.canUpgrade = upgrade
618 }
619
620 if (--this.syncsProcessing !== 0) return // ie not latest
621
622 if (this.needsSync === true || (this.core.tree.fork === this.remoteFork && this.core.tree.length > this.remoteLength)) {
623 this.signalUpgrade()
624 }
625
626 this._update()
627 }
628
629 _shouldUpdateCanUpgrade () {
630 return this.core.tree.fork === this.remoteFork &&
631 this.core.tree.length > this.remoteLength &&
632 this.canUpgrade === false &&
633 this.syncsProcessing === 0
634 }
635
636 async _updateCanUpgradeAndSync () {
637 const { length, fork } = this.core.tree
638
639 const canUpgrade = await this._canUpgrade(this.remoteLength, this.remoteFork)
640
641 if (this.syncsProcessing > 0 || length !== this.core.tree.length || fork !== this.core.tree.fork) {
642 return
643 }
644 if (canUpgrade === this.canUpgrade) {
645 return
646 }
647
648 this.canUpgrade = canUpgrade
649 this.sendSync()
650 }
651
652 // Safe to call in the background - never fails
653 async _canUpgrade (remoteLength, remoteFork) {
654 if (remoteFork !== this.core.tree.fork) return false
655
656 if (remoteLength === 0) return true
657 if (remoteLength >= this.core.tree.length) return false
658
659 try {
660 // Rely on caching to make sure this is cheap...
661 const canUpgrade = await this.core.tree.upgradeable(remoteLength)
662
663 if (remoteFork !== this.core.tree.fork) return false
664
665 return canUpgrade
666 } catch {
667 return false
668 }
669 }
670
671 async _getProof (msg) {
672 const proof = await this.core.tree.proof(msg)
673
674 if (proof.block) {
675 const index = msg.block.index
676
677 if (msg.fork !== this.core.tree.fork || !this.core.bitfield.get(index)) {
678 return null
679 }
680
681 proof.block.value = await this.core.blocks.get(index)
682 }
683
684 if (msg.manifest && !this.core.compat) {
685 proof.manifest = this.core.header.manifest
686 }
687
688 return proof
689 }
690
691 async onrequest (msg) {
692 const size = this.remoteRequests.size
693 this.remoteRequests.set(msg.id, msg)
694
695 // if size didnt change -> id overwrite -> old one is deleted, cancel current and re-add
696 if (size === this.remoteRequests.size) {
697 this._cancel(msg.id)
698 this.remoteRequests.set(msg.id, msg)
699 }
700
701 if (!this.protomux.drained || this.receiverQueue.length) {
702 this.receiverQueue.push(msg)
703 return
704 }
705
706 await this._handleRequest(msg)
707 }
708
709 oncancel (msg) {
710 this._cancel(msg.request)
711 }
712
713 _cancel (id) {
714 this.remoteRequests.delete(id)
715 this.receiverQueue.delete(id)
716 }
717
718 ondrain () {
719 return this._handleRequests()
720 }
721
722 async _handleRequests () {
723 if (this.receiverBusy) return
724 this.receiverBusy = true
725 this.protomux.cork()
726
727 while (this.remoteOpened && this.protomux.drained && this.receiverQueue.length > 0 && !this.removed) {
728 const msg = this.receiverQueue.shift()
729 await this._handleRequest(msg)
730 }
731
732 this.protomux.uncork()
733 this.receiverBusy = false
734 }
735
736 async _handleRequest (msg) {
737 let proof = null
738
739 // TODO: could still be answerable if (index, fork) is an ancestor of the current fork
740 if (msg.fork === this.core.tree.fork) {
741 try {
742 proof = await this._getProof(msg)
743 } catch (err) {
744 safetyCatch(err)
745 if (msg.fork === this.core.tree.fork && isCriticalError(err)) throw err
746 }
747 }
748
749 // if cancelled do not reply
750 if (this.remoteRequests.get(msg.id) !== msg) {
751 return
752 }
753
754 // sync from now on, so safe to delete from the map
755 this.remoteRequests.delete(msg.id)
756
757 if (proof === null) {
758 if (msg.manifest && this.core.header.manifest) {
759 const manifest = this.core.header.manifest
760 this.wireData.send({ request: msg.id, fork: this.core.tree.fork, block: null, hash: null, seek: null, upgrade: null, manifest })
761 incrementTx(this.stats.wireData, this.replicator.stats.wireData)
762 return
763 }
764
765 this.wireNoData.send({ request: msg.id })
766 return
767 }
768
769 if (proof.block !== null) {
770 this.replicator.onupload(proof.block.index, proof.block.value, this)
771 }
772
773 this.wireData.send({
774 request: msg.id,
775 fork: msg.fork,
776 block: proof.block,
777 hash: proof.hash,
778 seek: proof.seek,
779 upgrade: proof.upgrade,
780 manifest: proof.manifest
781 })
782 incrementTx(this.stats.wireData, this.replicator.stats.wireData)
783 }
784
785 _cancelRequest (req) {
786 if (req.priority === PRIORITY.CANCELLED) return
787 // mark as cancelled also and avoid re-entry
788 req.priority = PRIORITY.CANCELLED
789
790 this.inflight--
791 this.replicator._requestDone(req.id, false)
792
793 // clear inflight state
794 if (isBlockRequest(req)) this.replicator._unmarkInflight(req.block.index)
795 if (isUpgradeRequest(req)) this.replicator._clearInflightUpgrade(req)
796
797 if (this.roundtripQueue === null) this.roundtripQueue = new RoundtripQueue()
798 this.roundtripQueue.add(req.id)
799 this.wireCancel.send({ request: req.id })
800 incrementTx(this.stats.wireCancel, this.replicator.stats.wireCancel)
801 }
802
803 _checkIfConflict () {
804 this.paused = true
805
806 const length = Math.min(this.core.tree.length, this.remoteLength)
807 if (length === 0) return // pause and ignore
808
809 this.wireRequest.send({
810 id: 0, // TODO: use an more explicit id for this eventually...
811 fork: this.remoteFork,
812 block: null,
813 hash: null,
814 seek: null,
815 upgrade: {
816 start: 0,
817 length
818 }
819 })
820
821 incrementTx(this.stats.wireRequest, this.replicator.stats.wireRequest)
822 }
823
824 async ondata (data) {
825 // always allow a fork conflict proof to be sent
826 if (data.request === 0 && data.upgrade && data.upgrade.start === 0) {
827 if (await this.core.checkConflict(data, this)) return
828 this.paused = false
829 }
830
831 const req = data.request > 0 ? this.replicator._inflight.get(data.request) : null
832 const reorg = data.fork > this.core.tree.fork
833
834 // no push atm, TODO: check if this satisfies another pending request
835 // allow reorg pushes tho as those are not written to storage so we'll take all the help we can get
836 if (req === null && reorg === false) return
837
838 if (req !== null) {
839 if (req.peer !== this) return
840 this._onrequestroundtrip(req)
841 }
842
843 try {
844 if (reorg === true) return await this.replicator._onreorgdata(this, req, data)
845 } catch (err) {
846 safetyCatch(err)
847 if (isBlockRequest(req)) this.replicator._unmarkInflight(req.block.index)
848
849 this.paused = true
850 this.replicator.oninvalid(err, req, data, this)
851 return
852 }
853
854 this.dataProcessing++
855
856 try {
857 if (!matchingRequest(req, data) || !(await this.core.verify(data, this))) {
858 this.replicator._onnodata(this, req)
859 return
860 }
861 } catch (err) {
862 safetyCatch(err)
863 if (isBlockRequest(req)) this.replicator._unmarkInflight(req.block.index)
864
865 if (err.code === 'WRITE_FAILED') {
866 // For example, we don't want to keep pulling data when storage is full
867 // TODO: notify the user somehow
868 this.paused = true
869 return
870 }
871
872 if (this.core.closed && !isCriticalError(err)) return
873
874 if (err.code !== 'INVALID_OPERATION') {
875 // might be a fork, verify
876 this._checkIfConflict()
877 }
878
879 this.replicator._onnodata(this, req)
880 this.replicator.oninvalid(err, req, data, this)
881 return
882 } finally {
883 this.dataProcessing--
884 }
885
886 this.replicator._ondata(this, req, data)
887
888 if (this._shouldUpdateCanUpgrade() === true) {
889 this._updateCanUpgradeAndSync()
890 }
891 }
892
893 onnodata ({ request }) {
894 const req = request > 0 ? this.replicator._inflight.get(request) : null
895
896 if (req === null || req.peer !== this) return
897
898 this._onrequestroundtrip(req)
899 this.replicator._onnodata(this, req)
900 }
901
902 _onrequestroundtrip (req) {
903 if (req.priority === PRIORITY.CANCELLED) return
904 // to avoid re-entry we also just mark it as cancelled
905 req.priority = PRIORITY.CANCELLED
906
907 this.inflight--
908 this.replicator._requestDone(req.id, true)
909 if (this.roundtripQueue === null) return
910 const flushed = this.roundtripQueue.flush(req.rt)
911 if (flushed === null) return
912 for (const id of flushed) this.replicator._inflight.reusable(id)
913 }
914
915 onwant ({ start, length }) {
916 this.replicator._onwant(this, start, length)
917 }
918
919 onunwant () {
920 // TODO
921 }
922
923 onbitfield ({ start, bitfield }) {
924 if (start < this._remoteContiguousLength) this._remoteContiguousLength = start // bitfield is always the truth
925 this.remoteBitfield.insert(start, bitfield)
926 this.missingBlocks.insert(start, bitfield)
927 this._clearLocalRange(start, bitfield.byteLength * 8)
928 this._update()
929 }
930
931 _clearLocalRange (start, length) {
932 const bitfield = this.core.skipBitfield === null ? this.core.bitfield : this.core.skipBitfield
933
934 if (length === 1) {
935 this.missingBlocks.set(start, this._remoteHasBlock(start) && !bitfield.get(start))
936 return
937 }
938
939 const contig = Math.min(this.core.tree.length, this.core.header.hints.contiguousLength)
940
941 if (start + length < contig) {
942 const delta = contig - start
943 this.missingBlocks.setRange(start, delta, false)
944 return
945 }
946
947 const rem = start & 32767
948 if (rem > 0) {
949 start -= rem
950 length += rem
951 }
952
953 const end = start + Math.min(length, this.core.tree.length)
954 while (start < end) {
955 const local = bitfield.getBitfield(start)
956
957 if (local && local.bitfield) {
958 this.missingBlocks.clear(start, local.bitfield)
959 }
960
961 start += 32768
962 }
963 }
964
965 _resetMissingBlock (index) {
966 const bitfield = this.core.skipBitfield === null ? this.core.bitfield : this.core.skipBitfield
967 this.missingBlocks.set(index, this._remoteHasBlock(index) && !bitfield.get(index))
968 }
969
970 _unclearLocalRange (start, length) {
971 if (length === 1) {
972 this._resetMissingBlock(start)
973 return
974 }
975
976 const rem = start & 2097151
977 if (rem > 0) {
978 start -= rem
979 length += rem
980 }
981
982 const fixedStart = start
983
984 const end = start + Math.min(length, this.remoteLength)
985 while (start < end) {
986 const remote = this.remoteBitfield.getBitfield(start)
987 if (remote && remote.bitfield) {
988 this.missingBlocks.insert(start, remote.bitfield)
989 }
990
991 start += 2097152
992 }
993
994 this._clearLocalRange(fixedStart, length)
995 }
996
997 onrange ({ drop, start, length }) {
998 const has = drop === false
999
1000 if (drop === true && start < this._remoteContiguousLength) {
1001 this._remoteContiguousLength = start
1002 }
1003
1004 if (start === 0 && drop === false) {
1005 if (length > this._remoteContiguousLength) this._remoteContiguousLength = length
1006 } else if (length === 1) {
1007 const bitfield = this.core.skipBitfield === null ? this.core.bitfield : this.core.skipBitfield
1008 this.remoteBitfield.set(start, has)
1009 this.missingBlocks.set(start, has && !bitfield.get(start))
1010 } else {
1011 const rangeStart = this.remoteBitfield.findFirst(!has, start)
1012 const rangeLength = length - (rangeStart - start)
1013
1014 if (rangeLength > 0) {
1015 this.remoteBitfield.setRange(rangeStart, rangeLength, has)
1016 this.missingBlocks.setRange(rangeStart, rangeLength, has)
1017 if (has) this._clearLocalRange(rangeStart, rangeLength)
1018 }
1019 }
1020
1021 if (drop === false) this._update()
1022 }
1023
1024 onreorghint () {
1025 // TODO
1026 }
1027
1028 _update () {
1029 // TODO: if this is in a batch or similar it would be better to defer it
1030 // we could do that with nextTick/microtick mb? (combined with a property on the session to signal read buffer mb)
1031 this.replicator.updatePeer(this)
1032 }
1033
1034 async _onconflict () {
1035 this.protomux.cork()
1036 if (this.remoteLength > 0 && this.core.tree.fork === this.remoteFork) {
1037 await this.onrequest({
1038 id: 0,
1039 fork: this.core.tree.fork,
1040 block: null,
1041 hash: null,
1042 seek: null,
1043 upgrade: {
1044 start: 0,
1045 length: Math.min(this.core.tree.length, this.remoteLength)
1046 }
1047 })
1048 }
1049 this.channel.close()
1050 this.protomux.uncork()
1051 }
1052
1053 _makeRequest (needsUpgrade, priority, minLength) {
1054 if (needsUpgrade === true && this.replicator._shouldUpgrade(this) === false) {
1055 return null
1056 }
1057
1058 // ensure that the remote has signalled they have the length we request
1059 if (this.remoteLength < minLength) {
1060 return null
1061 }
1062
1063 if (needsUpgrade === false && this.replicator._autoUpgrade(this) === true) {
1064 needsUpgrade = true
1065 }
1066
1067 return {
1068 peer: this,
1069 rt: this.roundtripQueue === null ? 0 : this.roundtripQueue.tick,
1070 id: 0,
1071 fork: this.remoteFork,
1072 block: null,
1073 hash: null,
1074 seek: null,
1075 upgrade: needsUpgrade === false
1076 ? null
1077 : { start: this.core.tree.length, length: this.remoteLength - this.core.tree.length },
1078 // remote manifest check can be removed eventually...
1079 manifest: this.core.header.manifest === null && this.remoteHasManifest === true,
1080 priority
1081 }
1082 }
1083
1084 _requestManifest () {
1085 const req = this._makeRequest(false, 0, 0)
1086 this._send(req)
1087 }
1088
1089 _requestUpgrade (u) {
1090 const req = this._makeRequest(true, 0, 0)
1091 if (req === null) return false
1092
1093 this._send(req)
1094
1095 return true
1096 }
1097
1098 _requestSeek (s) {
1099 // if replicator is updating the seeks etc, bail and wait for it to drain
1100 if (this.replicator._updatesPending > 0) return false
1101
1102 const { length, fork } = this.core.tree
1103
1104 if (fork !== this.remoteFork) return false
1105
1106 if (s.seeker.start >= length) {
1107 const req = this._makeRequest(true, 0, 0)
1108
1109 // We need an upgrade for the seek, if non can be provided, skip
1110 if (req === null) return false
1111
1112 req.seek = this.remoteSupportsSeeks ? { bytes: s.seeker.bytes, padding: s.seeker.padding } : null
1113
1114 s.inflight.push(req)
1115 this._send(req)
1116
1117 return true
1118 }
1119
1120 const len = s.seeker.end - s.seeker.start
1121 const off = s.seeker.start + Math.floor(Math.random() * len)
1122
1123 for (let i = 0; i < len; i++) {
1124 let index = off + i
1125 if (index > s.seeker.end) index -= len
1126
1127 if (this._remoteHasBlock(index) === false) continue
1128 if (this.core.bitfield.get(index) === true) continue
1129 if (!this._hasTreeParent(index)) continue
1130
1131 // Check if this block is currently inflight - if so pick another
1132 const b = this.replicator._blocks.get(index)
1133 if (b !== null && b.inflight.length > 0) continue
1134
1135 // Block is not inflight, but we only want the hash, check if that is inflight
1136 const h = this.replicator._hashes.add(index, PRIORITY.NORMAL)
1137 if (h.inflight.length > 0) continue
1138
1139 const req = this._makeRequest(false, h.priority, index + 1)
1140 if (req === null) continue
1141
1142 const nodes = flatTree.depth(s.seeker.start + s.seeker.end - 1)
1143
1144 req.hash = { index: 2 * index, nodes }
1145 req.seek = this.remoteSupportsSeeks ? { bytes: s.seeker.bytes, padding: s.seeker.padding } : null
1146
1147 s.inflight.push(req)
1148 h.inflight.push(req)
1149 this._send(req)
1150
1151 return true
1152 }
1153
1154 this._maybeWant(s.seeker.start, len)
1155 return false
1156 }
1157
1158 _hasTreeParent (index) {
1159 if (this.remoteLength >= this.core.tree.length) return true
1160
1161 const ite = flatTree.iterator(index * 2)
1162
1163 let span = 2
1164 let length = 0
1165
1166 while (true) {
1167 ite.parent()
1168
1169 const left = (ite.index - ite.factor / 2 + 1) / 2
1170 length = left + span
1171
1172 // if larger than local AND larger than remote - they share the root so its ok
1173 if (length > this.core.tree.length) {
1174 if (length > this.remoteLength) return true
1175 break
1176 }
1177
1178 // its less than local but larger than remote so skip it
1179 if (length > this.remoteLength) break
1180
1181 span *= 2
1182 const first = this.core.bitfield.findFirst(true, left)
1183 if (first > -1 && first < length) return true
1184 }
1185
1186 // TODO: push to async queue and check against our local merkle tree if we actually can request this block
1187 return false
1188 }
1189
1190 _remoteHasBlock (index) {
1191 return index < this._remoteContiguousLength || this.remoteBitfield.get(index) === true
1192 }
1193
1194 _sendBlockRequest (req, b) {
1195 req.block = { index: b.index, nodes: 0 }
1196 this.replicator._markInflight(b.index)
1197
1198 b.inflight.push(req)
1199 this.replicator.hotswaps.add(b)
1200 this._send(req)
1201 }
1202
1203 _requestBlock (b) {
1204 const { length, fork } = this.core.tree
1205
1206 if (this._remoteHasBlock(b.index) === false || fork !== this.remoteFork) {
1207 this._maybeWant(b.index)
1208 return false
1209 }
1210
1211 if (!this._hasTreeParent(b.index)) {
1212 return false
1213 }
1214
1215 const req = this._makeRequest(b.index >= length, b.priority, b.index + 1)
1216 if (req === null) return false
1217
1218 this._sendBlockRequest(req, b)
1219
1220 return true
1221 }
1222
1223 _requestRangeBlock (index, length) {
1224 if (this.core.bitfield.get(index) === true || !this._hasTreeParent(index)) return false
1225
1226 const b = this.replicator._blocks.add(index, PRIORITY.NORMAL)
1227 if (b.inflight.length > 0) {
1228 this.missingBlocks.set(index, false) // in case we missed some states just set them ondemand, nbd
1229 return false
1230 }
1231
1232 const req = this._makeRequest(index >= length, b.priority, index + 1)
1233
1234 // If the request cannot be satisfied, dealloc the block request if no one is subscribed to it
1235 if (req === null) {
1236 b.gc()
1237 return false
1238 }
1239
1240 this._sendBlockRequest(req, b)
1241
1242 // Don't think this will ever happen, as the pending queue is drained before the range queue
1243 // but doesn't hurt to check this explicitly here also.
1244 if (b.queued) b.queued = false
1245 return true
1246 }
1247
1248 _findNext (i) {
1249 if (i < this._remoteContiguousLength) {
1250 if (this.core.skipBitfield === null) this.replicator._openSkipBitfield()
1251 i = this.core.skipBitfield.findFirst(false, i)
1252 if (i < this._remoteContiguousLength && i > -1) return i
1253 i = this._remoteContiguousLength
1254 }
1255
1256 return this.missingBlocks.findFirst(true, i)
1257 }
1258
1259 _requestRange (r) {
1260 const { length, fork } = this.core.tree
1261
1262 if (r.blocks) {
1263 let min = -1
1264 let max = -1
1265
1266 for (let i = r.start; i < r.end; i++) {
1267 const index = r.blocks[i]
1268 if (min === -1 || index < min) min = index
1269 if (max === -1 || index > max) max = index
1270 const has = index < this._remoteContiguousLength || this.missingBlocks.get(index) === true
1271 if (has === true && this._requestRangeBlock(index, length)) return true
1272 }
1273
1274 if (min > -1) this._maybeWant(min, max - min)
1275 return false
1276 }
1277
1278 const end = Math.min(this.core.tree.length, Math.min(r.end === -1 ? this.remoteLength : r.end, this.remoteLength))
1279 if (end <= r.start || fork !== this.remoteFork) return false
1280
1281 const len = end - r.start
1282 const off = r.start + (r.linear ? 0 : Math.floor(Math.random() * len))
1283
1284 let i = off
1285
1286 while (true) {
1287 i = this._findNext(i)
1288 if (i === -1 || i >= end) break
1289
1290 if (this._requestRangeBlock(i, length)) return true
1291 i++
1292 }
1293
1294 i = r.start
1295
1296 while (true) {
1297 i = this._findNext(i)
1298 if (i === -1 || i >= off) break
1299
1300 if (this._requestRangeBlock(i, length)) return true
1301 i++
1302 }
1303
1304 this._maybeWant(r.start, len)
1305 return false
1306 }
1307
1308 _requestForkProof (f) {
1309 const req = this._makeRequest(false, 0, 0)
1310
1311 req.upgrade = { start: 0, length: this.remoteLength }
1312 req.manifest = !this.core.header.manifest
1313
1314 f.inflight.push(req)
1315 this._send(req)
1316 }
1317
1318 _requestForkRange (f) {
1319 if (f.fork !== this.remoteFork || f.batch.want === null) return false
1320
1321 const end = Math.min(f.batch.want.end, this.remoteLength)
1322 if (end < f.batch.want.start) return false
1323
1324 const len = end - f.batch.want.start
1325 const off = f.batch.want.start + Math.floor(Math.random() * len)
1326
1327 for (let i = 0; i < len; i++) {
1328 let index = off + i
1329 if (index >= end) index -= len
1330
1331 if (this._remoteHasBlock(index) === false) continue
1332
1333 const req = this._makeRequest(false, 0, 0)
1334
1335 req.hash = { index: 2 * index, nodes: f.batch.want.nodes }
1336
1337 f.inflight.push(req)
1338 this._send(req)
1339
1340 return true
1341 }
1342
1343 this._maybeWant(f.batch.want.start, len)
1344 return false
1345 }
1346
1347 _maybeWant (start, length = 1) {
1348 if (start + length <= this.remoteContiguousLength) return
1349
1350 let i = Math.floor(start / DEFAULT_SEGMENT_SIZE)
1351 const n = Math.ceil((start + length) / DEFAULT_SEGMENT_SIZE)
1352
1353 for (; i < n; i++) {
1354 if (this.segmentsWanted.has(i)) continue
1355 this.segmentsWanted.add(i)
1356
1357 this.wireWant.send({
1358 start: i * DEFAULT_SEGMENT_SIZE,
1359 length: DEFAULT_SEGMENT_SIZE
1360 })
1361 incrementTx(this.stats.wireWant, this.replicator.stats.wireWant)
1362 }
1363 }
1364
1365 isActive () {
1366 if (this.paused || this.removed) return false
1367 return true
1368 }
1369
1370 async _send (req) {
1371 const fork = this.core.tree.fork
1372
1373 this.inflight++
1374 this.replicator._inflight.add(req)
1375
1376 if (req.upgrade !== null && req.fork === fork) {
1377 const u = this.replicator._addUpgrade()
1378 u.inflight.push(req)
1379 }
1380
1381 try {
1382 if (req.block !== null && req.fork === fork) {
1383 req.block.nodes = await this.core.tree.missingNodes(2 * req.block.index)
1384 if (req.priority === PRIORITY.CANCELLED) return
1385 }
1386 if (req.hash !== null && req.fork === fork && req.hash.nodes === 0) {
1387 req.hash.nodes = await this.core.tree.missingNodes(req.hash.index)
1388 if (req.priority === PRIORITY.CANCELLED) return
1389
1390 // nodes === 0, we already have it, bail
1391 if (req.hash.nodes === 0 && (req.hash.index & 1) === 0) {
1392 this.inflight--
1393 this.replicator._resolveHashLocally(this, req)
1394 return
1395 }
1396 }
1397 } catch (err) {
1398 this.stream.destroy(err)
1399 return
1400 }
1401
1402 this.wireRequest.send(req)
1403 incrementTx(this.stats.wireRequest, this.replicator.stats.wireRequest)
1404 }
1405}
1406
1407module.exports = class Replicator {
1408 static Peer = Peer // hack to be able to access Peer from outside this module
1409
1410 constructor (core, key, {
1411 notDownloadingLinger = NOT_DOWNLOADING_SLACK,
1412 eagerUpgrade = true,
1413 allowFork = true,
1414 inflightRange = null,
1415 onpeerupdate = noop,
1416 onupload = noop,
1417 oninvalid = noop
1418 } = {}) {
1419 this.key = key
1420 this.discoveryKey = core.crypto.discoveryKey(key)
1421 this.core = core
1422 this.eagerUpgrade = eagerUpgrade
1423 this.allowFork = allowFork
1424 this.onpeerupdate = onpeerupdate
1425 this.onupload = onupload
1426 this.oninvalid = oninvalid
1427 this.ondownloading = null // optional external hook for monitoring downloading status
1428 this.peers = []
1429 this.findingPeers = 0 // updateable from the outside
1430 this.destroyed = false
1431 this.downloading = false
1432 this.activeSessions = 0
1433
1434 this.hotswaps = new HotswapQueue()
1435 this.inflightRange = inflightRange || DEFAULT_MAX_INFLIGHT
1436
1437 // Note: nodata and unwant not currently tracked
1438 // tx = transmitted, rx = received
1439 this.stats = {
1440 wireSync: { tx: 0, rx: 0 },
1441 wireRequest: { tx: 0, rx: 0 },
1442 wireCancel: { tx: 0, rx: 0 },
1443 wireData: { tx: 0, rx: 0 },
1444 wireWant: { tx: 0, rx: 0 },
1445 wireBitfield: { tx: 0, rx: 0 },
1446 wireRange: { tx: 0, rx: 0 },
1447 wireExtension: { tx: 0, rx: 0 },
1448 hotswaps: 0
1449 }
1450
1451 this._attached = new Set()
1452 this._inflight = new InflightTracker()
1453 this._blocks = new BlockTracker()
1454 this._hashes = new BlockTracker()
1455
1456 this._queued = []
1457
1458 this._seeks = []
1459 this._upgrade = null
1460 this._reorgs = []
1461 this._ranges = []
1462
1463 this._hadPeers = false
1464 this._ifAvailable = 0
1465 this._updatesPending = 0
1466 this._applyingReorg = null
1467 this._manifestPeer = null
1468 this._hasSession = false
1469 this._peerSessions = 0
1470 this._notDownloadingLinger = notDownloadingLinger
1471 this._downloadingTimer = null
1472
1473 const self = this
1474 this._onstreamclose = onstreamclose
1475
1476 function onstreamclose () {
1477 self.detachFrom(this.userData)
1478 }
1479 }
1480
1481 updateActivity (inc, session) {
1482 this.activeSessions += inc
1483 this.setDownloading(this.activeSessions !== 0, session)
1484 }
1485
1486 isDownloading () {
1487 return this.downloading || !this._inflight.idle
1488 }
1489
1490 setDownloading (downloading) {
1491 clearTimeout(this._downloadingTimer)
1492
1493 if (this.destroyed) return
1494 if (downloading || this._notDownloadingLinger === 0) {
1495 this.setDownloadingNow(downloading)
1496 return
1497 }
1498
1499 this._downloadingTimer = setTimeout(setDownloadingLater, this._notDownloadingLinger, this, downloading)
1500 }
1501
1502 setDownloadingNow (downloading) {
1503 this._downloadingTimer = null
1504 if (this.downloading === downloading) return
1505 this.downloading = downloading
1506 if (!downloading && this.isDownloading()) return
1507
1508 for (const peer of this.peers) peer.signalUpgrade()
1509
1510 if (downloading) { // restart channel if needed...
1511 for (const protomux of this._attached) {
1512 if (!protomux.stream.handshakeHash) continue
1513 if (protomux.opened({ protocol: 'hypercore/alpha', id: this.discoveryKey })) continue
1514 this._makePeer(protomux, true)
1515 }
1516 } else {
1517 for (const peer of this.peers) peer.closeIfIdle()
1518 }
1519
1520 if (this.ondownloading !== null && downloading) this.ondownloading()
1521 }
1522
1523 cork () {
1524 for (const peer of this.peers) peer.protomux.cork()
1525 }
1526
1527 uncork () {
1528 for (const peer of this.peers) peer.protomux.uncork()
1529 }
1530
1531 // Called externally when a range of new blocks has been processed/removed
1532 onhave (start, length, drop = false) {
1533 for (const peer of this.peers) peer.broadcastRange(start, length, drop)
1534 }
1535
1536 // Called externally when a truncation upgrade has been processed
1537 ontruncate (newLength, truncated) {
1538 const notify = []
1539
1540 for (const blk of this._blocks) {
1541 if (blk.index < newLength) continue
1542 notify.push(blk)
1543 }
1544
1545 for (const blk of notify) {
1546 for (const r of blk.refs) {
1547 if (r.snapshot === false) continue
1548 blk.detach(r, SNAPSHOT_NOT_AVAILABLE())
1549 }
1550 }
1551
1552 for (const peer of this.peers) peer._unclearLocalRange(newLength, truncated)
1553 }
1554
1555 // Called externally when a upgrade has been processed
1556 onupgrade () {
1557 for (const peer of this.peers) peer.signalUpgrade()
1558 if (this._blocks.isEmpty() === false) this._resolveBlocksLocally()
1559 if (this._upgrade !== null) this._resolveUpgradeRequest(null)
1560 if (this._ranges.length !== 0 || this._seeks.length !== 0) this._updateNonPrimary(true)
1561 }
1562
1563 // Called externally when a conflict has been detected and verified
1564 async onconflict (from) {
1565 const all = []
1566 for (const peer of this.peers) {
1567 all.push(peer._onconflict())
1568 }
1569 await Promise.allSettled(all)
1570 }
1571
1572 async applyPendingReorg () {
1573 if (this._applyingReorg !== null) {
1574 await this._applyingReorg
1575 return true
1576 }
1577
1578 for (let i = this._reorgs.length - 1; i >= 0; i--) {
1579 const f = this._reorgs[i]
1580 if (f.batch !== null && f.batch.finished) {
1581 await this._applyReorg(f)
1582 return true
1583 }
1584 }
1585
1586 return false
1587 }
1588
1589 addUpgrade (session) {
1590 if (this._upgrade !== null) {
1591 const ref = this._upgrade.attach(session)
1592 this._checkUpgradeIfAvailable()
1593 return ref
1594 }
1595
1596 const ref = this._addUpgrade().attach(session)
1597
1598 this.updateAll()
1599
1600 return ref
1601 }
1602
1603 addBlock (session, index) {
1604 const b = this._blocks.add(index, PRIORITY.HIGH)
1605 const ref = b.attach(session)
1606
1607 this._queueBlock(b)
1608 this.updateAll()
1609
1610 return ref
1611 }
1612
1613 addSeek (session, seeker) {
1614 const s = new SeekRequest(this._seeks, seeker)
1615 const ref = s.attach(session)
1616
1617 this._seeks.push(s)
1618 this.updateAll()
1619
1620 return ref
1621 }
1622
1623 addRange (session, { start = 0, end = -1, length = toLength(start, end), blocks = null, linear = false, ifAvailable = false } = {}) {
1624 if (blocks !== null) { // if using blocks, start, end just acts as frames around the blocks array
1625 start = 0
1626 end = length = blocks.length
1627 }
1628
1629 const r = new RangeRequest(
1630 this._ranges,
1631 start,
1632 length === -1 ? -1 : start + length,
1633 linear,
1634 ifAvailable,
1635 blocks
1636 )
1637
1638 const ref = r.attach(session)
1639
1640 // Trigger this to see if this is already resolved...
1641 // Also auto compresses the range based on local bitfield
1642 clampRange(this.core, r)
1643
1644 this._ranges.push(r)
1645
1646 if (r.end !== -1 && r.start >= r.end) {
1647 this._resolveRangeRequest(r, this._ranges.length - 1)
1648 return ref
1649 }
1650
1651 this.updateAll()
1652
1653 return ref
1654 }
1655
1656 cancel (ref) {
1657 ref.context.detach(ref, null)
1658 }
1659
1660 clearRequests (session, err = null) {
1661 let cleared = false
1662 while (session.length > 0) {
1663 const ref = session[session.length - 1]
1664 ref.context.detach(ref, err)
1665 cleared = true
1666 }
1667
1668 if (cleared) this.updateAll()
1669 }
1670
1671 _addUpgradeMaybe () {
1672 return this.eagerUpgrade === true ? this._addUpgrade() : this._upgrade
1673 }
1674
1675 // TODO: this function is OVER called atm, at each updatePeer/updateAll
1676 // instead its more efficient to only call it when the conditions in here change - ie on sync/add/remove peer
1677 // Do this when we have more tests.
1678 _checkUpgradeIfAvailable () {
1679 if (this._ifAvailable > 0 && this.peers.length < MAX_PEERS_UPGRADE) return
1680 if (this._upgrade === null || this._upgrade.refs.length === 0) return
1681 if (this._hadPeers === false && this.findingPeers > 0) return
1682
1683 const maxPeers = Math.min(this.peers.length, MAX_PEERS_UPGRADE)
1684
1685 // check if a peer can upgrade us
1686
1687 for (let i = 0; i < maxPeers; i++) {
1688 const peer = this.peers[i]
1689
1690 if (peer.remoteSynced === false) return
1691
1692 if (this.core.tree.length === 0 && peer.remoteLength > 0) return
1693
1694 if (peer.remoteLength <= this._upgrade.length || peer.remoteFork !== this._upgrade.fork) continue
1695
1696 if (peer.syncsProcessing > 0) return
1697
1698 if (peer.lengthAcked !== this.core.tree.length && peer.remoteFork === this.core.tree.fork) return
1699 if (peer.remoteCanUpgrade === true) return
1700 }
1701
1702 // check if reorgs in progress...
1703
1704 if (this._applyingReorg !== null) return
1705
1706 // TODO: we prob should NOT wait for inflight reorgs here, seems better to just resolve the upgrade
1707 // and then apply the reorg on the next call in case it's slow - needs some testing in practice
1708
1709 for (let i = 0; i < this._reorgs.length; i++) {
1710 const r = this._reorgs[i]
1711 if (r.inflight.length > 0) return
1712 }
1713
1714 // if something is inflight, wait for that first
1715 if (this._upgrade.inflight.length > 0) return
1716
1717 // nothing to do, indicate no update avail
1718
1719 const u = this._upgrade
1720 this._upgrade = null
1721 u.resolve(false)
1722 }
1723
1724 _addUpgrade () {
1725 if (this._upgrade !== null) return this._upgrade
1726
1727 // TODO: needs a reorg: true/false flag to indicate if the user requested a reorg
1728 this._upgrade = new UpgradeRequest(this, this.core.tree.fork, this.core.tree.length)
1729
1730 return this._upgrade
1731 }
1732
1733 _addReorg (fork, peer) {
1734 if (this.allowFork === false) return null
1735
1736 // TODO: eager gc old reorgs from the same peer
1737 // not super important because they'll get gc'ed when the request finishes
1738 // but just spam the remote can do ...
1739
1740 for (const f of this._reorgs) {
1741 if (f.fork > fork && f.batch !== null) return null
1742 if (f.fork === fork) return f
1743 }
1744
1745 const f = {
1746 fork,
1747 inflight: [],
1748 batch: null
1749 }
1750
1751 this._reorgs.push(f)
1752
1753 // maintain sorted by fork
1754 let i = this._reorgs.length - 1
1755 while (i > 0 && this._reorgs[i - 1].fork > fork) {
1756 this._reorgs[i] = this._reorgs[i - 1]
1757 this._reorgs[--i] = f
1758 }
1759
1760 return f
1761 }
1762
1763 _shouldUpgrade (peer) {
1764 if (this._upgrade !== null && this._upgrade.inflight.length > 0) return false
1765 return peer.remoteCanUpgrade === true &&
1766 peer.remoteLength > this.core.tree.length &&
1767 peer.lengthAcked === this.core.tree.length
1768 }
1769
1770 _autoUpgrade (peer) {
1771 return this._upgrade !== null && peer.remoteFork === this.core.tree.fork && this._shouldUpgrade(peer)
1772 }
1773
1774 _addPeer (peer) {
1775 this._hadPeers = true
1776 this.peers.push(peer)
1777 this.updatePeer(peer)
1778 this.onpeerupdate(true, peer)
1779 }
1780
1781 _requestDone (id, roundtrip) {
1782 this._inflight.remove(id, roundtrip)
1783 if (this.isDownloading() === true) return
1784 for (const peer of this.peers) peer.signalUpgrade()
1785 }
1786
1787 _removePeer (peer) {
1788 this.peers.splice(this.peers.indexOf(peer), 1)
1789
1790 if (this._manifestPeer === peer) this._manifestPeer = null
1791
1792 for (const req of this._inflight) {
1793 if (req.peer !== peer) continue
1794 this._inflight.remove(req.id, true)
1795 this._clearRequest(peer, req)
1796 }
1797
1798 if (peer.useSession) this._closeSessionMaybe()
1799
1800 this.onpeerupdate(false, peer)
1801 this.updateAll()
1802 }
1803
1804 _queueBlock (b) {
1805 if (b.inflight.length > 0 || b.queued === true) return
1806 b.queued = true
1807 this._queued.push(b)
1808 }
1809
1810 _resolveHashLocally (peer, req) {
1811 this._requestDone(req.id, false)
1812 this._resolveBlockRequest(this._hashes, req.hash.index / 2, null, req)
1813 this.updatePeer(peer)
1814 }
1815
1816 // Runs in the background - not allowed to throw
1817 async _resolveBlocksLocally () {
1818 // TODO: check if fork compat etc. Requires that we pass down truncation info
1819
1820 let clear = null
1821
1822 for (const b of this._blocks) {
1823 if (this.core.bitfield.get(b.index) === false) continue
1824
1825 try {
1826 b.resolve(await this.core.blocks.get(b.index))
1827 } catch (err) {
1828 b.reject(err)
1829 }
1830
1831 if (clear === null) clear = []
1832 clear.push(b)
1833 }
1834
1835 if (clear === null) return
1836
1837 // Currently the block tracker does not support deletes during iteration, so we make
1838 // sure to clear them afterwards.
1839 for (const b of clear) {
1840 this._blocks.remove(b.index)
1841 removeHotswap(b)
1842 }
1843 }
1844
1845 _resolveBlockRequest (tracker, index, value, req) {
1846 const b = tracker.remove(index)
1847 if (b === null) return false
1848
1849 removeInflight(b.inflight, req)
1850 removeHotswap(b)
1851 b.queued = false
1852
1853 b.resolve(value)
1854
1855 if (b.inflight.length > 0) { // if anything is still inflight, cancel it
1856 for (let i = b.inflight.length - 1; i >= 0; i--) {
1857 const req = b.inflight[i]
1858 req.peer._cancelRequest(req)
1859 }
1860 }
1861
1862 return true
1863 }
1864
1865 _resolveUpgradeRequest (req) {
1866 if (req !== null) removeInflight(this._upgrade.inflight, req)
1867
1868 if (this.core.tree.length === this._upgrade.length && this.core.tree.fork === this._upgrade.fork) return false
1869
1870 const u = this._upgrade
1871 this._upgrade = null
1872 u.resolve(true)
1873
1874 return true
1875 }
1876
1877 _resolveRangeRequest (req, index) {
1878 const head = this._ranges.pop()
1879
1880 if (index < this._ranges.length) this._ranges[index] = head
1881
1882 req.resolve(true)
1883 }
1884
1885 _clearInflightBlock (tracker, req) {
1886 const isBlock = tracker === this._blocks
1887 const index = isBlock === true ? req.block.index : req.hash.index / 2
1888 const b = tracker.get(index)
1889
1890 if (b === null || removeInflight(b.inflight, req) === false) return
1891
1892 if (removeHotswap(b) === true && b.inflight.length > 0) {
1893 this.hotswaps.add(b)
1894 }
1895
1896 if (b.refs.length > 0 && isBlock === true) {
1897 this._queueBlock(b)
1898 return
1899 }
1900
1901 b.gc()
1902 }
1903
1904 _clearInflightUpgrade (req) {
1905 if (removeInflight(this._upgrade.inflight, req) === false) return
1906 this._upgrade.gc()
1907 }
1908
1909 _clearInflightSeeks (req) {
1910 for (const s of this._seeks) {
1911 if (removeInflight(s.inflight, req) === false) continue
1912 s.gc()
1913 }
1914 }
1915
1916 _clearInflightReorgs (req) {
1917 for (const r of this._reorgs) {
1918 removeInflight(r.inflight, req)
1919 }
1920 }
1921
1922 _clearOldReorgs (fork) {
1923 for (let i = 0; i < this._reorgs.length; i++) {
1924 const f = this._reorgs[i]
1925 if (f.fork >= fork) continue
1926 if (i === this._reorgs.length - 1) this._reorgs.pop()
1927 else this._reorgs[i] = this._reorgs.pop()
1928 i--
1929 }
1930 }
1931
1932 // "slow" updates here - async but not allowed to ever throw
1933 async _updateNonPrimary (updateAll) {
1934 // Check if running, if so skip it and the running one will issue another update for us (debounce)
1935 while (++this._updatesPending === 1) {
1936 let len = Math.min(MAX_RANGES, this._ranges.length)
1937
1938 for (let i = 0; i < len; i++) {
1939 const r = this._ranges[i]
1940
1941 clampRange(this.core, r)
1942
1943 if (r.end !== -1 && r.start >= r.end) {
1944 this._resolveRangeRequest(r, i--)
1945 if (len > this._ranges.length) len--
1946 if (this._ranges.length === MAX_RANGES) updateAll = true
1947 }
1948 }
1949
1950 for (let i = 0; i < this._seeks.length; i++) {
1951 const s = this._seeks[i]
1952
1953 let err = null
1954 let res = null
1955
1956 try {
1957 res = await s.seeker.update()
1958 } catch (error) {
1959 err = error
1960 }
1961
1962 if (!res && !err) continue
1963
1964 if (i < this._seeks.length - 1) this._seeks[i] = this._seeks.pop()
1965 else this._seeks.pop()
1966
1967 i--
1968
1969 if (err) s.reject(err)
1970 else s.resolve(res)
1971 }
1972
1973 // No additional updates scheduled - break
1974 if (--this._updatesPending === 0) break
1975 // Debounce the additional updates - continue
1976 this._updatesPending = 0
1977 }
1978
1979 if (this._inflight.idle || updateAll) this.updateAll()
1980 }
1981
1982 _maybeResolveIfAvailableRanges () {
1983 if (this._ifAvailable > 0 || !this._inflight.idle || !this._ranges.length) return
1984
1985 for (let i = 0; i < this.peers.length; i++) {
1986 if (this.peers[i].dataProcessing > 0) return
1987 }
1988
1989 for (let i = 0; i < this._ranges.length; i++) {
1990 const r = this._ranges[i]
1991
1992 if (r.ifAvailable) {
1993 this._resolveRangeRequest(r, i--)
1994 }
1995 }
1996 }
1997
1998 _clearRequest (peer, req) {
1999 if (req.block !== null) {
2000 this._clearInflightBlock(this._blocks, req)
2001 this._unmarkInflight(req.block.index)
2002 }
2003
2004 if (req.hash !== null) {
2005 this._clearInflightBlock(this._hashes, req)
2006 }
2007
2008 if (req.upgrade !== null && this._upgrade !== null) {
2009 this._clearInflightUpgrade(req)
2010 }
2011
2012 if (this._seeks.length > 0) {
2013 this._clearInflightSeeks(req)
2014 }
2015
2016 if (this._reorgs.length > 0) {
2017 this._clearInflightReorgs(req)
2018 }
2019 }
2020
2021 _onnodata (peer, req) {
2022 this._clearRequest(peer, req)
2023 this.updateAll()
2024 }
2025
2026 _openSkipBitfield () {
2027 // technically the skip bitfield gets bits cleared if .clear() is called
2028 // also which might be in inflight also, but that just results in that section being overcalled shortly
2029 // worst case, so ok for now
2030
2031 const bitfield = this.core.openSkipBitfield()
2032
2033 for (const req of this._inflight) {
2034 if (req.block) bitfield.set(req.block.index, true) // skip
2035 }
2036 }
2037
2038 _markInflight (index) {
2039 if (this.core.skipBitfield !== null) this.core.skipBitfield.set(index, true)
2040 for (const peer of this.peers) peer._markInflight(index)
2041 }
2042
2043 _unmarkInflight (index) {
2044 if (this.core.skipBitfield !== null) this.core.skipBitfield.set(index, this.core.bitfield.get(index))
2045 for (const peer of this.peers) peer._resetMissingBlock(index)
2046 }
2047
2048 _ondata (peer, req, data) {
2049 if (data.block !== null) {
2050 this._resolveBlockRequest(this._blocks, data.block.index, data.block.value, req)
2051 }
2052
2053 if (data.hash !== null && (data.hash.index & 1) === 0) {
2054 this._resolveBlockRequest(this._hashes, data.hash.index / 2, null, req)
2055 }
2056
2057 if (this._upgrade !== null) {
2058 this._resolveUpgradeRequest(req)
2059 }
2060
2061 if (this._seeks.length > 0) {
2062 this._clearInflightSeeks(req)
2063 }
2064
2065 if (this._reorgs.length > 0) {
2066 this._clearInflightReorgs(req)
2067 }
2068
2069 if (this._manifestPeer === peer && this.core.header.manifest !== null) {
2070 this._manifestPeer = null
2071 }
2072
2073 if (this._seeks.length > 0 || this._ranges.length > 0) this._updateNonPrimary(this._seeks.length > 0)
2074 this.updatePeer(peer)
2075 }
2076
2077 _onwant (peer, start, length) {
2078 const contig = Math.min(this.core.tree.length, this.core.header.hints.contiguousLength)
2079
2080 if (start + length < contig || (this.core.tree.length === contig)) {
2081 peer.wireRange.send({
2082 drop: false,
2083 start: 0,
2084 length: contig
2085 })
2086 incrementTx(peer.stats.wireRange, this.stats.wireRange)
2087 return
2088 }
2089
2090 length = Math.min(length, this.core.tree.length - start)
2091
2092 peer.protomux.cork()
2093
2094 for (const msg of this.core.bitfield.want(start, length)) {
2095 peer.wireBitfield.send(msg)
2096 incrementTx(peer.stats.wireBitfield, this.stats.wireBitfield)
2097 }
2098
2099 peer.protomux.uncork()
2100 }
2101
2102 async _onreorgdata (peer, req, data) {
2103 const newBatch = data.upgrade && await this.core.verifyReorg(data)
2104 const f = this._addReorg(data.fork, peer)
2105
2106 if (f === null) {
2107 this.updateAll()
2108 return
2109 }
2110
2111 removeInflight(f.inflight, req)
2112
2113 if (f.batch) {
2114 await f.batch.update(data)
2115 } else if (data.upgrade) {
2116 f.batch = newBatch
2117
2118 // Remove "older" reorgs in progress as we just verified this one.
2119 this._clearOldReorgs(f.fork)
2120 }
2121
2122 if (f.batch && f.batch.finished) {
2123 if (this._addUpgradeMaybe() !== null) {
2124 await this._applyReorg(f)
2125 }
2126 }
2127
2128 this.updateAll()
2129 }
2130
2131 // Never throws, allowed to run in the background
2132 async _applyReorg (f) {
2133 // TODO: more optimal here to check if potentially a better reorg
2134 // is available, ie higher fork, and request that one first.
2135 // This will request that one after this finishes, which is fine, but we
2136 // should investigate the complexity in going the other way
2137
2138 const u = this._upgrade
2139
2140 this._reorgs = [] // clear all as the nodes are against the old tree - easier
2141 this._applyingReorg = this.core.reorg(f.batch, null) // TODO: null should be the first/last peer?
2142
2143 try {
2144 await this._applyingReorg
2145 } catch (err) {
2146 this._upgrade = null
2147 u.reject(err)
2148 }
2149
2150 this._applyingReorg = null
2151
2152 if (this._upgrade !== null) {
2153 this._resolveUpgradeRequest(null)
2154 }
2155
2156 for (const peer of this.peers) this._updateFork(peer)
2157
2158 // TODO: all the remaining is a tmp workaround until we have a flag/way for ANY_FORK
2159 for (const r of this._ranges) {
2160 r.start = r.userStart
2161 r.end = r.userEnd
2162 }
2163
2164 this.updateAll()
2165 }
2166
2167 _maybeUpdate () {
2168 return this._upgrade !== null && this._upgrade.inflight.length === 0
2169 }
2170
2171 _maybeRequestManifest () {
2172 return this.core.header.manifest === null && this._manifestPeer === null
2173 }
2174
2175 _updateFork (peer) {
2176 if (this._applyingReorg !== null || this.allowFork === false || peer.remoteFork <= this.core.tree.fork) {
2177 return false
2178 }
2179
2180 const f = this._addReorg(peer.remoteFork, peer)
2181
2182 // TODO: one per peer is better
2183 if (f !== null && f.batch === null && f.inflight.length === 0) {
2184 return peer._requestForkProof(f)
2185 }
2186
2187 return false
2188 }
2189
2190 _updateHotswap (peer) {
2191 const maxHotswaps = peer.getMaxHotswapInflight()
2192 if (!peer.isActive() || peer.inflight >= maxHotswaps) return
2193
2194 for (const b of this.hotswaps.pick(peer)) {
2195 if (peer._requestBlock(b) === false) continue
2196 peer.stats.hotswaps++
2197 peer.replicator.stats.hotswaps++
2198 if (peer.inflight >= maxHotswaps) break
2199 }
2200 }
2201
2202 _updatePeer (peer) {
2203 if (!peer.isActive() || peer.inflight >= peer.getMaxInflight()) {
2204 return false
2205 }
2206
2207 // Eagerly request the manifest even if the remote length is 0. If not 0 we'll get as part of the upgrade request...
2208 if (this._maybeRequestManifest() === true && peer.remoteLength === 0 && peer.remoteHasManifest === true) {
2209 this._manifestPeer = peer
2210 peer._requestManifest()
2211 }
2212
2213 for (const s of this._seeks) {
2214 if (s.inflight.length > 0) continue // TODO: one per peer is better
2215 if (peer._requestSeek(s) === true) {
2216 return true
2217 }
2218 }
2219
2220 // Implied that any block in the queue should be requested, no matter how many inflights
2221 const blks = new RandomIterator(this._queued)
2222
2223 for (const b of blks) {
2224 if (b.queued === false || peer._requestBlock(b) === true) {
2225 b.queued = false
2226 blks.dequeue()
2227 return true
2228 }
2229 }
2230
2231 return false
2232 }
2233
2234 _updatePeerNonPrimary (peer) {
2235 if (!peer.isActive() || peer.inflight >= peer.getMaxInflight()) {
2236 return false
2237 }
2238
2239 const ranges = new RandomIterator(this._ranges)
2240 let tried = 0
2241
2242 for (const r of ranges) {
2243 if (peer._requestRange(r) === true) {
2244 return true
2245 }
2246 if (++tried >= MAX_RANGES) break
2247 }
2248
2249 // Iterate from newest fork to oldest fork...
2250 for (let i = this._reorgs.length - 1; i >= 0; i--) {
2251 const f = this._reorgs[i]
2252 if (f.batch !== null && f.inflight.length === 0 && peer._requestForkRange(f) === true) {
2253 return true
2254 }
2255 }
2256
2257 if (this._maybeUpdate() === true && peer._requestUpgrade(this._upgrade) === true) {
2258 return true
2259 }
2260
2261 return false
2262 }
2263
2264 updatePeer (peer) {
2265 // Quick shortcut to wait for flushing reorgs - not needed but less waisted requests
2266 if (this._applyingReorg !== null) return
2267
2268 while (this._updatePeer(peer) === true);
2269 while (this._updatePeerNonPrimary(peer) === true);
2270
2271 if (this.peers.length > 1 && this._blocks.isEmpty() === false) {
2272 this._updateHotswap(peer)
2273 }
2274
2275 this._checkUpgradeIfAvailable()
2276 this._maybeResolveIfAvailableRanges()
2277 }
2278
2279 updateAll () {
2280 // Quick shortcut to wait for flushing reorgs - not needed but less waisted requests
2281 if (this._applyingReorg !== null) return
2282
2283 const peers = new RandomIterator(this.peers)
2284
2285 for (const peer of peers) {
2286 if (this._updatePeer(peer) === true) {
2287 peers.requeue()
2288 }
2289 }
2290
2291 // Check if we can skip the non primary check fully
2292 if (this._maybeUpdate() === false && this._ranges.length === 0 && this._reorgs.length === 0) {
2293 this._checkUpgradeIfAvailable()
2294 return
2295 }
2296
2297 for (const peer of peers.restart()) {
2298 if (this._updatePeerNonPrimary(peer) === true) {
2299 peers.requeue()
2300 }
2301 }
2302
2303 this._checkUpgradeIfAvailable()
2304 this._maybeResolveIfAvailableRanges()
2305 }
2306
2307 _closeSessionMaybe () {
2308 if (this._hasSession && this._peerSessions === 0) {
2309 this._hasSession = false
2310 this.core.active--
2311 }
2312
2313 // we were the last active ref, so lets shut things down
2314 if (this.core.active === 0 && this.core.sessions.length === 0) {
2315 this.destroy()
2316 this.core.close().catch(safetyCatch)
2317 return
2318 }
2319
2320 // in case one session is still alive but its been marked for auto close also kill it
2321 if (this.core.sessions.length === 1 && this.core.active === 1 && this.core.sessions[0].autoClose) {
2322 this.core.sessions[0].close().catch(safetyCatch)
2323 }
2324 }
2325
2326 attached (protomux) {
2327 return this._attached.has(protomux)
2328 }
2329
2330 ensureSession () {
2331 if (this._hasSession) return
2332 this._hasSession = true
2333 this.core.active++
2334 }
2335
2336 attachTo (protomux, useSession) {
2337 if (this.core.closed) return
2338 if (useSession) this.ensureSession()
2339
2340 const makePeer = this._makePeer.bind(this, protomux, useSession)
2341
2342 this._attached.add(protomux)
2343 protomux.pair({ protocol: 'hypercore/alpha', id: this.discoveryKey }, makePeer)
2344 protomux.stream.setMaxListeners(0)
2345 protomux.stream.on('close', this._onstreamclose)
2346
2347 if (useSession) this._peerSessions++
2348 this._ifAvailable++
2349
2350 protomux.stream.opened.then((opened) => {
2351 if (useSession) this._peerSessions--
2352 this._ifAvailable--
2353
2354 if (opened && !this.destroyed) makePeer()
2355 else if (useSession) this._closeSessionMaybe()
2356 this._checkUpgradeIfAvailable()
2357 })
2358 }
2359
2360 detachFrom (protomux) {
2361 if (this._attached.delete(protomux)) {
2362 protomux.stream.removeListener('close', this._onstreamclose)
2363 protomux.unpair({ protocol: 'hypercore/alpha', id: this.discoveryKey })
2364 }
2365 }
2366
2367 destroy () {
2368 this.destroyed = true
2369
2370 if (this._downloadingTimer) {
2371 clearTimeout(this._downloadingTimer)
2372 this._downloadingTimer = null
2373 }
2374
2375 const waiting = []
2376
2377 while (this.peers.length) {
2378 const peer = this.peers[this.peers.length - 1]
2379 this.detachFrom(peer.protomux)
2380 peer.channel.close() // peer is removed from array in onclose
2381 waiting.push(peer.channel.fullyClosed())
2382 }
2383
2384 for (const protomux of this._attached) {
2385 this.detachFrom(protomux)
2386 }
2387
2388 return Promise.all(waiting)
2389 }
2390
2391 _makePeer (protomux, useSession) {
2392 const replicator = this
2393 if (protomux.opened({ protocol: 'hypercore/alpha', id: this.discoveryKey })) return onnochannel()
2394
2395 const channel = protomux.createChannel({
2396 userData: null,
2397 protocol: 'hypercore/alpha',
2398 aliases: ['hypercore'],
2399 id: this.discoveryKey,
2400 handshake: m.wire.handshake,
2401 messages: [
2402 { encoding: m.wire.sync, onmessage: onwiresync },
2403 { encoding: m.wire.request, onmessage: onwirerequest },
2404 { encoding: m.wire.cancel, onmessage: onwirecancel },
2405 { encoding: m.wire.data, onmessage: onwiredata },
2406 { encoding: m.wire.noData, onmessage: onwirenodata },
2407 { encoding: m.wire.want, onmessage: onwirewant },
2408 { encoding: m.wire.unwant, onmessage: onwireunwant },
2409 { encoding: m.wire.bitfield, onmessage: onwirebitfield },
2410 { encoding: m.wire.range, onmessage: onwirerange },
2411 { encoding: m.wire.extension, onmessage: onwireextension }
2412 ],
2413 onopen: onwireopen,
2414 onclose: onwireclose,
2415 ondrain: onwiredrain
2416 })
2417
2418 if (channel === null) return onnochannel()
2419
2420 const peer = new Peer(replicator, protomux, channel, useSession, this.inflightRange)
2421 const stream = protomux.stream
2422
2423 if (useSession) {
2424 // session may have been unref'd underneath us
2425 replicator.ensureSession()
2426 replicator._peerSessions++
2427 }
2428
2429 peer.channel.open({
2430 seeks: true,
2431 capability: caps.replicate(stream.isInitiator, this.key, stream.handshakeHash)
2432 })
2433
2434 return true
2435
2436 function onnochannel () {
2437 if (useSession) replicator._closeSessionMaybe()
2438 return false
2439 }
2440 }
2441}
2442
2443function matchingRequest (req, data) {
2444 if (data.block !== null && (req.block === null || req.block.index !== data.block.index)) return false
2445 if (data.hash !== null && (req.hash === null || req.hash.index !== data.hash.index)) return false
2446 if (data.seek !== null && (req.seek === null || req.seek.bytes !== data.seek.bytes)) return false
2447 if (data.upgrade !== null && req.upgrade === null) return false
2448 return req.fork === data.fork
2449}
2450
2451function removeHotswap (block) {
2452 if (block.hotswap === null) return false
2453 block.hotswap.ref.remove(block)
2454 return true
2455}
2456
2457function removeInflight (inf, req) {
2458 const i = inf.indexOf(req)
2459 if (i === -1) return false
2460 if (i < inf.length - 1) inf[i] = inf.pop()
2461 else inf.pop()
2462 return true
2463}
2464
2465function noop () {}
2466
2467function toLength (start, end) {
2468 return end === -1 ? -1 : (end < start ? 0 : end - start)
2469}
2470
2471function clampRange (core, r) {
2472 if (r.blocks === null) {
2473 const start = core.bitfield.firstUnset(r.start)
2474
2475 if (r.end === -1) r.start = start === -1 ? core.tree.length : start
2476 else if (start === -1 || start >= r.end) r.start = r.end
2477 else {
2478 r.start = start
2479
2480 const end = core.bitfield.lastUnset(r.end - 1)
2481
2482 if (end === -1 || start >= end + 1) r.end = r.start
2483 else r.end = end + 1
2484 }
2485 } else {
2486 while (r.start < r.end && core.bitfield.get(r.blocks[r.start])) r.start++
2487 while (r.start < r.end && core.bitfield.get(r.blocks[r.end - 1])) r.end--
2488 }
2489}
2490
2491function onrequesttimeout (req) {
2492 if (req.context) req.context.detach(req, REQUEST_TIMEOUT())
2493}
2494
2495function destroyRequestTimeout (req) {
2496 if (req.timeout !== null) {
2497 clearTimeout(req.timeout)
2498 req.timeout = null
2499 }
2500}
2501
2502function isCriticalError (err) {
2503 // TODO: expose .critical or similar on the hypercore errors that are critical (if all not are)
2504 return err.name === 'HypercoreError'
2505}
2506
2507function onwireopen (m, c) {
2508 return c.userData.onopen(m)
2509}
2510
2511function onwireclose (isRemote, c) {
2512 return c.userData.onclose(isRemote)
2513}
2514
2515function onwiredrain (c) {
2516 return c.userData.ondrain()
2517}
2518
2519function onwiresync (m, c) {
2520 incrementRx(c.userData.stats.wireSync, c.userData.replicator.stats.wireSync)
2521 return c.userData.onsync(m)
2522}
2523
2524function onwirerequest (m, c) {
2525 incrementRx(c.userData.stats.wireRequest, c.userData.replicator.stats.wireRequest)
2526 return c.userData.onrequest(m)
2527}
2528
2529function onwirecancel (m, c) {
2530 incrementRx(c.userData.stats.wireCancel, c.userData.replicator.stats.wireCancel)
2531 return c.userData.oncancel(m)
2532}
2533
2534function onwiredata (m, c) {
2535 incrementRx(c.userData.stats.wireData, c.userData.replicator.stats.wireData)
2536 return c.userData.ondata(m)
2537}
2538
2539function onwirenodata (m, c) {
2540 return c.userData.onnodata(m)
2541}
2542
2543function onwirewant (m, c) {
2544 incrementRx(c.userData.stats.wireWant, c.userData.replicator.stats.wireWant)
2545 return c.userData.onwant(m)
2546}
2547
2548function onwireunwant (m, c) {
2549 return c.userData.onunwant(m)
2550}
2551
2552function onwirebitfield (m, c) {
2553 incrementRx(c.userData.stats.wireBitfield, c.userData.replicator.stats.wireBitfield)
2554 return c.userData.onbitfield(m)
2555}
2556
2557function onwirerange (m, c) {
2558 incrementRx(c.userData.stats.wireRange, c.userData.replicator.stats.wireRange)
2559 return c.userData.onrange(m)
2560}
2561
2562function onwireextension (m, c) {
2563 incrementRx(c.userData.stats.wireExtension, c.userData.replicator.stats.wireExtension)
2564 return c.userData.onextension(m)
2565}
2566
2567function setDownloadingLater (repl, downloading, session) {
2568 repl.setDownloadingNow(downloading, session)
2569}
2570
2571function isBlockRequest (req) {
2572 return req !== null && req.block !== null
2573}
2574
2575function isUpgradeRequest (req) {
2576 return req !== null && req.upgrade !== null
2577}
2578
2579function incrementTx (stats1, stats2) {
2580 stats1.tx++
2581 stats2.tx++
2582}
2583
2584function incrementRx (stats1, stats2) {
2585 stats1.rx++
2586 stats2.rx++
2587}
node_modules/hypercore/lib/streams.js +130 -0
……@@ -0,0 +1,130 @@
1const { Writable, Readable } = require('streamx')
2
3class ReadStream extends Readable {
4 constructor (core, opts = {}) {
5 super()
6
7 this.core = core
8 this.start = opts.start || 0
9 this.end = typeof opts.end === 'number' ? opts.end : -1
10 this.snapshot = !opts.live && opts.snapshot !== false
11 this.live = !!opts.live
12 }
13
14 _open (cb) {
15 this._openP().then(cb, cb)
16 }
17
18 _read (cb) {
19 this._readP().then(cb, cb)
20 }
21
22 async _openP () {
23 if (this.end === -1) await this.core.update()
24 else await this.core.ready()
25 if (this.snapshot && this.end === -1) this.end = this.core.length
26 }
27
28 async _readP () {
29 const end = this.live ? -1 : (this.end === -1 ? this.core.length : this.end)
30 if (end >= 0 && this.start >= end) {
31 this.push(null)
32 return
33 }
34
35 this.push(await this.core.get(this.start++))
36 }
37}
38
39exports.ReadStream = ReadStream
40
41class WriteStream extends Writable {
42 constructor (core) {
43 super()
44 this.core = core
45 }
46
47 _writev (batch, cb) {
48 this._writevP(batch).then(cb, cb)
49 }
50
51 async _writevP (batch) {
52 await this.core.append(batch)
53 }
54}
55
56exports.WriteStream = WriteStream
57
58class ByteStream extends Readable {
59 constructor (core, opts = {}) {
60 super()
61
62 this._core = core
63 this._index = 0
64 this._range = null
65
66 this._byteOffset = opts.byteOffset || 0
67 this._byteLength = typeof opts.byteLength === 'number' ? opts.byteLength : -1
68 this._prefetch = typeof opts.prefetch === 'number' ? opts.prefetch : 32
69
70 this._applyOffset = this._byteOffset > 0
71 }
72
73 _open (cb) {
74 this._openp().then(cb, cb)
75 }
76
77 _read (cb) {
78 this._readp().then(cb, cb)
79 }
80
81 async _openp () {
82 if (this._byteLength === -1) {
83 await this._core.update()
84 this._byteLength = Math.max(this._core.byteLength - this._byteOffset, 0)
85 }
86 }
87
88 async _readp () {
89 let data = null
90
91 if (this._byteLength === 0) {
92 this.push(null)
93 return
94 }
95
96 let relativeOffset = 0
97
98 if (this._applyOffset) {
99 this._applyOffset = false
100
101 const [block, byteOffset] = await this._core.seek(this._byteOffset)
102
103 this._index = block
104 relativeOffset = byteOffset
105 }
106
107 this._predownload(this._index + 1)
108 data = await this._core.get(this._index++, { valueEncoding: 'binary' })
109
110 if (relativeOffset > 0) data = data.subarray(relativeOffset)
111
112 if (data.byteLength > this._byteLength) data = data.subarray(0, this._byteLength)
113 this._byteLength -= data.byteLength
114
115 this.push(data)
116 if (this._byteLength === 0) this.push(null)
117 }
118
119 _predownload (index) {
120 if (this._range) this._range.destroy()
121 this._range = this._core.download({ start: index, end: index + this._prefetch, linear: true })
122 }
123
124 _destroy (cb) {
125 if (this._range) this._range.destroy()
126 cb(null)
127 }
128}
129
130exports.ByteStream = ByteStream
node_modules/hypercore/lib/verifier.js +305 -0
……@@ -0,0 +1,305 @@
1const defaultCrypto = require('hypercore-crypto')
2const b4a = require('b4a')
3const c = require('compact-encoding')
4const flat = require('flat-tree')
5const { BAD_ARGUMENT } = require('hypercore-errors')
6const unslab = require('unslab')
7
8const m = require('./messages')
9const multisig = require('./multisig')
10const caps = require('./caps')
11
12class Signer {
13 constructor (crypto, manifestHash, version, index, { signature = 'ed25519', publicKey, namespace = caps.DEFAULT_NAMESPACE } = {}) {
14 if (!publicKey) throw BAD_ARGUMENT('public key is required for a signer')
15 if (signature !== 'ed25519') throw BAD_ARGUMENT('Only Ed25519 signatures are supported')
16
17 this.crypto = crypto
18 this.manifestHash = manifestHash
19 this.version = version
20 this.signer = index
21 this.signature = signature
22 this.publicKey = publicKey
23 this.namespace = namespace
24 }
25
26 _ctx () {
27 return this.version === 0 ? this.namespace : this.manifestHash
28 }
29
30 verify (batch, signature) {
31 return this.crypto.verify(batch.signable(this._ctx()), signature, this.publicKey)
32 }
33
34 sign (batch, keyPair) {
35 return this.crypto.sign(batch.signable(this._ctx()), keyPair.secretKey)
36 }
37}
38
39class CompatSigner extends Signer {
40 constructor (crypto, index, signer, legacy) {
41 super(crypto, null, 0, index, signer)
42 this.legacy = legacy
43 }
44
45 verify (batch, signature) {
46 return this.crypto.verify(batch.signableCompat(this.legacy), signature, this.publicKey)
47 }
48
49 sign (batch, keyPair) {
50 return this.crypto.sign(batch.signableCompat(this.legacy), keyPair.secretKey)
51 }
52}
53
54module.exports = class Verifier {
55 constructor (manifestHash, manifest, { compat = isCompat(manifestHash, manifest), crypto = defaultCrypto, legacy = false } = {}) {
56 const self = this
57
58 this.manifestHash = manifestHash
59 this.compat = compat || manifest === null
60 this.version = this.compat ? 0 : typeof manifest.version === 'number' ? manifest.version : 1
61 this.hash = manifest.hash || 'blake2b'
62 this.allowPatch = !this.compat && !!manifest.allowPatch
63 this.quorum = this.compat ? 1 : defaultQuorum(manifest)
64
65 this.signers = manifest.signers ? manifest.signers.map(createSigner) : []
66 this.prologue = this.compat ? null : (manifest.prologue || null)
67
68 function createSigner (signer, index) {
69 return self.compat
70 ? new CompatSigner(crypto, index, signer, legacy)
71 : new Signer(crypto, manifestHash, self.version, index, signer)
72 }
73 }
74
75 _verifyCompat (batch, signature) {
76 if (!signature) return false
77
78 if (this.compat || (!this.allowPatch && this.signers.length === 1)) {
79 return !!signature && this.signers[0].verify(batch, signature)
80 }
81
82 return this._verifyMulti(batch, signature)
83 }
84
85 _inflate (signature) {
86 if (this.version >= 1) return multisig.inflate(signature)
87 const { proofs, patch } = multisig.inflatev0(signature)
88
89 return {
90 proofs: proofs.map(proofToVersion1),
91 patch
92 }
93 }
94
95 _verifyMulti (batch, signature) {
96 if (!signature || this.quorum === 0) return false
97
98 const { proofs, patch } = this._inflate(signature)
99 if (proofs.length < this.quorum) return false
100
101 const tried = new Uint8Array(this.signers.length)
102 const nodes = this.allowPatch && patch.length ? toMap(patch) : null
103
104 for (let i = 0; i < this.quorum; i++) {
105 const inp = proofs[i]
106
107 let tree = batch
108
109 if (inp.patch && this.allowPatch) {
110 tree = batch.clone()
111
112 const upgrade = generateUpgrade(nodes, batch.length, inp.patch)
113 const proof = { fork: tree.fork, block: null, hash: null, seek: null, upgrade, manifest: null }
114
115 try {
116 if (!tree.verifyUpgrade(proof)) return false
117 } catch {
118 return false
119 }
120 }
121
122 if (inp.signer >= this.signers.length || tried[inp.signer]) return false
123 tried[inp.signer] = 1
124
125 const s = this.signers[inp.signer]
126 if (!s.verify(tree, inp.signature)) return false
127 }
128
129 return true
130 }
131
132 verify (batch, signature) {
133 if (this.version !== 1) {
134 return this._verifyCompat(batch, signature)
135 }
136
137 if (this.prologue !== null && batch.length <= this.prologue.length) {
138 return batch.length === this.prologue.length && b4a.equals(batch.hash(), this.prologue.hash)
139 }
140
141 return this._verifyMulti(batch, signature)
142 }
143
144 // TODO: better api for this that is more ... multisig-ey
145 sign (batch, keyPair) {
146 if (!keyPair || !keyPair.secretKey) throw BAD_ARGUMENT('No key pair was passed')
147
148 for (const s of this.signers) {
149 if (b4a.equals(s.publicKey, keyPair.publicKey)) {
150 const signature = s.sign(batch, keyPair)
151 if (this.signers.length !== 1 || this.version === 0) return signature
152 return this.assemble([{ signer: 0, signature, patch: 0, nodes: null }])
153 }
154 }
155
156 throw BAD_ARGUMENT('Public key is not a declared signer')
157 }
158
159 assemble (inputs) {
160 return this.version === 0 ? multisig.assemblev0(inputs) : multisig.assemble(inputs)
161 }
162
163 static manifestHash (manifest) {
164 return manifestHash(manifest)
165 }
166
167 static defaultSignerManifest (publicKey) {
168 return {
169 version: 1,
170 hash: 'blake2b',
171 allowPatch: false,
172 quorum: 1,
173 signers: [{
174 signature: 'ed25519',
175 namespace: caps.DEFAULT_NAMESPACE,
176 publicKey
177 }],
178 prologue: null
179 }
180 }
181
182 static fromManifest (manifest, opts) {
183 const m = this.createManifest(manifest)
184 return new this(manifestHash(m), m, opts)
185 }
186
187 static createManifest (inp) {
188 if (!inp) return null
189
190 const manifest = {
191 version: typeof inp.version === 'number' ? inp.version : 1,
192 hash: 'blake2b',
193 allowPatch: !!inp.allowPatch,
194 quorum: defaultQuorum(inp),
195 signers: inp.signers ? inp.signers.map(parseSigner) : [],
196 prologue: null
197 }
198
199 if (inp.hash && inp.hash !== 'blake2b') throw BAD_ARGUMENT('Only Blake2b hashes are supported')
200
201 if (inp.prologue) {
202 if (!(b4a.isBuffer(inp.prologue.hash) && inp.prologue.hash.byteLength === 32) || !(inp.prologue.length >= 0)) {
203 throw BAD_ARGUMENT('Invalid prologue')
204 }
205
206 manifest.prologue = inp.prologue
207 manifest.prologue.hash = unslab(manifest.prologue.hash)
208 }
209
210 return manifest
211 }
212
213 static isValidManifest (key, manifest) {
214 return b4a.equals(key, manifestHash(manifest))
215 }
216
217 static isCompat (key, manifest) {
218 return isCompat(key, manifest)
219 }
220
221 static sign (manifest, batch, keyPair, opts) {
222 return Verifier.fromManifest(manifest, opts).sign(batch, keyPair)
223 }
224}
225
226function toMap (nodes) {
227 const m = new Map()
228 for (const node of nodes) m.set(node.index, node)
229 return m
230}
231
232function isCompat (key, manifest) {
233 return !!(manifest && manifest.signers.length === 1 && b4a.equals(key, manifest.signers[0].publicKey))
234}
235
236function defaultQuorum (man) {
237 if (typeof man.quorum === 'number') return man.quorum
238 if (!man.signers || !man.signers.length) return 0
239 return (man.signers.length >> 1) + 1
240}
241
242function generateUpgrade (patch, start, length) {
243 const upgrade = { start, length, nodes: null, additionalNodes: [], signature: null }
244
245 const from = start * 2
246 const to = from + length * 2
247
248 for (const ite = flat.iterator(0); ite.fullRoot(to); ite.nextTree()) {
249 if (ite.index + ite.factor / 2 < from) continue
250
251 if (upgrade.nodes === null && ite.contains(from - 2)) {
252 upgrade.nodes = []
253
254 const root = ite.index
255 const target = from - 2
256
257 ite.seek(target)
258
259 while (ite.index !== root) {
260 ite.sibling()
261 if (ite.index > target) upgrade.nodes.push(patch.get(ite.index))
262 ite.parent()
263 }
264
265 continue
266 }
267
268 if (upgrade.nodes === null) upgrade.nodes = []
269 upgrade.nodes.push(patch.get(ite.index))
270 }
271
272 if (upgrade.nodes === null) upgrade.nodes = []
273 return upgrade
274}
275
276function parseSigner (signer) {
277 validateSigner(signer)
278 return {
279 signature: 'ed25519',
280 namespace: unslab(signer.namespace || caps.DEFAULT_NAMESPACE),
281 publicKey: unslab(signer.publicKey)
282 }
283}
284
285function validateSigner (signer) {
286 if (!signer || !signer.publicKey) throw BAD_ARGUMENT('Signer missing public key')
287 if (signer.signature && signer.signature !== 'ed25519') throw BAD_ARGUMENT('Only Ed25519 signatures are supported')
288}
289
290function manifestHash (manifest) {
291 const state = { start: 0, end: 32, buffer: null }
292 m.manifest.preencode(state, manifest)
293 state.buffer = b4a.allocUnsafe(state.end)
294 c.raw.encode(state, caps.MANIFEST)
295 m.manifest.encode(state, manifest)
296 return defaultCrypto.hash(state.buffer)
297}
298
299function proofToVersion1 (proof) {
300 return {
301 signer: proof.signer,
302 signature: proof.signature,
303 patch: proof.patch ? proof.patch.length : 0
304 }
305}
node_modules/hypercore/messages.js +2 -0
……@@ -0,0 +1,2 @@
1// explicitly exposed as hypercore/messages
2module.exports = require('./lib/messages')
node_modules/hypercore/package.json +81 -0
……@@ -0,0 +1,81 @@
1{
2 "name": "hypercore",
3 "version": "10.38.2",
4 "description": "Hypercore is a secure, distributed append-only log",
5 "main": "index.js",
6 "scripts": {
7 "test": "standard && node test/all.js",
8 "test:generate": "brittle -r test/all.js test/*.js"
9 },
10 "repository": {
11 "type": "git",
12 "url": "git+https://github.com/holepunchto/hypercore.git"
13 },
14 "contributors": [
15 {
16 "name": "Mathias Buus",
17 "email": "mathiasbuus@gmail.com",
18 "url": "https://mafinto.sh"
19 },
20 {
21 "name": "Andrew Osheroff",
22 "email": "andrewosh@gmail.com",
23 "url": "https://andrewosh.com"
24 }
25 ],
26 "license": "MIT",
27 "bugs": {
28 "url": "https://github.com/holepunchto/hypercore/issues"
29 },
30 "homepage": "https://github.com/holepunchto/hypercore#readme",
31 "files": [
32 "index.js",
33 "errors.js",
34 "messages.js",
35 "lib/**.js"
36 ],
37 "imports": {
38 "events": {
39 "bare": "bare-events",
40 "default": "events"
41 }
42 },
43 "dependencies": {
44 "@hyperswarm/secret-stream": "^6.0.0",
45 "b4a": "^1.1.0",
46 "bare-events": "^2.2.0",
47 "big-sparse-array": "^1.0.3",
48 "compact-encoding": "^2.11.0",
49 "crc-universal": "^1.0.2",
50 "fast-fifo": "^1.3.0",
51 "flat-tree": "^1.9.0",
52 "hypercore-crypto": "^3.2.1",
53 "hypercore-errors": "^1.2.0",
54 "hypercore-id-encoding": "^1.2.0",
55 "is-options": "^1.0.1",
56 "protomux": "^3.5.0",
57 "quickbit-universal": "^2.2.0",
58 "random-access-file": "^4.0.0",
59 "random-array-iterator": "^1.0.0",
60 "safety-catch": "^1.0.1",
61 "sodium-universal": "^4.0.0",
62 "streamx": "^2.12.4",
63 "unslab": "^1.3.0",
64 "xache": "^1.1.0",
65 "z32": "^1.0.0"
66 },
67 "devDependencies": {
68 "brittle": "^3.0.0",
69 "debugging-stream": "^3.1.0",
70 "hyperswarm": "^4.3.6",
71 "rache": "^1.0.0",
72 "random-access-memory": "^6.1.0",
73 "random-access-memory-overlay": "^3.0.0",
74 "range-parser": "^1.2.1",
75 "speedometer": "^1.1.0",
76 "standard": "^17.0.0",
77 "test-tmp": "^1.0.2",
78 "tiny-byte-size": "^1.1.0",
79 "udx-native": "^1.6.1"
80 }
81}
node_modules/hyperdrive/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/hyperdrive/README.md +399 -0
……@@ -0,0 +1,399 @@
1# Hyperdrive
2
3[See API docs at docs.holepunch.to](https://docs.holepunch.to/building-blocks/hyperdrive)
4
5Hyperdrive is a secure, real-time distributed file system
6
7## Install
8
9```sh
10npm install hyperdrive
11```
12
13## Usage
14
15```js
16const Hyperdrive = require('hyperdrive')
17const Corestore = require('corestore')
18
19const store = new Corestore('./storage')
20const drive = new Hyperdrive(store)
21
22await drive.put('/blob.txt', Buffer.from('example'))
23await drive.put('/images/logo.png', Buffer.from('..'))
24await drive.put('/images/old-logo.png', Buffer.from('..'))
25
26const buffer = await drive.get('/blob.txt')
27console.log(buffer) // => <Buffer ..> "example"
28
29const entry = await drive.entry('/blob.txt')
30console.log(entry) // => { seq, key, value: { executable, linkname, blob, metadata } }
31
32await drive.del('/images/old-logo.png')
33
34await drive.symlink('/images/logo.shortcut', '/images/logo.png')
35
36for await (const file of drive.list('/images')) {
37 console.log('list', file) // => { key, value }
38}
39
40const rs = drive.createReadStream('/blob.txt')
41for await (const chunk of rs) {
42 console.log('rs', chunk) // => <Buffer ..>
43}
44
45const ws = drive.createWriteStream('/blob.txt')
46ws.write('new example')
47ws.end()
48ws.once('close', () => console.log('file saved'))
49```
50
51## API
52
53#### `const drive = new Hyperdrive(store, [key])`
54
55Creates a new Hyperdrive instance. `store` must be an instance of `Corestore`.
56
57By default it uses the core at `{ name: 'db' }` from `store`, unless you set the public `key`.
58
59#### `await drive.ready()`
60
61Waits until internal state is loaded.
62
63Use it once before reading synchronous properties like `drive.discoveryKey`, unless you called any of the other APIs.
64
65#### `await drive.close()`
66
67Fully close this drive, including its underlying Hypercore backed datastructures.
68
69#### `drive.corestore`
70
71The Corestore instance used as storage.
72
73#### `drive.db`
74
75The underlying Hyperbee backing the drive file structure.
76
77#### `drive.core`
78
79The Hypercore used for `drive.db`.
80
81#### `drive.id`
82
83String containing the id (z-base-32 of the public key) identifying this drive.
84
85#### `drive.key`
86
87The public key of the Hypercore backing the drive.
88
89#### `drive.discoveryKey`
90
91The hash of the public key of the Hypercore backing the drive.
92
93Can be used as a `topic` to seed the drive using Hyperswarm.
94
95#### `drive.contentKey`
96
97The public key of the [Hyperblobs](https://github.com/holepunchto/hyperblobs) instance holding blobs associated with entries in the drive.
98
99#### `drive.writable`
100
101Boolean indicating if we can write or delete data in this drive.
102
103#### `drive.readable`
104
105Boolean indicating if we can read from this drive. After closing the drive this will be `false`.
106
107#### `drive.version`
108
109Number that indicates how many modifications were made, useful as a version identifier.
110
111#### `drive.supportsMetadata`
112
113Boolean indicating if the drive handles or not metadata. Always `true`.
114
115#### `await drive.put(path, buffer, [options])`
116
117Creates a file at `path` in the drive. `options` are the same as in `createWriteStream`.
118
119#### `const buffer = await drive.get(path, [options])`
120
121Returns the blob at `path` in the drive. If no blob exists, returns `null`.
122
123It also returns `null` for symbolic links.
124
125`options` include:
126```js
127{
128 wait: true, // Wait for block to be downloaded
129 timeout: 0 // Wait at max some milliseconds (0 means no timeout)
130}
131```
132
133#### `const entry = await drive.entry(path, [options])`
134
135Returns the entry at `path` in the drive. It looks like this:
136```js
137{
138 seq: Number,
139 key: String,
140 value: {
141 executable: Boolean, // Whether the blob at path is an executable
142 linkname: null, // If entry not symlink, otherwise a string to the entry this links to
143 blob: { // Hyperblobs id that can be used to fetch the blob associated with this entry
144 blockOffset: Number,
145 blockLength: Number,
146 byteOffset: Number,
147 byteLength: Number
148 },
149 metadata: null
150 }
151}
152```
153
154`options` include:
155```js
156{
157 follow: false, // Follow symlinks, 16 max or throws an error
158 wait: true, // Wait for block to be downloaded
159 timeout: 0 // Wait at max some milliseconds (0 means no timeout)
160}
161```
162
163#### `const exists = await drive.exists(path)`
164
165Returns `true` if the entry at `path` does exists, otherwise `false`.
166
167#### `await drive.del(path)`
168
169Deletes the file at `path` from the drive.
170
171#### `const comparison = drive.compare(entryA, entryB)`
172
173Returns `0` if entries are the same, `1` if `entryA` is older, and `-1` if `entryB` is older.
174
175#### `const cleared = await drive.clear(path, [options])`
176
177Deletes the blob from storage to free up space, but the file structure reference is kept.
178
179`options` include:
180```js
181{
182 diff: false // Returned `cleared` bytes object is null unless you enable this
183}
184```
185
186#### `const cleared = await drive.clearAll([options])`
187
188Deletes all the blobs from storage to free up space, similar to how `drive.clear()` works.
189
190`options` include:
191```js
192{
193 diff: false // Returned `cleared` bytes object is null unless you enable this
194}
195```
196
197#### `await drive.truncate(version, [options] })`
198
199Truncates the Hyperdrive to a previous version (both the file-structure reference and the blobs).
200
201A `blobs: <length>` option can be passed in if you know the corresponding blobs length, but it is recommended to let the method figure it out for you.
202
203#### `await drive.purge()`
204
205Purge both cores (db and blobs) from your storage, completely removing all the drive's data.
206
207#### `await drive.symlink(path, linkname)`
208
209Creates an entry in drive at `path` that points to the entry at `linkname`.
210
211If a blob entry currently exists at `path` then it will get overwritten and `drive.get(key)` will return `null`, while `drive.entry(key)` will return the entry with symlink information.
212
213#### `const batch = drive.batch()`
214
215Useful for atomically mutate the drive, has the same interface as Hyperdrive.
216
217#### `await batch.flush()`
218
219Commit a batch of mutations to the underlying drive.
220
221#### `const stream = drive.list(folder, [options])`
222
223Returns a stream of all entries in the drive at paths prefixed with `folder`.
224
225`options` include:
226```js
227{
228 recursive: true | false // Whether to descend into all subfolders or not,
229 ignore: String || Array // Ignore files and folders by name,
230 wait: true, // Wait for block to be downloaded.
231}
232```
233
234#### `const stream = drive.readdir(folder, [options])`
235
236Returns a stream of all subpaths of entries in drive stored at paths prefixed by `folder`.
237
238`options` include:
239```js
240{
241 wait: true, // Wait for block to be downloaded
242}
243```
244
245#### `const stream = await drive.entries([range], [options])`
246
247Returns a read stream of entries in the drive.
248
249`options` are the same as `Hyperbee().createReadStream([range], [options])`.
250
251#### `const mirror = drive.mirror(out, [options])`
252
253Efficiently mirror this drive into another. Returns a [`MirrorDrive`](https://github.com/holepunchto/mirror-drive#api) instance constructed with `options`.
254
255Call `await mirror.done()` to wait for the mirroring to finish.
256
257#### `const watcher = drive.watch([folder])`
258
259Returns an iterator that listens on `folder` to yield changes, by default on `/`.
260
261Usage example:
262```js
263for await (const [current, previous] of watcher) {
264 console.log(current.version)
265 console.log(previous.version)
266}
267```
268
269Those `current` and `previous` are snapshots that are auto-closed before next value.
270
271Don't close those snapshots yourself because they're used internally, let them be auto-closed.
272
273`await watcher.ready()`
274
275Waits until the watcher is loaded and detecting changes.
276
277`await watcher.destroy()`
278
279Stops the watcher. You could also stop it by using `break` in the loop.
280
281#### `const rs = drive.createReadStream(path, [options])`
282
283Returns a stream to read out the blob stored in the drive at `path`.
284
285`options` include:
286```js
287{
288 start: Number, // `start` and `end` are inclusive
289 end: Number,
290 length: Number, // `length` overrides `end`, they're not meant to be used together
291 wait: true, // Wait for blocks to be downloaded
292 timeout: 0 // Wait at max some milliseconds (0 means no timeout)
293}
294```
295
296#### `const ws = drive.createWriteStream(path, [options])`
297
298Stream a blob into the drive at `path`.
299
300`options` include:
301```js
302{
303 executable: Boolean,
304 metadata: null // Extended file information i.e. arbitrary JSON value
305}
306```
307
308#### `await drive.download(folder, [options])`
309
310Downloads the blobs corresponding to all entries in the drive at paths prefixed with `folder`.
311
312`options` are the same as those for `drive.list(folder, [options])`.
313
314#### `const snapshot = drive.checkout(version)`
315
316Get a read-only snapshot of a previous version.
317
318#### `const stream = drive.diff(version, folder, [options])`
319
320Efficiently create a stream of the shallow changes to `folder` between `version` and `drive.version`.
321
322Each entry is sorted by key and looks like this:
323```js
324{
325 left: Object, // Entry in folder at drive.version for some path
326 right: Object, // Entry in folder at drive.checkout(version) for some path
327}
328```
329
330If an entry exists in `drive.version` of the `folder` but not in `version`, then `left` is set and `right` will be `null`, and vice versa.
331
332#### `await drive.downloadDiff(version, folder, [options])`
333
334Downloads all the blobs in `folder` corresponding to entries in `drive.checkout(version)` that are not in `drive.version`.
335
336In other words, downloads all the blobs added to `folder` up to `version` of the drive.
337
338#### `await drive.downloadRange(dbRanges, blobRanges)`
339
340Downloads the entries and blobs stored in the [ranges][core-range-docs] `dbRanges` and `blobRanges`.
341
342#### `const done = drive.findingPeers()`
343
344Indicate to Hyperdrive that you're finding peers in the background, requests will be on hold until this is done.
345
346Call `done()` when your current discovery iteration is done, i.e. after `swarm.flush()` finishes.
347
348#### `const stream = drive.replicate(isInitiatorOrStream)`
349
350Usage example:
351```js
352const swarm = new Hyperswarm()
353const done = drive.findingPeers()
354swarm.on('connection', (socket) => drive.replicate(socket))
355swarm.join(drive.discoveryKey)
356swarm.flush().then(done, done)
357```
358
359See more about how replicate works at [corestore.replicate][store-replicate-docs].
360
361#### `const updated = await drive.update([options])`
362
363Waits for initial proof of the new drive version until all `findingPeers` are done.
364
365`options` include:
366```js
367{
368 wait: false
369}
370```
371
372Use `drive.findingPeers()` or `{ wait: true }` to make await `drive.update()` blocking.
373
374#### `const blobs = await drive.getBlobs()`
375
376Returns the [Hyperblobs](https://github.com/holepunchto/hyperblobs) instance storing the blobs indexed by drive entries.
377
378```js
379await drive.put('/file.txt', Buffer.from('hi'))
380
381const buffer1 = await drive.get('/file.txt')
382
383const blobs = await drive.getBlobs()
384const entry = await drive.entry('/file.txt')
385const buffer2 = await blobs.get(entry.value.blob)
386
387// => buffer1 and buffer2 are equals
388```
389
390[core-range-docs]: https://github.com/holepunchto/hypercore#const-range--coredownloadrange
391[store-replicate-docs]: https://github.com/holepunchto/corestore#const-stream--storereplicateoptsorstream
392
393#### `const blobsLength = await drive.getBlobsLength(checkout)`
394
395Returns the length of the Hyperblobs instance at the time of the specified Hyperdrive version (defaults to the current version).
396
397## License
398
399Apache-2.0
node_modules/hyperdrive/index.js +756 -0
……@@ -0,0 +1,756 @@
1const Hyperbee = require('hyperbee')
2const Hyperblobs = require('hyperblobs')
3const isOptions = require('is-options')
4const { Writable, Readable } = require('streamx')
5const unixPathResolve = require('unix-path-resolve')
6const MirrorDrive = require('mirror-drive')
7const SubEncoder = require('sub-encoder')
8const ReadyResource = require('ready-resource')
9const safetyCatch = require('safety-catch')
10const crypto = require('hypercore-crypto')
11const Hypercore = require('hypercore')
12const { BLOCK_NOT_AVAILABLE, BAD_ARGUMENT } = require('hypercore-errors')
13const Monitor = require('./lib/monitor')
14
15const keyEncoding = new SubEncoder('files', 'utf-8')
16
17const [BLOBS] = crypto.namespace('hyperdrive', 1)
18
19module.exports = class Hyperdrive extends ReadyResource {
20 constructor (corestore, key, opts = {}) {
21 super()
22
23 if (isOptions(key)) {
24 opts = key
25 key = null
26 }
27
28 this.corestore = corestore
29 this.db = opts._db || makeBee(key, corestore, opts)
30 this.core = this.db.core
31 this.blobs = null
32 this.supportsMetadata = true
33 this.encryptionKey = opts.encryptionKey || null
34 this.monitors = new Set()
35
36 this._active = opts.active !== false
37 this._openingBlobs = null
38 this._onwait = opts.onwait || null
39 this._batching = !!(opts._checkout === null && opts._db)
40 this._checkout = opts._checkout || null
41
42 this.ready().catch(safetyCatch)
43 }
44
45 [Symbol.asyncIterator] () {
46 return this.entries()[Symbol.asyncIterator]()
47 }
48
49 static async getDriveKey (corestore) {
50 const core = makeBee(undefined, corestore)
51 await core.ready()
52 const key = core.key
53 await core.close()
54 return key
55 }
56
57 static getContentKey (m, key) {
58 if (m instanceof Hypercore) {
59 if (m.core.compat) return null
60 return Hyperdrive.getContentKey(m.manifest, m.key)
61 }
62
63 const manifest = generateContentManifest(m, key)
64 if (!manifest) return null
65
66 return Hypercore.key(manifest)
67 }
68
69 _generateBlobsManifest () {
70 const m = this.db.core.manifest
71 if (this.db.core.core.compat) return null
72
73 return generateContentManifest(m, this.core.key)
74 }
75
76 get id () {
77 return this.core.id
78 }
79
80 get key () {
81 return this.core.key
82 }
83
84 get discoveryKey () {
85 return this.core.discoveryKey
86 }
87
88 get contentKey () {
89 return this.blobs?.core.key
90 }
91
92 get version () {
93 return this.db.version
94 }
95
96 get writable () {
97 return this.core.writable
98 }
99
100 get readable () {
101 return this.core.readable
102 }
103
104 findingPeers () {
105 return this.corestore.findingPeers()
106 }
107
108 async truncate (version, { blobs = -1 } = {}) {
109 if (!this.opened) await this.ready()
110
111 if (version > this.core.length) {
112 throw BAD_ARGUMENT('Bad truncation length')
113 }
114
115 const blobsVersion = blobs === -1 ? await this.getBlobsLength(version) : blobs
116 const bl = await this.getBlobs()
117
118 if (blobsVersion > bl.core.length) {
119 throw BAD_ARGUMENT('Bad truncation length')
120 }
121
122 await this.core.truncate(version)
123 await bl.core.truncate(blobsVersion)
124 }
125
126 async getBlobsLength (checkout) {
127 if (!this.opened) await this.ready()
128
129 if (!checkout) checkout = this.version
130
131 const c = this.db.checkout(checkout)
132
133 try {
134 return await getBlobsLength(c)
135 } finally {
136 await c.close()
137 }
138 }
139
140 replicate (isInitiator, opts) {
141 return this.corestore.replicate(isInitiator, opts)
142 }
143
144 update (opts) {
145 return this.db.update(opts)
146 }
147
148 _makeCheckout (snapshot) {
149 return new Hyperdrive(this.corestore, this.key, {
150 onwait: this._onwait,
151 encryptionKey: this.encryptionKey,
152 _checkout: this._checkout || this,
153 _db: snapshot
154 })
155 }
156
157 checkout (version) {
158 return this._makeCheckout(this.db.checkout(version))
159 }
160
161 batch () {
162 return new Hyperdrive(this.corestore, this.key, {
163 onwait: this._onwait,
164 encryptionKey: this.encryptionKey,
165 _checkout: null,
166 _db: this.db.batch()
167 })
168 }
169
170 setActive (bool) {
171 const active = !!bool
172 if (active === this._active) return
173 this._active = active
174 this.core.setActive(active)
175 if (this.blobs) this.blobs.core.setActive(active)
176 }
177
178 async flush () {
179 await this.db.flush()
180 return this.close()
181 }
182
183 async _close () {
184 if (this.blobs && (!this._checkout || this.blobs !== this._checkout.blobs)) {
185 await this.blobs.core.close()
186 }
187
188 await this.db.close()
189
190 if (!this._checkout && !this._batching) {
191 await this.corestore.close()
192 }
193
194 await this.closeMonitors()
195 }
196
197 async _openBlobsFromHeader (opts) {
198 if (this.blobs) return true
199
200 const header = await getBee(this.db).getHeader(opts)
201 if (!header) return false
202
203 if (this.blobs) return true
204
205 const contentKey = header.metadata && header.metadata.contentFeed && header.metadata.contentFeed.subarray(0, 32)
206 const blobsKey = contentKey || Hypercore.key(this._generateBlobsManifest())
207 if (!blobsKey || blobsKey.length < 32) throw new Error('Invalid or no Blob store key set')
208
209 const blobsCore = this.corestore.get({
210 key: blobsKey,
211 cache: false,
212 onwait: this._onwait,
213 encryptionKey: this.encryptionKey,
214 keyPair: (!contentKey && this.db.core.writable) ? this.db.core.keyPair : null,
215 active: this._active
216 })
217 await blobsCore.ready()
218
219 if (this.closing) {
220 await blobsCore.close()
221 return false
222 }
223
224 this.blobs = new Hyperblobs(blobsCore)
225
226 this.emit('blobs', this.blobs)
227 this.emit('content-key', blobsCore.key)
228
229 return true
230 }
231
232 async _open () {
233 if (this._checkout) {
234 await this._checkout.ready()
235 this.blobs = this._checkout.blobs
236 return
237 }
238
239 await this._openBlobsFromHeader({ wait: false })
240
241 if (this.db.core.writable && !this.blobs) {
242 const m = this._generateBlobsManifest()
243 const blobsCore = this.corestore.get({
244 manifest: m,
245 name: m ? null : this.db.core.id + '/blobs', // simple trick to avoid blobs clashing if no namespace is provided...
246 cache: false,
247 onwait: this._onwait,
248 encryptionKey: this.encryptionKey,
249 compat: this.db.core.core.compat,
250 active: this._active,
251 keyPair: (m && this.db.core.writable) ? this.db.core.keyPair : null
252 })
253 await blobsCore.ready()
254
255 this.blobs = new Hyperblobs(blobsCore)
256
257 if (!m) getBee(this.db).metadata.contentFeed = this.blobs.core.key
258
259 this.emit('blobs', this.blobs)
260 this.emit('content-key', blobsCore.key)
261 }
262
263 await this.db.ready()
264
265 if (!this.blobs) {
266 // eagerly load the blob store....
267 this._openingBlobs = this._openBlobsFromHeader()
268 this._openingBlobs.catch(safetyCatch)
269 }
270 }
271
272 async getBlobs () {
273 if (this.blobs) return this.blobs
274
275 if (this._checkout) {
276 this.blobs = await this._checkout.getBlobs()
277 } else {
278 await this.ready()
279 await this._openingBlobs
280 }
281
282 return this.blobs
283 }
284
285 monitor (name, opts = {}) {
286 const monitor = new Monitor(this, { name, ...opts })
287 this.monitors.add(monitor)
288 return monitor
289 }
290
291 async closeMonitors () {
292 const closing = []
293 for (const monitor of this.monitors) closing.push(monitor.close())
294 await Promise.allSettled(closing)
295 }
296
297 async get (name, opts) {
298 const node = await this.entry(name, opts)
299 if (!node?.value.blob) return null
300 await this.getBlobs()
301 const res = await this.blobs.get(node.value.blob, opts)
302
303 if (res === null) throw BLOCK_NOT_AVAILABLE()
304 return res
305 }
306
307 async put (name, buf, { executable = false, metadata = null } = {}) {
308 await this.getBlobs()
309 const blob = await this.blobs.put(buf)
310 return this.db.put(std(name, false), { executable, linkname: null, blob, metadata }, { keyEncoding })
311 }
312
313 async del (name) {
314 return this.db.del(std(name, false), { keyEncoding })
315 }
316
317 compare (a, b) {
318 const diff = a.seq - b.seq
319 return diff > 0 ? 1 : (diff < 0 ? -1 : 0)
320 }
321
322 async clear (name, opts) {
323 if (!this.opened) await this.ready()
324
325 let node = null
326
327 try {
328 node = await this.entry(name, { wait: false })
329 } catch {
330 // do nothing, prop not available
331 }
332
333 if (node === null || this.blobs === null) {
334 return (opts && opts.diff) ? { blocks: 0 } : null
335 }
336
337 return this.blobs.clear(node.value.blob, opts)
338 }
339
340 async clearAll (opts) {
341 if (!this.opened) await this.ready()
342
343 if (this.blobs === null) {
344 return (opts && opts.diff) ? { blocks: 0 } : null
345 }
346
347 return this.blobs.core.clear(0, this.blobs.core.length, opts)
348 }
349
350 async purge () {
351 if (this._checkout || this._batch) throw new Error('Can only purge the main session')
352
353 await this.ready() // Ensure blobs loaded if present
354 await this.close()
355
356 const proms = [this.core.purge()]
357 if (this.blobs) proms.push(this.blobs.core.purge())
358 await Promise.all(proms)
359 }
360
361 async symlink (name, dst, { metadata = null } = {}) {
362 return this.db.put(std(name, false), { executable: false, linkname: dst, blob: null, metadata }, { keyEncoding })
363 }
364
365 async entry (name, opts) {
366 if (!opts || !opts.follow) return this._entry(name, opts)
367
368 for (let i = 0; i < 16; i++) {
369 const node = await this._entry(name, opts)
370 if (!node || !node.value.linkname) return node
371
372 name = unixPathResolve(node.key, node.value.linkname)
373 }
374
375 throw new Error('Recursive symlink')
376 }
377
378 async _entry (name, opts) {
379 if (typeof name !== 'string') return name
380
381 return this.db.get(std(name, false), { ...opts, keyEncoding })
382 }
383
384 async exists (name) {
385 return await this.entry(name) !== null
386 }
387
388 watch (folder) {
389 folder = std(folder || '/', true)
390
391 return this.db.watch(prefixRange(folder), { keyEncoding, map: (snap) => this._makeCheckout(snap) })
392 }
393
394 diff (length, folder, opts) {
395 if (typeof folder === 'object' && folder && !opts) return this.diff(length, null, folder)
396
397 folder = std(folder || '/', true)
398
399 return this.db.createDiffStream(length, prefixRange(folder), { ...opts, keyEncoding })
400 }
401
402 async downloadDiff (length, folder, opts) {
403 const dls = []
404
405 for await (const entry of this.diff(length, folder, opts)) {
406 if (!entry.left) continue
407 const b = entry.left.value.blob
408 if (!b) continue
409 const blobs = await this.getBlobs()
410 dls.push(blobs.core.download({ start: b.blockOffset, length: b.blockLength }))
411 }
412
413 const proms = []
414 for (const r of dls) proms.push(r.downloaded())
415
416 await Promise.allSettled(proms)
417 }
418
419 async downloadRange (dbRanges, blobRanges) {
420 const dls = []
421
422 await this.ready()
423
424 for (const range of dbRanges) {
425 dls.push(this.db.core.download(range))
426 }
427
428 const blobs = await this.getBlobs()
429
430 for (const range of blobRanges) {
431 dls.push(blobs.core.download(range))
432 }
433
434 const proms = []
435 for (const r of dls) proms.push(r.downloaded())
436
437 await Promise.allSettled(proms)
438 }
439
440 entries (range, opts) {
441 const stream = this.db.createReadStream(range, { ...opts, keyEncoding })
442 if (opts && opts.ignore) stream._readableState.map = createStreamMapIgnore(opts.ignore)
443 return stream
444 }
445
446 async download (folder = '/', opts) {
447 if (typeof folder === 'object') return this.download(undefined, folder)
448
449 const dls = []
450 const entry = (!folder || folder.endsWith('/')) ? null : await this.entry(folder)
451
452 if (entry) {
453 const b = entry.value.blob
454 if (!b) return
455 const blobs = await this.getBlobs()
456 await blobs.core.download({ start: b.blockOffset, length: b.blockLength }).downloaded()
457 return
458 }
459
460 // first preload the list so we can use the full power afterwards to actually preload everything
461 // eslint-disable-next-line
462 for await (const _ of this.list(folder, opts)) {
463 // ignore
464 }
465
466 for await (const entry of this.list(folder, opts)) {
467 const b = entry.value.blob
468 if (!b) continue
469
470 const blobs = await this.getBlobs()
471 dls.push(blobs.core.download({ start: b.blockOffset, length: b.blockLength }))
472 }
473
474 const proms = []
475 for (const r of dls) proms.push(r.downloaded())
476
477 await Promise.allSettled(proms)
478 }
479
480 // atm always recursive, but we should add some depth thing to it
481 list (folder, opts = {}) {
482 if (typeof folder === 'object') return this.list(undefined, folder)
483
484 folder = std(folder || '/', true)
485
486 const ignore = opts.ignore ? normalizeIgnore(opts.ignore) : null
487 const stream = opts && opts.recursive === false ? shallowReadStream(this.db, folder, false, ignore, opts) : this.entries(prefixRange(folder), { ...opts, ignore })
488 return stream
489 }
490
491 readdir (folder, opts) {
492 folder = std(folder || '/', true)
493 return shallowReadStream(this.db, folder, true, null, opts)
494 }
495
496 mirror (out, opts) {
497 return new MirrorDrive(this, out, opts)
498 }
499
500 createReadStream (name, opts) {
501 const self = this
502
503 let destroyed = false
504 let rs = null
505
506 const stream = new Readable({
507 open (cb) {
508 self.getBlobs().then(onblobs, cb)
509
510 function onblobs () {
511 self.entry(name).then(onnode, cb)
512 }
513
514 function onnode (node) {
515 if (destroyed) return cb(null)
516 if (!node) return cb(new Error('Blob does not exist'))
517 if (self.closing) return cb(new Error('Closed'))
518
519 if (!node.value.blob) {
520 stream.push(null)
521 return cb(null)
522 }
523
524 rs = self.blobs.createReadStream(node.value.blob, opts)
525
526 rs.on('data', function (data) {
527 if (!stream.push(data)) rs.pause()
528 })
529
530 rs.on('end', function () {
531 stream.push(null)
532 })
533
534 rs.on('error', function (err) {
535 stream.destroy(err)
536 })
537
538 cb(null)
539 }
540 },
541 read (cb) {
542 rs.resume()
543 cb(null)
544 },
545 predestroy () {
546 destroyed = true
547 if (rs) rs.destroy()
548 }
549 })
550
551 return stream
552 }
553
554 createWriteStream (name, { executable = false, metadata = null } = {}) {
555 const self = this
556
557 let destroyed = false
558 let ws = null
559 let ondrain = null
560 let onfinish = null
561
562 const stream = new Writable({
563 open (cb) {
564 self.getBlobs().then(onblobs, cb)
565
566 function onblobs () {
567 if (destroyed) return cb(null)
568
569 ws = self.blobs.createWriteStream()
570
571 ws.on('error', function (err) {
572 stream.destroy(err)
573 })
574
575 ws.on('close', function () {
576 const err = new Error('Closed')
577 callOndrain(err)
578 callOnfinish(err)
579 })
580
581 ws.on('finish', function () {
582 callOnfinish(null)
583 })
584
585 ws.on('drain', function () {
586 callOndrain(null)
587 })
588
589 cb(null)
590 }
591 },
592 write (data, cb) {
593 if (ws.write(data) === true) return cb(null)
594 ondrain = cb
595 },
596 final (cb) {
597 onfinish = cb
598 ws.end()
599 },
600 predestroy () {
601 destroyed = true
602 if (ws) ws.destroy()
603 }
604 })
605
606 return stream
607
608 function callOnfinish (err) {
609 if (!onfinish) return
610
611 const cb = onfinish
612 onfinish = null
613
614 if (err) return cb(err)
615 self.db.put(std(name, false), { executable, linkname: null, blob: ws.id, metadata }, { keyEncoding }).then(() => cb(null), cb)
616 }
617
618 function callOndrain (err) {
619 if (ondrain) {
620 const cb = ondrain
621 ondrain = null
622 cb(err)
623 }
624 }
625 }
626
627 static normalizePath (name) {
628 return std(name, false)
629 }
630}
631
632function shallowReadStream (files, folder, keys, ignore, opts) {
633 let prev = '/'
634 let prevName = ''
635
636 return new Readable({
637 async read (cb) {
638 let node = null
639
640 try {
641 node = await files.peek(prefixRange(folder, prev), { ...opts, keyEncoding })
642 } catch (err) {
643 return cb(err)
644 }
645
646 if (!node) {
647 this.push(null)
648 return cb(null)
649 }
650
651 const suffix = node.key.slice(folder.length + 1)
652 const i = suffix.indexOf('/')
653 const name = i === -1 ? suffix : suffix.slice(0, i)
654
655 prev = '/' + name + (i === -1 ? '' : '0')
656
657 // just in case someone does /foo + /foo/bar, but we should prop not even support that
658 if (name === prevName) {
659 this._read(cb)
660 return
661 }
662
663 prevName = name
664
665 if (ignore && isIgnored(node.key, ignore)) {
666 this._read(cb)
667 return
668 }
669
670 this.push(keys ? name : node)
671 cb(null)
672 }
673 })
674}
675
676function makeBee (key, corestore, opts = {}) {
677 const name = key ? undefined : 'db'
678 const core = corestore.get({ key, name, exclusive: true, onwait: opts.onwait, encryptionKey: opts.encryptionKey, compat: opts.compat, active: opts.active })
679
680 return new Hyperbee(core, {
681 keyEncoding: 'utf-8',
682 valueEncoding: 'json',
683 metadata: { contentFeed: null }
684 })
685}
686
687function getBee (bee) {
688 // A Batch instance will have a .tree property for the actual Hyperbee
689 return bee.tree || bee
690}
691
692function std (name, removeSlash) {
693 // Note: only remove slash if you're going to use it as prefix range
694 name = unixPathResolve('/', name)
695 if (removeSlash && name.endsWith('/')) name = name.slice(0, -1)
696 validateFilename(name)
697 return name
698}
699
700function validateFilename (name) {
701 if (name === '/') throw new Error('Invalid filename: ' + name)
702}
703
704function prefixRange (name, prev = '/') {
705 // '0' is binary +1 of /
706 return { gt: name + prev, lt: name + '0' }
707}
708
709function generateContentManifest (m, key) {
710 if (m.version < 1) return null
711
712 const signers = []
713
714 if (!key) key = Hypercore.key(m)
715
716 for (const s of m.signers) {
717 const namespace = crypto.hash([BLOBS, key, s.namespace])
718 signers.push({ ...s, namespace })
719 }
720
721 return {
722 version: m.version,
723 hash: 'blake2b',
724 allowPatch: m.allowPatch,
725 quorum: m.quorum,
726 signers,
727 prologue: null // TODO: could be configurable through the header still...
728 }
729}
730
731async function getBlobsLength (db) {
732 let length = 0
733
734 for await (const { value } of db.createReadStream()) {
735 const b = value && value.blob
736 if (!b) continue
737 const len = b.blockOffset + b.blockLength
738 if (len > length) length = len
739 }
740
741 return length
742}
743
744function normalizeIgnore (ignore) {
745 return [].concat(ignore).map(e => unixPathResolve('/', e))
746}
747
748function isIgnored (key, ignore) {
749 return ignore.some(e => e === key || key.startsWith(e + '/'))
750}
751
752function createStreamMapIgnore (ignore) {
753 return (node) => {
754 return isIgnored(node.key, ignore) ? null : node
755 }
756}
node_modules/hyperdrive/lib/monitor.js +123 -0
……@@ -0,0 +1,123 @@
1const ReadyResource = require('ready-resource')
2const safetyCatch = require('safety-catch')
3const speedometer = require('speedometer')
4
5module.exports = class Monitor extends ReadyResource {
6 constructor (drive, opts = {}) {
7 super()
8 this.drive = drive
9 this.blobs = null
10 this.name = opts.name || null
11 this.entry = opts.entry || null
12 this.peers = 0
13
14 this._boundOnUpload = this._onUpload.bind(this)
15 this._boundOnDownload = this._onDownload.bind(this)
16 this._boundPeerUpdate = this._updatePeers.bind(this)
17
18 const stats = {
19 startTime: 0,
20 percentage: 0,
21 peers: 0,
22 speed: 0,
23 blocks: 0,
24 totalBytes: 0, // local + bytes loaded during monitoring
25 monitoringBytes: 0, // bytes loaded during monitoring
26 targetBytes: 0,
27 targetBlocks: 0
28 }
29
30 // Updated on each upload/download event
31 this.uploadStats = { ...stats }
32 this.downloadStats = { ...stats }
33
34 this.uploadSpeedometer = null
35 this.downloadSpeedometer = null
36
37 this.ready().catch(safetyCatch)
38 }
39
40 async _open () {
41 await this.drive.ready()
42 this.blobs = await this.drive.getBlobs()
43 if (!this.entry && this.name) this.entry = await this.drive.entry(this.name)
44 if (this.entry) this._setEntryInfo()
45
46 this.uploadSpeedometer = speedometer()
47 this.downloadSpeedometer = speedometer()
48
49 this._updatePeers()
50
51 // Handlers
52 this.blobs.core.on('peer-add', this._boundPeerUpdate)
53 this.blobs.core.on('peer-remove', this._boundPeerUpdate)
54 this.blobs.core.on('upload', this._boundOnUpload)
55 this.blobs.core.on('download', this._boundOnDownload)
56 }
57
58 async _close () {
59 this.blobs.core.off('peer-add', this._boundPeerUpdate)
60 this.blobs.core.off('peer-remove', this._boundPeerUpdate)
61 this.blobs.core.off('upload', this._boundOnUpload)
62 this.blobs.core.off('download', this._boundOnDownload)
63 this.drive.monitors.delete(this)
64 }
65
66 _setEntryInfo () {
67 if (!this.downloadStats.targetBytes || !this.downloadStats.targetBlocks) {
68 this.downloadStats.targetBytes = this.entry.value.blob.byteLength
69 this.downloadStats.targetBlocks = this.entry.value.blob.blockLength
70 }
71
72 if (!this.uploadStats.targetBytes || !this.uploadStats.targetBlocks) {
73 this.uploadStats.targetBytes = this.entry.value.blob.byteLength
74 this.uploadStats.targetBlocks = this.entry.value.blob.blockLength
75 }
76 }
77
78 _onUpload (index, bytes, from) {
79 this._updateStats(this.uploadSpeedometer, this.uploadStats, index, bytes, from)
80 }
81
82 _onDownload (index, bytes, from) {
83 this._updateStats(this.downloadSpeedometer, this.downloadStats, index, bytes, from)
84 }
85
86 _updatePeers () {
87 this.uploadStats.peers = this.downloadStats.peers = this.peers = this.blobs.core.peers.length
88 }
89
90 _updateStats (speed, stats, index, bytes, from) {
91 if (!this.entry || this.closing) return
92 if (!isWithinRange(index, this.entry)) return
93
94 if (!stats.startTime) stats.startTime = Date.now()
95
96 stats.speed = speed(bytes)
97 stats.blocks++
98 stats.monitoringBytes += bytes
99 stats.totalBytes += bytes
100 // NOTE: you should not rely on the percentage until the monitor is initialized with the local state of the file
101 stats.percentage = toFixed(stats.blocks / stats.targetBlocks * 100)
102
103 this.emit('update')
104 }
105
106 downloadSpeed () {
107 return this.downloadSpeedometer ? this.downloadSpeedometer() : 0
108 }
109
110 uploadSpeed () {
111 return this.uploadSpeedometer ? this.uploadSpeedometer() : 0
112 }
113}
114
115function isWithinRange (index, entry) {
116 if (!entry || !entry.value) return
117 const { blockOffset, blockLength } = entry.value.blob
118 return index >= blockOffset && index < blockOffset + blockLength
119}
120
121function toFixed (n) {
122 return Math.round(n * 100) / 100
123}
node_modules/hyperdrive/package.json +48 -0
……@@ -0,0 +1,48 @@
1{
2 "name": "hyperdrive",
3 "version": "11.13.4",
4 "description": "Hyperdrive is a secure, real-time distributed file system",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "lib/**.js"
9 ],
10 "repository": {
11 "type": "git",
12 "url": "git+https://github.com/holepunchto/hyperdrive.git"
13 },
14 "scripts": {
15 "test": "standard && brittle test.js"
16 },
17 "author": "Holepunch",
18 "license": "Apache-2.0",
19 "bugs": {
20 "url": "https://github.com/holepunchto/hyperdrive/issues"
21 },
22 "homepage": "https://github.com/holepunchto/hyperdrive#readme",
23 "dependencies": {
24 "hyperbee": "^2.11.1",
25 "hyperblobs": "^2.3.0",
26 "hypercore": "^10.33.0",
27 "hypercore-errors": "^1.0.0",
28 "is-options": "^1.0.2",
29 "mirror-drive": "^1.2.0",
30 "ready-resource": "^1.0.0",
31 "safety-catch": "^1.0.2",
32 "speedometer": "^1.1.0",
33 "streamx": "^2.12.4",
34 "sub-encoder": "^2.1.1",
35 "unix-path-resolve": "^1.0.2"
36 },
37 "devDependencies": {
38 "b4a": "^1.6.0",
39 "brittle": "^3.1.0",
40 "corestore": "^6.8.1",
41 "hypercore-crypto": "^3.4.0",
42 "hyperdht": "^6.6.0",
43 "hyperswarm": "^4.0.0",
44 "random-access-memory": "^6.0.0",
45 "standard": "^17.0.0",
46 "test-tmp": "^1.3.0"
47 }
48}
node_modules/is-options/.travis.yml +7 -0
……@@ -0,0 +1,7 @@
1language: node_js
2sudo: false
3node_js:
4 - 4
5 - 6
6 - 8
7 - 9
node_modules/is-options/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2018 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/is-options/README.md +39 -0
……@@ -0,0 +1,39 @@
1# is-options
2
3Easily check if input is an options map
4
5```
6npm install is-options
7```
8
9[![Build Status](https://travis-ci.org/mafintosh/is-options.svg?branch=master)](https://travis-ci.org/mafintosh/is-options)
10
11## Usage
12
13``` js
14var isOptions = require('is-options')
15
16thing('', {foo: true}) // key='', opts={foo: true}
17thing({foo: true}) // key=undefined, opts={foo: true}
18thing(Buffer.from('buf'), {foo: true}) // key=Buffer('buf'), opts={foo: true}
19
20function thing (optionalKey, opts) {
21 if (isOptions(optionalKey)) {
22 opts = optionalKey
23 optionalKey = undefined
24 }
25
26 console.log('key', optionalKey)
27 console.log('options', opts)
28}
29```
30
31## API
32
33#### `bool = isOptions(obj)`
34
35Returns true is `obj` is an object and not a buffer
36
37## License
38
39MIT
node_modules/is-options/index.js +5 -0
……@@ -0,0 +1,5 @@
1const b4a = require('b4a')
2
3module.exports = function isOptions (opts) {
4 return typeof opts === 'object' && opts && !b4a.isBuffer(opts)
5}
node_modules/is-options/package.json +26 -0
……@@ -0,0 +1,26 @@
1{
2 "name": "is-options",
3 "version": "1.0.2",
4 "description": "Easily check if input is an options map",
5 "main": "index.js",
6 "dependencies": {
7 "b4a": "^1.1.1"
8 },
9 "devDependencies": {
10 "standard": "^11.0.1",
11 "tape": "^4.9.0"
12 },
13 "scripts": {
14 "test": "standard && tape test.js"
15 },
16 "repository": {
17 "type": "git",
18 "url": "https://github.com/mafintosh/is-options.git"
19 },
20 "author": "Mathias Buus (@mafintosh)",
21 "license": "MIT",
22 "bugs": {
23 "url": "https://github.com/mafintosh/is-options/issues"
24 },
25 "homepage": "https://github.com/mafintosh/is-options"
26}
node_modules/is-options/test.js +13 -0
……@@ -0,0 +1,13 @@
1const tape = require('tape')
2const isOptions = require('./')
3
4tape('works', function (t) {
5 t.ok(isOptions({}))
6 t.notOk(isOptions(''))
7 t.notOk(isOptions(Buffer.from('hi')))
8 t.notOk(isOptions())
9 t.notOk(isOptions(null))
10 t.notOk(isOptions(42))
11 t.notOk(isOptions(undefined))
12 t.end()
13})
node_modules/mirror-drive/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/mirror-drive/README.md +81 -0
……@@ -0,0 +1,81 @@
1# mirror-drive
2
3Mirror a Hyperdrive or Localdrive into another one
4
5```
6npm i mirror-drive
7```
8
9## Usage
10
11```js
12import MirrorDrive from 'mirror-drive'
13
14const src = new Localdrive('./src')
15const dst = new Hyperdrive(store)
16
17const mirror = new MirrorDrive(src, dst)
18console.log(mirror.count) // => { files: 0, add: 0, remove: 0, change: 0 }
19
20for await (const diff of mirror) {
21 console.log(diff) /* {
22 op: 'add',
23 key: '/new-file.txt',
24 bytesRemoved: 0,
25 bytesAdded: 4
26 }*/
27}
28
29console.log(mirror.count) // => { files: 1, add: 1, remove: 0, change: 0 }
30```
31
32Another example:
33
34```js
35const mirror = new MirrorDrive(src, dst)
36
37console.log(mirror.count) // => { files: 0, add: 0, remove: 0, change: 0 }
38await mirror.done()
39console.log(mirror.count) // => { files: 1, add: 1, remove: 0, change: 0 }
40```
41
42## API
43
44#### `const mirror = new MirrorDrive(src, dst, [options])`
45
46Creates a mirror instance to efficiently move `src` drive into `dst` drive.
47
48Available `options`:
49
50```js
51{
52 prefix: '/',
53 dryRun: false,
54 prune: true,
55 includeEquals: false,
56 filter: (key) => true,
57 metadataEquals: (srcMetadata, dstMetadata) => { ... }
58 batch: false,
59 entries: null // Array of key entries (if you use this then prefix is ignored)
60 ignore: String || Array // Ignore source files and folders by name.
61 transformers: [] // Array of factory functions (key) => stream
62}
63```
64
65#### `mirror.count`
66
67It counts the total files proccessed, added, removed, and changed.
68
69Default value: `{ files: 0, add: 0, remove: 0, change: 0 }`
70
71#### `await mirror.done()`
72
73It starts processing all the diffing until is done.
74
75## Transformers
76
77Apply content transformers during mirroring. Each item in `transformers` is a factory function `(key) => stream | null` that returns a new stream (or `null`) for that file. MirrorDrive always pipes through all provided transformers. If a `transformer` returns `null` it is safely skipped.
78
79## License
80
81Apache-2.0
node_modules/mirror-drive/index.js +418 -0
……@@ -0,0 +1,418 @@
1const EventEmitter = require('events')
2const sameData = require('same-data')
3const unixPathResolve = require('unix-path-resolve')
4const streamEquals = require('binary-stream-equals')
5const speedometer = require('speedometer')
6const { pipelinePromise, isStream } = require('streamx')
7const RabinStream = require('rabin-stream')
8
9const SAME = 0
10const DIFF = 1
11const DIFF_META = 2
12
13class Monitor extends EventEmitter {
14 constructor(mirror, { interval = 250 } = {}) {
15 super()
16
17 this.mirror = mirror
18 this.interval = setInterval(this.update.bind(this), interval)
19 this.stats = null
20 this.index = mirror.monitors.push(this) - 1
21
22 this.update() // populate latest stats
23 }
24
25 get preloaded() {
26 return this.mirror.preloaded
27 }
28
29 get destroyed() {
30 return this.index === -1
31 }
32
33 update() {
34 if (this.index === -1) return
35
36 // NOTE: immutable (append-only) data structure
37 this.stats = {
38 peers: this.mirror.peers.length,
39 download: {
40 bytes: this.mirror.downloadedBytes,
41 blocks: this.mirror.downloadedBlocks,
42 speed: this.mirror.downloadSpeed(),
43 progress: this.mirror.downloadProgress
44 },
45 upload: {
46 bytes: this.mirror.uploadedBytes,
47 blocks: this.mirror.uploadedBlocks,
48 speed: this.mirror.uploadSpeed()
49 }
50 }
51
52 this.emit('update', this.stats)
53 }
54
55 destroy() {
56 if (this.index === -1) return
57
58 clearInterval(this.interval)
59
60 const head = this.mirror.monitors.pop()
61 if (head !== this) {
62 this.mirror.monitors[this.index] = head
63 head.index = this.index
64 }
65
66 this.index = -1
67 this.emit('destroy')
68 }
69}
70
71module.exports = class MirrorDrive {
72 constructor(src, dst, opts = {}) {
73 this.src = src
74 this.dst = dst
75
76 this.prefix = toArray(opts.prefix || '/')
77 this.dedup = !!opts.dedup
78 this.dryRun = !!opts.dryRun
79 this.prune = opts.prune !== false
80 this.preload = opts.preload !== false && !!src.getBlobs
81 this.preloaded = false
82 this.includeProgress = !!opts.progress && !!src.getBlobs
83 this.includeEquals = !!opts.includeEquals
84 this.filter = opts.filter || null
85 this.metadataEquals = opts.metadataEquals || null
86 this.batch = !!opts.batch
87 this.entries = opts.entries || null
88 this.transformers = opts.transformers || []
89
90 this.count = { files: 0, add: 0, remove: 0, change: 0 }
91 this.bytesRemoved = 0
92 this.bytesAdded = 0
93 this.ignore = opts.ignore ? toIgnoreFunction(opts.ignore) : null
94 this.finished = false
95
96 this.downloadedBlocks = 0
97 this.downloadedBlocksEstimate = 0
98 this.downloadedBytes = 0
99 this.downloadSpeed = this.includeProgress ? speedometer() : null
100
101 this.uploadedBlocks = 0
102 this.uploadedBytes = 0
103 this.uploadSpeed = this.includeProgress ? speedometer() : null
104
105 this.monitors = []
106 this.iterator = this._init()
107 }
108
109 [Symbol.asyncIterator]() {
110 return this.iterator
111 }
112
113 get peers() {
114 return this.src.core?.peers || []
115 }
116
117 get downloadProgress() {
118 if (this.finished) return 1
119 if (!this.downloadedBlocksEstimate) return 0
120 // leave 3% incase our estimatation is wrong - then at least it wont appear done...
121 return Math.min(0.99, this.downloadedBlocks / this.downloadedBlocksEstimate)
122 }
123
124 monitor(opts) {
125 this.includeProgress = true
126 if (this.downloadSpeed === null) this.downloadSpeed = speedometer()
127 if (this.uploadSpeed === null) this.uploadSpeed = speedometer()
128 return new Monitor(this, opts)
129 }
130
131 async done() {
132 while (true) {
133 const { done } = await this.iterator.next()
134 if (done) break
135 }
136 }
137
138 _onupload(index, byteLength) {
139 this.uploadedBlocks++
140 this.uploadedBytes += byteLength
141 this.uploadSpeed(byteLength)
142 }
143
144 _ondownload(index, byteLength) {
145 this.downloadedBlocks++
146 this.downloadedBytes += byteLength
147 this.downloadSpeed(byteLength)
148 }
149
150 async _flushPreload(entries) {
151 const ranges = []
152 const blobs = await this.src.getBlobs()
153
154 for (const entry of entries) {
155 const blob = entry.value.blob
156 if (!blob) continue
157 const dl = blobs.core.download({ start: blob.blockOffset, length: blob.blockLength })
158 await dl.ready()
159 ranges.push(dl)
160 }
161
162 this.downloadedBlocksEstimate = this.downloadedBlocks
163 for (const dl of ranges) {
164 if (!dl.request.context) continue
165 this.downloadedBlocksEstimate += dl.request.context.end - dl.request.context.start
166 }
167 this.preloaded = true
168 for (const m of this.monitors) {
169 m.emit('preloaded')
170 }
171
172 for (const dl of ranges) {
173 await dl.done()
174 }
175 }
176
177 async *_init() {
178 try {
179 for await (const out of this._mirror()) yield out
180 } finally {
181 while (this.monitors.length) {
182 this.monitors[this.monitors.length - 1].destroy()
183 }
184 }
185 }
186
187 async *_mirror() {
188 await this.src.ready()
189 await this.dst.ready()
190
191 if (this.dst.core && !this.dst.core.writable) throw new Error('Destination must be writable')
192
193 const blobs = this.includeProgress ? await this.src.getBlobs() : null
194 const onupload = this._onupload.bind(this)
195 const ondownload = this._ondownload.bind(this)
196
197 if (blobs) {
198 blobs.core.on('upload', onupload)
199 blobs.core.on('download', ondownload)
200 }
201
202 const dst = this.batch ? this.dst.batch() : this.dst
203
204 if (this.prune) {
205 for await (const [key, dstEntry, srcEntry] of this._list(this.dst, this.src, null)) {
206 if (srcEntry) continue
207
208 this.count.remove++
209 this.bytesRemoved += blobLength(dstEntry)
210 yield { op: 'remove', key, bytesRemoved: blobLength(dstEntry), bytesAdded: 0 }
211
212 if (!this.dryRun) await dst.del(key)
213 }
214 }
215
216 if (this.preload) {
217 const entries = []
218
219 for await (const [, srcEntry] of this._list(this.src, null, this.filter)) {
220 entries.push(srcEntry)
221 }
222
223 // flush in bg
224 this._flushPreload(entries).catch(noop)
225 }
226
227 for await (const [key, srcEntry, dstEntry] of this._list(this.src, dst, this.filter)) {
228 if (!srcEntry) continue // Due entries option, src entry might not exist probably because it was pruned
229
230 this.count.files++
231
232 // If transformers are provided, we can't know if same before running them
233 const hasTransformers = this.transformers && this.transformers.length > 0
234
235 const s = hasTransformers === false ? await same(this, srcEntry, dstEntry) : DIFF
236
237 if (s === SAME) {
238 if (this.includeEquals) {
239 yield { op: 'equal', key, bytesRemoved: 0, bytesAdded: 0 }
240 }
241 continue
242 }
243
244 const onlyMetadata = s === DIFF_META && !!dst.putEntry
245 const dedup = !!dst.putEntry && this.dedup
246
247 if (dstEntry) {
248 const removed = onlyMetadata ? 0 : blobLength(dstEntry)
249 const added = onlyMetadata ? 0 : blobLength(srcEntry)
250 this.count.change++
251 this.bytesRemoved += removed
252 this.bytesAdded += added
253 yield {
254 op: 'change',
255 key,
256 bytesRemoved: removed,
257 bytesAdded: added
258 }
259 } else {
260 this.count.add++
261 this.bytesAdded += blobLength(srcEntry)
262 yield { op: 'add', key, bytesRemoved: 0, bytesAdded: blobLength(srcEntry) }
263 }
264
265 if (this.dryRun) {
266 continue
267 }
268
269 const transformers = []
270
271 for (const transformer of this.transformers) {
272 if (typeof transformer !== 'function') throw new Error('transformer must be a function')
273
274 const stream = transformer(key)
275
276 if (stream === null) continue
277 if (!isStream(stream)) throw new Error('transformer must return a stream')
278
279 transformers.push(stream)
280 }
281
282 if (srcEntry.value.linkname) {
283 await dst.symlink(key, srcEntry.value.linkname)
284 } else if (!onlyMetadata) {
285 if (dedup) transformers.push(new RabinStream())
286 await pipelinePromise(
287 this.src.createReadStream(srcEntry),
288 ...transformers,
289 dst.createWriteStream(key, {
290 dedup,
291 executable: srcEntry.value.executable,
292 metadata: srcEntry.value.metadata
293 })
294 )
295 } else {
296 await dst.putEntry(key, {
297 executable: srcEntry.value.executable,
298 linkname: srcEntry.value.linkname,
299 blob: dstEntry.value.blob,
300 metadata: srcEntry.value.metadata
301 })
302 }
303 }
304
305 if (this.batch) await dst.flush()
306
307 if (blobs) {
308 blobs.core.off('upload', onupload)
309 blobs.core.off('download', ondownload)
310 }
311
312 this.finished = true
313 }
314
315 async *_list(a, b, filter) {
316 const lists = []
317
318 for (const prefix of this.prefix) {
319 if (this.entries) {
320 lists.push(this.entries)
321 } else {
322 const stream = a.list(prefix, { ignore: this.ignore })
323 if (stream.on) {
324 stream.on('error', noop)
325 stream.resume()
326 stream.pause()
327 }
328 lists.push(stream)
329 }
330 }
331
332 for (let i = 0; i < this.prefix.length; i++) {
333 const prefix = this.prefix[i]
334 const list = lists[i]
335
336 for await (const entry of list) {
337 const key = typeof entry === 'object' ? entry.key : entry
338
339 if (filter && !filter(key)) continue
340
341 const entryA = await a.entry(entry)
342 const entryB = b ? await b.entry(key) : null
343
344 yield [key, entryA, entryB]
345 }
346
347 if (prefix !== '/' && (!filter || filter(prefix))) {
348 const entryA = await a.entry(prefix)
349 const entryB = b ? await b.entry(prefix) : null
350
351 if (!entryA && !entryB) continue
352
353 yield [prefix, entryA, entryB]
354 }
355 }
356 }
357}
358
359function blobLength(entry) {
360 return entry.value.blob ? entry.value.blob.byteLength : 0
361}
362
363async function same(m, srcEntry, dstEntry) {
364 if (!dstEntry) return DIFF
365
366 if (srcEntry.value.linkname || dstEntry.value.linkname) {
367 return srcEntry.value.linkname === dstEntry.value.linkname ? SAME : DIFF
368 }
369
370 if (!sizeEquals(srcEntry, dstEntry)) return DIFF
371
372 const eq = await streamEquals(m.src.createReadStream(srcEntry), m.dst.createReadStream(dstEntry))
373 const diff = eq ? DIFF_META : DIFF
374
375 if (srcEntry.value.executable !== dstEntry.value.executable) return diff
376 if (!metadataEquals(m, srcEntry, dstEntry)) return diff
377
378 return eq ? SAME : DIFF
379}
380
381function sizeEquals(srcEntry, dstEntry) {
382 const srcBlob = srcEntry.value.blob
383 const dstBlob = dstEntry.value.blob
384
385 if (!srcBlob && !dstBlob) return true
386 if (!srcBlob || !dstBlob) return false
387
388 return srcBlob.byteLength === dstBlob.byteLength
389}
390
391function metadataEquals(m, srcEntry, dstEntry) {
392 if (!m.src.supportsMetadata || !m.dst.supportsMetadata) return true
393
394 const srcMetadata = srcEntry.value.metadata
395 const dstMetadata = dstEntry.value.metadata
396
397 if (m.metadataEquals) {
398 return m.metadataEquals(srcMetadata, dstMetadata)
399 }
400
401 const noMetadata = !srcMetadata && !dstMetadata
402 const identicalMetadata = !!(srcMetadata && dstMetadata && sameData(srcMetadata, dstMetadata))
403
404 return noMetadata || identicalMetadata
405}
406
407function toIgnoreFunction(ignore) {
408 if (typeof ignore === 'function') return ignore
409
410 const all = [].concat(ignore).map((e) => unixPathResolve('/', e))
411 return (key) => all.some((path) => path === key || key.startsWith(path + '/'))
412}
413
414function toArray(prefix) {
415 return Array.isArray(prefix) ? prefix : [prefix]
416}
417
418function noop() {}
node_modules/mirror-drive/package.json +61 -0
……@@ -0,0 +1,61 @@
1{
2 "name": "mirror-drive",
3 "version": "1.13.0",
4 "description": "Mirror a hyperdrive or localdrive into another one",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "lib/**.js"
9 ],
10 "imports": {
11 "events": {
12 "bare": "bare-events"
13 },
14 "os": {
15 "bare": "bare-os",
16 "default": "os"
17 },
18 "stream": {
19 "bare": "bare-stream",
20 "default": "stream"
21 }
22 },
23 "scripts": {
24 "format": "prettier --write .",
25 "lint": "prettier --check . && lunte",
26 "test": "npm run test:node && npm run test:bare",
27 "test:node": "brittle-node test/*.js",
28 "test:bare": "brittle-bare test/*.js"
29 },
30 "repository": {
31 "type": "git",
32 "url": "https://github.com/holepunchto/mirror-drive.git"
33 },
34 "author": "Lucas Barrena (@LuKks)",
35 "license": "Apache-2.0",
36 "bugs": {
37 "url": "https://github.com/holepunchto/mirror-drive/issues"
38 },
39 "homepage": "https://github.com/holepunchto/mirror-drive",
40 "devDependencies": {
41 "b4a": "^1.6.0",
42 "bare-os": "^3.0.1",
43 "bare-stream": "^2.6.5",
44 "brittle": "^3.1.0",
45 "corestore": "^6.0.6",
46 "hyperdrive": "^13.0.0",
47 "localdrive": "^2.2.0",
48 "lunte": "^1.0.0",
49 "prettier": "^3.6.2",
50 "prettier-config-holepunch": "^2.0.0"
51 },
52 "dependencies": {
53 "bare-events": "^2.8.2",
54 "binary-stream-equals": "^1.0.0",
55 "rabin-stream": "^2.0.0",
56 "same-data": "^1.0.0",
57 "speedometer": "^1.1.0",
58 "streamx": "^2.22.1",
59 "unix-path-resolve": "^1.0.2"
60 }
61}
node_modules/mutexify/.travis.yml +7 -0
……@@ -0,0 +1,7 @@
1language: node_js
2node_js:
3 - '10'
4 - '12'
5 - '14'
6cache:
7 npm: false
node_modules/mutexify/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2014 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/mutexify/README.md +72 -0
……@@ -0,0 +1,72 @@
1# mutexify
2
3Bike shed mutex lock implementation in node.js
4
5```
6npm install mutexify
7```
8
9[![build status](http://img.shields.io/travis/mafintosh/mutexify.svg?style=flat)](http://travis-ci.org/mafintosh/mutexify)
10
11Hasn't this been done before? Yes, but the specific semantics of this made some of my code simpler.
12
13## Usage
14
15
16``` js
17var mutexify = require('mutexify')
18var lock = mutexify()
19
20lock(function(release) {
21 console.log('i am now locked')
22 setTimeout(function() {
23 release()
24 }, 1000)
25})
26
27lock(function(release) {
28 console.log('1 second later')
29 release()
30})
31```
32
33A common pattern is to call a callback after you release the lock.
34To do this in a one-liner pass the callback and the value to `release(cb, err, value)`
35
36``` js
37var write = function(data, cb) {
38 lock(function(release) {
39 fs.writeFile('locked-file.txt', data, release.bind(null, cb))
40 })
41}
42```
43
44`mutexify` guarantees that the order that a mutex was requested in is the order that access will be given.
45
46You can read the lock's current state on the `lock.locked` property.
47
48### Usage with promises
49
50`mutexify` provides a Promise-based alternative.
51
52```js
53const mutexify = require('mutexify/promise')
54
55;(async () => {
56 var lock = mutexify()
57
58 var release = await lock()
59 console.log('i am now locked')
60 setTimeout(function () {
61 release()
62 }, 1000)
63
64 release = await lock()
65 console.log('1 second later')
66 release()
67})()
68```
69
70## License
71
72MIT
node_modules/mutexify/index.js +31 -0
……@@ -0,0 +1,31 @@
1var queueTick = require('queue-tick')
2
3var mutexify = function () {
4 var queue = []
5 var used = null
6
7 var call = function () {
8 used(release)
9 }
10
11 var acquire = function (fn) {
12 if (used) return queue.push(fn)
13 used = fn
14 acquire.locked = true
15 queueTick(call)
16 return 0
17 }
18
19 acquire.locked = false
20
21 var release = function (fn, err, value) {
22 used = null
23 acquire.locked = false
24 if (queue.length) acquire(queue.shift())
25 if (fn) fn(err, value)
26 }
27
28 return acquire
29}
30
31module.exports = mutexify
node_modules/mutexify/package.json +32 -0
……@@ -0,0 +1,32 @@
1{
2 "name": "mutexify",
3 "version": "1.4.0",
4 "description": "mutex lock for javascript",
5 "main": "index.js",
6 "dependencies": {
7 "queue-tick": "^1.0.0"
8 },
9 "devDependencies": {
10 "standard": "^14.3.3",
11 "tape": "^3.0.2"
12 },
13 "scripts": {
14 "test": "tape test.js",
15 "posttest": "npm run lint",
16 "lint": "standard"
17 },
18 "repository": {
19 "type": "git",
20 "url": "https://github.com/mafintosh/mutexify.git"
21 },
22 "author": "Mathias Buus (@mafintosh)",
23 "license": "MIT",
24 "bugs": {
25 "url": "https://github.com/mafintosh/mutexify/issues"
26 },
27 "keywords": [
28 "mutex",
29 "lock"
30 ],
31 "homepage": "https://github.com/mafintosh/mutexify"
32}
node_modules/mutexify/promise.js +18 -0
……@@ -0,0 +1,18 @@
1var mutexify = require('.')
2
3var mutexifyPromise = function () {
4 var lock = mutexify()
5
6 var acquire = function () {
7 return new Promise(lock)
8 }
9
10 Object.defineProperty(acquire, 'locked', {
11 get: function () { return lock.locked },
12 enumerable: true
13 })
14
15 return acquire
16}
17
18module.exports = mutexifyPromise
node_modules/mutexify/test.js +78 -0
……@@ -0,0 +1,78 @@
1var tape = require('tape')
2var mutexify = require('./')
3var mutexifyPromise = require('./promise')
4
5tape('locks', function (t) {
6 t.plan(21)
7
8 var lock = mutexify()
9 var used = false
10 t.ok(!lock.locked, 'not locked')
11
12 for (var i = 0; i < 10; i++) {
13 lock(function (release) {
14 t.ok(!used, 'one at the time')
15 t.ok(lock.locked, 'locked')
16 used = true
17 setImmediate(function () {
18 used = false
19 release()
20 })
21 })
22 }
23})
24
25tape('calls callback', function (t) {
26 var lock = mutexify()
27
28 var cb = function (err, value) {
29 t.same(err, null)
30 t.same(value, 'hello world')
31 t.end()
32 }
33
34 lock(function (release) {
35 release(cb, null, 'hello world')
36 })
37})
38
39tape('calls the locking callbacks in a different stack', function (t) {
40 t.plan(2)
41
42 var lock = mutexify()
43
44 var topScopeFinished = false
45 var secondScopeFinished = false
46
47 lock(function (release) {
48 t.ok(topScopeFinished, 'the test function has already finished running')
49 release()
50 secondScopeFinished = true
51 })
52
53 lock(function (release) {
54 t.ok(secondScopeFinished, 'the last lock\'s call stack is done')
55 release()
56 t.end()
57 })
58
59 topScopeFinished = true
60})
61
62tape('locks with promises', async function (t) {
63 t.plan(21)
64
65 var lock = mutexifyPromise()
66 var used = false
67 t.ok(!lock.locked, 'not locked')
68 for (var i = 0; i < 10; i++) {
69 var release = await lock()
70 t.ok(!used, 'one at the time')
71 t.ok(lock.locked, 'locked')
72 used = true
73 setImmediate(function () {
74 used = false
75 release()
76 })
77 }
78})
node_modules/nanoassert/.travis.yml +18 -0
……@@ -0,0 +1,18 @@
1sudo: false
2language: node_js
3node_js:
4 - lts/*
5jobs:
6 include:
7 - stage: npm release
8 node_js: node
9 script: echo "Deploying to npm ..."
10 deploy:
11 provider: npm
12 email:
13 secure: "Xxe2IEoT27tWFCCN3suwAtioeWSy5IhTEqqAIy6I6MbFAbqq4npU0lQ6mL5+kI5H6S2luFZwf1Eex1lXNfNAdGFI0sSnjOcKyw7HUsU/D7fNpQmtnnlSAJmz0z7qtWGzrNM/ihTFxAo5CYRJq2uemZ7tZTah0ePcXfiQxK3ZcnI2kS5yR+bQqZQVMy0yT0zHhTGoTsWaF3yAaZrlqLK5VNwIMahmRbz+BTtzNPgB9c9RA5tDla+GPevF3jaFw+Fwuv8M38idRERzJMJ7nYnBOC7XXssk25d+2ErsX61wqAxrXTaPmV9Mg6Njp5hLdl6PA2wMOSSHMfbqrRmjB2yvKzqvcB/Z34lhpd7/0PT2iWVA78aSGwLuTDIxcyeRNdYLMhVrMt/mPHTtzw2xckdg1NNkXEwyXowTLqMEB+8AnRt7Vuy/wOgw60l1AvYB3VJsmwkOR/bL3p8Q1weRj4hYJgB0W4YWeAh7d0NcvE4zwML849n5t37k1tHtcOY0ZVqea1ENJfja1IjFsNN4ki99y8wCm+ba5d+AJaqn0+ChluZfnQTqSqFHxfEEEy8v+TGXl+F8j6YT9iYfnyPHwYLjXx4GcFzlhSDiDF+Dxr155TU2XsSVB9zrL6Mv8TzOiazgosBFZO2Jz3EnWjEr21oFuKPHyb0FJ0nC5UMLHx3youU="
14 api_key: # 1ed6
15 secure: "zX7inYgOYTPpbMMU2BHPcGwbuPRadcFUfgANuvFk81ZWTgmoZkGSl/YUbacQmpg8QcuSvw6m5Gpv518hNKGHIlvKgf02PADJNoMoHNK+vpCzwhHxAEddAYO7Up18vNPs+erDlnDBa9LhnTbNeGh9bUvb1ylDDlvdsNCbDIU+dFsTxJCqG9jma0P5UJIbj6S+oMB+pVYZ64e82k7H3PE4PFctUPuahMcKhuO/rt9t/62IXzC7f1CIPwpm6bOfhkwtpO9UswyLkpscERIEWjLY5GgwIi/t4Zp3wV1J0EjczhA1+ZnUvCM9HelSAiWxqQrkCZSEFDI3Q9x9ZOgBCjwBt7BcNOb68UMASYFpVJZ4iVu+BmdhKPpSYqb+fIxxSFJuXOmND2wSNkxM/ETKkYRGu3rG9g52TMegtYYZXfD/oYLtozfdBVtCymjZ9Pt4Bw/IcpmcuS8gfWJqziXIlD+7hOaZHAwcTg7zpSQvnUN0pxcumztWCgSSUpIWffn2YdQRuM3ih7Za6Qeve7ZkuKdi6uzvuoLB8WXt6xy7X+KIG7Ng3LTvCWvIkBuOXNAV9sRyF5BNwm0QbVMAwYO5MeK2acUxOFxLFNQLEkl+2pKHWcDPAXFuX0sgRfCc336cCUAauN7B83IAScHGx50BjG4ldRPOPlXWQawRDcsBQm5h7W0="
16 on:
17 tags: true
18 node: node
node_modules/nanoassert/LICENSE +13 -0
……@@ -0,0 +1,13 @@
1Copyright (c) 2017, Emil Bay <github@tixz.dk>
2
3Permission to use, copy, modify, and/or distribute this software for any
4purpose with or without fee is hereby granted, provided that the above
5copyright notice and this permission notice appear in all copies.
6
7THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
node_modules/nanoassert/README.md +44 -0
……@@ -0,0 +1,44 @@
1# `nanoassert`
2
3[![Build Status](https://travis-ci.org/emilbayes/nanoassert.svg?branch=master)](https://travis-ci.org/emilbayes/nanoassert)
4
5> Nanoscale assertion module
6
7## Usage
8
9```js
10var assert = require('nanoassert')
11
12assert(a !== b, `${a} !== ${b}`)
13```
14
15## API
16
17### `assert(declaration, [message])`
18
19Assert that `declaration` is truthy otherwise throw `AssertionError` with
20optional `message`. In Javascript runtimes that use v8, you will get a nicer
21stack trace with this error.
22If you want friendlier messages you can use template strings to show the
23assertion made like in the example above.
24
25## Why
26
27I like to write public facing code very defensively, but have reservations about
28the size incurred by the `assert` module. I only use the top-level `assert`
29method anyway.
30
31## `nanoassert@^1.1.0`
32
33Docs for the previous version, which is used by many modules on npm, can be
34[found here](https://github.com/emilbayes/nanoassert/tree/v1.1.0)
35
36## Install
37
38```sh
39npm install nanoassert
40```
41
42## License
43
44[ISC](LICENSE)
node_modules/nanoassert/example.js +5 -0
……@@ -0,0 +1,5 @@
1var assert = require('.')
2
3var a = 1
4var b = 1
5assert(a !== b, `${a} !== ${b}`)
node_modules/nanoassert/index.js +18 -0
……@@ -0,0 +1,18 @@
1module.exports = assert
2
3class AssertionError extends Error {}
4AssertionError.prototype.name = 'AssertionError'
5
6/**
7 * Minimal assert function
8 * @param {any} t Value to check if falsy
9 * @param {string=} m Optional assertion error message
10 * @throws {AssertionError}
11 */
12function assert (t, m) {
13 if (!t) {
14 var err = new AssertionError(m)
15 if (Error.captureStackTrace) Error.captureStackTrace(err, assert)
16 throw err
17 }
18}
node_modules/nanoassert/package.json +31 -0
……@@ -0,0 +1,31 @@
1{
2 "name": "nanoassert",
3 "version": "2.0.0",
4 "description": "Nanoscale assertion module",
5 "main": "index.js",
6 "dependencies": {},
7 "devDependencies": {
8 "tape": "^4.9.1"
9 },
10 "scripts": {
11 "test": "tape test.js"
12 },
13 "repository": {
14 "type": "git",
15 "url": "git+https://github.com/emilbayes/nanoassert.git"
16 },
17 "keywords": [
18 "assert",
19 "unassert",
20 "power-assert",
21 "tiny",
22 "nano",
23 "pico"
24 ],
25 "author": "Emil Bay <github@tixz.dk>",
26 "license": "ISC",
27 "bugs": {
28 "url": "https://github.com/emilbayes/nanoassert/issues"
29 },
30 "homepage": "https://github.com/emilbayes/nanoassert#readme"
31}
node_modules/nanoassert/test.js +27 -0
……@@ -0,0 +1,27 @@
1var assert = require('.')
2var test = require('tape')
3
4test('test', function (t) {
5 try {
6 assert(true === true) // test that it doesn't throw
7 t.pass('does not throw on truthy')
8 } catch (e) {
9 t.fail()
10 }
11
12 t.throws(assert.bind(null, false), 'throws on falsy')
13
14 try {
15 assert(false)
16 } catch (e) {
17 t.equal(e.message, '', 'default message')
18 }
19
20 try {
21 assert(false, 'hello world')
22 } catch (e) {
23 t.equal(e.message, 'hello world', 'custom message')
24 }
25
26 t.end()
27})
node_modules/noise-curve-ed/README.md +36 -0
……@@ -0,0 +1,36 @@
1# noise-curve-ed
2
3Ed25519 elliptic curve operations for [`noise-handshake`](https://github.com/chm-diederichs/noise-handshake)
4
5## Usage
6```js
7const curve = require('noise-curve-ed')
8const Noise = require('noise-handshake')
9
10const handshake = new Noise(pattern, initiator, staticKeyPair, { curve })
11```
12
13## API
14
15#### constants
16
17`DHLEN` = 32
18`PKLEN` = 32
19`SCALARLEN` = 32
20`SKLEN` = 64
21`ALG` = 'Ed25519'
22
23#### `generateKeyPair([privKey])`
24
25Generate a new keypair, optionally pass in a preexisting `privKey`. Return value is of the form:
26
27```
28{
29 publicKey,
30 secretKey,
31}
32```
33
34#### `dh(publicKey, { secretKey, scalar })`
35
36Perform DH between `publicKey` and `secretKey`/`scalar` and return the result.
node_modules/noise-curve-ed/index.js +71 -0
……@@ -0,0 +1,71 @@
1/* eslint-disable camelcase */
2const sodium = require('sodium-universal')
3const assert = require('nanoassert')
4const b4a = require('b4a')
5
6const DHLEN = sodium.crypto_scalarmult_ed25519_BYTES
7const PKLEN = sodium.crypto_scalarmult_ed25519_BYTES
8const SCALARLEN = sodium.crypto_scalarmult_ed25519_BYTES
9const SKLEN = sodium.crypto_sign_SECRETKEYBYTES
10const ALG = 'Ed25519'
11
12module.exports = {
13 DHLEN,
14 PKLEN,
15 SCALARLEN,
16 SKLEN,
17 ALG,
18 name: ALG,
19 generateKeyPair,
20 dh
21}
22
23function generateKeyPair (privKey) {
24 if (privKey) return generateSeedKeyPair(privKey.subarray(0, 32))
25
26 const keyPair = {}
27 keyPair.secretKey = b4a.alloc(SKLEN)
28 keyPair.publicKey = b4a.alloc(PKLEN)
29
30 sodium.crypto_sign_keypair(keyPair.publicKey, keyPair.secretKey)
31 return keyPair
32}
33
34function generateSeedKeyPair (seed) {
35 const keyPair = {}
36 keyPair.secretKey = b4a.alloc(SKLEN)
37 keyPair.publicKey = b4a.alloc(PKLEN)
38
39 sodium.crypto_sign_seed_keypair(keyPair.publicKey, keyPair.secretKey, seed)
40 return keyPair
41}
42
43function dh (publicKey, { scalar, secretKey }) {
44 // tweaked keys expose scalar directly
45 if (!scalar) {
46 assert(secretKey.byteLength === SKLEN)
47
48 // libsodium stores seed not actual scalar
49 const sk = b4a.alloc(64)
50 sodium.crypto_hash_sha512(sk, secretKey.subarray(0, 32))
51 sk[0] &= 248
52 sk[31] &= 127
53 sk[31] |= 64
54
55 scalar = sk.subarray(0, 32)
56 }
57
58 assert(scalar.byteLength === SCALARLEN)
59 assert(publicKey.byteLength === PKLEN)
60
61 const output = b4a.alloc(DHLEN)
62
63 // we clamp if necessary above
64 sodium.crypto_scalarmult_ed25519_noclamp(
65 output,
66 scalar,
67 publicKey
68 )
69
70 return output
71}
node_modules/noise-curve-ed/node_modules/sodium-native/CMakeLists.txt +279 -0
……@@ -0,0 +1,279 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6find_package(cmake-npm REQUIRED PATHS node_modules/cmake-npm)
7
8set(CMAKE_POSITION_INDEPENDENT_CODE ON)
9
10project(sodium_native C ASM CXX)
11
12fetch_package("github:jedisct1/libsodium#e18eee6" SOURCE_DIR sodium)
13
14fetch_package("github:holepunchto/libjstl#098664c")
15
16bare_target(target)
17
18if(target MATCHES "win32")
19 add_compile_options(/MT$<$<CONFIG:Debug>:d>)
20endif()
21
22file(COPY_FILE "${sodium}/builds/msvc/version.h" "${sodium}/src/libsodium/include/sodium/version.h")
23
24file(GLOB_RECURSE sodium_headers CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.h")
25file(GLOB_RECURSE sodium_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.c")
26file(GLOB_RECURSE sodium_asm_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.S")
27
28add_library(sodium OBJECT)
29
30target_sources(
31 sodium
32 INTERFACE
33 ${sodium_headers}
34 PRIVATE
35 ${sodium_sources}
36)
37
38target_include_directories(
39 sodium
40 INTERFACE
41 "${sodium}/src/libsodium/include"
42 PRIVATE
43 "${sodium}/src/libsodium/include/sodium"
44)
45
46if(NOT target MATCHES "win32")
47 target_compile_options(
48 sodium
49 PRIVATE
50 -fvisibility=hidden
51 -fno-strict-aliasing
52 -fwrapv
53 -flax-vector-conversions
54 )
55endif()
56
57target_compile_definitions(
58 sodium
59 PUBLIC
60 SODIUM_STATIC=1
61 PRIVATE
62 _GNU_SOURCE=1
63 CONFIGURED=1
64 DEV_MODE=1
65 HAVE_ATOMIC_OPS=1
66 HAVE_C11_MEMORY_FENCES=1
67 HAVE_CET_H=1
68 HAVE_GCC_MEMORY_FENCES=1
69 HAVE_INLINE_ASM=1
70 HAVE_INTTYPES_H=1
71 HAVE_STDINT_H=1
72 HAVE_TI_MODE=1
73)
74
75if(target MATCHES "darwin|ios")
76 target_compile_definitions(
77 sodium
78 PRIVATE
79 ASM_HIDE_SYMBOL=.private_extern
80 TLS=_Thread_local
81 HAVE_ARC4RANDOM=1
82 HAVE_ARC4RANDOM_BUF=1
83 HAVE_CATCHABLE_ABRT=1
84 HAVE_CATCHABLE_SEGV=1
85 HAVE_CLOCK_GETTIME=1
86 HAVE_GETPID=1
87 HAVE_MADVISE=1
88 HAVE_MEMSET_S=1
89 HAVE_MLOCK=1
90 HAVE_MMAP=1
91 HAVE_MPROTECT=1
92 HAVE_NANOSLEEP=1
93 HAVE_POSIX_MEMALIGN=1
94 HAVE_PTHREAD=1
95 HAVE_PTHREAD_PRIO_INHERIT=1
96 HAVE_RAISE=1
97 HAVE_SYSCONF=1
98 HAVE_SYS_MMAN_H=1
99 HAVE_SYS_PARAM_H=1
100 HAVE_WEAK_SYMBOLS=1
101 )
102
103 if(NOT target MATCHES "ios")
104 target_compile_definitions(
105 sodium
106 PRIVATE
107 HAVE_GETENTROPY=1
108 HAVE_SYS_RANDOM_H=1
109 )
110 endif()
111endif()
112
113if(target MATCHES "linux")
114 target_compile_definitions(
115 sodium
116 PRIVATE
117 ASM_HIDE_SYMBOL=.hidden
118 TLS=_Thread_local
119 HAVE_CATCHABLE_ABRT=1
120 HAVE_CATCHABLE_SEGV=1
121 HAVE_CLOCK_GETTIME=1
122 HAVE_GETPID=1
123 HAVE_MADVISE=1
124 HAVE_MLOCK=1
125 HAVE_MMAP=1
126 HAVE_MPROTECT=1
127 HAVE_NANOSLEEP=1
128 HAVE_POSIX_MEMALIGN=1
129 HAVE_PTHREAD_PRIO_INHERIT=1
130 HAVE_PTHREAD=1
131 HAVE_RAISE=1
132 HAVE_SYSCONF=1
133 HAVE_SYS_AUXV_H=1
134 HAVE_SYS_MMAN_H=1
135 HAVE_SYS_PARAM_H=1
136 HAVE_SYS_RANDOM_H=1
137 HAVE_WEAK_SYMBOLS=1
138 )
139endif()
140
141if(target MATCHES "win32")
142 target_compile_definitions(
143 sodium
144 PRIVATE
145 _CRT_SECURE_NO_WARNINGS=1
146 HAVE_RAISE=1
147 )
148endif()
149
150if(target MATCHES "x64")
151 target_compile_definitions(
152 sodium
153 PRIVATE
154 HAVE_CPUID=1
155 HAVE_RDRAND=1
156 HAVE_EMMINTRIN_H=1 # SSE2
157 HAVE_PMMINTRIN_H=1 # SSE3
158 HAVE_TMMINTRIN_H=1 # SSSE3
159 HAVE_SMMINTRIN_H=1 # SSE4.1
160 HAVE_WMMINTRIN_H=1 # AES
161 HAVE_AVXINTRIN_H=1 # AVX
162 HAVE_AVX2INTRIN_H=1 # AVX2
163 HAVE_AVX512FINTRIN_H # AVX512F
164 )
165
166 if(NOT target MATCHES "win32")
167 target_compile_definitions(
168 sodium
169 PRIVATE
170 HAVE_AMD64_ASM=1
171 HAVE_AVX_ASM=1
172 )
173
174 target_sources(
175 sodium
176 PRIVATE
177 ${sodium_asm_sources}
178 )
179 endif()
180endif()
181
182if(target MATCHES "arm64")
183 target_compile_definitions(
184 sodium
185 PRIVATE
186 HAVE_ARMCRYPTO=1
187 )
188endif()
189
190if(CMAKE_C_BYTE_ORDER MATCHES "BIG_ENDIAN")
191 target_compile_definitions(
192 sodium
193 PRIVATE
194 NATIVE_BIG_ENDIAN=1
195 )
196else()
197 target_compile_definitions(
198 sodium
199 PRIVATE
200 NATIVE_LITTLE_ENDIAN=1
201 )
202endif()
203
204if(target MATCHES "linux|android")
205 target_link_options(
206 sodium
207 PUBLIC
208 -Wl,-z,noexecstack
209 )
210endif()
211
212add_library(sodium_extensions OBJECT)
213
214target_sources(
215 sodium_extensions
216 PRIVATE
217 extensions/tweak/tweak.c
218 extensions/tweak/tweak.h
219 extensions/pbkdf2/pbkdf2.c
220 extensions/pbkdf2/pbkdf2.h
221)
222
223target_link_libraries(
224 sodium_extensions
225 PUBLIC
226 sodium
227)
228
229add_bare_module(sodium_native_bare)
230
231target_sources(
232 ${sodium_native_bare}
233 PRIVATE
234 binding.cc
235)
236
237target_link_libraries(
238 ${sodium_native_bare}
239 PRIVATE
240 $<TARGET_OBJECTS:sodium>
241 $<TARGET_OBJECTS:sodium_extensions>
242 jstl
243 PUBLIC
244 sodium
245 sodium_extensions
246)
247
248add_napi_module(sodium_native_node)
249
250target_sources(
251 ${sodium_native_node}
252 PRIVATE
253 binding.cc
254)
255
256target_compile_definitions(
257 ${sodium_native_node}
258 PRIVATE
259 NAPI_VERSION=9
260)
261
262target_link_libraries(
263 ${sodium_native_node}
264 PRIVATE
265 $<TARGET_OBJECTS:sodium>
266 $<TARGET_OBJECTS:sodium_extensions>
267 jstl
268 PUBLIC
269 sodium
270 sodium_extensions
271)
272
273resolve_node_module(bare-compat-napi compat)
274
275target_include_directories(
276 ${sodium_native_node}
277 PRIVATE
278 "${compat}/include"
279)
node_modules/noise-curve-ed/node_modules/sodium-native/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2016 Mathias Buus and Emil Bay
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/noise-curve-ed/node_modules/sodium-native/README.md +51 -0
……@@ -0,0 +1,51 @@
1# sodium-native
2
3Low level bindings for [libsodium](https://github.com/jedisct1/libsodium).
4
5```
6npm install sodium-native
7```
8
9The goal of this project is to be thin, stable, unopionated wrapper around libsodium.
10
11All methods exposed are more or less a direct translation of the libsodium c-api.
12This means that most data types are buffers and you have to manage allocating return values and passing them in as arguments instead of receiving them as return values.
13
14This makes this API harder to use than other libsodium wrappers out there, but also means that you'll be able to get a lot of perf / memory improvements as you can do stuff like inline encryption / decryption, reuse buffers etc.
15
16This also makes this library useful as a foundation for more high level crypto abstractions that you want to make.
17
18## Usage
19
20```js
21var sodium = require('sodium-native')
22
23var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
24var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) // secure buffer
25var message = Buffer.from('Hello, World!')
26var ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
27
28sodium.randombytes_buf(nonce) // insert random data into nonce
29sodium.randombytes_buf(key) // insert random data into key
30
31// encrypted message is stored in ciphertext.
32sodium.crypto_secretbox_easy(ciphertext, message, nonce, key)
33
34console.log('Encrypted message:', ciphertext)
35
36var plainText = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES)
37
38if (!sodium.crypto_secretbox_open_easy(plainText, ciphertext, nonce, key)) {
39 console.log('Decryption failed!')
40} else {
41 console.log('Decrypted message:', plainText, '(' + plainText.toString() + ')')
42}
43```
44
45## Documentation
46
47Complete documentation may be found on the [sodium-friends website](https://sodium-friends.github.io/docs/docs/getstarted)
48
49## License
50
51MIT
node_modules/noise-curve-ed/node_modules/sodium-native/binding.cc +4094 -0
……@@ -0,0 +1,4094 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4#include <jstl.h>
5#include <sodium.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <string.h>
9#include <uv.h>
10
11#include "extensions/pbkdf2/pbkdf2.h"
12#include "extensions/tweak/tweak.h"
13
14#define assert_bounds(arraybuffer) \
15 assert(arraybuffer##_offset + arraybuffer##_len <= arraybuffer.size())
16
17static inline void
18sn_sodium_memzero(
19 js_env_t *,
20 js_receiver_t,
21 js_typedarray_span_t<> buf
22) {
23 sodium_memzero(buf.data(), buf.size_bytes());
24}
25
26static inline int
27sn_sodium_mlock(
28 js_env_t *,
29 js_receiver_t,
30 js_typedarray_span_t<> buf
31) {
32 return sodium_mlock(buf.data(), buf.size_bytes());
33}
34
35static inline int
36sn_sodium_munlock(
37 js_env_t *,
38 js_receiver_t,
39 js_typedarray_span_t<> buf
40) {
41 return sodium_munlock(buf.data(), buf.size_bytes());
42}
43
44static void
45sn_external_arraybuffer_finalize(js_env_t *env, uint8_t *ptr) {
46 sodium_free(ptr);
47}
48
49static js_arraybuffer_t
50sn_sodium_malloc(js_env_t *env, js_receiver_t, uint32_t len) {
51 int err;
52
53 auto ptr = reinterpret_cast<uint8_t *>(sodium_malloc(len));
54
55 js_arraybuffer_t buffer;
56
57 err = js_create_external_arraybuffer<sn_external_arraybuffer_finalize>(env, ptr, len, buffer);
58 assert(err == 0);
59
60 return buffer;
61}
62
63static void
64sn_sodium_free(js_env_t *env, js_receiver_t, js_arraybuffer_t buf) {
65 int err;
66
67 std::span<uint8_t> view;
68 err = js_get_arraybuffer_info(env, buf, view);
69 assert(err == 0);
70
71 if (view.empty()) return;
72
73 err = js_detach_arraybuffer(env, buf);
74 assert(err == 0);
75}
76
77static inline int
78sn_sodium_mprotect_noaccess(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
79 return sodium_mprotect_noaccess(buf.data());
80}
81
82static inline int
83sn_sodium_mprotect_readonly(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
84 return sodium_mprotect_readonly(buf.data());
85}
86
87static inline int
88sn_sodium_mprotect_readwrite(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
89 return sodium_mprotect_readwrite(buf.data());
90}
91
92static inline uint32_t // TODO: test envless
93sn_randombytes_random(js_env_t *env, js_receiver_t) {
94 return randombytes_random();
95}
96
97static inline uint32_t // TODO: test envless
98sn_randombytes_uniform(js_env_t *env, js_receiver_t, uint32_t upper_bound) {
99 return randombytes_uniform(upper_bound);
100}
101
102static inline void
103sn_randombytes_buf(
104 js_env_t *env,
105 js_receiver_t,
106 js_arraybuffer_span_t buf,
107 uint32_t buf_offset,
108 uint32_t buf_len
109) {
110 assert_bounds(buf);
111
112 randombytes_buf(&buf[buf_offset], buf_len);
113}
114
115static inline void
116sn_randombytes_buf_deterministic(
117 js_env_t *env,
118 js_receiver_t,
119
120 js_arraybuffer_span_t buf,
121 uint32_t buf_offset,
122 uint32_t buf_len,
123
124 js_arraybuffer_span_t seed,
125 uint32_t seed_offset,
126 uint32_t seed_len
127) {
128 assert_bounds(buf);
129 assert_bounds(seed);
130
131 assert(seed_len == randombytes_SEEDBYTES);
132
133 randombytes_buf_deterministic(&buf[buf_offset], buf_len, &seed[seed_offset]);
134}
135
136static inline bool
137sn_sodium_memcmp(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
138 if (a.size_bytes() != b.size_bytes()) return false;
139
140 return sodium_memcmp(a.data(), b.data(), a.size_bytes()) == 0;
141}
142
143static inline void
144sn_sodium_increment(js_env_t *, js_receiver_t, js_typedarray_span_t<> n) {
145 sodium_increment(n.data(), n.size_bytes());
146}
147
148static inline void
149sn_sodium_add(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
150 sodium_add(a.data(), b.data(), a.size_bytes());
151}
152
153static inline void
154sn_sodium_sub(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
155 sodium_sub(a.data(), b.data(), a.size_bytes());
156}
157
158static inline int32_t
159sn_sodium_compare(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
160 return sodium_compare(a.data(), b.data(), a.size_bytes());
161}
162
163static inline bool
164sn_sodium_is_zero(js_env_t *, js_receiver_t, js_typedarray_span_t<> buffer, uint32_t len) {
165 assert(len <= buffer.size_bytes());
166
167 return sodium_is_zero(buffer.data(), len) != 0;
168}
169
170static inline uint32_t
171sn_sodium_pad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t unpadded_buflen, uint32_t blocksize) {
172 size_t padded_buflen;
173
174 sodium_pad(&padded_buflen, buf.data(), unpadded_buflen, blocksize, buf.size_bytes());
175
176 return padded_buflen;
177}
178
179static inline uint32_t
180sn_sodium_unpad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t padded_buflen, uint32_t blocksize) {
181 size_t unpadded_buflen;
182
183 sodium_unpad(&unpadded_buflen, buf.data(), padded_buflen, blocksize);
184
185 return unpadded_buflen;
186}
187
188static inline int
189sn_crypto_sign_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
190 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
191 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
192
193 return crypto_sign_keypair(pk.data(), sk.data());
194}
195
196static inline int
197sn_crypto_sign_seed_keypair(
198 js_env_t *,
199 js_receiver_t,
200 js_typedarray_span_t<> pk,
201 js_typedarray_span_t<> sk,
202 js_typedarray_span_t<> seed
203) {
204 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
205 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
206 assert(seed.size_bytes() == crypto_sign_SEEDBYTES);
207
208 return crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data());
209}
210
211static inline int
212sn_crypto_sign(
213 js_env_t *,
214 js_receiver_t,
215 js_typedarray_span_t<> sm,
216 js_typedarray_span_t<> m,
217 js_typedarray_span_t<> sk
218) {
219 assert(sm.size_bytes() == crypto_sign_BYTES + m.size_bytes());
220 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
221
222 return crypto_sign(sm.data(), NULL, m.data(), m.size_bytes(), sk.data());
223}
224
225static inline bool
226sn_crypto_sign_open(
227 js_env_t *,
228 js_receiver_t,
229 js_typedarray_span_t<> m,
230 js_typedarray_span_t<> sm,
231 js_typedarray_span_t<> pk
232) {
233 assert(m.size_bytes() == sm.size_bytes() - crypto_sign_BYTES);
234 assert(sm.size_bytes() >= crypto_sign_BYTES);
235 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
236
237 return crypto_sign_open(m.data(), NULL, sm.data(), sm.size_bytes(), pk.data()) == 0;
238}
239
240static inline int
241sn_crypto_sign_detached(
242 js_env_t *env,
243 js_receiver_t,
244 js_typedarray_span_t<> sig,
245 js_typedarray_span_t<> m,
246 js_typedarray_span_t<> sk
247) {
248 assert(sig.size_bytes() == crypto_sign_BYTES);
249 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
250
251 return crypto_sign_detached(sig.data(), NULL, m.data(), m.size_bytes(), sk.data());
252}
253
254static inline bool
255sn_crypto_sign_verify_detached(
256 js_env_t *env,
257 js_receiver_t,
258
259 js_arraybuffer_span_t sig,
260 uint32_t sig_offset,
261 uint32_t sig_len,
262
263 js_arraybuffer_span_t m,
264 uint32_t m_offset,
265 uint32_t m_len,
266
267 js_arraybuffer_span_t pk,
268 uint32_t pk_offset,
269 uint32_t pk_len
270) {
271 assert_bounds(sig);
272 assert_bounds(m);
273 assert_bounds(pk);
274
275 assert(sig_len >= crypto_sign_BYTES);
276 assert(pk_len == crypto_sign_PUBLICKEYBYTES);
277
278 return crypto_sign_verify_detached(&sig[sig_offset], &m[m_offset], m_len, &pk[pk_offset]) == 0;
279}
280
281static inline int
282sn_crypto_sign_ed25519_sk_to_pk(
283 js_env_t *,
284 js_receiver_t,
285 js_typedarray_span_t<> pk,
286 js_typedarray_span_t<> sk
287) {
288 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
289 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
290
291 return crypto_sign_ed25519_sk_to_pk(pk.data(), sk.data());
292}
293
294static inline int
295sn_crypto_sign_ed25519_pk_to_curve25519(
296 js_env_t *,
297 js_receiver_t,
298 js_typedarray_span_t<> x25519_pk,
299 js_typedarray_span_t<> ed25519_pk
300) {
301 assert(x25519_pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
302 assert(ed25519_pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
303
304 return crypto_sign_ed25519_pk_to_curve25519(x25519_pk.data(), ed25519_pk.data());
305}
306
307static inline int
308sn_crypto_sign_ed25519_sk_to_curve25519(
309 js_env_t *,
310 js_receiver_t,
311 js_typedarray_span_t<> x25519_sk,
312 js_typedarray_span_t<> ed25519_sk
313) {
314 assert(x25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES);
315 assert(
316 ed25519_sk.size_bytes() == crypto_sign_SECRETKEYBYTES ||
317 ed25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES
318 );
319
320 return crypto_sign_ed25519_sk_to_curve25519(x25519_sk.data(), ed25519_sk.data());
321}
322
323static inline int
324sn_crypto_generichash(
325 js_env_t *env,
326 js_receiver_t,
327
328 js_arraybuffer_span_t out,
329 uint32_t out_offset,
330 uint32_t out_len,
331
332 js_arraybuffer_span_t in,
333 uint32_t in_offset,
334 uint32_t in_len,
335
336 js_arraybuffer_span_t key,
337 uint32_t key_offset,
338 uint32_t key_len
339) {
340 assert_bounds(out);
341 assert(
342 out_len >= crypto_generichash_BYTES_MIN &&
343 out_len <= crypto_generichash_BYTES_MAX
344 );
345
346 assert_bounds(in);
347
348 uint8_t *key_data = NULL;
349 if (key_len) {
350 assert_bounds(key);
351 assert(
352 key_len >= crypto_generichash_KEYBYTES_MIN &&
353 key_len <= crypto_generichash_KEYBYTES_MAX
354 );
355 key_data = &key[key_offset];
356 }
357
358 return crypto_generichash(&out[out_offset], out_len, &in[in_offset], in_len, key_data, key_len);
359}
360
361static inline int
362sn_crypto_generichash_batch(
363 js_env_t *env,
364 js_receiver_t,
365 js_typedarray_t<uint8_t> out,
366 std::vector<js_typedarray_span_t<>> batch,
367 bool use_key,
368 js_typedarray_t<uint8_t> key
369) {
370 int err;
371
372 uint8_t *out_data;
373 size_t out_len;
374 err = js_get_typedarray_info(env, out, out_data, out_len);
375 assert(err == 0);
376 assert(
377 out_len >= crypto_generichash_BYTES_MIN &&
378 out_len <= crypto_generichash_BYTES_MAX
379 );
380
381 uint8_t *key_data = NULL;
382 size_t key_len = 0;
383 if (use_key) {
384 err = js_get_typedarray_info(env, key, key_data, key_len);
385 assert(err == 0);
386 assert(
387 key_len >= crypto_generichash_KEYBYTES_MIN &&
388 key_len <= crypto_generichash_KEYBYTES_MAX
389 );
390 }
391
392 crypto_generichash_state state;
393 err = crypto_generichash_init(&state, key_data, key_len, out_len);
394 if (err != 0) return err;
395
396 for (auto &buf : batch) {
397 err = crypto_generichash_update(&state, buf.data(), buf.size());
398 if (err != 0) return err;
399 }
400
401 return crypto_generichash_final(&state, out_data, out_len);
402}
403
404static inline void
405sn_crypto_generichash_keygen(
406 js_env_t *env,
407 js_receiver_t,
408
409 js_arraybuffer_span_t key,
410 uint32_t key_offset,
411 uint32_t key_len
412) {
413 assert_bounds(key);
414 assert(key_len == crypto_generichash_KEYBYTES);
415
416 crypto_generichash_keygen(&key[key_offset]);
417}
418
419static inline int
420sn_crypto_generichash_init(
421 js_env_t *env,
422 js_receiver_t,
423
424 js_arraybuffer_span_t state,
425 uint32_t state_offset,
426 uint32_t state_len,
427
428 js_arraybuffer_span_t key,
429 uint32_t key_offset,
430 uint32_t key_len,
431
432 uint32_t out_len
433) {
434 assert_bounds(state);
435
436 assert(state_len == sizeof(crypto_generichash_state));
437
438 uint8_t *key_data = NULL;
439 if (key_len) {
440 assert_bounds(key);
441 assert(
442 key_len >= crypto_generichash_KEYBYTES_MIN &&
443 key_len <= crypto_generichash_KEYBYTES_MAX
444 );
445 key_data = &key[key_offset];
446 }
447
448 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
449
450 return crypto_generichash_init(state_data, key_data, key_len, out_len);
451}
452
453static inline int
454sn_crypto_generichash_update(
455 js_env_t *env,
456 js_receiver_t,
457
458 js_arraybuffer_span_t state,
459 uint32_t state_offset,
460 uint32_t state_len,
461
462 js_arraybuffer_span_t in,
463 uint32_t in_offset,
464 uint32_t in_len
465) {
466 assert_bounds(state);
467 assert_bounds(in);
468
469 assert(state_len == sizeof(crypto_generichash_state));
470
471 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
472
473 return crypto_generichash_update(state_data, &in[in_offset], in_len);
474}
475
476static inline int
477sn_crypto_generichash_final(
478 js_env_t *env,
479 js_receiver_t,
480
481 js_arraybuffer_span_t state,
482 uint32_t state_offset,
483 uint32_t state_len,
484
485 js_arraybuffer_span_t out,
486 uint32_t out_offset,
487 uint32_t out_len
488) {
489 assert_bounds(state);
490 assert_bounds(out);
491
492 assert(state_len == sizeof(crypto_generichash_state));
493
494 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
495
496 return crypto_generichash_final(state_data, &out[out_offset], out_len);
497}
498
499static inline int
500sn_crypto_box_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
501 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
502 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
503
504 return crypto_box_keypair(pk.data(), sk.data());
505}
506
507static inline int
508sn_crypto_box_seed_keypair(
509 js_env_t *,
510 js_receiver_t,
511 js_typedarray_span_t<> pk,
512 js_typedarray_span_t<> sk,
513 js_typedarray_span_t<> seed
514) {
515 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
516 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
517 assert(seed.size_bytes() == crypto_box_SEEDBYTES);
518
519 return crypto_box_seed_keypair(pk.data(), sk.data(), seed.data());
520}
521
522static inline int
523sn_crypto_box_easy(
524 js_env_t *,
525 js_receiver_t,
526 js_typedarray_span_t<> c,
527 js_typedarray_span_t<> m,
528 js_typedarray_span_t<> n,
529 js_typedarray_span_t<> pk,
530 js_typedarray_span_t<> sk
531) {
532 assert(c.size_bytes() == m.size_bytes() + crypto_box_MACBYTES);
533 assert(n.size_bytes() == crypto_box_NONCEBYTES);
534 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
535 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
536
537 return crypto_box_easy(c.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
538}
539
540static inline bool
541sn_crypto_box_open_easy(
542 js_env_t *,
543 js_receiver_t,
544 js_typedarray_span_t<> m,
545 js_typedarray_span_t<> c,
546 js_typedarray_span_t<> n,
547 js_typedarray_span_t<> pk,
548 js_typedarray_span_t<> sk
549) {
550 assert(c.size_bytes() >= crypto_box_MACBYTES);
551 assert(m.size_bytes() == c.size_bytes() - crypto_box_MACBYTES);
552 assert(n.size_bytes() == crypto_box_NONCEBYTES);
553 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
554 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
555
556 return crypto_box_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
557}
558
559static inline int
560sn_crypto_box_detached(
561 js_env_t *,
562 js_receiver_t,
563 js_typedarray_span_t<> c,
564 js_typedarray_span_t<> mac,
565 js_typedarray_span_t<> m,
566 js_typedarray_span_t<> n,
567 js_typedarray_span_t<> pk,
568 js_typedarray_span_t<> sk
569) {
570 assert(c.size_bytes() == m.size_bytes());
571 assert(mac.size_bytes() == crypto_box_MACBYTES);
572 assert(n.size_bytes() == crypto_box_NONCEBYTES);
573 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
574 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
575
576 return crypto_box_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
577}
578
579static inline bool
580sn_crypto_box_open_detached(
581 js_env_t *,
582 js_receiver_t,
583 js_typedarray_span_t<> m,
584 js_typedarray_span_t<> c,
585 js_typedarray_span_t<> mac,
586 js_typedarray_span_t<> n,
587 js_typedarray_span_t<> pk,
588 js_typedarray_span_t<> sk
589) {
590 assert(m.size_bytes() == c.size_bytes());
591 assert(mac.size_bytes() == crypto_box_MACBYTES);
592 assert(n.size_bytes() == crypto_box_NONCEBYTES);
593 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
594 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
595
596 return crypto_box_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
597}
598
599static inline int
600sn_crypto_box_seal(
601 js_env_t *,
602 js_receiver_t,
603 js_typedarray_span_t<> c,
604 js_typedarray_span_t<> m,
605 js_typedarray_span_t<> pk
606) {
607 assert(c.size_bytes() == m.size_bytes() + crypto_box_SEALBYTES);
608 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
609
610 return crypto_box_seal(c.data(), m.data(), m.size_bytes(), pk.data());
611}
612
613static inline bool
614sn_crypto_box_seal_open(
615 js_env_t *env,
616 js_receiver_t,
617
618 js_arraybuffer_span_t m,
619 uint32_t m_offset,
620 uint32_t m_len,
621
622 js_arraybuffer_span_t c,
623 uint32_t c_offset,
624 uint32_t c_len,
625
626 js_arraybuffer_span_t pk,
627 uint32_t pk_offset,
628 uint32_t pk_len,
629
630 js_arraybuffer_span_t sk,
631 uint32_t sk_offset,
632 uint32_t sk_len
633) {
634 assert_bounds(m);
635 assert_bounds(c);
636 assert_bounds(pk);
637 assert_bounds(sk);
638
639 assert(m_len == c_len - crypto_box_SEALBYTES);
640 assert(c_len >= crypto_box_SEALBYTES);
641 assert(sk_len == crypto_box_SECRETKEYBYTES);
642 assert(pk_len == crypto_box_PUBLICKEYBYTES);
643
644 return crypto_box_seal_open(&m[m_offset], &c[c_offset], c_len, &pk[pk_offset], &sk[sk_offset]) == 0;
645}
646
647static inline int
648sn_crypto_secretbox_easy(
649 js_env_t *,
650 js_receiver_t,
651 js_typedarray_span_t<> c,
652 js_typedarray_span_t<> m,
653 js_typedarray_span_t<> n,
654 js_typedarray_span_t<> k
655) {
656 assert(c.size_bytes() == m.size_bytes() + crypto_secretbox_MACBYTES);
657 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
658 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
659
660 return crypto_secretbox_easy(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
661}
662
663static inline bool
664sn_crypto_secretbox_open_easy(
665 js_env_t *,
666 js_receiver_t,
667 js_typedarray_span_t<> m,
668 js_typedarray_span_t<> c,
669 js_typedarray_span_t<> n,
670 js_typedarray_span_t<> k
671) {
672 assert(m.size_bytes() == c.size_bytes() - crypto_secretbox_MACBYTES);
673 assert(c.size_bytes() >= crypto_secretbox_MACBYTES);
674 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
675 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
676
677 return crypto_secretbox_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), k.data()) == 0;
678}
679
680static inline int
681sn_crypto_secretbox_detached(
682 js_env_t *,
683 js_receiver_t,
684 js_typedarray_span_t<> c,
685 js_typedarray_span_t<> mac,
686 js_typedarray_span_t<> m,
687 js_typedarray_span_t<> n,
688 js_typedarray_span_t<> k
689) {
690 assert(c.size_bytes() == m.size_bytes());
691 assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
692 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
693 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
694
695 return crypto_secretbox_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), k.data());
696}
697
698static inline bool
699sn_crypto_secretbox_open_detached(
700 js_env_t *,
701 js_receiver_t,
702 js_typedarray_span_t<> m,
703 js_typedarray_span_t<> c,
704 js_typedarray_span_t<> mac,
705 js_typedarray_span_t<> n,
706 js_typedarray_span_t<> k
707) {
708 assert(m.size_bytes() == c.size_bytes());
709 assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
710 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
711 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
712
713 return crypto_secretbox_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), k.data()) == 0;
714}
715
716static inline int
717sn_crypto_stream(
718 js_env_t *,
719 js_receiver_t,
720 js_typedarray_span_t<> c,
721 js_typedarray_span_t<> n,
722 js_typedarray_span_t<> k
723) {
724 assert(n.size_bytes() == crypto_stream_NONCEBYTES);
725 assert(k.size_bytes() == crypto_stream_KEYBYTES);
726
727 return crypto_stream(c.data(), c.size_bytes(), n.data(), k.data());
728}
729
730static inline int
731sn_crypto_stream_xor(
732 js_env_t *env,
733 js_receiver_t,
734
735 js_arraybuffer_span_t c,
736 uint32_t c_offset,
737 uint32_t c_len,
738
739 js_arraybuffer_span_t m,
740 uint32_t m_offset,
741 uint32_t m_len,
742
743 js_arraybuffer_span_t n,
744 uint32_t n_offset,
745 uint32_t n_len,
746
747 js_arraybuffer_span_t k,
748 uint32_t k_offset,
749 uint32_t k_len
750) {
751 assert_bounds(c);
752 assert_bounds(m);
753 assert_bounds(n);
754 assert_bounds(k);
755
756 assert(c_len == m_len);
757 assert(n_len == crypto_stream_NONCEBYTES);
758 assert(k_len == crypto_stream_KEYBYTES);
759
760 return crypto_stream_xor(&c[c_offset], &m[m_offset], m_len, &n[n_offset], &k[k_offset]);
761}
762
763static inline int
764sn_crypto_stream_chacha20(
765 js_env_t *,
766 js_receiver_t,
767 js_typedarray_span_t<> c,
768 js_typedarray_span_t<> n,
769 js_typedarray_span_t<> k
770) {
771 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
772 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
773
774 return crypto_stream_chacha20(c.data(), c.size_bytes(), n.data(), k.data());
775}
776
777static inline int
778sn_crypto_stream_chacha20_xor(
779 js_env_t *,
780 js_receiver_t,
781 js_typedarray_span_t<> c,
782 js_typedarray_span_t<> m,
783 js_typedarray_span_t<> n,
784 js_typedarray_span_t<> k
785) {
786 assert(c.size_bytes() == m.size_bytes());
787 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
788 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
789
790 return crypto_stream_chacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
791}
792
793static inline int
794sn_crypto_stream_chacha20_xor_ic(
795 js_env_t *,
796 js_receiver_t,
797 js_typedarray_span_t<> c,
798 js_typedarray_span_t<> m,
799 js_typedarray_span_t<> n,
800 uint32_t ic,
801 js_typedarray_span_t<> k
802) {
803 assert(c.size_bytes() == m.size_bytes());
804 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
805 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
806
807 return crypto_stream_chacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
808}
809
810static inline int
811sn_crypto_stream_chacha20_ietf(
812 js_env_t *,
813 js_receiver_t,
814 js_typedarray_span_t<> c,
815 js_typedarray_span_t<> n,
816 js_typedarray_span_t<> k
817) {
818 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
819 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
820
821 return crypto_stream_chacha20_ietf(c.data(), c.size_bytes(), n.data(), k.data());
822}
823
824static inline int
825sn_crypto_stream_chacha20_ietf_xor(
826 js_env_t *,
827 js_receiver_t,
828 js_typedarray_span_t<> c,
829 js_typedarray_span_t<> m,
830 js_typedarray_span_t<> n,
831 js_typedarray_span_t<> k
832) {
833 assert(c.size_bytes() == m.size_bytes());
834 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
835 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
836
837 return crypto_stream_chacha20_ietf_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
838}
839
840static inline int
841sn_crypto_stream_chacha20_ietf_xor_ic(
842 js_env_t *,
843 js_receiver_t,
844 js_typedarray_span_t<> c,
845 js_typedarray_span_t<> m,
846 js_typedarray_span_t<> n,
847 uint32_t ic,
848 js_typedarray_span_t<> k
849) {
850 assert(c.size_bytes() == m.size_bytes());
851 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
852 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
853
854 return crypto_stream_chacha20_ietf_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
855}
856
857static inline int
858sn_crypto_stream_xchacha20(
859 js_env_t *,
860 js_receiver_t,
861 js_typedarray_span_t<> c,
862 js_typedarray_span_t<> n,
863 js_typedarray_span_t<> k
864) {
865 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
866 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
867
868 return crypto_stream_xchacha20(c.data(), c.size_bytes(), n.data(), k.data());
869}
870
871static inline int
872sn_crypto_stream_xchacha20_xor(
873 js_env_t *,
874 js_receiver_t,
875 js_typedarray_span_t<> c,
876 js_typedarray_span_t<> m,
877 js_typedarray_span_t<> n,
878 js_typedarray_span_t<> k
879) {
880 assert(c.size_bytes() == m.size_bytes());
881 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
882 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
883
884 return crypto_stream_xchacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
885}
886
887static inline int
888sn_crypto_stream_xchacha20_xor_ic(
889 js_env_t *,
890 js_receiver_t,
891 js_typedarray_span_t<> c,
892 js_typedarray_span_t<> m,
893 js_typedarray_span_t<> n,
894 uint32_t ic,
895 js_typedarray_span_t<> k
896) {
897 assert(c.size_bytes() == m.size_bytes());
898 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
899 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
900
901 return crypto_stream_xchacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
902}
903
904static inline int
905sn_crypto_stream_salsa20(
906 js_env_t *,
907 js_receiver_t,
908 js_typedarray_span_t<> c,
909 js_typedarray_span_t<> n,
910 js_typedarray_span_t<> k
911) {
912 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
913 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
914
915 return crypto_stream_salsa20(c.data(), c.size_bytes(), n.data(), k.data());
916}
917
918static inline int
919sn_crypto_stream_salsa20_xor(
920 js_env_t *,
921 js_receiver_t,
922 js_typedarray_span_t<> c,
923 js_typedarray_span_t<> m,
924 js_typedarray_span_t<> n,
925 js_typedarray_span_t<> k
926) {
927 assert(c.size_bytes() == m.size_bytes());
928 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
929 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
930
931 return crypto_stream_salsa20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
932}
933
934static inline int
935sn_crypto_stream_salsa20_xor_ic(
936 js_env_t *,
937 js_receiver_t,
938 js_typedarray_span_t<> c,
939 js_typedarray_span_t<> m,
940 js_typedarray_span_t<> n,
941 uint32_t ic,
942 js_typedarray_span_t<> k
943) {
944 assert(c.size_bytes() == m.size_bytes());
945 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
946 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
947
948 return crypto_stream_salsa20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
949}
950
951static inline int
952sn_crypto_auth(
953 js_env_t *,
954 js_receiver_t,
955 js_typedarray_span_t<> out,
956 js_typedarray_span_t<> in,
957 js_typedarray_span_t<> k
958) {
959 assert(out.size_bytes() == crypto_auth_BYTES);
960 assert(k.size_bytes() == crypto_auth_KEYBYTES);
961
962 return crypto_auth(out.data(), in.data(), in.size_bytes(), k.data());
963}
964
965static inline bool
966sn_crypto_auth_verify(
967 js_env_t *,
968 js_receiver_t,
969 js_typedarray_span_t<> h,
970 js_typedarray_span_t<> in,
971 js_typedarray_span_t<> k
972) {
973 assert(h.size_bytes() == crypto_auth_BYTES);
974 assert(k.size_bytes() == crypto_auth_KEYBYTES);
975
976 return crypto_auth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
977}
978
979static inline int
980sn_crypto_onetimeauth(
981 js_env_t *,
982 js_receiver_t,
983 js_typedarray_span_t<> out,
984 js_typedarray_span_t<> in,
985 js_typedarray_span_t<> k
986) {
987 assert(out.size_bytes() == crypto_onetimeauth_BYTES);
988 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
989
990 return crypto_onetimeauth(out.data(), in.data(), in.size_bytes(), k.data());
991}
992
993static inline int
994sn_crypto_onetimeauth_init(
995 js_env_t *,
996 js_receiver_t,
997 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
998 js_typedarray_span_t<> k
999) {
1000 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
1001
1002 return crypto_onetimeauth_init(&*state, k.data());
1003}
1004
1005static inline int
1006sn_crypto_onetimeauth_update(
1007 js_env_t *,
1008 js_receiver_t,
1009 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
1010 js_typedarray_span_t<> in
1011) {
1012 return crypto_onetimeauth_update(&*state, in.data(), in.size_bytes());
1013}
1014
1015static inline int
1016sn_crypto_onetimeauth_final(
1017 js_env_t *,
1018 js_receiver_t,
1019 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
1020 js_typedarray_span_t<> out
1021) {
1022 assert(out.size_bytes() == crypto_onetimeauth_BYTES);
1023
1024 return crypto_onetimeauth_final(&*state, out.data());
1025}
1026
1027static inline bool
1028sn_crypto_onetimeauth_verify(
1029 js_env_t *,
1030 js_receiver_t,
1031 js_typedarray_span_t<> h,
1032 js_typedarray_span_t<> in,
1033 js_typedarray_span_t<> k
1034) {
1035 assert(h.size_bytes() == crypto_onetimeauth_BYTES);
1036 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
1037
1038 return crypto_onetimeauth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
1039}
1040
1041// CHECK: memlimit can be >32bit
1042static inline int
1043sn_crypto_pwhash(
1044 js_env_t *,
1045 js_receiver_t,
1046 js_typedarray_span_t<> out,
1047 js_typedarray_span_of_t<char> passwd,
1048 js_typedarray_span_t<> salt,
1049 uint64_t opslimit,
1050 uint64_t memlimit,
1051 int32_t alg
1052) {
1053 assert(out.size_bytes() >= crypto_pwhash_BYTES_MIN);
1054 assert(out.size_bytes() <= crypto_pwhash_BYTES_MAX);
1055 assert(salt.size_bytes() == crypto_pwhash_SALTBYTES);
1056 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1057 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1058 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1059 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1060 assert(alg == 1 || alg == 2); // Argon2i or Argon2id
1061
1062 return crypto_pwhash(
1063 out.data(),
1064 out.size_bytes(),
1065 passwd.data(),
1066 passwd.size_bytes(),
1067 salt.data(),
1068 opslimit,
1069 memlimit,
1070 alg
1071 );
1072}
1073
1074static inline int
1075sn_crypto_pwhash_str(
1076 js_env_t *,
1077 js_receiver_t,
1078 js_typedarray_span_of_t<char> out,
1079 js_typedarray_span_of_t<char> passwd,
1080 uint64_t opslimit,
1081 uint64_t memlimit
1082) {
1083 assert(out.size_bytes() == crypto_pwhash_STRBYTES);
1084 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1085 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1086 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1087 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1088
1089 return crypto_pwhash_str(
1090 out.data(),
1091 passwd.data(),
1092 passwd.size_bytes(),
1093 opslimit,
1094 memlimit
1095 );
1096}
1097
1098static inline bool
1099sn_crypto_pwhash_str_verify(
1100 js_env_t *,
1101 js_receiver_t,
1102 js_typedarray_span_of_t<char> str,
1103 js_typedarray_span_of_t<char> passwd
1104) {
1105 assert(str.size_bytes() == crypto_pwhash_STRBYTES);
1106
1107 return crypto_pwhash_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
1108}
1109
1110// CHECK: returns 1, 0, -1
1111static inline bool
1112sn_crypto_pwhash_str_needs_rehash(
1113 js_env_t *,
1114 js_receiver_t,
1115 js_typedarray_span_of_t<char> str,
1116 uint64_t opslimit,
1117 uint64_t memlimit
1118) {
1119 assert(str.size_bytes() == crypto_pwhash_STRBYTES);
1120 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1121 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1122 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1123 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1124
1125 return crypto_pwhash_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
1126}
1127
1128// CHECK: memlimit can be >32bit
1129static inline int
1130sn_crypto_pwhash_scryptsalsa208sha256(
1131 js_env_t *,
1132 js_receiver_t,
1133 js_typedarray_span_t<> out,
1134 js_typedarray_span_of_t<char> passwd,
1135 js_typedarray_span_t<> salt,
1136 uint64_t opslimit,
1137 uint64_t memlimit
1138) {
1139 assert(out.size_bytes() >= crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
1140 assert(out.size_bytes() <= crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
1141 assert(salt.size_bytes() == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
1142 assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
1143 assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
1144 assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
1145 assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
1146
1147 return crypto_pwhash_scryptsalsa208sha256(
1148 out.data(),
1149 out.size_bytes(),
1150 passwd.data(),
1151 passwd.size_bytes(),
1152 salt.data(),
1153 opslimit,
1154 memlimit
1155 );
1156}
1157
1158static inline int
1159sn_crypto_pwhash_scryptsalsa208sha256_str(
1160 js_env_t *,
1161 js_receiver_t,
1162 js_typedarray_span_of_t<char> out,
1163 js_typedarray_span_of_t<char> passwd,
1164 uint64_t opslimit,
1165 uint64_t memlimit
1166) {
1167 assert(out.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1168 assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
1169 assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
1170 assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
1171 assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
1172
1173 return crypto_pwhash_scryptsalsa208sha256_str(
1174 out.data(),
1175 passwd.data(),
1176 passwd.size_bytes(),
1177 opslimit,
1178 memlimit
1179 );
1180}
1181
1182static inline bool
1183sn_crypto_pwhash_scryptsalsa208sha256_str_verify(
1184 js_env_t *,
1185 js_receiver_t,
1186 js_typedarray_span_of_t<char> str,
1187 js_typedarray_span_of_t<char> passwd
1188) {
1189 assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1190
1191 return crypto_pwhash_scryptsalsa208sha256_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
1192}
1193
1194static inline bool
1195sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
1196 js_env_t *,
1197 js_receiver_t,
1198 js_typedarray_span_of_t<char> str,
1199 uint64_t opslimit,
1200 uint64_t memlimit
1201) {
1202 assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1203 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1204 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1205 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1206 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1207
1208 return crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
1209}
1210
1211static inline int
1212sn_crypto_kx_keypair(
1213 js_env_t *,
1214 js_receiver_t,
1215 js_typedarray_span_t<> pk,
1216 js_typedarray_span_t<> sk
1217) {
1218 assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1219 assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1220
1221 return crypto_kx_keypair(pk.data(), sk.data());
1222}
1223
1224static inline int
1225sn_crypto_kx_seed_keypair(
1226 js_env_t *,
1227 js_receiver_t,
1228 js_typedarray_span_t<> pk,
1229 js_typedarray_span_t<> sk,
1230 js_typedarray_span_t<> seed
1231) {
1232 assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1233 assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1234 assert(seed.size_bytes() == crypto_kx_SEEDBYTES);
1235
1236 return crypto_kx_seed_keypair(pk.data(), sk.data(), seed.data());
1237}
1238
1239static inline int
1240sn_crypto_kx_client_session_keys(
1241 js_env_t *,
1242 js_receiver_t,
1243 std::optional<js_typedarray_span_t<>> rx,
1244 std::optional<js_typedarray_span_t<>> tx,
1245 js_typedarray_span_t<> client_pk,
1246 js_typedarray_span_t<> client_sk,
1247 js_typedarray_span_t<> server_pk
1248) {
1249 assert(rx.has_value() || tx.has_value());
1250
1251 if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1252 if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1253
1254 assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1255 assert(client_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1256 assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1257
1258 return crypto_kx_client_session_keys(
1259 rx ? rx->data() : nullptr,
1260 tx ? tx->data() : nullptr,
1261 client_pk.data(),
1262 client_sk.data(),
1263 server_pk.data()
1264 );
1265}
1266
1267static inline int
1268sn_crypto_kx_server_session_keys(
1269 js_env_t *,
1270 js_receiver_t,
1271 std::optional<js_typedarray_span_t<>> rx,
1272 std::optional<js_typedarray_span_t<>> tx,
1273 js_typedarray_span_t<> server_pk,
1274 js_typedarray_span_t<> server_sk,
1275 js_typedarray_span_t<> client_pk
1276) {
1277 assert(rx.has_value() || tx.has_value());
1278
1279 if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1280 if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1281
1282 assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1283 assert(server_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1284 assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1285
1286 return crypto_kx_server_session_keys(
1287 rx ? rx->data() : nullptr,
1288 tx ? tx->data() : nullptr,
1289 server_pk.data(),
1290 server_sk.data(),
1291 client_pk.data()
1292 );
1293}
1294
1295static inline int
1296sn_crypto_scalarmult_base(
1297 js_env_t *,
1298 js_receiver_t,
1299 js_typedarray_span_t<> q,
1300 js_typedarray_span_t<> n
1301) {
1302 assert(q.size_bytes() == crypto_scalarmult_BYTES);
1303 assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
1304
1305 return crypto_scalarmult_base(q.data(), n.data());
1306}
1307
1308static inline int
1309sn_crypto_scalarmult(
1310 js_env_t *,
1311 js_receiver_t,
1312 js_typedarray_span_t<> q,
1313 js_typedarray_span_t<> n,
1314 js_typedarray_span_t<> p
1315) {
1316 assert(q.size_bytes() == crypto_scalarmult_BYTES);
1317 assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
1318 assert(p.size_bytes() == crypto_scalarmult_BYTES);
1319
1320 return crypto_scalarmult(q.data(), n.data(), p.data());
1321}
1322
1323static inline int
1324sn_crypto_scalarmult_ed25519_base(
1325 js_env_t *,
1326 js_receiver_t,
1327 js_typedarray_span_t<> q,
1328 js_typedarray_span_t<> n
1329) {
1330 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1331 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1332
1333 return crypto_scalarmult_ed25519_base(q.data(), n.data());
1334}
1335
1336static inline int
1337sn_crypto_scalarmult_ed25519(
1338 js_env_t *,
1339 js_receiver_t,
1340 js_typedarray_span_t<> q,
1341 js_typedarray_span_t<> n,
1342 js_typedarray_span_t<> p
1343) {
1344 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1345 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1346 assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1347
1348 return crypto_scalarmult_ed25519(q.data(), n.data(), p.data());
1349}
1350
1351static inline bool
1352sn_crypto_core_ed25519_is_valid_point(
1353 js_env_t *,
1354 js_receiver_t,
1355 js_typedarray_span_t<> p
1356) {
1357 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1358
1359 return crypto_core_ed25519_is_valid_point(p.data()) != 0;
1360}
1361
1362static inline int
1363sn_crypto_core_ed25519_from_uniform(
1364 js_env_t *,
1365 js_receiver_t,
1366 js_typedarray_span_t<> p,
1367 js_typedarray_span_t<> r
1368) {
1369 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1370 assert(r.size_bytes() == crypto_core_ed25519_UNIFORMBYTES);
1371
1372 return crypto_core_ed25519_from_uniform(p.data(), r.data());
1373}
1374
1375static inline int
1376sn_crypto_scalarmult_ed25519_base_noclamp(
1377 js_env_t *,
1378 js_receiver_t,
1379 js_typedarray_span_t<> q,
1380 js_typedarray_span_t<> n
1381) {
1382 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1383 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1384
1385 return crypto_scalarmult_ed25519_base_noclamp(q.data(), n.data());
1386}
1387
1388static inline int
1389sn_crypto_scalarmult_ed25519_noclamp(
1390 js_env_t *,
1391 js_receiver_t,
1392 js_typedarray_span_t<> q,
1393 js_typedarray_span_t<> n,
1394 js_typedarray_span_t<> p
1395) {
1396 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1397 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1398 assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1399
1400 return crypto_scalarmult_ed25519_noclamp(q.data(), n.data(), p.data());
1401}
1402
1403static inline int
1404sn_crypto_core_ed25519_add(
1405 js_env_t *,
1406 js_receiver_t,
1407 js_typedarray_span_t<> r,
1408 js_typedarray_span_t<> p,
1409 js_typedarray_span_t<> q
1410) {
1411 assert(r.size_bytes() == crypto_core_ed25519_BYTES);
1412 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1413 assert(q.size_bytes() == crypto_core_ed25519_BYTES);
1414
1415 return crypto_core_ed25519_add(r.data(), p.data(), q.data());
1416}
1417
1418static inline int
1419sn_crypto_core_ed25519_sub(
1420 js_env_t *,
1421 js_receiver_t,
1422 js_typedarray_span_t<> r,
1423 js_typedarray_span_t<> p,
1424 js_typedarray_span_t<> q
1425) {
1426 assert(r.size_bytes() == crypto_core_ed25519_BYTES);
1427 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1428 assert(q.size_bytes() == crypto_core_ed25519_BYTES);
1429
1430 return crypto_core_ed25519_sub(r.data(), p.data(), q.data());
1431}
1432
1433static inline void
1434sn_crypto_core_ed25519_scalar_random(
1435 js_env_t *,
1436 js_receiver_t,
1437 js_typedarray_span_t<> r
1438) {
1439 assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1440
1441 crypto_core_ed25519_scalar_random(r.data());
1442}
1443
1444static inline void
1445sn_crypto_core_ed25519_scalar_reduce(
1446 js_env_t *,
1447 js_receiver_t,
1448 js_typedarray_span_t<> r,
1449 js_typedarray_span_t<> s
1450) {
1451 assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1452 assert(s.size_bytes() == crypto_core_ed25519_NONREDUCEDSCALARBYTES);
1453
1454 crypto_core_ed25519_scalar_reduce(r.data(), s.data());
1455}
1456
1457static inline void
1458sn_crypto_core_ed25519_scalar_invert(
1459 js_env_t *,
1460 js_receiver_t,
1461 js_typedarray_span_t<> recip,
1462 js_typedarray_span_t<> s
1463) {
1464 assert(recip.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1465 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1466
1467 crypto_core_ed25519_scalar_invert(recip.data(), s.data());
1468}
1469
1470static inline void
1471sn_crypto_core_ed25519_scalar_negate(
1472 js_env_t *,
1473 js_receiver_t,
1474 js_typedarray_span_t<> neg,
1475 js_typedarray_span_t<> s
1476) {
1477 assert(neg.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1478 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1479
1480 crypto_core_ed25519_scalar_negate(neg.data(), s.data());
1481}
1482
1483static inline void
1484sn_crypto_core_ed25519_scalar_complement(
1485 js_env_t *,
1486 js_receiver_t,
1487 js_typedarray_span_t<> comp,
1488 js_typedarray_span_t<> s
1489) {
1490 assert(comp.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1491 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1492
1493 crypto_core_ed25519_scalar_complement(comp.data(), s.data());
1494}
1495
1496static inline void
1497sn_crypto_core_ed25519_scalar_add(
1498 js_env_t *,
1499 js_receiver_t,
1500 js_typedarray_span_t<> z,
1501 js_typedarray_span_t<> x,
1502 js_typedarray_span_t<> y
1503) {
1504 assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1505 assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1506 assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1507
1508 crypto_core_ed25519_scalar_add(z.data(), x.data(), y.data());
1509}
1510
1511static inline void
1512sn_crypto_core_ed25519_scalar_sub(
1513 js_env_t *,
1514 js_receiver_t,
1515 js_typedarray_span_t<> z,
1516 js_typedarray_span_t<> x,
1517 js_typedarray_span_t<> y
1518) {
1519 assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1520 assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1521 assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1522
1523 crypto_core_ed25519_scalar_sub(z.data(), x.data(), y.data());
1524}
1525
1526static inline int
1527sn_crypto_shorthash(
1528 js_env_t *,
1529 js_receiver_t,
1530 js_typedarray_span_t<> out,
1531 js_typedarray_span_t<> in,
1532 js_typedarray_span_t<> k
1533) {
1534 assert(out.size_bytes() == crypto_shorthash_BYTES);
1535 assert(k.size_bytes() == crypto_shorthash_KEYBYTES);
1536
1537 return crypto_shorthash(out.data(), in.data(), in.size_bytes(), k.data());
1538}
1539
1540static inline void
1541sn_crypto_kdf_keygen(
1542 js_env_t *,
1543 js_receiver_t,
1544 js_typedarray_span_t<> key
1545) {
1546 assert(key.size_bytes() == crypto_kdf_KEYBYTES);
1547
1548 crypto_kdf_keygen(key.data());
1549}
1550
1551static inline int
1552sn_crypto_kdf_derive_from_key(
1553 js_env_t *,
1554 js_receiver_t,
1555 js_typedarray_span_t<> subkey,
1556 uint64_t subkey_id,
1557 js_typedarray_span_of_t<char> ctx,
1558 js_typedarray_span_t<> key
1559) {
1560 assert(subkey.size_bytes() >= crypto_kdf_BYTES_MIN);
1561 assert(subkey.size_bytes() <= crypto_kdf_BYTES_MAX);
1562 assert(ctx.size_bytes() == crypto_kdf_CONTEXTBYTES);
1563 assert(key.size_bytes() == crypto_kdf_KEYBYTES);
1564
1565 return crypto_kdf_derive_from_key(
1566 subkey.data(),
1567 subkey.size_bytes(),
1568 subkey_id,
1569 ctx.data(),
1570 key.data()
1571 );
1572}
1573
1574static inline int
1575sn_crypto_hash(
1576 js_env_t *,
1577 js_receiver_t,
1578 js_typedarray_span_t<> out,
1579 js_typedarray_span_t<> in
1580) {
1581 assert(out.size_bytes() == crypto_hash_BYTES);
1582
1583 return crypto_hash(out.data(), in.data(), in.size_bytes());
1584}
1585
1586static inline int
1587sn_crypto_hash_sha256(
1588 js_env_t *,
1589 js_receiver_t,
1590 js_typedarray_span_t<> out,
1591 js_typedarray_span_t<> in
1592) {
1593 assert(out.size_bytes() == crypto_hash_sha256_BYTES);
1594
1595 return crypto_hash_sha256(out.data(), in.data(), in.size_bytes());
1596}
1597
1598static inline int
1599sn_crypto_hash_sha256_init(
1600 js_env_t *,
1601 js_receiver_t,
1602 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state
1603) {
1604 return crypto_hash_sha256_init(&*state);
1605}
1606
1607static inline int
1608sn_crypto_hash_sha256_update(
1609 js_env_t *,
1610 js_receiver_t,
1611 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
1612 js_typedarray_span_t<> in
1613) {
1614 return crypto_hash_sha256_update(&*state, in.data(), in.size_bytes());
1615}
1616
1617static inline int
1618sn_crypto_hash_sha256_final(
1619 js_env_t *,
1620 js_receiver_t,
1621 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
1622 js_typedarray_span_t<> out
1623) {
1624 assert(out.size_bytes() == crypto_hash_sha256_BYTES);
1625
1626 return crypto_hash_sha256_final(&*state, out.data());
1627}
1628
1629static inline int
1630sn_crypto_hash_sha512(
1631 js_env_t *,
1632 js_receiver_t,
1633 js_typedarray_span_t<> out,
1634 js_typedarray_span_t<> in
1635) {
1636 assert(out.size_bytes() == crypto_hash_sha512_BYTES);
1637
1638 return crypto_hash_sha512(out.data(), in.data(), in.size_bytes());
1639}
1640
1641static inline int
1642sn_crypto_hash_sha512_init(
1643 js_env_t *,
1644 js_receiver_t,
1645 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state
1646) {
1647 return crypto_hash_sha512_init(&*state);
1648}
1649
1650static inline int
1651sn_crypto_hash_sha512_update(
1652 js_env_t *,
1653 js_receiver_t,
1654 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
1655 js_typedarray_span_t<> in
1656) {
1657 return crypto_hash_sha512_update(&*state, in.data(), in.size_bytes());
1658}
1659
1660static inline int
1661sn_crypto_hash_sha512_final(
1662 js_env_t *,
1663 js_receiver_t,
1664 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
1665 js_typedarray_span_t<> out
1666) {
1667 assert(out.size_bytes() == crypto_hash_sha512_BYTES);
1668
1669 return crypto_hash_sha512_final(&*state, out.data());
1670}
1671
1672static inline void
1673sn_crypto_aead_xchacha20poly1305_ietf_keygen(
1674 js_env_t *,
1675 js_receiver_t,
1676 js_typedarray_span_t<> k
1677) {
1678 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1679
1680 crypto_aead_xchacha20poly1305_ietf_keygen(k.data());
1681}
1682
1683static inline uint64_t
1684sn_crypto_aead_xchacha20poly1305_ietf_encrypt(
1685 js_env_t *,
1686 js_receiver_t,
1687 js_typedarray_span_t<> c,
1688 js_typedarray_span_t<> m,
1689 std::optional<js_typedarray_span_t<>> ad,
1690 js_typedarray_span_t<> npub,
1691 js_typedarray_span_t<> k
1692) {
1693 assert(c.size_bytes() == m.size_bytes() + crypto_aead_xchacha20poly1305_ietf_ABYTES);
1694 assert(c.size_bytes() <= 0xffffffff);
1695 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1696 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1697
1698 uint8_t *ad_data = nullptr;
1699 size_t ad_size = 0;
1700 if (ad) {
1701 ad_data = ad->data();
1702 ad_size = ad->size_bytes();
1703 }
1704
1705 unsigned long long clen = 0;
1706 int status = crypto_aead_xchacha20poly1305_ietf_encrypt(
1707 c.data(),
1708 &clen,
1709 m.data(),
1710 m.size_bytes(),
1711 ad_data,
1712 ad_size,
1713 nullptr,
1714 npub.data(),
1715 k.data()
1716 );
1717
1718 if (status < 0) return status;
1719
1720 return clen;
1721}
1722
1723static inline uint64_t
1724sn_crypto_aead_xchacha20poly1305_ietf_decrypt(
1725 js_env_t *,
1726 js_receiver_t,
1727 js_typedarray_span_t<> m,
1728 js_typedarray_span_t<> c,
1729 std::optional<js_typedarray_span_t<>> ad,
1730 js_typedarray_span_t<> npub,
1731 js_typedarray_span_t<> k
1732) {
1733 assert(m.size_bytes() == c.size_bytes() - crypto_aead_xchacha20poly1305_ietf_ABYTES);
1734 assert(m.size_bytes() <= 0xffffffff);
1735 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1736 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1737
1738 uint8_t *ad_data = nullptr;
1739 size_t ad_size = 0;
1740 if (ad) {
1741 ad_data = ad->data();
1742 ad_size = ad->size_bytes();
1743 }
1744
1745 unsigned long long mlen = 0;
1746 int status = crypto_aead_xchacha20poly1305_ietf_decrypt(
1747 m.data(),
1748 &mlen,
1749 nullptr,
1750 c.data(),
1751 c.size_bytes(),
1752 ad_data,
1753 ad_size,
1754 npub.data(),
1755 k.data()
1756 );
1757
1758 if (status < 0) return status;
1759
1760 return mlen;
1761}
1762
1763static inline uint64_t
1764sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
1765 js_env_t *,
1766 js_receiver_t,
1767 js_typedarray_span_t<> c,
1768 js_typedarray_span_t<> mac,
1769 js_typedarray_span_t<> m,
1770 std::optional<js_typedarray_span_t<>> ad,
1771 js_typedarray_span_t<> npub,
1772 js_typedarray_span_t<> k
1773) {
1774 assert(c.size_bytes() == m.size_bytes());
1775 assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
1776 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1777 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1778
1779 uint8_t *ad_data = nullptr;
1780 size_t ad_size = 0;
1781 if (ad) {
1782 ad_data = ad->data();
1783 ad_size = ad->size_bytes();
1784 }
1785
1786 unsigned long long maclen = 0;
1787 int status = crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
1788 c.data(),
1789 mac.data(),
1790 &maclen,
1791 m.data(),
1792 m.size_bytes(),
1793 ad_data,
1794 ad_size,
1795 nullptr,
1796 npub.data(),
1797 k.data()
1798 );
1799
1800 if (status < 0) return status;
1801
1802 return maclen;
1803}
1804
1805static inline int
1806sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
1807 js_env_t *,
1808 js_receiver_t,
1809 js_typedarray_span_t<> m,
1810 js_typedarray_span_t<> c,
1811 js_typedarray_span_t<> mac,
1812 std::optional<js_typedarray_span_t<>> ad,
1813 js_typedarray_span_t<> npub,
1814 js_typedarray_span_t<> k
1815) {
1816 assert(m.size_bytes() == c.size_bytes());
1817 assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
1818 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1819 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1820
1821 uint8_t *ad_data = nullptr;
1822 size_t ad_size = 0;
1823 if (ad) {
1824 ad_data = ad->data();
1825 ad_size = ad->size_bytes();
1826 }
1827
1828 return crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
1829 m.data(),
1830 nullptr,
1831 c.data(),
1832 c.size_bytes(),
1833 mac.data(),
1834 ad_data,
1835 ad_size,
1836 npub.data(),
1837 k.data()
1838 );
1839}
1840
1841static inline void
1842sn_crypto_aead_chacha20poly1305_ietf_keygen(
1843 js_env_t *,
1844 js_receiver_t,
1845 js_typedarray_span_t<> k
1846) {
1847 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1848
1849 crypto_aead_chacha20poly1305_ietf_keygen(k.data());
1850}
1851
1852static inline uint64_t
1853sn_crypto_aead_chacha20poly1305_ietf_encrypt(
1854 js_env_t *,
1855 js_receiver_t,
1856 js_typedarray_span_t<> c,
1857 js_typedarray_span_t<> m,
1858 std::optional<js_typedarray_span_t<>> ad,
1859 js_typedarray_span_t<> npub,
1860 js_typedarray_span_t<> k
1861) {
1862 assert(c.size_bytes() == m.size_bytes() + crypto_aead_chacha20poly1305_ietf_ABYTES);
1863 assert(c.size_bytes() <= 0xffffffff);
1864 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1865 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1866
1867 uint8_t *ad_data = nullptr;
1868 size_t ad_size = 0;
1869 if (ad) {
1870 ad_data = ad->data();
1871 ad_size = ad->size_bytes();
1872 }
1873
1874 unsigned long long clen = 0;
1875 int status = crypto_aead_chacha20poly1305_ietf_encrypt(
1876 c.data(),
1877 &clen,
1878 m.data(),
1879 m.size_bytes(),
1880 ad_data,
1881 ad_size,
1882 nullptr,
1883 npub.data(),
1884 k.data()
1885 );
1886
1887 if (status < 0) return status;
1888
1889 return clen;
1890}
1891
1892static inline uint64_t
1893sn_crypto_aead_chacha20poly1305_ietf_decrypt(
1894 js_env_t *,
1895 js_receiver_t,
1896 js_typedarray_span_t<> m,
1897 js_typedarray_span_t<> c,
1898 std::optional<js_typedarray_span_t<>> ad,
1899 js_typedarray_span_t<> npub,
1900 js_typedarray_span_t<> k
1901) {
1902 assert(m.size_bytes() == c.size_bytes() - crypto_aead_chacha20poly1305_ietf_ABYTES);
1903 assert(m.size_bytes() <= 0xffffffff);
1904 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1905 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1906
1907 uint8_t *ad_data = nullptr;
1908 size_t ad_size = 0;
1909 if (ad) {
1910 ad_data = ad->data();
1911 ad_size = ad->size_bytes();
1912 }
1913
1914 unsigned long long mlen = 0;
1915 int status = crypto_aead_chacha20poly1305_ietf_decrypt(
1916 m.data(),
1917 &mlen,
1918 nullptr,
1919 c.data(),
1920 c.size_bytes(),
1921 ad_data,
1922 ad_size,
1923 npub.data(),
1924 k.data()
1925 );
1926
1927 if (status < 0) return status;
1928
1929 return mlen;
1930}
1931
1932static inline uint64_t
1933sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached(
1934 js_env_t *,
1935 js_receiver_t,
1936 js_typedarray_span_t<> c,
1937 js_typedarray_span_t<> mac,
1938 js_typedarray_span_t<> m,
1939 std::optional<js_typedarray_span_t<>> ad,
1940 js_typedarray_span_t<> npub,
1941 js_typedarray_span_t<> k
1942) {
1943 assert(c.size_bytes() == m.size_bytes());
1944 assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
1945 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1946 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1947
1948 uint8_t *ad_data = nullptr;
1949 size_t ad_size = 0;
1950 if (ad) {
1951 ad_data = ad->data();
1952 ad_size = ad->size_bytes();
1953 }
1954
1955 unsigned long long maclen = 0;
1956 int status = crypto_aead_chacha20poly1305_ietf_encrypt_detached(
1957 c.data(),
1958 mac.data(),
1959 &maclen,
1960 m.data(),
1961 m.size_bytes(),
1962 ad_data,
1963 ad_size,
1964 nullptr,
1965 npub.data(),
1966 k.data()
1967 );
1968
1969 if (status < 0) return status;
1970
1971 return maclen;
1972}
1973
1974static inline int
1975sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached(
1976 js_env_t *,
1977 js_receiver_t,
1978 js_typedarray_span_t<> m,
1979 js_typedarray_span_t<> c,
1980 js_typedarray_span_t<> mac,
1981 std::optional<js_typedarray_span_t<>> ad,
1982 js_typedarray_span_t<> npub,
1983 js_typedarray_span_t<> k
1984) {
1985 assert(m.size_bytes() == c.size_bytes());
1986 assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
1987 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1988 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1989
1990 uint8_t *ad_data = nullptr;
1991 size_t ad_size = 0;
1992 if (ad) {
1993 ad_data = ad->data();
1994 ad_size = ad->size_bytes();
1995 }
1996
1997 return crypto_aead_chacha20poly1305_ietf_decrypt_detached(
1998 m.data(),
1999 nullptr,
2000 c.data(),
2001 c.size_bytes(),
2002 mac.data(),
2003 ad_data,
2004 ad_size,
2005 npub.data(),
2006 k.data()
2007 );
2008}
2009
2010static inline void
2011sn_crypto_secretstream_xchacha20poly1305_keygen(
2012 js_env_t *env,
2013 js_receiver_t,
2014
2015 js_arraybuffer_span_t k,
2016 uint32_t k_offset,
2017 uint32_t k_len
2018) {
2019 assert_bounds(k);
2020 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2021
2022 crypto_secretstream_xchacha20poly1305_keygen(&k[k_offset]);
2023}
2024
2025static inline int
2026sn_crypto_secretstream_xchacha20poly1305_init_push(
2027 js_env_t *env,
2028 js_receiver_t,
2029
2030 js_arraybuffer_span_t state,
2031 uint32_t state_offset,
2032 uint32_t state_len,
2033
2034 js_arraybuffer_span_t header,
2035 uint32_t header_offset,
2036 uint32_t header_len,
2037
2038 js_arraybuffer_span_t k,
2039 uint32_t k_offset,
2040 uint32_t k_len
2041) {
2042 assert_bounds(state);
2043 assert_bounds(header);
2044 assert_bounds(k);
2045
2046 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2047 assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
2048 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2049
2050 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2051
2052 return crypto_secretstream_xchacha20poly1305_init_push(state_data, &header[header_offset], &k[k_offset]);
2053}
2054
2055static inline uint64_t
2056sn_crypto_secretstream_xchacha20poly1305_push(
2057 js_env_t *env,
2058 js_receiver_t,
2059
2060 js_arraybuffer_span_t state,
2061 uint32_t state_offset,
2062 uint32_t state_len,
2063
2064 js_arraybuffer_span_t c,
2065 uint32_t c_offset,
2066 uint32_t c_len,
2067
2068 js_arraybuffer_span_t m,
2069 uint32_t m_offset,
2070 uint32_t m_len,
2071
2072 js_arraybuffer_span_t ad,
2073 uint32_t ad_offset,
2074 uint32_t ad_len,
2075
2076 uint32_t tag
2077) {
2078 assert_bounds(state);
2079 assert_bounds(c);
2080 assert_bounds(m);
2081
2082 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2083 assert(c_len == m_len + crypto_secretstream_xchacha20poly1305_ABYTES);
2084 assert(c_len <= 0xffffffff && "32bit integer");
2085
2086 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2087
2088 uint8_t *ad_data = NULL;
2089 if (ad_len) {
2090 assert_bounds(ad);
2091 ad_data = &ad[ad_offset];
2092 }
2093
2094 unsigned long long clen = 0;
2095 int status = crypto_secretstream_xchacha20poly1305_push(
2096 state_data,
2097 &c[c_offset],
2098 &clen,
2099 &m[m_offset],
2100 m_len,
2101 ad_data,
2102 ad_len,
2103 tag
2104 );
2105
2106 if (status < 0) return status;
2107
2108 return clen;
2109}
2110
2111static inline int
2112sn_crypto_secretstream_xchacha20poly1305_init_pull(
2113 js_env_t *,
2114 js_receiver_t,
2115
2116 js_arraybuffer_span_t state,
2117 uint32_t state_offset,
2118 uint32_t state_len,
2119
2120 js_arraybuffer_span_t header,
2121 uint32_t header_offset,
2122 uint32_t header_len,
2123
2124 js_arraybuffer_span_t k,
2125 uint32_t k_offset,
2126 uint32_t k_len
2127) {
2128 assert_bounds(state);
2129 assert_bounds(header);
2130 assert_bounds(k);
2131
2132 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2133 assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
2134 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2135
2136 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2137
2138 return crypto_secretstream_xchacha20poly1305_init_pull(state_data, &header[header_offset], &k[k_offset]);
2139}
2140
2141static inline uint64_t
2142sn_crypto_secretstream_xchacha20poly1305_pull(
2143 js_env_t *env,
2144 js_receiver_t,
2145
2146 js_arraybuffer_span_t state,
2147 uint32_t state_offset,
2148 uint32_t state_len,
2149
2150 js_arraybuffer_span_t m,
2151 uint32_t m_offset,
2152 uint32_t m_len,
2153
2154 js_arraybuffer_span_t tag,
2155 uint32_t tag_offset,
2156 uint32_t tag_len,
2157
2158 js_arraybuffer_span_t c,
2159 uint32_t c_offset,
2160 uint32_t c_len,
2161
2162 js_arraybuffer_span_t ad,
2163 uint32_t ad_offset,
2164 uint32_t ad_len
2165) {
2166 assert_bounds(state);
2167 assert_bounds(m);
2168 assert_bounds(tag);
2169 assert_bounds(c);
2170
2171 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2172 assert(c_len >= crypto_secretstream_xchacha20poly1305_ABYTES);
2173 assert(tag_len == 1);
2174 assert(m_len == c_len - crypto_secretstream_xchacha20poly1305_ABYTES);
2175 assert(m_len <= 0xffffffff);
2176
2177 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2178
2179 uint8_t *ad_data = NULL;
2180 if (ad_len) {
2181 assert_bounds(ad);
2182 ad_data = &ad[ad_offset];
2183 }
2184
2185 unsigned long long mlen = 0;
2186 int status = crypto_secretstream_xchacha20poly1305_pull(
2187 state_data,
2188 &m[m_offset],
2189 &mlen,
2190 &tag[tag_offset],
2191 &c[c_offset],
2192 c_len,
2193 ad_data,
2194 ad_len
2195 );
2196
2197 if (status < 0) return status;
2198
2199 return mlen;
2200}
2201
2202static inline void
2203sn_crypto_secretstream_xchacha20poly1305_rekey(
2204 js_env_t *,
2205 js_receiver_t,
2206
2207 js_arraybuffer_span_t state,
2208 uint32_t state_offset,
2209 uint32_t state_len
2210) {
2211 assert_bounds(state);
2212
2213 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2214
2215 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2216
2217 crypto_secretstream_xchacha20poly1305_rekey(state_data);
2218}
2219
2220struct sn_async_task {
2221 uv_work_t task;
2222 js_env_t *env;
2223 js_persistent_t<js_function_t<void, int>> cb;
2224 js_deferred_teardown_t *teardown;
2225 int code = 0;
2226 bool exiting = false;
2227
2228 sn_async_task(js_env_t *env) : env(env) {
2229 int err;
2230 err = js_add_teardown_callback<on_teardown, sn_async_task>(env, this, teardown);
2231 assert(err == 0);
2232 }
2233
2234 ~sn_async_task() {
2235 int err;
2236 err = js_finish_teardown_callback(teardown);
2237 assert(err == 0);
2238 }
2239
2240private:
2241 static void
2242 on_teardown(js_deferred_teardown_t *teardown, sn_async_task *req) {
2243 req->exiting = true;
2244 }
2245};
2246
2247struct sn_async_pwhash_request : sn_async_task {
2248 js_persistent_t<js_arraybuffer_t> out_ref;
2249 std::span<uint8_t> out;
2250
2251 js_persistent_t<js_arraybuffer_t> pwd_ref;
2252 std::span<char> pwd;
2253
2254 js_persistent_t<js_arraybuffer_t> salt_ref;
2255 std::span<uint8_t> salt;
2256
2257 uint64_t opslimit;
2258 size_t memlimit;
2259 int alg;
2260
2261 sn_async_pwhash_request(js_env_t *env) : sn_async_task(env) {}
2262};
2263
2264static void
2265async_pwhash_execute(uv_work_t *uv_req) {
2266 auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
2267
2268 req->code = crypto_pwhash(
2269 req->out.data(),
2270 req->out.size(),
2271 req->pwd.data(),
2272 req->pwd.size(),
2273 req->salt.data(),
2274 req->opslimit,
2275 req->memlimit,
2276 req->alg
2277 );
2278}
2279
2280static void
2281async_pwhash_complete(uv_work_t *uv_req, int status) {
2282 int err;
2283
2284 auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
2285
2286 if (req->exiting) return delete req;
2287
2288 js_handle_scope_t *scope;
2289 err = js_open_handle_scope(req->env, &scope);
2290 assert(err == 0);
2291
2292 js_function_t<void, int> callback;
2293 err = js_get_reference_value(req->env, req->cb, callback);
2294 assert(err == 0);
2295
2296 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2297 assert(err != js_pending_exception);
2298
2299 err = js_close_handle_scope(req->env, scope);
2300 assert(err == 0);
2301
2302 delete req;
2303}
2304
2305static inline void
2306sn_crypto_pwhash_async(
2307 js_env_t *env,
2308 js_receiver_t,
2309
2310 js_arraybuffer_t out,
2311 uint32_t out_offset,
2312 uint32_t out_len,
2313
2314 js_arraybuffer_t pwd,
2315 uint32_t pwd_offset,
2316 uint32_t pwd_len,
2317
2318 js_arraybuffer_t salt,
2319 uint32_t salt_offset,
2320 uint32_t salt_len,
2321
2322 uint64_t opslimit,
2323 uint64_t memlimit,
2324 uint32_t alg,
2325
2326 js_function_t<void, int> callback
2327) {
2328 int err;
2329
2330 auto *req = new sn_async_pwhash_request(env);
2331
2332 std::span<uint8_t> out_view;
2333 err = js_get_arraybuffer_info(env, out, out_view);
2334 assert(err == 0);
2335 assert(out_offset + out_len <= out_view.size());
2336
2337 req->out = {&out_view[out_offset], out_len};
2338
2339 std::span<char> pwd_view;
2340 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2341 assert(err == 0);
2342 assert(pwd_offset + pwd_len <= pwd_view.size());
2343
2344 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2345
2346 std::span<uint8_t> salt_view;
2347 err = js_get_arraybuffer_info(env, salt, salt_view);
2348 assert(err == 0);
2349 assert(salt_offset + salt_len <= salt_view.size());
2350
2351 req->salt = {&salt_view[salt_offset], salt_len};
2352
2353 req->opslimit = opslimit;
2354 req->memlimit = memlimit;
2355 req->alg = alg;
2356
2357 err = js_create_reference(env, out, req->out_ref);
2358 assert(err == 0);
2359
2360 err = js_create_reference(env, pwd, req->pwd_ref);
2361 assert(err == 0);
2362
2363 err = js_create_reference(env, salt, req->salt_ref);
2364 assert(err == 0);
2365
2366 err = js_create_reference(env, callback, req->cb);
2367 assert(err == 0);
2368
2369 uv_loop_t *loop;
2370 err = js_get_env_loop(env, &loop);
2371 assert(err == 0);
2372
2373 err = uv_queue_work(loop, &req->task, async_pwhash_execute, async_pwhash_complete);
2374 assert(err == 0);
2375}
2376
2377struct sn_async_pwhash_str_request : sn_async_task {
2378 js_persistent_t<js_arraybuffer_t> out_ref;
2379 std::span<char> out;
2380
2381 js_persistent_t<js_arraybuffer_t> pwd_ref;
2382 std::span<char> pwd;
2383
2384 uint64_t opslimit;
2385 size_t memlimit;
2386
2387 sn_async_pwhash_str_request(js_env_t *env) : sn_async_task(env) {}
2388};
2389
2390static void
2391async_pwhash_str_execute(uv_work_t *uv_req) {
2392 auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
2393
2394 req->code = crypto_pwhash_str(
2395 req->out.data(),
2396 req->pwd.data(),
2397 req->pwd.size(),
2398 req->opslimit,
2399 req->memlimit
2400 );
2401}
2402
2403static void
2404async_pwhash_str_complete(uv_work_t *uv_req, int status) {
2405 int err;
2406
2407 auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
2408
2409 if (req->exiting) return delete req;
2410
2411 js_handle_scope_t *scope;
2412 err = js_open_handle_scope(req->env, &scope);
2413 assert(err == 0);
2414
2415 js_function_t<void, int> callback;
2416 err = js_get_reference_value(req->env, req->cb, callback);
2417 assert(err == 0);
2418
2419 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2420 assert(err != js_pending_exception);
2421
2422 err = js_close_handle_scope(req->env, scope);
2423 assert(err == 0);
2424
2425 delete req;
2426}
2427
2428static inline void
2429sn_crypto_pwhash_str_async(
2430 js_env_t *env,
2431 js_receiver_t,
2432
2433 js_arraybuffer_t out,
2434 uint32_t out_offset,
2435 uint32_t out_len,
2436
2437 js_arraybuffer_t pwd,
2438 uint32_t pwd_offset,
2439 uint32_t pwd_len,
2440
2441 uint64_t opslimit,
2442 uint64_t memlimit,
2443 js_function_t<void, int> callback
2444) {
2445 int err;
2446
2447 auto *req = new sn_async_pwhash_str_request(env);
2448
2449 std::span<char> out_view;
2450 err = js_get_arraybuffer_info(env, out, out_view);
2451 assert(err == 0);
2452 assert(out_offset + out_len <= out_view.size());
2453
2454 req->out = {&out_view[out_offset], out_len};
2455
2456 std::span<char> pwd_view;
2457 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2458 assert(err == 0);
2459 assert(pwd_offset + pwd_len <= pwd_view.size());
2460
2461 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2462
2463 req->opslimit = opslimit;
2464 req->memlimit = memlimit;
2465
2466 err = js_create_reference(env, out, req->out_ref);
2467 assert(err == 0);
2468
2469 err = js_create_reference(env, pwd, req->pwd_ref);
2470 assert(err == 0);
2471
2472 err = js_create_reference(env, callback, req->cb);
2473 assert(err == 0);
2474
2475 uv_loop_t *loop;
2476 err = js_get_env_loop(env, &loop);
2477 assert(err == 0);
2478
2479 err = uv_queue_work(loop, &req->task, async_pwhash_str_execute, async_pwhash_str_complete);
2480 assert(err == 0);
2481}
2482
2483struct sn_async_pwhash_str_verify_request : sn_async_task {
2484 js_persistent_t<js_arraybuffer_t> str_ref;
2485 std::span<char> str;
2486
2487 js_persistent_t<js_arraybuffer_t> pwd_ref;
2488 std::span<char> pwd;
2489
2490 sn_async_pwhash_str_verify_request(js_env_t *env) : sn_async_task(env) {}
2491};
2492
2493static void
2494async_pwhash_str_verify_execute(uv_work_t *uv_req) {
2495 auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
2496
2497 req->code = crypto_pwhash_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
2498}
2499
2500static void
2501async_pwhash_str_verify_complete(uv_work_t *uv_req, int status) {
2502 int err;
2503
2504 auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
2505
2506 if (req->exiting) return delete req;
2507
2508 js_handle_scope_t *scope;
2509 err = js_open_handle_scope(req->env, &scope);
2510 assert(err == 0);
2511
2512 js_function_t<void, int> callback;
2513 err = js_get_reference_value(req->env, req->cb, callback);
2514 assert(err == 0);
2515
2516 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2517 assert(err != js_pending_exception);
2518
2519 err = js_close_handle_scope(req->env, scope);
2520 assert(err == 0);
2521
2522 delete req;
2523}
2524
2525static inline void
2526sn_crypto_pwhash_str_verify_async(
2527 js_env_t *env,
2528 js_receiver_t,
2529
2530 js_arraybuffer_t str,
2531 uint32_t str_offset,
2532 uint32_t str_len,
2533
2534 js_arraybuffer_t pwd,
2535 uint32_t pwd_offset,
2536 uint32_t pwd_len,
2537
2538 js_function_t<void, int> callback
2539) {
2540 int err;
2541
2542 auto *req = new sn_async_pwhash_str_verify_request(env);
2543
2544 std::span<char> str_view;
2545 err = js_get_arraybuffer_info(env, str, str_view);
2546 assert(err == 0);
2547 assert(str_offset + str_len <= str_view.size());
2548
2549 req->str = {&str_view[str_offset], str_len};
2550
2551 std::span<char> pwd_view;
2552 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2553 assert(err == 0);
2554 assert(pwd_offset + pwd_len <= pwd_view.size());
2555
2556 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2557
2558 err = js_create_reference(env, str, req->str_ref);
2559 assert(err == 0);
2560
2561 err = js_create_reference(env, pwd, req->pwd_ref);
2562 assert(err == 0);
2563
2564 err = js_create_reference(env, callback, req->cb);
2565 assert(err == 0);
2566
2567 uv_loop_t *loop;
2568 err = js_get_env_loop(env, &loop);
2569 assert(err == 0);
2570
2571 err = uv_queue_work(loop, &req->task, async_pwhash_str_verify_execute, async_pwhash_str_verify_complete);
2572 assert(err == 0);
2573}
2574
2575struct sn_async_pwhash_scryptsalsa208sha256_request : sn_async_task {
2576 js_persistent_t<js_arraybuffer_t> out_ref;
2577 std::span<uint8_t> out;
2578
2579 js_persistent_t<js_arraybuffer_t> pwd_ref;
2580 std::span<char> pwd;
2581
2582 js_persistent_t<js_arraybuffer_t> salt_ref;
2583 std::span<uint8_t> salt;
2584
2585 uint64_t opslimit;
2586 size_t memlimit;
2587
2588 sn_async_pwhash_scryptsalsa208sha256_request(js_env_t *env) : sn_async_task(env) {}
2589};
2590
2591static void
2592async_pwhash_scryptsalsa208sha256_execute(uv_work_t *uv_req) {
2593 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
2594
2595 req->code = crypto_pwhash_scryptsalsa208sha256(
2596 req->out.data(),
2597 req->out.size(),
2598 req->pwd.data(),
2599 req->pwd.size(),
2600 req->salt.data(),
2601 req->opslimit,
2602 req->memlimit
2603 );
2604}
2605
2606static void
2607async_pwhash_scryptsalsa208sha256_complete(uv_work_t *uv_req, int status) {
2608 int err;
2609
2610 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
2611
2612 if (req->exiting) return delete req;
2613
2614 js_handle_scope_t *scope;
2615 err = js_open_handle_scope(req->env, &scope);
2616 assert(err == 0);
2617
2618 js_function_t<void, int> callback;
2619 err = js_get_reference_value(req->env, req->cb, callback);
2620 assert(err == 0);
2621
2622 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2623 assert(err != js_pending_exception);
2624
2625 err = js_close_handle_scope(req->env, scope);
2626 assert(err == 0);
2627
2628 delete req;
2629}
2630
2631static inline void
2632sn_crypto_pwhash_scryptsalsa208sha256_async(
2633 js_env_t *env,
2634 js_receiver_t,
2635
2636 js_arraybuffer_t out,
2637 uint32_t out_offset,
2638 uint32_t out_len,
2639
2640 js_arraybuffer_t pwd,
2641 uint32_t pwd_offset,
2642 uint32_t pwd_len,
2643
2644 js_arraybuffer_t salt,
2645 uint32_t salt_offset,
2646 uint32_t salt_len,
2647
2648 uint64_t opslimit,
2649 uint64_t memlimit,
2650
2651 js_function_t<void, int> callback
2652) {
2653 int err;
2654
2655 auto *req = new sn_async_pwhash_scryptsalsa208sha256_request(env);
2656
2657 std::span<uint8_t> out_view;
2658 err = js_get_arraybuffer_info(env, out, out_view);
2659 assert(err == 0);
2660 assert(out_offset + out_len <= out_view.size());
2661
2662 req->out = {&out_view[out_offset], out_len};
2663
2664 std::span<char> pwd_view;
2665 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2666 assert(err == 0);
2667 assert(pwd_offset + pwd_len <= pwd_view.size());
2668
2669 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2670
2671 std::span<uint8_t> salt_view;
2672 err = js_get_arraybuffer_info(env, salt, salt_view);
2673 assert(err == 0);
2674 assert(salt_offset + salt_len <= salt_view.size());
2675 assert(salt_len == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
2676
2677 req->salt = {&salt_view[salt_offset], salt_len};
2678
2679 req->opslimit = opslimit;
2680 req->memlimit = memlimit;
2681
2682 err = js_create_reference(env, out, req->out_ref);
2683 assert(err == 0);
2684
2685 err = js_create_reference(env, pwd, req->pwd_ref);
2686 assert(err == 0);
2687
2688 err = js_create_reference(env, salt, req->salt_ref);
2689 assert(err == 0);
2690
2691 err = js_create_reference(env, callback, req->cb);
2692 assert(err == 0);
2693
2694 uv_loop_t *loop;
2695 err = js_get_env_loop(env, &loop);
2696 assert(err == 0);
2697
2698 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_execute, async_pwhash_scryptsalsa208sha256_complete);
2699 assert(err == 0);
2700}
2701
2702struct sn_async_pwhash_scryptsalsa208sha256_str_request : sn_async_task {
2703 js_persistent_t<js_arraybuffer_t> out_ref;
2704 std::span<char> out;
2705
2706 js_persistent_t<js_arraybuffer_t> pwd_ref;
2707 std::span<char> pwd;
2708
2709 uint64_t opslimit;
2710 size_t memlimit;
2711
2712 sn_async_pwhash_scryptsalsa208sha256_str_request(js_env_t *env) : sn_async_task(env) {}
2713};
2714
2715static void
2716async_pwhash_scryptsalsa208sha256_str_execute(uv_work_t *uv_req) {
2717 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
2718
2719 req->code = crypto_pwhash_scryptsalsa208sha256_str(
2720 req->out.data(),
2721 req->pwd.data(),
2722 req->pwd.size(),
2723 req->opslimit,
2724 req->memlimit
2725 );
2726}
2727
2728static void
2729async_pwhash_scryptsalsa208sha256_str_complete(uv_work_t *uv_req, int status) {
2730 int err;
2731
2732 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
2733
2734 if (req->exiting) return delete req;
2735
2736 js_handle_scope_t *scope;
2737 err = js_open_handle_scope(req->env, &scope);
2738 assert(err == 0);
2739
2740 js_function_t<void, int> callback;
2741 err = js_get_reference_value(req->env, req->cb, callback);
2742 assert(err == 0);
2743
2744 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2745 assert(err != js_pending_exception);
2746
2747 err = js_close_handle_scope(req->env, scope);
2748 assert(err == 0);
2749
2750 delete req;
2751}
2752
2753static inline void
2754sn_crypto_pwhash_scryptsalsa208sha256_str_async(
2755 js_env_t *env,
2756 js_receiver_t,
2757
2758 js_arraybuffer_t out,
2759 uint32_t out_offset,
2760 uint32_t out_len,
2761
2762 js_arraybuffer_t pwd,
2763 uint32_t pwd_offset,
2764 uint32_t pwd_len,
2765
2766 uint64_t opslimit,
2767 uint64_t memlimit,
2768
2769 js_function_t<void, int> callback
2770) {
2771 int err;
2772
2773 auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_request(env);
2774
2775 std::span<char> out_view;
2776 err = js_get_arraybuffer_info(env, out, out_view);
2777 assert(err == 0);
2778 assert(out_offset + out_len <= out_view.size());
2779
2780 req->out = {&out_view[out_offset], out_len};
2781
2782 std::span<char> pwd_view;
2783 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2784 assert(err == 0);
2785 assert(pwd_offset + pwd_len <= pwd_view.size());
2786
2787 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2788
2789 req->opslimit = opslimit;
2790 req->memlimit = memlimit;
2791
2792 err = js_create_reference(env, out, req->out_ref);
2793 assert(err == 0);
2794
2795 err = js_create_reference(env, pwd, req->pwd_ref);
2796 assert(err == 0);
2797
2798 err = js_create_reference(env, callback, req->cb);
2799 assert(err == 0);
2800
2801 uv_loop_t *loop;
2802 err = js_get_env_loop(env, &loop);
2803 assert(err == 0);
2804
2805 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_execute, async_pwhash_scryptsalsa208sha256_str_complete);
2806 assert(err == 0);
2807}
2808
2809struct sn_async_pwhash_scryptsalsa208sha256_str_verify_request : sn_async_task {
2810 js_persistent_t<js_arraybuffer_t> str_ref;
2811 std::span<char> str;
2812
2813 js_persistent_t<js_arraybuffer_t> pwd_ref;
2814 std::span<char> pwd;
2815
2816 sn_async_pwhash_scryptsalsa208sha256_str_verify_request(js_env_t *env) : sn_async_task(env) {}
2817};
2818
2819static void
2820async_pwhash_scryptsalsa208sha256_str_verify_execute(uv_work_t *uv_req) {
2821 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
2822
2823 req->code = crypto_pwhash_scryptsalsa208sha256_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
2824}
2825
2826static void
2827async_pwhash_scryptsalsa208sha256_str_verify_complete(uv_work_t *uv_req, int status) {
2828 int err;
2829
2830 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
2831
2832 if (req->exiting) return delete req;
2833
2834 js_handle_scope_t *scope;
2835 err = js_open_handle_scope(req->env, &scope);
2836 assert(err == 0);
2837
2838 js_function_t<void, int> callback;
2839 err = js_get_reference_value(req->env, req->cb, callback);
2840 assert(err == 0);
2841
2842 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2843 assert(err != js_pending_exception);
2844
2845 err = js_close_handle_scope(req->env, scope);
2846 assert(err == 0);
2847
2848 delete req;
2849}
2850
2851static inline void
2852sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async(
2853 js_env_t *env,
2854 js_receiver_t,
2855
2856 js_arraybuffer_t str,
2857 uint32_t str_offset,
2858 uint32_t str_len,
2859
2860 js_arraybuffer_t pwd,
2861 uint32_t pwd_offset,
2862 uint32_t pwd_len,
2863
2864 js_function_t<void, int> callback
2865) {
2866 int err;
2867
2868 auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_verify_request(env);
2869
2870 std::span<char> str_view;
2871 err = js_get_arraybuffer_info(env, str, str_view);
2872 assert(err == 0);
2873 assert(str_offset + str_len <= str_view.size());
2874
2875 req->str = {&str_view[str_offset], str_len};
2876
2877 std::span<char> pwd_view;
2878 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2879 assert(err == 0);
2880 assert(pwd_offset + pwd_len <= pwd_view.size());
2881
2882 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2883
2884 err = js_create_reference(env, str, req->str_ref);
2885 assert(err == 0);
2886
2887 err = js_create_reference(env, pwd, req->pwd_ref);
2888 assert(err == 0);
2889
2890 err = js_create_reference(env, callback, req->cb);
2891 assert(err == 0);
2892
2893 uv_loop_t *loop;
2894 err = js_get_env_loop(env, &loop);
2895 assert(err == 0);
2896
2897 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_verify_execute, async_pwhash_scryptsalsa208sha256_str_verify_complete);
2898 assert(err == 0);
2899}
2900
2901struct sn_crypto_stream_xor_state {
2902 unsigned char n[crypto_stream_NONCEBYTES];
2903 unsigned char k[crypto_stream_KEYBYTES];
2904 unsigned char next_block[64];
2905 int remainder;
2906 uint64_t block_counter;
2907};
2908
2909static inline void
2910sn_crypto_stream_xor_wrap_init(
2911 js_env_t *,
2912 js_receiver_t,
2913 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
2914 js_typedarray_span_t<> n,
2915 js_typedarray_span_t<> k
2916) {
2917 assert(n.size_bytes() == crypto_stream_NONCEBYTES);
2918 assert(k.size_bytes() == crypto_stream_KEYBYTES);
2919
2920 state->remainder = 0;
2921 state->block_counter = 0;
2922 memcpy(state->n, n.data(), crypto_stream_NONCEBYTES);
2923 memcpy(state->k, k.data(), crypto_stream_KEYBYTES);
2924}
2925
2926static inline void
2927sn_crypto_stream_xor_wrap_update(
2928 js_env_t *,
2929 js_receiver_t,
2930 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
2931 js_typedarray_span_t<> c,
2932 js_typedarray_span_t<> m
2933) {
2934 assert(c.size_bytes() == m.size_bytes());
2935
2936 auto next_block = state->next_block;
2937
2938 size_t m_size = m.size_bytes();
2939 auto *c_ptr = c.data();
2940 auto *m_ptr = m.data();
2941
2942 if (state->remainder) {
2943 uint64_t offset = 0;
2944 int rem = state->remainder;
2945
2946 while (rem < 64 && offset < m_size) {
2947 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
2948 ++offset;
2949 ++rem;
2950 }
2951
2952 c_ptr += offset;
2953 m_ptr += offset;
2954 m_size -= offset;
2955 state->remainder = (rem == 64) ? 0 : rem;
2956
2957 if (m_size == 0) return;
2958 }
2959
2960 state->remainder = m_size & 63;
2961 size_t main_len = m_size - state->remainder;
2962
2963 crypto_stream_xsalsa20_xor_ic(c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k);
2964 state->block_counter += main_len / 64;
2965
2966 if (state->remainder) {
2967 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
2968 memcpy(next_block, m_ptr + main_len, state->remainder);
2969
2970 crypto_stream_xsalsa20_xor_ic(
2971 next_block, next_block, 64, state->n, state->block_counter, state->k
2972 );
2973 memcpy(c_ptr + main_len, next_block, state->remainder);
2974
2975 state->block_counter++;
2976 }
2977}
2978
2979static inline void
2980sn_crypto_stream_xor_wrap_final(
2981 js_env_t *,
2982 js_receiver_t,
2983 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state
2984) {
2985 sodium_memzero(state->n, sizeof(state->n));
2986 sodium_memzero(state->k, sizeof(state->k));
2987 sodium_memzero(state->next_block, sizeof(state->next_block));
2988 state->remainder = 0;
2989}
2990
2991struct sn_crypto_stream_chacha20_xor_state {
2992 unsigned char n[crypto_stream_chacha20_NONCEBYTES];
2993 unsigned char k[crypto_stream_chacha20_KEYBYTES];
2994 unsigned char next_block[64];
2995 int remainder;
2996 uint64_t block_counter;
2997};
2998
2999static inline void
3000sn_crypto_stream_chacha20_xor_wrap_init(
3001 js_env_t *,
3002 js_receiver_t,
3003 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
3004 js_typedarray_span_t<> n,
3005 js_typedarray_span_t<> k
3006) {
3007 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
3008 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
3009
3010 state->remainder = 0;
3011 state->block_counter = 0;
3012 memcpy(state->n, n.data(), crypto_stream_chacha20_NONCEBYTES);
3013 memcpy(state->k, k.data(), crypto_stream_chacha20_KEYBYTES);
3014}
3015
3016static inline void
3017sn_crypto_stream_chacha20_xor_wrap_update(
3018 js_env_t *,
3019 js_receiver_t,
3020 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
3021 js_typedarray_span_t<> c,
3022 js_typedarray_span_t<> m
3023) {
3024 assert(c.size_bytes() == m.size_bytes());
3025
3026 auto *next_block = state->next_block;
3027
3028 size_t m_size = m.size_bytes();
3029 auto *c_ptr = c.data();
3030 auto *m_ptr = m.data();
3031
3032 if (state->remainder) {
3033 uint64_t offset = 0;
3034 int rem = state->remainder;
3035
3036 while (rem < 64 && offset < m_size) {
3037 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3038 offset++;
3039 rem++;
3040 }
3041
3042 c_ptr += offset;
3043 m_ptr += offset;
3044 m_size -= offset;
3045 state->remainder = (rem == 64) ? 0 : rem;
3046
3047 if (m_size == 0) return;
3048 }
3049
3050 state->remainder = m_size & 63;
3051 size_t main_len = m_size - state->remainder;
3052
3053 crypto_stream_chacha20_xor_ic(
3054 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3055 );
3056
3057 state->block_counter += main_len / 64;
3058
3059 if (state->remainder) {
3060 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3061 memcpy(next_block, m_ptr + main_len, state->remainder);
3062
3063 crypto_stream_chacha20_xor_ic(
3064 next_block, next_block, 64, state->n, state->block_counter, state->k
3065 );
3066 memcpy(c_ptr + main_len, next_block, state->remainder);
3067
3068 state->block_counter++;
3069 }
3070}
3071
3072static inline void
3073sn_crypto_stream_chacha20_xor_wrap_final(
3074 js_env_t *,
3075 js_receiver_t,
3076 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state
3077) {
3078 sodium_memzero(state->n, sizeof(state->n));
3079 sodium_memzero(state->k, sizeof(state->k));
3080 sodium_memzero(state->next_block, sizeof(state->next_block));
3081 state->remainder = 0;
3082}
3083
3084struct sn_crypto_stream_chacha20_ietf_xor_state {
3085 unsigned char n[crypto_stream_chacha20_ietf_NONCEBYTES];
3086 unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES];
3087 unsigned char next_block[64];
3088 int remainder;
3089 uint64_t block_counter;
3090};
3091
3092static inline void
3093sn_crypto_stream_chacha20_ietf_xor_wrap_init(
3094 js_env_t *,
3095 js_receiver_t,
3096 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
3097 js_typedarray_span_t<> n,
3098 js_typedarray_span_t<> k
3099) {
3100 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
3101 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
3102
3103 state->remainder = 0;
3104 state->block_counter = 0;
3105 memcpy(state->n, n.data(), crypto_stream_chacha20_ietf_NONCEBYTES);
3106 memcpy(state->k, k.data(), crypto_stream_chacha20_ietf_KEYBYTES);
3107}
3108
3109static inline void
3110sn_crypto_stream_chacha20_ietf_xor_wrap_update(
3111 js_env_t *,
3112 js_receiver_t,
3113 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
3114 js_typedarray_span_t<> c,
3115 js_typedarray_span_t<> m
3116) {
3117 assert(c.size_bytes() == m.size_bytes());
3118
3119 auto *next_block = state->next_block;
3120
3121 size_t m_size = m.size_bytes();
3122 auto *c_ptr = c.data();
3123 auto *m_ptr = m.data();
3124
3125 if (state->remainder) {
3126 uint64_t offset = 0;
3127 int rem = state->remainder;
3128
3129 while (rem < 64 && offset < m_size) {
3130 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3131 offset++;
3132 rem++;
3133 }
3134
3135 c_ptr += offset;
3136 m_ptr += offset;
3137 m_size -= offset;
3138 state->remainder = (rem == 64) ? 0 : rem;
3139
3140 if (m_size == 0) return;
3141 }
3142
3143 state->remainder = m_size & 63;
3144 size_t main_len = m_size - state->remainder;
3145
3146 crypto_stream_chacha20_ietf_xor_ic(
3147 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3148 );
3149
3150 state->block_counter += main_len / 64;
3151
3152 if (state->remainder) {
3153 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3154 memcpy(next_block, m_ptr + main_len, state->remainder);
3155
3156 crypto_stream_chacha20_ietf_xor_ic(
3157 next_block, next_block, 64, state->n, state->block_counter, state->k
3158 );
3159 memcpy(c_ptr + main_len, next_block, state->remainder);
3160
3161 state->block_counter++;
3162 }
3163}
3164
3165static inline void
3166sn_crypto_stream_chacha20_ietf_xor_wrap_final(
3167 js_env_t *,
3168 js_receiver_t,
3169 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state
3170) {
3171 sodium_memzero(state->n, sizeof(state->n));
3172 sodium_memzero(state->k, sizeof(state->k));
3173 sodium_memzero(state->next_block, sizeof(state->next_block));
3174 state->remainder = 0;
3175}
3176
3177struct sn_crypto_stream_xchacha20_xor_state {
3178 unsigned char n[crypto_stream_xchacha20_NONCEBYTES];
3179 unsigned char k[crypto_stream_xchacha20_KEYBYTES];
3180 unsigned char next_block[64];
3181 int remainder;
3182 uint64_t block_counter;
3183};
3184
3185static inline void
3186sn_crypto_stream_xchacha20_xor_wrap_init(
3187 js_env_t *,
3188 js_receiver_t,
3189 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
3190 js_typedarray_span_t<> n,
3191 js_typedarray_span_t<> k
3192) {
3193 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
3194 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
3195
3196 state->remainder = 0;
3197 state->block_counter = 0;
3198 memcpy(state->n, n.data(), crypto_stream_xchacha20_NONCEBYTES);
3199 memcpy(state->k, k.data(), crypto_stream_xchacha20_KEYBYTES);
3200}
3201
3202static inline void
3203sn_crypto_stream_xchacha20_xor_wrap_update(
3204 js_env_t *,
3205 js_receiver_t,
3206 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
3207 js_typedarray_span_t<> c,
3208 js_typedarray_span_t<> m
3209) {
3210 assert(c.size_bytes() == m.size_bytes());
3211
3212 auto *next_block = state->next_block;
3213
3214 size_t m_size = m.size_bytes();
3215 auto *c_ptr = c.data();
3216 auto *m_ptr = m.data();
3217
3218 if (state->remainder) {
3219 uint64_t offset = 0;
3220 int rem = state->remainder;
3221
3222 while (rem < 64 && offset < m_size) {
3223 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3224 ++offset;
3225 ++rem;
3226 }
3227
3228 c_ptr += offset;
3229 m_ptr += offset;
3230 m_size -= offset;
3231 state->remainder = (rem == 64) ? 0 : rem;
3232
3233 if (m_size == 0) return;
3234 }
3235
3236 state->remainder = m_size & 63;
3237 size_t main_len = m_size - state->remainder;
3238
3239 crypto_stream_xchacha20_xor_ic(
3240 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3241 );
3242
3243 state->block_counter += main_len / 64;
3244
3245 if (state->remainder) {
3246 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3247 memcpy(next_block, m_ptr + main_len, state->remainder);
3248
3249 crypto_stream_xchacha20_xor_ic(
3250 next_block, next_block, 64, state->n, state->block_counter, state->k
3251 );
3252 memcpy(c_ptr + main_len, next_block, state->remainder);
3253
3254 state->block_counter++;
3255 }
3256}
3257
3258static inline void
3259sn_crypto_stream_xchacha20_xor_wrap_final(
3260 js_env_t *,
3261 js_receiver_t,
3262 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state
3263) {
3264 sodium_memzero(state->n, sizeof(state->n));
3265 sodium_memzero(state->k, sizeof(state->k));
3266 sodium_memzero(state->next_block, sizeof(state->next_block));
3267 state->remainder = 0;
3268}
3269
3270struct sn_crypto_stream_salsa20_xor_state {
3271 unsigned char n[crypto_stream_salsa20_NONCEBYTES];
3272 unsigned char k[crypto_stream_salsa20_KEYBYTES];
3273 unsigned char next_block[64];
3274 int remainder;
3275 uint64_t block_counter;
3276};
3277
3278static inline void
3279sn_crypto_stream_salsa20_xor_wrap_init(
3280 js_env_t *,
3281 js_receiver_t,
3282 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
3283 js_typedarray_span_t<> n,
3284 js_typedarray_span_t<> k
3285) {
3286 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
3287 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
3288
3289 state->remainder = 0;
3290 state->block_counter = 0;
3291 memcpy(state->n, n.data(), crypto_stream_salsa20_NONCEBYTES);
3292 memcpy(state->k, k.data(), crypto_stream_salsa20_KEYBYTES);
3293}
3294
3295static inline void
3296sn_crypto_stream_salsa20_xor_wrap_update(
3297 js_env_t *,
3298 js_receiver_t,
3299 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
3300 js_typedarray_span_t<> c,
3301 js_typedarray_span_t<> m
3302) {
3303 assert(c.size_bytes() == m.size_bytes());
3304
3305 auto *next_block = state->next_block;
3306
3307 size_t m_size = m.size_bytes();
3308 auto *c_ptr = c.data();
3309 auto *m_ptr = m.data();
3310
3311 if (state->remainder) {
3312 uint64_t offset = 0;
3313 int rem = state->remainder;
3314
3315 while (rem < 64 && offset < m_size) {
3316 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3317 ++offset;
3318 ++rem;
3319 }
3320
3321 c_ptr += offset;
3322 m_ptr += offset;
3323 m_size -= offset;
3324 state->remainder = (rem == 64) ? 0 : rem;
3325
3326 if (m_size == 0) return;
3327 }
3328
3329 state->remainder = m_size & 63;
3330 size_t main_len = m_size - state->remainder;
3331
3332 crypto_stream_salsa20_xor_ic(
3333 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3334 );
3335
3336 state->block_counter += main_len / 64;
3337
3338 if (state->remainder) {
3339 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3340 memcpy(next_block, m_ptr + main_len, state->remainder);
3341
3342 crypto_stream_salsa20_xor_ic(
3343 next_block, next_block, 64, state->n, state->block_counter, state->k
3344 );
3345 memcpy(c_ptr + main_len, next_block, state->remainder);
3346
3347 state->block_counter++;
3348 }
3349}
3350
3351static inline void
3352sn_crypto_stream_salsa20_xor_wrap_final(
3353 js_env_t *,
3354 js_receiver_t,
3355 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state
3356) {
3357 sodium_memzero(state->n, sizeof(state->n));
3358 sodium_memzero(state->k, sizeof(state->k));
3359 sodium_memzero(state->next_block, sizeof(state->next_block));
3360 state->remainder = 0;
3361}
3362
3363// Experimental API
3364
3365static inline void
3366sn_extension_tweak_ed25519_base(
3367 js_env_t *,
3368 js_receiver_t,
3369 js_typedarray_span_t<> n,
3370 js_typedarray_span_t<> p,
3371 js_typedarray_span_t<> ns
3372) {
3373 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3374 assert(p.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3375
3376 sn__extension_tweak_ed25519_base(p.data(), n.data(), ns.data(), ns.size_bytes());
3377}
3378
3379static inline int
3380sn_extension_tweak_ed25519_sign_detached(
3381 js_env_t *,
3382 js_receiver_t,
3383 js_typedarray_span_t<> sig,
3384 js_typedarray_span_t<> m,
3385 js_typedarray_span_t<> scalar,
3386 std::optional<js_typedarray_span_t<>> pk
3387) {
3388 assert(sig.size_bytes() == crypto_sign_BYTES);
3389 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3390
3391 uint8_t *pk_data = nullptr;
3392 if (pk) {
3393 assert(pk->size_bytes() == crypto_sign_PUBLICKEYBYTES);
3394 pk_data = pk->data();
3395 }
3396
3397 return sn__extension_tweak_ed25519_sign_detached(
3398 sig.data(),
3399 nullptr,
3400 m.data(),
3401 m.size_bytes(),
3402 scalar.data(),
3403 pk_data
3404 );
3405}
3406
3407static inline void
3408sn_extension_tweak_ed25519_sk_to_scalar(
3409 js_env_t *,
3410 js_receiver_t,
3411 js_typedarray_span_t<> n,
3412 js_typedarray_span_t<> sk
3413) {
3414 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3415 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
3416
3417 sn__extension_tweak_ed25519_sk_to_scalar(n.data(), sk.data());
3418}
3419
3420static inline void
3421sn_extension_tweak_ed25519_scalar(
3422 js_env_t *,
3423 js_receiver_t,
3424 js_typedarray_span_t<> scalar_out,
3425 js_typedarray_span_t<> scalar,
3426 js_typedarray_span_t<> ns
3427) {
3428 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3429 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3430
3431 sn__extension_tweak_ed25519_scalar(scalar_out.data(), scalar.data(), ns.data(), ns.size_bytes());
3432}
3433
3434static inline int
3435sn_extension_tweak_ed25519_pk(
3436 js_env_t *,
3437 js_receiver_t,
3438 js_typedarray_span_t<> tpk,
3439 js_typedarray_span_t<> pk,
3440 js_typedarray_span_t<> ns
3441) {
3442 assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3443 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3444
3445 return sn__extension_tweak_ed25519_pk(tpk.data(), pk.data(), ns.data(), ns.size_bytes());
3446}
3447
3448static inline void
3449sn_extension_tweak_ed25519_keypair(
3450 js_env_t *,
3451 js_receiver_t,
3452 js_typedarray_span_t<> pk,
3453 js_typedarray_span_t<> scalar_out,
3454 js_typedarray_span_t<> scalar_in,
3455 js_typedarray_span_t<> ns
3456) {
3457 assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3458 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3459 assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3460
3461 sn__extension_tweak_ed25519_keypair(
3462 pk.data(),
3463 scalar_out.data(),
3464 scalar_in.data(),
3465 ns.data(),
3466 ns.size_bytes()
3467 );
3468}
3469
3470static inline void
3471sn_extension_tweak_ed25519_scalar_add(
3472 js_env_t *,
3473 js_receiver_t,
3474 js_typedarray_span_t<> scalar_out,
3475 js_typedarray_span_t<> scalar,
3476 js_typedarray_span_t<> n
3477) {
3478 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3479 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3480 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3481
3482 sn__extension_tweak_ed25519_scalar_add(scalar_out.data(), scalar.data(), n.data());
3483}
3484
3485static inline int
3486sn_extension_tweak_ed25519_pk_add(
3487 js_env_t *,
3488 js_receiver_t,
3489 js_typedarray_span_t<> tpk,
3490 js_typedarray_span_t<> pk,
3491 js_typedarray_span_t<> p
3492) {
3493 assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3494 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3495 assert(p.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3496
3497 return sn__extension_tweak_ed25519_pk_add(tpk.data(), pk.data(), p.data());
3498}
3499
3500static inline int
3501sn_extension_tweak_ed25519_keypair_add(
3502 js_env_t *,
3503 js_receiver_t,
3504 js_typedarray_span_t<> pk,
3505 js_typedarray_span_t<> scalar_out,
3506 js_typedarray_span_t<> scalar_in,
3507 js_typedarray_span_t<> tweak
3508) {
3509 assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3510 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3511 assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3512 assert(tweak.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3513
3514 return sn__extension_tweak_ed25519_keypair_add(
3515 pk.data(),
3516 scalar_out.data(),
3517 scalar_in.data(),
3518 tweak.data()
3519 );
3520}
3521
3522static inline int
3523sn_extension_pbkdf2_sha512(
3524 js_env_t *,
3525 js_receiver_t,
3526 js_typedarray_span_t<> out,
3527 js_typedarray_span_t<> passwd,
3528 js_typedarray_span_t<> salt,
3529 uint64_t iter,
3530 uint64_t outlen
3531) {
3532
3533 assert(iter >= sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
3534 assert(outlen <= sn__extension_pbkdf2_sha512_BYTES_MAX);
3535 assert(out.size_bytes() >= static_cast<size_t>(outlen));
3536
3537 return sn__extension_pbkdf2_sha512(
3538 passwd.data(),
3539 passwd.size_bytes(),
3540 salt.data(),
3541 salt.size_bytes(),
3542 iter,
3543 out.data(),
3544 outlen
3545 );
3546}
3547
3548struct sn_async_pbkdf2_sha512_request : sn_async_task {
3549 js_persistent_t<js_arraybuffer_t> out_ref;
3550 std::span<uint8_t> out;
3551
3552 size_t outlen;
3553
3554 js_persistent_t<js_arraybuffer_t> pwd_ref;
3555 std::span<uint8_t> pwd;
3556
3557 js_persistent_t<js_arraybuffer_t> salt_ref;
3558 std::span<uint8_t> salt;
3559
3560 uint64_t iter;
3561
3562 sn_async_pbkdf2_sha512_request(js_env_t *env) : sn_async_task(env) {}
3563};
3564
3565static void
3566async_pbkdf2_sha512_execute(uv_work_t *uv_req) {
3567 auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
3568
3569 req->code = sn__extension_pbkdf2_sha512(
3570 req->pwd.data(),
3571 req->pwd.size(),
3572 req->salt.data(),
3573 req->salt.size(),
3574 req->iter,
3575 req->out.data(),
3576 req->outlen
3577 );
3578}
3579
3580static void
3581async_pbkdf2_sha512_complete(uv_work_t *uv_req, int status) {
3582 int err;
3583
3584 auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
3585
3586 if (req->exiting) return delete req;
3587
3588 js_handle_scope_t *scope;
3589 err = js_open_handle_scope(req->env, &scope);
3590 assert(err == 0);
3591
3592 js_function_t<void, int> callback;
3593 err = js_get_reference_value(req->env, req->cb, callback);
3594 assert(err == 0);
3595
3596 err = js_call_function_with_checkpoint(req->env, callback, req->code);
3597 assert(err != js_pending_exception);
3598
3599 err = js_close_handle_scope(req->env, scope);
3600 assert(err == 0);
3601
3602 delete req;
3603}
3604
3605static inline void
3606sn_extension_pbkdf2_sha512_async(
3607 js_env_t *env,
3608 js_receiver_t,
3609
3610 js_arraybuffer_t out,
3611 uint32_t out_offset,
3612 uint32_t out_len,
3613
3614 js_arraybuffer_t pwd,
3615 uint32_t pwd_offset,
3616 uint32_t pwd_len,
3617
3618 js_arraybuffer_t salt,
3619 uint32_t salt_offset,
3620 uint32_t salt_len,
3621
3622 uint64_t iter,
3623 uint64_t outlen,
3624
3625 js_function_t<void, int> callback
3626) {
3627 int err;
3628
3629 auto *req = new sn_async_pbkdf2_sha512_request(env);
3630
3631 std::span<uint8_t> out_view;
3632 err = js_get_arraybuffer_info(env, out, out_view);
3633 assert(err == 0);
3634 assert(out_offset + out_len <= out_view.size());
3635
3636 req->out = {&out_view[out_offset], out_len};
3637
3638 std::span<uint8_t> pwd_view;
3639 err = js_get_arraybuffer_info(env, pwd, pwd_view);
3640 assert(err == 0);
3641 assert(pwd_offset + pwd_len <= pwd_view.size());
3642
3643 req->pwd = {&pwd_view[pwd_offset], pwd_len};
3644
3645 std::span<uint8_t> salt_view;
3646 err = js_get_arraybuffer_info(env, salt, salt_view);
3647 assert(err == 0);
3648 assert(salt_offset + salt_len <= salt_view.size());
3649
3650 req->salt = {&salt_view[salt_offset], salt_len};
3651
3652 req->iter = iter;
3653 req->outlen = outlen;
3654
3655 err = js_create_reference(env, out, req->out_ref);
3656 assert(err == 0);
3657
3658 err = js_create_reference(env, pwd, req->pwd_ref);
3659 assert(err == 0);
3660
3661 err = js_create_reference(env, salt, req->salt_ref);
3662 assert(err == 0);
3663
3664 err = js_create_reference(env, callback, req->cb);
3665 assert(err == 0);
3666
3667 uv_loop_t *loop;
3668 err = js_get_env_loop(env, &loop);
3669 assert(err == 0);
3670
3671 err = uv_queue_work(loop, &req->task, async_pbkdf2_sha512_execute, async_pbkdf2_sha512_complete);
3672 assert(err == 0);
3673}
3674
3675static js_value_t *
3676sodium_native_exports(js_env_t *env, js_value_t *exports) {
3677 int err;
3678
3679 err = sodium_init();
3680 assert(err >= 0);
3681
3682#define V_FUNCTION(name, fn) \
3683 err = js_set_property<fn>(env, exports, name); \
3684 assert(err == 0);
3685
3686#define V_FUNCTION_NOSCOPE(name, fn) \
3687 err = js_set_property<fn, js_function_options_t{.scoped = false}>(env, exports, name); \
3688 assert(err == 0);
3689
3690#define V_UINT32(name, constant) \
3691 err = js_set_property(env, exports, name, static_cast<uint32_t>(constant)); \
3692 assert(err == 0);
3693
3694#define V_UINT64(name, constant) \
3695 err = js_set_property(env, exports, name, static_cast<int64_t>(std::min<uint64_t>(constant, js_max_safe_integer))); \
3696 assert(err == 0);
3697
3698#define V_STRING(name, str) \
3699 err = js_set_property(env, exports, name, str); \
3700 assert(err == 0);
3701
3702 // memory
3703
3704 V_FUNCTION("sodium_memzero", sn_sodium_memzero);
3705 V_FUNCTION("sodium_mlock", sn_sodium_mlock);
3706 V_FUNCTION("sodium_munlock", sn_sodium_munlock);
3707 V_FUNCTION("sodium_malloc", sn_sodium_malloc);
3708 V_FUNCTION("sodium_free", sn_sodium_free);
3709 V_FUNCTION("sodium_mprotect_noaccess", sn_sodium_mprotect_noaccess);
3710 V_FUNCTION("sodium_mprotect_readonly", sn_sodium_mprotect_readonly);
3711 V_FUNCTION("sodium_mprotect_readwrite", sn_sodium_mprotect_readwrite);
3712
3713 // randombytes
3714
3715 V_FUNCTION_NOSCOPE("randombytes_buf", sn_randombytes_buf);
3716 V_FUNCTION_NOSCOPE("randombytes_buf_deterministic", sn_randombytes_buf_deterministic);
3717 V_FUNCTION_NOSCOPE("randombytes_random", sn_randombytes_random);
3718 V_FUNCTION_NOSCOPE("randombytes_uniform", sn_randombytes_uniform);
3719
3720 V_UINT32("randombytes_SEEDBYTES", randombytes_SEEDBYTES);
3721
3722 // sodium helpers
3723
3724 V_FUNCTION("sodium_memcmp", sn_sodium_memcmp);
3725 V_FUNCTION("sodium_increment", sn_sodium_increment);
3726 V_FUNCTION("sodium_add", sn_sodium_add);
3727 V_FUNCTION("sodium_sub", sn_sodium_sub);
3728 V_FUNCTION("sodium_compare", sn_sodium_compare);
3729 V_FUNCTION("sodium_is_zero", sn_sodium_is_zero);
3730 V_FUNCTION("sodium_pad", sn_sodium_pad);
3731 V_FUNCTION("sodium_unpad", sn_sodium_unpad);
3732
3733 // crypto_aead
3734
3735 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_keygen", sn_crypto_aead_xchacha20poly1305_ietf_keygen);
3736 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt", sn_crypto_aead_xchacha20poly1305_ietf_encrypt);
3737 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt", sn_crypto_aead_xchacha20poly1305_ietf_decrypt);
3738 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached);
3739 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached);
3740 V_UINT32("crypto_aead_xchacha20poly1305_ietf_ABYTES", crypto_aead_xchacha20poly1305_ietf_ABYTES);
3741 V_UINT32("crypto_aead_xchacha20poly1305_ietf_KEYBYTES", crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
3742 V_UINT32("crypto_aead_xchacha20poly1305_ietf_NPUBBYTES", crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
3743 V_UINT32("crypto_aead_xchacha20poly1305_ietf_NSECBYTES", crypto_aead_xchacha20poly1305_ietf_NSECBYTES);
3744 V_UINT64("crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX);
3745
3746 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_keygen", sn_crypto_aead_chacha20poly1305_ietf_keygen);
3747 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt", sn_crypto_aead_chacha20poly1305_ietf_encrypt);
3748 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt", sn_crypto_aead_chacha20poly1305_ietf_decrypt);
3749 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached);
3750 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached);
3751 V_UINT32("crypto_aead_chacha20poly1305_ietf_ABYTES", crypto_aead_chacha20poly1305_ietf_ABYTES);
3752 V_UINT32("crypto_aead_chacha20poly1305_ietf_KEYBYTES", crypto_aead_chacha20poly1305_ietf_KEYBYTES);
3753 V_UINT32("crypto_aead_chacha20poly1305_ietf_NPUBBYTES", crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
3754 V_UINT32("crypto_aead_chacha20poly1305_ietf_NSECBYTES", crypto_aead_chacha20poly1305_ietf_NSECBYTES);
3755 V_UINT64("crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
3756
3757 // crypto_auth
3758
3759 V_FUNCTION("crypto_auth", sn_crypto_auth);
3760 V_FUNCTION("crypto_auth_verify", sn_crypto_auth_verify);
3761 V_UINT32("crypto_auth_BYTES", crypto_auth_BYTES);
3762 V_UINT32("crypto_auth_KEYBYTES", crypto_auth_KEYBYTES);
3763 V_STRING("crypto_auth_PRIMITIVE", crypto_auth_PRIMITIVE);
3764
3765 // crypto_box
3766
3767 V_FUNCTION("crypto_box_keypair", sn_crypto_box_keypair);
3768 V_FUNCTION("crypto_box_seed_keypair", sn_crypto_box_seed_keypair);
3769 V_FUNCTION("crypto_box_easy", sn_crypto_box_easy);
3770 V_FUNCTION("crypto_box_open_easy", sn_crypto_box_open_easy);
3771 V_FUNCTION("crypto_box_detached", sn_crypto_box_detached);
3772 V_FUNCTION("crypto_box_open_detached", sn_crypto_box_open_detached);
3773 V_FUNCTION("crypto_box_seal", sn_crypto_box_seal);
3774 V_FUNCTION_NOSCOPE("crypto_box_seal_open", sn_crypto_box_seal_open);
3775
3776 V_UINT32("crypto_box_SEEDBYTES", crypto_box_SEEDBYTES);
3777 V_UINT32("crypto_box_PUBLICKEYBYTES", crypto_box_PUBLICKEYBYTES);
3778 V_UINT32("crypto_box_SECRETKEYBYTES", crypto_box_SECRETKEYBYTES);
3779 V_UINT32("crypto_box_NONCEBYTES", crypto_box_NONCEBYTES);
3780 V_UINT32("crypto_box_MACBYTES", crypto_box_MACBYTES);
3781 V_UINT32("crypto_box_SEALBYTES", crypto_box_SEALBYTES);
3782 V_STRING("crypto_box_PRIMITIVE", crypto_box_PRIMITIVE);
3783
3784 // crypto_core
3785
3786 V_FUNCTION("crypto_core_ed25519_is_valid_point", sn_crypto_core_ed25519_is_valid_point);
3787 V_FUNCTION("crypto_core_ed25519_from_uniform", sn_crypto_core_ed25519_from_uniform);
3788 V_FUNCTION("crypto_core_ed25519_add", sn_crypto_core_ed25519_add);
3789 V_FUNCTION("crypto_core_ed25519_sub", sn_crypto_core_ed25519_sub);
3790 V_FUNCTION("crypto_core_ed25519_scalar_random", sn_crypto_core_ed25519_scalar_random);
3791 V_FUNCTION("crypto_core_ed25519_scalar_reduce", sn_crypto_core_ed25519_scalar_reduce);
3792 V_FUNCTION("crypto_core_ed25519_scalar_invert", sn_crypto_core_ed25519_scalar_invert);
3793 V_FUNCTION("crypto_core_ed25519_scalar_negate", sn_crypto_core_ed25519_scalar_negate);
3794 V_FUNCTION("crypto_core_ed25519_scalar_complement", sn_crypto_core_ed25519_scalar_complement);
3795 V_FUNCTION("crypto_core_ed25519_scalar_add", sn_crypto_core_ed25519_scalar_add);
3796 V_FUNCTION("crypto_core_ed25519_scalar_sub", sn_crypto_core_ed25519_scalar_sub);
3797 V_UINT32("crypto_core_ed25519_BYTES", crypto_core_ed25519_BYTES);
3798 V_UINT32("crypto_core_ed25519_UNIFORMBYTES", crypto_core_ed25519_UNIFORMBYTES);
3799 V_UINT32("crypto_core_ed25519_SCALARBYTES", crypto_core_ed25519_SCALARBYTES);
3800 V_UINT32("crypto_core_ed25519_NONREDUCEDSCALARBYTES", crypto_core_ed25519_NONREDUCEDSCALARBYTES);
3801
3802 // crypto_kdf
3803
3804 V_FUNCTION("crypto_kdf_keygen", sn_crypto_kdf_keygen);
3805 V_FUNCTION("crypto_kdf_derive_from_key", sn_crypto_kdf_derive_from_key);
3806 V_UINT32("crypto_kdf_BYTES_MIN", crypto_kdf_BYTES_MIN);
3807 V_UINT32("crypto_kdf_BYTES_MAX", crypto_kdf_BYTES_MAX);
3808 V_UINT32("crypto_kdf_CONTEXTBYTES", crypto_kdf_CONTEXTBYTES);
3809 V_UINT32("crypto_kdf_KEYBYTES", crypto_kdf_KEYBYTES);
3810 V_STRING("crypto_kdf_PRIMITIVE", crypto_kdf_PRIMITIVE);
3811
3812 // crypto_kx
3813
3814 V_FUNCTION("crypto_kx_keypair", sn_crypto_kx_keypair);
3815 V_FUNCTION("crypto_kx_seed_keypair", sn_crypto_kx_seed_keypair);
3816 V_FUNCTION("crypto_kx_client_session_keys", sn_crypto_kx_client_session_keys);
3817 V_FUNCTION("crypto_kx_server_session_keys", sn_crypto_kx_server_session_keys);
3818 V_UINT32("crypto_kx_PUBLICKEYBYTES", crypto_kx_PUBLICKEYBYTES);
3819 V_UINT32("crypto_kx_SECRETKEYBYTES", crypto_kx_SECRETKEYBYTES);
3820 V_UINT32("crypto_kx_SEEDBYTES", crypto_kx_SEEDBYTES);
3821 V_UINT32("crypto_kx_SESSIONKEYBYTES", crypto_kx_SESSIONKEYBYTES);
3822 V_STRING("crypto_kx_PRIMITIVE", crypto_kx_PRIMITIVE);
3823
3824 // crypto_generichash
3825
3826 V_FUNCTION_NOSCOPE("crypto_generichash", sn_crypto_generichash);
3827 V_FUNCTION("crypto_generichash_batch", sn_crypto_generichash_batch);
3828 V_FUNCTION_NOSCOPE("crypto_generichash_keygen", sn_crypto_generichash_keygen);
3829 V_FUNCTION_NOSCOPE("crypto_generichash_init", sn_crypto_generichash_init);
3830 V_FUNCTION_NOSCOPE("crypto_generichash_update", sn_crypto_generichash_update);
3831 V_FUNCTION_NOSCOPE("crypto_generichash_final", sn_crypto_generichash_final);
3832
3833 V_UINT32("crypto_generichash_STATEBYTES", sizeof(crypto_generichash_state));
3834 V_STRING("crypto_generichash_PRIMITIVE", crypto_generichash_PRIMITIVE);
3835 V_UINT32("crypto_generichash_BYTES_MIN", crypto_generichash_BYTES_MIN);
3836 V_UINT32("crypto_generichash_BYTES_MAX", crypto_generichash_BYTES_MAX);
3837 V_UINT32("crypto_generichash_BYTES", crypto_generichash_BYTES);
3838 V_UINT32("crypto_generichash_KEYBYTES_MIN", crypto_generichash_KEYBYTES_MIN);
3839 V_UINT32("crypto_generichash_KEYBYTES_MAX", crypto_generichash_KEYBYTES_MAX);
3840 V_UINT32("crypto_generichash_KEYBYTES", crypto_generichash_KEYBYTES);
3841
3842 // crypto_hash
3843
3844 V_FUNCTION("crypto_hash", sn_crypto_hash);
3845 V_UINT32("crypto_hash_BYTES", crypto_hash_BYTES);
3846 V_STRING("crypto_hash_PRIMITIVE", crypto_hash_PRIMITIVE);
3847
3848 V_FUNCTION("crypto_hash_sha256", sn_crypto_hash_sha256);
3849 V_FUNCTION("crypto_hash_sha256_init", sn_crypto_hash_sha256_init);
3850 V_FUNCTION("crypto_hash_sha256_update", sn_crypto_hash_sha256_update);
3851 V_FUNCTION("crypto_hash_sha256_final", sn_crypto_hash_sha256_final);
3852 V_UINT32("crypto_hash_sha256_STATEBYTES", sizeof(crypto_hash_sha256_state));
3853 V_UINT32("crypto_hash_sha256_BYTES", crypto_hash_sha256_BYTES);
3854
3855 V_FUNCTION("crypto_hash_sha512", sn_crypto_hash_sha512);
3856 V_FUNCTION("crypto_hash_sha512_init", sn_crypto_hash_sha512_init);
3857 V_FUNCTION("crypto_hash_sha512_update", sn_crypto_hash_sha512_update);
3858 V_FUNCTION("crypto_hash_sha512_final", sn_crypto_hash_sha512_final);
3859 V_UINT32("crypto_hash_sha512_STATEBYTES", sizeof(crypto_hash_sha512_state));
3860 V_UINT32("crypto_hash_sha512_BYTES", crypto_hash_sha512_BYTES);
3861
3862 // crypto_onetimeauth
3863
3864 V_FUNCTION("crypto_onetimeauth", sn_crypto_onetimeauth);
3865 V_FUNCTION("crypto_onetimeauth_verify", sn_crypto_onetimeauth_verify);
3866 V_FUNCTION("crypto_onetimeauth_init", sn_crypto_onetimeauth_init);
3867 V_FUNCTION("crypto_onetimeauth_update", sn_crypto_onetimeauth_update);
3868 V_FUNCTION("crypto_onetimeauth_final", sn_crypto_onetimeauth_final);
3869 V_UINT32("crypto_onetimeauth_STATEBYTES", sizeof(crypto_onetimeauth_state));
3870 V_UINT32("crypto_onetimeauth_BYTES", crypto_onetimeauth_BYTES);
3871 V_UINT32("crypto_onetimeauth_KEYBYTES", crypto_onetimeauth_KEYBYTES);
3872 V_STRING("crypto_onetimeauth_PRIMITIVE", crypto_onetimeauth_PRIMITIVE);
3873
3874 // crypto_pwhash
3875
3876 V_FUNCTION("crypto_pwhash", sn_crypto_pwhash);
3877 V_FUNCTION("crypto_pwhash_str", sn_crypto_pwhash_str);
3878 V_FUNCTION("crypto_pwhash_str_verify", sn_crypto_pwhash_str_verify);
3879 V_FUNCTION("crypto_pwhash_str_needs_rehash", sn_crypto_pwhash_str_needs_rehash);
3880 V_FUNCTION("crypto_pwhash_async", sn_crypto_pwhash_async);
3881 V_FUNCTION("crypto_pwhash_str_async", sn_crypto_pwhash_str_async);
3882 V_FUNCTION("crypto_pwhash_str_verify_async", sn_crypto_pwhash_str_verify_async);
3883 V_UINT32("crypto_pwhash_ALG_ARGON2I13", crypto_pwhash_ALG_ARGON2I13);
3884 V_UINT32("crypto_pwhash_ALG_ARGON2ID13", crypto_pwhash_ALG_ARGON2ID13);
3885 V_UINT32("crypto_pwhash_ALG_DEFAULT", crypto_pwhash_ALG_DEFAULT);
3886 V_UINT32("crypto_pwhash_BYTES_MIN", crypto_pwhash_BYTES_MIN);
3887 V_UINT32("crypto_pwhash_BYTES_MAX", crypto_pwhash_BYTES_MAX);
3888 V_UINT32("crypto_pwhash_PASSWD_MIN", crypto_pwhash_PASSWD_MIN);
3889 V_UINT32("crypto_pwhash_PASSWD_MAX", crypto_pwhash_PASSWD_MAX);
3890 V_UINT32("crypto_pwhash_SALTBYTES", crypto_pwhash_SALTBYTES);
3891 V_UINT32("crypto_pwhash_STRBYTES", crypto_pwhash_STRBYTES);
3892 V_STRING("crypto_pwhash_STRPREFIX", crypto_pwhash_STRPREFIX);
3893 V_UINT32("crypto_pwhash_OPSLIMIT_MIN", crypto_pwhash_OPSLIMIT_MIN);
3894 V_UINT32("crypto_pwhash_OPSLIMIT_MAX", crypto_pwhash_OPSLIMIT_MAX);
3895 V_UINT64("crypto_pwhash_MEMLIMIT_MIN", crypto_pwhash_MEMLIMIT_MIN);
3896 V_UINT64("crypto_pwhash_MEMLIMIT_MAX", crypto_pwhash_MEMLIMIT_MAX);
3897 V_UINT32("crypto_pwhash_OPSLIMIT_INTERACTIVE", crypto_pwhash_OPSLIMIT_INTERACTIVE);
3898 V_UINT64("crypto_pwhash_MEMLIMIT_INTERACTIVE", crypto_pwhash_MEMLIMIT_INTERACTIVE);
3899 V_UINT32("crypto_pwhash_OPSLIMIT_MODERATE", crypto_pwhash_OPSLIMIT_MODERATE);
3900 V_UINT64("crypto_pwhash_MEMLIMIT_MODERATE", crypto_pwhash_MEMLIMIT_MODERATE);
3901 V_UINT32("crypto_pwhash_OPSLIMIT_SENSITIVE", crypto_pwhash_OPSLIMIT_SENSITIVE);
3902 V_UINT64("crypto_pwhash_MEMLIMIT_SENSITIVE", crypto_pwhash_MEMLIMIT_SENSITIVE);
3903 V_STRING("crypto_pwhash_PRIMITIVE", crypto_pwhash_PRIMITIVE);
3904
3905 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256", sn_crypto_pwhash_scryptsalsa208sha256);
3906 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str", sn_crypto_pwhash_scryptsalsa208sha256_str);
3907 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify", sn_crypto_pwhash_scryptsalsa208sha256_str_verify);
3908 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_needs_rehash", sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash);
3909 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_async", sn_crypto_pwhash_scryptsalsa208sha256_async);
3910 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_async", sn_crypto_pwhash_scryptsalsa208sha256_str_async)
3911 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify_async", sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async);
3912 V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MIN", crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
3913 V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MAX", crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
3914 V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN", crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN);
3915 V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX", crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX);
3916 V_UINT64("crypto_pwhash_scryptsalsa208sha256_SALTBYTES", crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
3917 V_UINT64("crypto_pwhash_scryptsalsa208sha256_STRBYTES", crypto_pwhash_scryptsalsa208sha256_STRBYTES);
3918 V_STRING("crypto_pwhash_scryptsalsa208sha256_STRPREFIX", crypto_pwhash_scryptsalsa208sha256_STRPREFIX);
3919 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
3920 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
3921 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
3922 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
3923 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
3924 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
3925 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE);
3926 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE);
3927
3928 // crypto_scalarmult
3929
3930 V_FUNCTION("crypto_scalarmult_base", sn_crypto_scalarmult_base);
3931 V_FUNCTION("crypto_scalarmult", sn_crypto_scalarmult);
3932 V_STRING("crypto_scalarmult_PRIMITIVE", crypto_scalarmult_PRIMITIVE);
3933 V_UINT32("crypto_scalarmult_BYTES", crypto_scalarmult_BYTES);
3934 V_UINT32("crypto_scalarmult_SCALARBYTES", crypto_scalarmult_SCALARBYTES);
3935
3936 V_FUNCTION("crypto_scalarmult_ed25519_base", sn_crypto_scalarmult_ed25519_base);
3937 V_FUNCTION("crypto_scalarmult_ed25519", sn_crypto_scalarmult_ed25519);
3938 V_FUNCTION("crypto_scalarmult_ed25519_base_noclamp", sn_crypto_scalarmult_ed25519_base_noclamp);
3939 V_FUNCTION("crypto_scalarmult_ed25519_noclamp", sn_crypto_scalarmult_ed25519_noclamp);
3940 V_UINT32("crypto_scalarmult_ed25519_BYTES", crypto_scalarmult_ed25519_BYTES);
3941 V_UINT32("crypto_scalarmult_ed25519_SCALARBYTES", crypto_scalarmult_ed25519_SCALARBYTES);
3942
3943 // crypto_secretbox
3944
3945 V_FUNCTION("crypto_secretbox_easy", sn_crypto_secretbox_easy);
3946 V_FUNCTION("crypto_secretbox_open_easy", sn_crypto_secretbox_open_easy);
3947 V_FUNCTION("crypto_secretbox_detached", sn_crypto_secretbox_detached);
3948 V_FUNCTION("crypto_secretbox_open_detached", sn_crypto_secretbox_open_detached);
3949 V_UINT32("crypto_secretbox_KEYBYTES", crypto_secretbox_KEYBYTES);
3950 V_UINT32("crypto_secretbox_NONCEBYTES", crypto_secretbox_NONCEBYTES);
3951 V_UINT32("crypto_secretbox_MACBYTES", crypto_secretbox_MACBYTES);
3952 V_STRING("crypto_secretbox_PRIMITIVE", crypto_secretbox_PRIMITIVE);
3953
3954 // crypto_secretstream
3955
3956 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_keygen", sn_crypto_secretstream_xchacha20poly1305_keygen);
3957 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_push", sn_crypto_secretstream_xchacha20poly1305_init_push);
3958 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_pull", sn_crypto_secretstream_xchacha20poly1305_init_pull);
3959 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_push", sn_crypto_secretstream_xchacha20poly1305_push);
3960 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_pull", sn_crypto_secretstream_xchacha20poly1305_pull);
3961 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_rekey", sn_crypto_secretstream_xchacha20poly1305_rekey);
3962
3963 V_UINT32("crypto_secretstream_xchacha20poly1305_STATEBYTES", sizeof(crypto_secretstream_xchacha20poly1305_state));
3964 V_UINT32("crypto_secretstream_xchacha20poly1305_ABYTES", crypto_secretstream_xchacha20poly1305_ABYTES);
3965 V_UINT32("crypto_secretstream_xchacha20poly1305_HEADERBYTES", crypto_secretstream_xchacha20poly1305_HEADERBYTES);
3966 V_UINT32("crypto_secretstream_xchacha20poly1305_KEYBYTES", crypto_secretstream_xchacha20poly1305_KEYBYTES);
3967 V_UINT32("crypto_secretstream_xchacha20poly1305_TAGBYTES", 1);
3968 V_UINT64("crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX", crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX);
3969 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_MESSAGE", crypto_secretstream_xchacha20poly1305_TAG_MESSAGE);
3970 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_PUSH", crypto_secretstream_xchacha20poly1305_TAG_PUSH);
3971 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_REKEY", crypto_secretstream_xchacha20poly1305_TAG_REKEY);
3972 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_FINAL", crypto_secretstream_xchacha20poly1305_TAG_FINAL);
3973
3974 // crypto_shorthash
3975
3976 V_FUNCTION("crypto_shorthash", sn_crypto_shorthash);
3977 V_UINT32("crypto_shorthash_BYTES", crypto_shorthash_BYTES);
3978 V_UINT32("crypto_shorthash_KEYBYTES", crypto_shorthash_KEYBYTES);
3979 V_STRING("crypto_shorthash_PRIMITIVE", crypto_shorthash_PRIMITIVE);
3980
3981 // crypto_sign
3982
3983 V_FUNCTION("crypto_sign_keypair", sn_crypto_sign_keypair);
3984 V_FUNCTION("crypto_sign_seed_keypair", sn_crypto_sign_seed_keypair);
3985 V_FUNCTION("crypto_sign", sn_crypto_sign);
3986 V_FUNCTION("crypto_sign_open", sn_crypto_sign_open);
3987 V_FUNCTION("crypto_sign_detached", sn_crypto_sign_detached);
3988 V_FUNCTION_NOSCOPE("crypto_sign_verify_detached", sn_crypto_sign_verify_detached);
3989 V_FUNCTION("crypto_sign_ed25519_sk_to_pk", sn_crypto_sign_ed25519_sk_to_pk);
3990 V_FUNCTION("crypto_sign_ed25519_pk_to_curve25519", sn_crypto_sign_ed25519_pk_to_curve25519);
3991 V_FUNCTION("crypto_sign_ed25519_sk_to_curve25519", sn_crypto_sign_ed25519_sk_to_curve25519);
3992
3993 V_UINT32("crypto_sign_SEEDBYTES", crypto_sign_SEEDBYTES);
3994 V_UINT32("crypto_sign_PUBLICKEYBYTES", crypto_sign_PUBLICKEYBYTES);
3995 V_UINT32("crypto_sign_SECRETKEYBYTES", crypto_sign_SECRETKEYBYTES);
3996 V_UINT32("crypto_sign_BYTES", crypto_sign_BYTES);
3997
3998 // crypto_stream
3999
4000 V_FUNCTION("crypto_stream", sn_crypto_stream);
4001 V_UINT32("crypto_stream_KEYBYTES", crypto_stream_KEYBYTES);
4002 V_UINT32("crypto_stream_NONCEBYTES", crypto_stream_NONCEBYTES);
4003 V_STRING("crypto_stream_PRIMITIVE", crypto_stream_PRIMITIVE);
4004
4005 V_FUNCTION_NOSCOPE("crypto_stream_xor", sn_crypto_stream_xor);
4006 V_FUNCTION("crypto_stream_xor_init", sn_crypto_stream_xor_wrap_init);
4007 V_FUNCTION("crypto_stream_xor_update", sn_crypto_stream_xor_wrap_update);
4008 V_FUNCTION("crypto_stream_xor_final", sn_crypto_stream_xor_wrap_final);
4009 V_UINT32("crypto_stream_xor_STATEBYTES", sizeof(sn_crypto_stream_xor_state));
4010
4011 V_FUNCTION("crypto_stream_chacha20", sn_crypto_stream_chacha20);
4012 V_UINT32("crypto_stream_chacha20_KEYBYTES", crypto_stream_chacha20_KEYBYTES);
4013 V_UINT32("crypto_stream_chacha20_NONCEBYTES", crypto_stream_chacha20_NONCEBYTES);
4014 V_UINT64("crypto_stream_chacha20_MESSAGEBYTES_MAX", crypto_stream_chacha20_MESSAGEBYTES_MAX);
4015
4016 V_FUNCTION("crypto_stream_chacha20_xor", sn_crypto_stream_chacha20_xor);
4017 V_FUNCTION("crypto_stream_chacha20_xor_ic", sn_crypto_stream_chacha20_xor_ic);
4018 V_FUNCTION("crypto_stream_chacha20_xor_init", sn_crypto_stream_chacha20_xor_wrap_init);
4019 V_FUNCTION("crypto_stream_chacha20_xor_update", sn_crypto_stream_chacha20_xor_wrap_update);
4020 V_FUNCTION("crypto_stream_chacha20_xor_final", sn_crypto_stream_chacha20_xor_wrap_final);
4021 V_UINT32("crypto_stream_chacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_xor_state));
4022
4023 V_FUNCTION("crypto_stream_chacha20_ietf", sn_crypto_stream_chacha20_ietf);
4024 V_UINT32("crypto_stream_chacha20_ietf_KEYBYTES", crypto_stream_chacha20_ietf_KEYBYTES);
4025 V_UINT32("crypto_stream_chacha20_ietf_NONCEBYTES", crypto_stream_chacha20_ietf_NONCEBYTES);
4026 V_UINT64("crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX", crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX);
4027 V_UINT32("crypto_stream_chacha20_ietf_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_ietf_xor_state));
4028
4029 V_FUNCTION("crypto_stream_chacha20_ietf_xor", sn_crypto_stream_chacha20_ietf_xor);
4030 V_FUNCTION("crypto_stream_chacha20_ietf_xor_ic", sn_crypto_stream_chacha20_ietf_xor_ic);
4031 V_FUNCTION("crypto_stream_chacha20_ietf_xor_init", sn_crypto_stream_chacha20_ietf_xor_wrap_init);
4032 V_FUNCTION("crypto_stream_chacha20_ietf_xor_update", sn_crypto_stream_chacha20_ietf_xor_wrap_update);
4033 V_FUNCTION("crypto_stream_chacha20_ietf_xor_final", sn_crypto_stream_chacha20_ietf_xor_wrap_final);
4034
4035 V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
4036 V_UINT32("crypto_stream_xchacha20_KEYBYTES", crypto_stream_xchacha20_KEYBYTES);
4037 V_UINT32("crypto_stream_xchacha20_NONCEBYTES", crypto_stream_xchacha20_NONCEBYTES);
4038 V_UINT64("crypto_stream_xchacha20_MESSAGEBYTES_MAX", crypto_stream_xchacha20_MESSAGEBYTES_MAX);
4039
4040 V_FUNCTION("crypto_stream_xchacha20_xor", sn_crypto_stream_xchacha20_xor);
4041 V_FUNCTION("crypto_stream_xchacha20_xor_ic", sn_crypto_stream_xchacha20_xor_ic);
4042 V_FUNCTION("crypto_stream_xchacha20_xor_init", sn_crypto_stream_xchacha20_xor_wrap_init);
4043 V_FUNCTION("crypto_stream_xchacha20_xor_update", sn_crypto_stream_xchacha20_xor_wrap_update);
4044 V_FUNCTION("crypto_stream_xchacha20_xor_final", sn_crypto_stream_xchacha20_xor_wrap_final);
4045 V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
4046 V_UINT32("crypto_stream_xchacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_xchacha20_xor_state));
4047
4048 V_FUNCTION("crypto_stream_salsa20", sn_crypto_stream_salsa20);
4049 V_UINT32("crypto_stream_salsa20_KEYBYTES", crypto_stream_salsa20_KEYBYTES);
4050 V_UINT32("crypto_stream_salsa20_NONCEBYTES", crypto_stream_salsa20_NONCEBYTES);
4051 V_UINT64("crypto_stream_salsa20_MESSAGEBYTES_MAX", crypto_stream_salsa20_MESSAGEBYTES_MAX);
4052
4053 V_FUNCTION("crypto_stream_salsa20_xor", sn_crypto_stream_salsa20_xor);
4054 V_FUNCTION("crypto_stream_salsa20_xor_ic", sn_crypto_stream_salsa20_xor_ic);
4055 V_FUNCTION("crypto_stream_salsa20_xor_init", sn_crypto_stream_salsa20_xor_wrap_init);
4056 V_FUNCTION("crypto_stream_salsa20_xor_update", sn_crypto_stream_salsa20_xor_wrap_update);
4057 V_FUNCTION("crypto_stream_salsa20_xor_final", sn_crypto_stream_salsa20_xor_wrap_final);
4058 V_UINT32("crypto_stream_salsa20_xor_STATEBYTES", sizeof(sn_crypto_stream_salsa20_xor_state));
4059
4060 // extensions
4061
4062 // tweak
4063
4064 V_FUNCTION("extension_tweak_ed25519_base", sn_extension_tweak_ed25519_base);
4065 V_FUNCTION("extension_tweak_ed25519_sign_detached", sn_extension_tweak_ed25519_sign_detached);
4066 V_FUNCTION("extension_tweak_ed25519_sk_to_scalar", sn_extension_tweak_ed25519_sk_to_scalar);
4067 V_FUNCTION("extension_tweak_ed25519_scalar", sn_extension_tweak_ed25519_scalar);
4068 V_FUNCTION("extension_tweak_ed25519_pk", sn_extension_tweak_ed25519_pk);
4069 V_FUNCTION("extension_tweak_ed25519_keypair", sn_extension_tweak_ed25519_keypair);
4070 V_FUNCTION("extension_tweak_ed25519_scalar_add", sn_extension_tweak_ed25519_scalar_add);
4071 V_FUNCTION("extension_tweak_ed25519_pk_add", sn_extension_tweak_ed25519_pk_add);
4072 V_FUNCTION("extension_tweak_ed25519_keypair_add", sn_extension_tweak_ed25519_keypair_add);
4073 V_UINT32("extension_tweak_ed25519_BYTES", sn__extension_tweak_ed25519_BYTES);
4074 V_UINT32("extension_tweak_ed25519_SCALARBYTES", sn__extension_tweak_ed25519_SCALARBYTES);
4075
4076 // pbkdf2
4077
4078 V_FUNCTION("extension_pbkdf2_sha512", sn_extension_pbkdf2_sha512);
4079 V_FUNCTION("extension_pbkdf2_sha512_async", sn_extension_pbkdf2_sha512_async);
4080 V_UINT32("extension_pbkdf2_sha512_SALTBYTES", sn__extension_pbkdf2_sha512_SALTBYTES);
4081 V_UINT32("extension_pbkdf2_sha512_HASHBYTES", sn__extension_pbkdf2_sha512_HASHBYTES);
4082 V_UINT32("extension_pbkdf2_sha512_ITERATIONS_MIN", sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
4083 V_UINT64("extension_pbkdf2_sha512_BYTES_MAX", sn__extension_pbkdf2_sha512_BYTES_MAX);
4084
4085#undef V_FUNCTION
4086#undef V_FUNCTION_NOSCOPE
4087#undef V_UINT32
4088#undef V_UINT64
4089#undef V_STRING
4090
4091 return exports;
4092}
4093
4094BARE_MODULE(sodium_native, sodium_native_exports)
node_modules/noise-curve-ed/node_modules/sodium-native/binding.js +2 -0
……@@ -0,0 +1,2 @@
1require.addon = require('require-addon')
2module.exports = require.addon('.', __filename)
node_modules/noise-curve-ed/node_modules/sodium-native/extensions/pbkdf2/pbkdf2.c +90 -0
……@@ -0,0 +1,90 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
29 */
30
31#include <string.h>
32#include <sodium.h>
33
34#include "pbkdf2.h"
35
36/**
37 * pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
38 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
39 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
40 */
41int
42sn__extension_pbkdf2_sha512(const unsigned char *passwd, size_t passwdlen,
43 const unsigned char *salt, size_t saltlen, uint64_t c,
44 unsigned char *buf, size_t dkLen)
45{
46 crypto_auth_hmacsha512_state PShctx, hctx;
47 size_t i;
48 unsigned char ivec[4];
49 unsigned char U[64];
50 unsigned char T[64];
51 uint64_t j;
52 unsigned int k;
53 size_t clen;
54
55 if (dkLen > sn__extension_pbkdf2_sha512_BYTES_MAX) {
56 return -1;
57 }
58
59 crypto_auth_hmacsha512_init(&PShctx, passwd, passwdlen);
60 crypto_auth_hmacsha512_update(&PShctx, salt, saltlen);
61
62 for (i = 0; i * crypto_auth_hmacsha512_BYTES < dkLen; i++) {
63 SN_PBKDF2_STORE32_BE(ivec, (uint32_t)(i + 1));
64 memcpy(&hctx, &PShctx, sizeof(crypto_auth_hmacsha512_state));
65 crypto_auth_hmacsha512_update(&hctx, ivec, 4);
66 crypto_auth_hmacsha512_final(&hctx, U);
67
68 memcpy(T, U, crypto_auth_hmacsha512_BYTES);
69 /* LCOV_EXCL_START */
70 for (j = 2; j <= c; j++) {
71 crypto_auth_hmacsha512_init(&hctx, passwd, passwdlen);
72 crypto_auth_hmacsha512_update(&hctx, U, crypto_auth_hmacsha512_BYTES);
73 crypto_auth_hmacsha512_final(&hctx, U);
74
75 for (k = 0; k < crypto_auth_hmacsha512_BYTES; k++) {
76 T[k] ^= U[k];
77 }
78 }
79 /* LCOV_EXCL_STOP */
80
81 clen = dkLen - i * crypto_auth_hmacsha512_BYTES;
82 if (clen > crypto_auth_hmacsha512_BYTES) {
83 clen = crypto_auth_hmacsha512_BYTES;
84 }
85 memcpy(&buf[i * crypto_auth_hmacsha512_BYTES], T, clen);
86 }
87 sodium_memzero((void *) &PShctx, sizeof PShctx);
88
89 return 0;
90}
node_modules/noise-curve-ed/node_modules/sodium-native/extensions/pbkdf2/pbkdf2.h +60 -0
……@@ -0,0 +1,60 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28/*
29 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
30 */
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35#include <sodium.h>
36
37#define SN_PBKDF2_STORE32_BE(buf, n32) \
38 buf[0] = n32 >> 24 & 0xff; \
39 buf[1] = n32 >> 16 & 0xff; \
40 buf[2] = n32 >> 8 & 0xff; \
41 buf[3] = n32 >> 0 & 0xff;
42
43#define sn__extension_pbkdf2_sha512_SALTBYTES 16U
44
45#define sn__extension_pbkdf2_sha512_HASHBYTES crypto_hash_sha512_BYTES
46
47#define sn__extension_pbkdf2_sha512_ITERATIONS_MIN 1U
48
49#define sn__extension_pbkdf2_sha512_BYTES_MAX 0x3fffffffc0ULL
50
51/**
52 * extension_pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
53 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
54 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
55 */
56int sn__extension_pbkdf2_sha512(const unsigned char *, size_t, const unsigned char *, size_t,
57 uint64_t, unsigned char *, size_t);
58#ifdef __cplusplus
59};
60#endif
node_modules/noise-curve-ed/node_modules/sodium-native/extensions/tweak/tweak.c +206 -0
……@@ -0,0 +1,206 @@
1#include "tweak.h"
2
3/*
4 *EXPERIMENTAL API*
5
6 This module is an experimental implementation of a key tweaking protocol
7 over ed25519 keys. The signature algorithm has been reimplemented from
8 libsodium, but the nonce generation algorithm is *non-standard*.
9
10 Use at your own risk
11*/
12
13static void _extension_tweak_nonce (unsigned char *nonce, const unsigned char *n,
14 const unsigned char *m, unsigned long long mlen)
15{
16 // dom2(x, y) with x = 0 (not prehashed) and y = "crypto_tweak_ed25519"
17 static const unsigned char TWEAK_PREFIX[32 + 2 + 20] = {
18 'S', 'i', 'g', 'E', 'd', '2', '5', '5', '1', '9', ' ',
19 'n', 'o', ' ', 'E', 'd', '2', '5', '5', '1', '9', ' ',
20 'c', 'o', 'l', 'l', 'i', 's', 'i', 'o', 'n', 's', 0,
21 20, 'c', 'r', 'y', 'p', 't', 'o', '_', 't', 'w', 'e',
22 'a', 'k', '_', 'e', 'd', '2', '5', '5', '1', '9'
23 };
24
25 crypto_hash_sha512_state hs;
26
27 crypto_hash_sha512_init(&hs);
28 crypto_hash_sha512_update(&hs, TWEAK_PREFIX, sizeof TWEAK_PREFIX);
29 crypto_hash_sha512_update(&hs, n, 32);
30 crypto_hash_sha512_update(&hs, m, mlen);
31 crypto_hash_sha512_final(&hs, nonce);
32}
33
34static inline void
35_crypto_sign_ed25519_clamp(unsigned char k[32])
36{
37 k[0] &= 248;
38 k[31] &= 127;
39 k[31] |= 64;
40}
41
42static void _extension_tweak_ed25519(unsigned char *q, unsigned char *n,
43 const unsigned char *ns, unsigned long long nslen)
44{
45 sodium_memzero(q, sizeof q);
46
47 crypto_hash(n, ns, nslen);
48 n[31] &= 127; // clear highest bit
49
50 crypto_scalarmult_ed25519_base_noclamp(q, n);
51
52 // hash tweak until we get a valid tweaked q
53 while (crypto_core_ed25519_is_valid_point(q) != 1) {
54 crypto_hash(n, n, 32);
55 n[31] &= 127; // clear highest bit
56
57 crypto_scalarmult_ed25519_base_noclamp(q, n);
58 }
59}
60
61void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
62 const unsigned char *ns, unsigned long long nslen)
63{
64 unsigned char n64[64];
65
66 _extension_tweak_ed25519(pk, n64, ns, nslen);
67
68 SN_TWEAK_COPY_32(scalar, n64)
69}
70
71int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
72 const unsigned char *m, unsigned long long mlen,
73 const unsigned char *n, unsigned char *pk)
74{
75 crypto_hash_sha512_state hs;
76
77 unsigned char nonce[64];
78 unsigned char R[32];
79 unsigned char hram[64];
80 unsigned char _pk[32];
81
82 // check if pk was passed
83 if (pk == NULL) {
84 pk = _pk;
85
86 // derive pk from scalar
87 if (crypto_scalarmult_ed25519_base_noclamp(pk, n) != 0) {
88 return -1;
89 }
90 }
91
92 _extension_tweak_nonce(nonce, n, m, mlen);
93 crypto_core_ed25519_scalar_reduce(nonce, nonce);
94
95 // R = G ^ nonce : curve point from nonce
96 if (crypto_scalarmult_ed25519_base_noclamp(R, nonce) != 0) {
97 return -1;
98 }
99
100 // generate challenge as h(ram) = hash(R, pk, message)
101 crypto_hash_sha512_init(&hs);
102 crypto_hash_sha512_update(&hs, R, 32);
103 crypto_hash_sha512_update(&hs, pk, 32);
104 crypto_hash_sha512_update(&hs, m, mlen);
105
106 crypto_hash_sha512_final(&hs, hram);
107
108 crypto_core_ed25519_scalar_reduce(hram, hram);
109
110 // sig = nonce + n * h(ram)
111 crypto_core_ed25519_scalar_mul(sig, hram, n);
112 crypto_core_ed25519_scalar_add(sig + 32, nonce, sig);
113
114 SN_TWEAK_COPY_32(sig, R)
115
116 if (siglen_p != NULL) {
117 *siglen_p = 64U;
118 }
119
120 return 0;
121}
122
123// tweak a secret key
124void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *n, const unsigned char *sk)
125{
126 unsigned char n64[64];
127
128 // get sk scalar from seed, cf. crypto_sign_keypair_seed
129 crypto_hash(n64, sk, 32);
130 _crypto_sign_ed25519_clamp(n64);
131
132 SN_TWEAK_COPY_32(n, n64)
133}
134
135// tweak a secret key
136void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
137 const unsigned char *scalar,
138 const unsigned char *ns,
139 unsigned long long nslen)
140{
141 unsigned char n[64];
142 unsigned char q[32];
143
144 _extension_tweak_ed25519(q, n, ns, nslen);
145 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
146}
147
148// tweak a public key
149int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
150 const unsigned char *pk,
151 const unsigned char *ns,
152 unsigned long long nslen)
153{
154 unsigned char n[64];
155 unsigned char q[32];
156
157 _extension_tweak_ed25519(q, n, ns, nslen);
158 return crypto_core_ed25519_add(tpk, q, pk);
159}
160
161
162void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
163 unsigned char *scalar, const unsigned char *ns,
164 unsigned long long nslen)
165{
166 unsigned char n64[64];
167
168 crypto_hash(n64, ns, nslen);
169 n64[31] &= 127; // clear highest bit
170
171 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
172 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
173
174 // hash tweak until we get a valid tweaked point
175 while (crypto_core_ed25519_is_valid_point(pk) != 1) {
176 crypto_hash(n64, n64, 32);
177 n64[31] &= 127; // clear highest bit
178
179 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
180 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
181 }
182}
183
184// add tweak to scalar
185void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
186 const unsigned char *scalar,
187 const unsigned char *n)
188{
189 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
190}
191
192// add tweak point to public key
193int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
194 const unsigned char *pk,
195 const unsigned char *q)
196{
197 return crypto_core_ed25519_add(tpk, pk, q);
198}
199
200
201int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
202 unsigned char *scalar, const unsigned char *tweak)
203{
204 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, tweak);
205 return crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
206}
node_modules/noise-curve-ed/node_modules/sodium-native/extensions/tweak/tweak.h +62 -0
……@@ -0,0 +1,62 @@
1#ifdef __cplusplus
2extern "C" {
3#endif
4
5#include <sodium.h>
6
7// copy 32 bytes using int64_t pointers
8#define SN_TWEAK_COPY_32(a, b) \
9 { \
10 long long *dst = (long long *) a; \
11 long long *src = (long long *) b; \
12 dst[0] = src[0]; \
13 dst[1] = src[1]; \
14 dst[2] = src[2]; \
15 dst[3] = src[3]; \
16 }
17
18#define sn__extension_tweak_ed25519_BYTES crypto_sign_ed25519_PUBLICKEYBYTES
19
20#define sn__extension_tweak_ed25519_SCALARBYTES crypto_scalarmult_ed25519_SCALARBYTES
21
22int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
23 const unsigned char *m, unsigned long long mlen,
24 const unsigned char *n, unsigned char *pk);
25
26void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
27 const unsigned char *ns, unsigned long long nslen);
28
29void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *scalar, const unsigned char *sk);
30
31// tweak a secret key
32void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
33 const unsigned char *scalar,
34 const unsigned char *ns,
35 unsigned long long nslen);
36
37// tweak a public key
38int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
39 const unsigned char *pk,
40 const unsigned char *ns,
41 unsigned long long nslen);
42
43void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
44 unsigned char *scalar, const unsigned char *ns,
45 unsigned long long nslen);
46
47// add tweak scalar to private key
48void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
49 const unsigned char *scalar,
50 const unsigned char *n);
51
52// add tweak point to public key
53int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
54 const unsigned char *pk,
55 const unsigned char *q);
56
57int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
58 unsigned char *scalar, const unsigned char *tweak);
59
60#ifdef __cplusplus
61};
62#endif
node_modules/noise-curve-ed/node_modules/sodium-native/index.js +3231 -0
……@@ -0,0 +1,3231 @@
1const assert = require('assert')
2const binding = require('./binding')
3const { isNode } = require('which-runtime')
4
5const OPTIONAL = Buffer.from(new ArrayBuffer(0))
6
7module.exports = exports = { ...binding }
8
9// memory
10
11exports.sodium_memzero = function (buf) {
12 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
13
14 binding.sodium_memzero(buf)
15}
16
17exports.sodium_mlock = function (buf) {
18 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
19
20 const res = binding.sodium_mlock(buf)
21
22 if (res !== 0) throw new Error('memory lock failed')
23}
24
25exports.sodium_munlock = function (buf) {
26 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
27
28 const res = binding.sodium_munlock(buf)
29
30 if (res !== 0) throw new Error('memory unlock failed')
31}
32
33exports.sodium_malloc = function (size) {
34 assert(size >= 0, 'invalid size')
35
36 const buf = Buffer.from(binding.sodium_malloc(size))
37 buf.secure = true
38 return buf
39}
40
41exports.sodium_free = function (buf) {
42 if (!buf || !buf.secure) return
43
44 binding.sodium_free(buf.buffer)
45}
46
47exports.sodium_mprotect_noaccess = function (buf) {
48 const res = binding.sodium_mprotect_noaccess(buf.buffer)
49
50 if (res !== 0) throw new Error('failed to lock buffer')
51}
52
53exports.sodium_mprotect_readonly = function (buf) {
54 const res = binding.sodium_mprotect_readonly(buf.buffer)
55
56 if (res !== 0) throw new Error('failed to unlock buffer')
57}
58
59exports.sodium_mprotect_readwrite = function (buf) {
60 const res = binding.sodium_mprotect_readwrite(buf.buffer)
61
62 if (res !== 0) throw new Error('failed to unlock buffer')
63}
64
65// crypto_randombytes
66
67exports.randombytes_buf = function (buffer) {
68 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
69
70 binding.randombytes_buf(buffer.buffer, buffer.byteOffset, buffer.byteLength)
71}
72
73exports.randombytes_buf_deterministic = function (buffer, seed) {
74 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
75 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
76 assert(
77 seed.byteLength === binding.randombytes_SEEDBYTES,
78 "seed must be 'randombytes_SEEDBYTES' bytes"
79 )
80
81 binding.randombytes_buf_deterministic(
82 buffer.buffer,
83 buffer.byteOffset,
84 buffer.byteLength,
85
86 seed.buffer,
87 seed.byteOffset,
88 seed.byteLength
89 )
90}
91
92// sodium_helpers
93
94exports.sodium_memcmp = function (a, b) {
95 assert(ArrayBuffer.isView(a), 'a must be a typed array')
96 assert(ArrayBuffer.isView(b), 'b must be a typed array')
97 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
98
99 return binding.sodium_memcmp(a, b)
100}
101
102exports.sodium_add = function (a, b) {
103 assert(ArrayBuffer.isView(a), 'a must be a typed array')
104 assert(ArrayBuffer.isView(b), 'b must be a typed array')
105 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
106
107 binding.sodium_add(a, b)
108}
109
110exports.sodium_sub = function (a, b) {
111 assert(ArrayBuffer.isView(a), 'a must be a typed array')
112 assert(ArrayBuffer.isView(b), 'b must be a typed array')
113 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
114
115 binding.sodium_sub(a, b)
116}
117
118exports.sodium_compare = function (a, b) {
119 assert(ArrayBuffer.isView(a), 'a must be a typed array')
120 assert(ArrayBuffer.isView(b), 'b must be a typed array')
121 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
122
123 return binding.sodium_compare(a, b)
124}
125
126exports.sodium_is_zero = function (buffer, length) {
127 if (length === undefined) length = buffer.byteLength
128
129 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
130 assert(length >= 0 && length <= buffer.byteLength, 'invalid length')
131
132 return binding.sodium_is_zero(buffer, length)
133}
134
135exports.sodium_pad = function (buffer, unpaddedBuflen, blockSize) {
136 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
137 assert(unpaddedBuflen <= buffer.byteLength, 'unpadded length cannot exceed buffer length')
138 assert(blockSize <= buffer.byteLength, 'block size cannot exceed buffer length')
139 assert(blockSize >= 1, 'block size must be at least 1 byte')
140 assert(
141 buffer.byteLength >= unpaddedBuflen + (blockSize - (unpaddedBuflen % blockSize)),
142 'buf not long enough'
143 )
144
145 return binding.sodium_pad(buffer, unpaddedBuflen, blockSize)
146}
147
148exports.sodium_unpad = function (buffer, paddedBuflen, blockSize) {
149 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
150 assert(paddedBuflen <= buffer.byteLength, 'unpadded length cannot exceed buffer length')
151 assert(blockSize <= buffer.byteLength, 'block size cannot exceed buffer length')
152 assert(blockSize >= 1, 'block size must be at least 1 byte')
153
154 return binding.sodium_unpad(buffer, paddedBuflen, blockSize)
155}
156
157// crypto_sign
158
159exports.crypto_sign_keypair = function (pk, sk) {
160 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
161 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
162 assert(
163 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
164 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
165 )
166 assert(
167 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
168 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
169 )
170
171 const res = binding.crypto_sign_keypair(pk, sk)
172
173 if (res !== 0) throw new Error('status: ' + res)
174}
175
176exports.crypto_sign_seed_keypair = function (pk, sk, seed) {
177 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
178 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
179 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
180 assert(
181 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
182 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
183 )
184 assert(
185 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
186 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
187 )
188 assert(
189 seed.byteLength === binding.crypto_sign_SEEDBYTES,
190 "seed must be 'crypto_sign_SEEDBYTES' bytes"
191 )
192
193 const res = binding.crypto_sign_seed_keypair(pk, sk, seed)
194
195 if (res !== 0) throw new Error('status: ' + res)
196}
197
198exports.crypto_sign = function (sm, m, sk) {
199 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
200 assert(ArrayBuffer.isView(m), 'm must be a typed array')
201 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
202 assert(
203 sm.byteLength === binding.crypto_sign_BYTES + m.byteLength,
204 "sm must be 'm.byteLength + crypto_sign_BYTES' bytes"
205 )
206 assert(
207 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
208 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
209 )
210
211 const res = binding.crypto_sign(sm, m, sk)
212
213 if (res !== 0) throw new Error('status: ' + res)
214}
215
216exports.crypto_sign_open = function (m, sm, pk) {
217 assert(ArrayBuffer.isView(m), 'm must be a typed array')
218 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
219 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
220 assert(
221 sm.byteLength >= binding.crypto_sign_BYTES,
222 "sm must be at least 'crypto_sign_BYTES' bytes"
223 )
224 assert(
225 m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
226 "m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
227 )
228 assert(
229 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
230 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
231 )
232
233 const res = binding.crypto_sign_open(m, sm, pk)
234
235 if (res !== 0) throw new Error('status: ' + res)
236}
237
238exports.crypto_sign_open = function (m, sm, pk) {
239 assert(ArrayBuffer.isView(m), 'm must be a typed array')
240 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
241 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
242 assert(
243 sm.byteLength >= binding.crypto_sign_BYTES,
244 "sm must be at least 'crypto_sign_BYTES' bytes"
245 )
246 assert(
247 m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
248 "m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
249 )
250 assert(
251 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
252 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
253 )
254
255 return binding.crypto_sign_open(m, sm, pk)
256}
257
258exports.crypto_sign_detached = function (sig, m, sk) {
259 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
260 assert(ArrayBuffer.isView(m), 'm must be a typed array')
261 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
262 assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes")
263 assert(
264 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
265 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
266 )
267
268 const res = binding.crypto_sign_detached(sig, m, sk)
269
270 if (res !== 0) throw new Error('status: ' + res)
271}
272
273exports.crypto_sign_verify_detached = function (sig, m, pk) {
274 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
275 assert(ArrayBuffer.isView(m), 'm must be a typed array')
276 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
277 assert(
278 sig.byteLength >= binding.crypto_sign_BYTES,
279 "sig must be at least 'crypto_sign_BYTES' bytes"
280 )
281 assert(
282 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
283 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
284 )
285
286 return binding.crypto_sign_verify_detached(
287 sig.buffer,
288 sig.byteOffset,
289 sig.byteLength,
290
291 m.buffer,
292 m.byteOffset,
293 m.byteLength,
294
295 pk.buffer,
296 pk.byteOffset,
297 pk.byteLength
298 )
299}
300
301exports.crypto_sign_ed25519_sk_to_pk = function (pk, sk) {
302 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
303 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
304 assert(
305 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
306 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
307 )
308 assert(
309 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
310 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
311 )
312
313 const res = binding.crypto_sign_ed25519_sk_to_pk(pk, sk)
314
315 if (res !== 0) throw new Error('status: ' + res)
316}
317
318exports.crypto_sign_ed25519_pk_to_curve25519 = function (x25519pk, ed25519pk) {
319 assert(ArrayBuffer.isView(x25519pk), 'x25519pk must be a typed array')
320 assert(ArrayBuffer.isView(ed25519pk), 'ed25519pk must be a typed array')
321 assert(
322 x25519pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
323 "x25519pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
324 )
325 assert(
326 ed25519pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
327 "ed25519pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
328 )
329
330 const res = binding.crypto_sign_ed25519_pk_to_curve25519(x25519pk, ed25519pk)
331
332 if (res !== 0) throw new Error('status: ' + res)
333}
334
335exports.crypto_sign_ed25519_sk_to_curve25519 = function (x25519sk, ed25519sk) {
336 assert(ArrayBuffer.isView(x25519sk), 'x25519sk must be a typed array')
337 assert(ArrayBuffer.isView(ed25519sk), 'ed25519sk must be a typed array')
338 assert(
339 x25519sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
340 "x25519sk must be 'crypto_box_SECRETKEYBYTES' bytes"
341 )
342
343 const edLen = ed25519sk.byteLength
344
345 assert(
346 edLen === binding.crypto_sign_SECRETKEYBYTES || edLen === binding.crypto_box_SECRETKEYBYTES,
347 "ed25519sk must be 'crypto_sign_SECRETKEYBYTES' or 'crypto_sign_SECRETKEYBYTES - crypto_sign_PUBLICKEYBYTES' bytes"
348 )
349
350 const res = binding.crypto_sign_ed25519_sk_to_curve25519(x25519sk, ed25519sk)
351
352 if (res !== 0) throw new Error('status: ' + res)
353}
354
355// crypto_box
356
357exports.crypto_box_keypair = function (pk, sk) {
358 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
359 assert(
360 pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
361 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
362 )
363 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
364 assert(
365 sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
366 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
367 )
368
369 const res = binding.crypto_box_keypair(pk, sk)
370
371 if (res !== 0) throw new Error('status: ' + res)
372}
373
374exports.crypto_box_seed_keypair = function (pk, sk, seed) {
375 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
376 assert(
377 pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
378 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
379 )
380 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
381 assert(
382 sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
383 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
384 )
385 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
386 assert(
387 seed.byteLength === binding.crypto_box_SEEDBYTES,
388 "seed must be 'crypto_box_SEEDBYTES' bytes"
389 )
390
391 const res = binding.crypto_box_seed_keypair(pk, sk, seed)
392
393 if (res !== 0) throw new Error('status: ' + res)
394}
395
396exports.crypto_box_easy = function (c, m, n, pk, sk) {
397 assert(ArrayBuffer.isView(c), 'c must be a typed array')
398 assert(ArrayBuffer.isView(m), 'm must be a typed array')
399 assert(ArrayBuffer.isView(n), 'n must be a typed array')
400 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
401 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
402 assert(
403 c.byteLength === m.byteLength + exports.crypto_box_MACBYTES,
404 "c must be 'm.byteLength + crypto_box_MACBYTES' bytes"
405 )
406 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
407 assert(
408 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
409 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
410 )
411 assert(
412 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
413 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
414 )
415
416 const res = binding.crypto_box_easy(c, m, n, pk, sk)
417
418 if (res !== 0) throw new Error('status: ' + res)
419}
420
421exports.crypto_box_detached = function (c, mac, m, n, pk, sk) {
422 assert(ArrayBuffer.isView(c), 'c must be a typed array')
423 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
424 assert(ArrayBuffer.isView(m), 'm must be a typed array')
425 assert(ArrayBuffer.isView(n), 'n must be a typed array')
426 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
427 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
428 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
429 assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes")
430 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
431 assert(
432 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
433 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
434 )
435 assert(
436 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
437 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
438 )
439
440 const res = binding.crypto_box_detached(c, mac, m, n, pk, sk)
441
442 if (res !== 0) throw new Error('status: ' + res)
443}
444
445exports.crypto_box_open_easy = function (m, c, n, pk, sk) {
446 assert(ArrayBuffer.isView(m), 'm must be a typed array')
447 assert(ArrayBuffer.isView(c), 'c must be a typed array')
448 assert(ArrayBuffer.isView(n), 'n must be a typed array')
449 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
450 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
451 assert(
452 c.byteLength >= exports.crypto_box_MACBYTES,
453 "c must be at least 'crypto_box_MACBYTES' bytes"
454 )
455 assert(
456 m.byteLength === c.byteLength - exports.crypto_box_MACBYTES,
457 "m must be 'c.byteLength - crypto_box_MACBYTES' bytes"
458 )
459 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
460 assert(
461 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
462 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
463 )
464 assert(
465 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
466 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
467 )
468
469 return binding.crypto_box_open_easy(m, c, n, pk, sk)
470}
471
472exports.crypto_box_open_detached = function (m, c, mac, n, pk, sk) {
473 assert(ArrayBuffer.isView(m), 'm must be a typed array')
474 assert(ArrayBuffer.isView(c), 'c must be a typed array')
475 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
476 assert(ArrayBuffer.isView(n), 'n must be a typed array')
477 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
478 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
479 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
480 assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes")
481 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
482 assert(
483 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
484 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
485 )
486 assert(
487 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
488 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
489 )
490
491 return binding.crypto_box_open_detached(m, c, mac, n, pk, sk)
492}
493
494exports.crypto_box_seal = function (c, m, pk) {
495 assert(ArrayBuffer.isView(c), 'c must be a typed array')
496 assert(ArrayBuffer.isView(m), 'm must be a typed array')
497 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
498 assert(
499 c.byteLength === m.byteLength + exports.crypto_box_SEALBYTES,
500 "c must be 'm.byteLength + crypto_box_SEALBYTES' bytes"
501 )
502 assert(
503 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
504 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
505 )
506
507 const res = binding.crypto_box_seal(c, m, pk)
508
509 if (res !== 0) throw new Error('status: ' + res)
510}
511
512exports.crypto_box_seal_open = function (m, c, pk, sk) {
513 assert(ArrayBuffer.isView(m), 'm must be a typed array')
514 assert(ArrayBuffer.isView(c), 'c must be a typed array')
515 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
516 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
517 assert(
518 c.byteLength >= exports.crypto_box_SEALBYTES,
519 "c must be at least 'crypto_box_SEALBYTES' bytes"
520 )
521 assert(
522 m.byteLength === c.byteLength - exports.crypto_box_SEALBYTES,
523 "m must be 'c.byteLength - crypto_box_SEALBYTES' bytes"
524 )
525 assert(
526 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
527 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
528 )
529 assert(
530 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
531 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
532 )
533
534 return binding.crypto_box_seal_open(
535 m.buffer,
536 m.byteOffset,
537 m.byteLength,
538
539 c.buffer,
540 c.byteOffset,
541 c.byteLength,
542
543 pk.buffer,
544 pk.byteOffset,
545 pk.byteLength,
546
547 sk.buffer,
548 sk.byteOffset,
549 sk.byteLength
550 )
551}
552
553// crypto_secretbox
554
555exports.crypto_secretbox_easy = function (c, m, n, k) {
556 assert(ArrayBuffer.isView(c), 'c must be a typed array')
557 assert(ArrayBuffer.isView(m), 'm must be a typed array')
558 assert(ArrayBuffer.isView(n), 'n must be a typed array')
559 assert(ArrayBuffer.isView(k), 'k must be a typed array')
560 assert(
561 c.byteLength === m.byteLength + binding.crypto_secretbox_MACBYTES,
562 "c must be 'm.byteLength + crypto_secretbox_MACBYTES' bytes"
563 )
564 assert(
565 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
566 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
567 )
568 assert(
569 k.byteLength === binding.crypto_secretbox_KEYBYTES,
570 "k must be 'crypto_secretbox_KEYBYTES' bytes"
571 )
572
573 const res = binding.crypto_secretbox_easy(c, m, n, k)
574
575 if (res !== 0) throw new Error('status: ' + res)
576}
577
578exports.crypto_secretbox_open_easy = function (m, c, n, k) {
579 assert(ArrayBuffer.isView(m), 'm must be a typed array')
580 assert(ArrayBuffer.isView(c), 'c must be a typed array')
581 assert(ArrayBuffer.isView(n), 'n must be a typed array')
582 assert(ArrayBuffer.isView(k), 'k must be a typed array')
583 assert(
584 c.byteLength >= binding.crypto_secretbox_MACBYTES,
585 "c must be at least 'crypto_secretbox_MACBYTES' bytes"
586 )
587 assert(
588 m.byteLength === c.byteLength - binding.crypto_secretbox_MACBYTES,
589 "m must be 'c.byteLength - crypto_secretbox_MACBYTES' bytes"
590 )
591 assert(
592 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
593 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
594 )
595 assert(
596 k.byteLength === binding.crypto_secretbox_KEYBYTES,
597 "k must be 'crypto_secretbox_KEYBYTES' bytes"
598 )
599
600 return binding.crypto_secretbox_open_easy(m, c, n, k)
601}
602
603exports.crypto_secretbox_detached = function (c, mac, m, n, k) {
604 assert(ArrayBuffer.isView(c), 'c must be a typed array')
605 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
606 assert(ArrayBuffer.isView(m), 'm must be a typed array')
607 assert(ArrayBuffer.isView(n), 'n must be a typed array')
608 assert(ArrayBuffer.isView(k), 'k must be a typed array')
609 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
610 assert(
611 mac.byteLength === binding.crypto_secretbox_MACBYTES,
612 "mac must be 'crypto_secretbox_MACBYTES' bytes"
613 )
614 assert(
615 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
616 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
617 )
618 assert(
619 k.byteLength === binding.crypto_secretbox_KEYBYTES,
620 "k must be 'crypto_secretbox_KEYBYTES' bytes"
621 )
622
623 const res = binding.crypto_secretbox_detached(c, mac, m, n, k)
624
625 if (res !== 0) throw new Error('status: ' + res)
626}
627
628exports.crypto_secretbox_open_detached = function (m, c, mac, n, k) {
629 assert(ArrayBuffer.isView(m), 'm must be a typed array')
630 assert(ArrayBuffer.isView(c), 'c must be a typed array')
631 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
632 assert(ArrayBuffer.isView(n), 'n must be a typed array')
633 assert(ArrayBuffer.isView(k), 'k must be a typed array')
634 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
635 assert(
636 mac.byteLength === binding.crypto_secretbox_MACBYTES,
637 "mac must be 'crypto_secretbox_MACBYTES' bytes"
638 )
639 assert(
640 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
641 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
642 )
643 assert(
644 k.byteLength === binding.crypto_secretbox_KEYBYTES,
645 "k must be 'crypto_secretbox_KEYBYTES' bytes"
646 )
647
648 return binding.crypto_secretbox_open_detached(m, c, mac, n, k)
649}
650
651// crypto_generichash
652
653exports.crypto_generichash = function (output, input, key) {
654 if (!key) key = OPTIONAL
655
656 assert(ArrayBuffer.isView(output), 'output must be a typed array')
657 assert(ArrayBuffer.isView(input), 'input must be a typed array')
658 assert(
659 output.byteLength >= binding.crypto_generichash_BYTES_MIN &&
660 output.byteLength <= binding.crypto_generichash_BYTES_MAX,
661 'output must be between crypto_generichash_BYTES_MIN and crypto_generichash_BYTES_MAX bytes'
662 )
663
664 if (key !== OPTIONAL) {
665 assert(ArrayBuffer.isView(key), 'key must be a typed array')
666 assert(
667 key.byteLength >= binding.crypto_generichash_KEYBYTES_MIN &&
668 key.byteLength <= binding.crypto_generichash_KEYBYTES_MAX,
669 'key must be between crypto_generichash_KEYBYTES_MIN and crypto_generichash_KEYBYTES_MAX bytes'
670 )
671 }
672
673 const res = binding.crypto_generichash(
674 output.buffer,
675 output.byteOffset,
676 output.byteLength,
677
678 input.buffer,
679 input.byteOffset,
680 input.byteLength,
681
682 key.buffer,
683 key.byteOffset,
684 key.byteLength
685 )
686
687 if (res !== 0) throw new Error('status: ' + res)
688}
689
690exports.crypto_generichash_batch = function (output, batch, key) {
691 assert(ArrayBuffer.isView(output), 'output must be a typed array')
692
693 if (isNode || batch.length < 4) {
694 const res = binding.crypto_generichash_batch(output, batch, !!key, key || OPTIONAL)
695 if (res !== 0) throw new Error('status: ' + res)
696 } else {
697 const state = Buffer.alloc(binding.crypto_generichash_STATEBYTES)
698
699 exports.crypto_generichash_init(state, key, output.byteLength)
700
701 for (const buf of batch) {
702 exports.crypto_generichash_update(state, buf)
703 }
704
705 exports.crypto_generichash_final(state, output)
706 }
707}
708
709exports.crypto_generichash_keygen = function (key) {
710 assert(ArrayBuffer.isView(key), 'key must be a typed array')
711 assert(
712 key.byteLength === binding.crypto_generichash_KEYBYTES,
713 "key must be 'crypto_generichash_KEYBYTES' bytes"
714 )
715
716 const res = binding.crypto_generichash_keygen(key.buffer, key.byteOffset, key.byteLength)
717
718 if (res !== 0) throw new Error('status: ' + res)
719}
720
721exports.crypto_generichash_init = function (state, key, outputLength) {
722 if (!key) key = OPTIONAL
723
724 assert(ArrayBuffer.isView(state), 'state must be a typed array')
725 assert(
726 state.byteLength === binding.crypto_generichash_STATEBYTES,
727 "state must be 'crypto_generichash_STATEBYTES' bytes"
728 )
729
730 const res = binding.crypto_generichash_init(
731 state.buffer,
732 state.byteOffset,
733 state.byteLength,
734
735 key.buffer,
736 key.byteOffset,
737 key.byteLength,
738
739 outputLength
740 )
741
742 if (res !== 0) throw new Error('status: ' + res)
743}
744
745exports.crypto_generichash_update = function (state, input) {
746 assert(ArrayBuffer.isView(state), 'state must be a typed array')
747 assert(ArrayBuffer.isView(input), 'input must be a typed array')
748 assert(
749 state.byteLength === binding.crypto_generichash_STATEBYTES,
750 "state must be 'crypto_generichash_STATEBYTES' bytes"
751 )
752
753 const res = binding.crypto_generichash_update(
754 state.buffer,
755 state.byteOffset,
756 state.byteLength,
757
758 input.buffer,
759 input.byteOffset,
760 input.byteLength
761 )
762
763 if (res !== 0) throw new Error('status: ' + res)
764}
765
766exports.crypto_generichash_final = function (state, output) {
767 assert(ArrayBuffer.isView(state), 'state must be a typed array')
768 assert(ArrayBuffer.isView(output), 'output must be a typed array')
769 assert(
770 state.byteLength === binding.crypto_generichash_STATEBYTES,
771 "state must be 'crypto_generichash_STATEBYTES' bytes"
772 )
773
774 const res = binding.crypto_generichash_final(
775 state.buffer,
776 state.byteOffset,
777 state.byteLength,
778
779 output.buffer,
780 output.byteOffset,
781 output.byteLength
782 )
783
784 if (res !== 0) throw new Error('status: ' + res)
785}
786
787// secretstream
788
789exports.crypto_secretstream_xchacha20poly1305_keygen = function (k) {
790 assert(ArrayBuffer.isView(k), 'k must be a typed array')
791 assert(
792 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
793 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
794 )
795
796 binding.crypto_secretstream_xchacha20poly1305_keygen(k.buffer, k.byteOffset, k.byteLength)
797}
798
799exports.crypto_secretstream_xchacha20poly1305_init_push = function (state, header, k) {
800 assert(ArrayBuffer.isView(state), 'state must be a typed array')
801 assert(ArrayBuffer.isView(header), 'header must be a typed array')
802 assert(ArrayBuffer.isView(k), 'k must be a typed array')
803 assert(
804 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
805 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
806 )
807 assert(
808 header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
809 "header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
810 )
811 assert(
812 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
813 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
814 )
815
816 const res = binding.crypto_secretstream_xchacha20poly1305_init_push(
817 state.buffer,
818 state.byteOffset,
819 state.byteLength,
820
821 header.buffer,
822 header.byteOffset,
823 header.byteLength,
824
825 k.buffer,
826 k.byteOffset,
827 k.byteLength
828 )
829
830 if (res !== 0) throw new Error('status: ' + res)
831}
832
833exports.crypto_secretstream_xchacha20poly1305_init_pull = function (state, header, k) {
834 assert(ArrayBuffer.isView(state), 'state must be a typed array')
835 assert(ArrayBuffer.isView(header), 'header must be a typed array')
836 assert(ArrayBuffer.isView(k), 'k must be a typed array')
837 assert(
838 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
839 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
840 )
841 assert(
842 header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
843 "header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
844 )
845 assert(
846 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
847 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
848 )
849
850 const res = binding.crypto_secretstream_xchacha20poly1305_init_pull(
851 state.buffer,
852 state.byteOffset,
853 state.byteLength,
854
855 header.buffer,
856 header.byteOffset,
857 header.byteLength,
858
859 k.buffer,
860 k.byteOffset,
861 k.byteLength
862 )
863
864 if (res !== 0) throw new Error('status: ' + res)
865}
866
867exports.crypto_secretstream_xchacha20poly1305_push = function (state, c, m, ad, tag) {
868 if (!ad) ad = OPTIONAL
869
870 assert(ArrayBuffer.isView(state), 'state must be a typed array')
871 assert(ArrayBuffer.isView(c), 'c must be a typed array')
872 assert(ArrayBuffer.isView(m), 'm must be a typed array')
873 assert(
874 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
875 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
876 )
877 assert(
878 c.byteLength === m.byteLength + binding.crypto_secretstream_xchacha20poly1305_ABYTES,
879 "c must be 'm.byteLength + crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
880 )
881
882 const res = binding.crypto_secretstream_xchacha20poly1305_push(
883 state.buffer,
884 state.byteOffset,
885 state.byteLength,
886
887 c.buffer,
888 c.byteOffset,
889 c.byteLength,
890
891 m.buffer,
892 m.byteOffset,
893 m.byteLength,
894
895 ad.buffer,
896 ad.byteOffset,
897 ad.byteLength,
898
899 tag
900 )
901
902 if (res < 0) throw new Error('push failed')
903
904 return res
905}
906
907exports.crypto_secretstream_xchacha20poly1305_pull = function (state, m, tag, c, ad) {
908 if (!ad) ad = OPTIONAL
909
910 assert(ArrayBuffer.isView(state), 'state must be a typed array')
911 assert(
912 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
913 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
914 )
915 assert(ArrayBuffer.isView(tag), 'tag must be a typed array')
916 assert(tag.byteLength === 1, 'tag must be 1 byte')
917
918 assert(ArrayBuffer.isView(c), 'c must be a typed array')
919 assert(
920 c.byteLength >= binding.crypto_secretstream_xchacha20poly1305_ABYTES,
921 "c must be at least 'crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
922 )
923 assert(ArrayBuffer.isView(m), 'm must be a typed array')
924 assert(
925 m.byteLength === c.byteLength - binding.crypto_secretstream_xchacha20poly1305_ABYTES,
926 "m must be 'c.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
927 )
928
929 const res = binding.crypto_secretstream_xchacha20poly1305_pull(
930 state.buffer,
931 state.byteOffset,
932 state.byteLength,
933
934 m.buffer,
935 m.byteOffset,
936 m.byteLength,
937
938 tag.buffer,
939 tag.byteOffset,
940 tag.byteLength,
941
942 c.buffer,
943 c.byteOffset,
944 c.byteLength,
945
946 ad.buffer,
947 ad.byteOffset,
948 ad.byteLength
949 )
950
951 if (res < 0) throw new Error('pull failed')
952
953 return res
954}
955
956exports.crypto_secretstream_xchacha20poly1305_rekey = function (state) {
957 assert(ArrayBuffer.isView(state), 'state must be a typed array')
958 assert(
959 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
960 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
961 )
962
963 binding.crypto_secretstream_xchacha20poly1305_rekey(
964 state.buffer,
965 state.byteOffset,
966 state.byteLength
967 )
968}
969
970// crypto_stream
971
972exports.crypto_stream = function (c, n, k) {
973 assert(ArrayBuffer.isView(c), 'c must be a typed array')
974 assert(ArrayBuffer.isView(n), 'n must be a typed array')
975 assert(ArrayBuffer.isView(k), 'k must be a typed array')
976 assert(
977 n.byteLength === binding.crypto_stream_NONCEBYTES,
978 "n must be 'crypto_stream_NONCEBYTES' bytes"
979 )
980 assert(
981 k.byteLength === binding.crypto_stream_KEYBYTES,
982 "k must be 'crypto_stream_KEYBYTES' bytes"
983 )
984
985 const res = binding.crypto_stream(c, n, k)
986
987 if (res !== 0) throw new Error('status: ' + res)
988}
989
990exports.crypto_stream_xor = function (c, m, n, k) {
991 assert(ArrayBuffer.isView(c), 'c must be a typed array')
992 assert(ArrayBuffer.isView(m), 'm must be a typed array')
993 assert(ArrayBuffer.isView(n), 'n must be a typed array')
994 assert(ArrayBuffer.isView(k), 'k must be a typed array')
995 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
996 assert(
997 n.byteLength === binding.crypto_stream_NONCEBYTES,
998 "n must be 'crypto_stream_NONCEBYTES' bytes"
999 )
1000 assert(
1001 k.byteLength === binding.crypto_stream_KEYBYTES,
1002 "k must be 'crypto_stream_KEYBYTES' bytes"
1003 )
1004
1005 const res = binding.crypto_stream_xor(
1006 c.buffer,
1007 c.byteOffset,
1008 c.byteLength,
1009
1010 m.buffer,
1011 m.byteOffset,
1012 m.byteLength,
1013
1014 n.buffer,
1015 n.byteOffset,
1016 n.byteLength,
1017
1018 k.buffer,
1019 k.byteOffset,
1020 k.byteLength
1021 )
1022
1023 if (res !== 0) throw new Error('status: ' + res)
1024}
1025
1026exports.crypto_stream_chacha20 = function (c, n, k) {
1027 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1028 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1029 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1030 assert(
1031 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1032 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1033 )
1034 assert(
1035 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1036 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1037 )
1038
1039 const res = binding.crypto_stream_chacha20(c, n, k)
1040
1041 if (res !== 0) throw new Error('status: ' + res)
1042}
1043
1044exports.crypto_stream_chacha20_xor = function (c, m, n, k) {
1045 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1046 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1047 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1048 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1049 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1050 assert(
1051 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1052 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1053 )
1054 assert(
1055 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1056 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1057 )
1058
1059 const res = binding.crypto_stream_chacha20_xor(c, m, n, k)
1060
1061 if (res !== 0) throw new Error('status: ' + res)
1062}
1063
1064exports.crypto_stream_chacha20_xor_ic = function (c, m, n, ic, k) {
1065 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1066 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1067 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1068 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1069 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1070 assert(
1071 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1072 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1073 )
1074 assert(
1075 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1076 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1077 )
1078
1079 const res = binding.crypto_stream_chacha20_xor_ic(c, m, n, ic, k)
1080
1081 if (res !== 0) throw new Error('status: ' + res)
1082}
1083
1084exports.crypto_stream_chacha20_ietf = function (c, n, k) {
1085 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1086 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1087 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1088 assert(
1089 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1090 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1091 )
1092 assert(
1093 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1094 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1095 )
1096
1097 const res = binding.crypto_stream_chacha20_ietf(c, n, k)
1098
1099 if (res !== 0) throw new Error('status: ' + res)
1100}
1101
1102exports.crypto_stream_chacha20_ietf_xor = function (c, m, n, k) {
1103 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1104 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1105 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1106 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1107 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1108 assert(
1109 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1110 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1111 )
1112 assert(
1113 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1114 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1115 )
1116
1117 const res = binding.crypto_stream_chacha20_ietf_xor(c, m, n, k)
1118
1119 if (res !== 0) throw new Error('status: ' + res)
1120}
1121
1122exports.crypto_stream_chacha20_ietf_xor_ic = function (c, m, n, ic, k) {
1123 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1124 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1125 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1126 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1127 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1128 assert(
1129 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1130 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1131 )
1132 assert(
1133 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1134 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1135 )
1136
1137 const res = binding.crypto_stream_chacha20_ietf_xor_ic(c, m, n, ic, k)
1138
1139 if (res !== 0) throw new Error('status: ' + res)
1140}
1141
1142exports.crypto_stream_xchacha20 = function (c, n, k) {
1143 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1144 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1145 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1146 assert(
1147 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1148 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1149 )
1150 assert(
1151 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1152 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1153 )
1154
1155 const res = binding.crypto_stream_xchacha20(c, n, k)
1156
1157 if (res !== 0) throw new Error('status: ' + res)
1158}
1159
1160exports.crypto_stream_xchacha20_xor = function (c, m, n, k) {
1161 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1162 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1163 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1164 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1165 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1166 assert(
1167 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1168 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1169 )
1170 assert(
1171 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1172 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1173 )
1174
1175 const res = binding.crypto_stream_xchacha20_xor(c, m, n, k)
1176
1177 if (res !== 0) throw new Error('status: ' + res)
1178}
1179
1180exports.crypto_stream_xchacha20_xor_ic = function (c, m, n, ic, k) {
1181 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1182 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1183 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1184 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1185 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1186 assert(
1187 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1188 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1189 )
1190 assert(
1191 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1192 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1193 )
1194
1195 const res = binding.crypto_stream_xchacha20_xor_ic(c, m, n, ic, k)
1196
1197 if (res !== 0) throw new Error('status: ' + res)
1198}
1199
1200exports.crypto_stream_salsa20 = function (c, n, k) {
1201 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1202 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1203 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1204 assert(
1205 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1206 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1207 )
1208 assert(
1209 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1210 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1211 )
1212
1213 const res = binding.crypto_stream_salsa20(c, n, k)
1214
1215 if (res !== 0) throw new Error('status: ' + res)
1216}
1217
1218exports.crypto_stream_salsa20_xor = function (c, m, n, k) {
1219 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1220 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1221 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1222 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1223 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1224 assert(
1225 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1226 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1227 )
1228 assert(
1229 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1230 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1231 )
1232
1233 const res = binding.crypto_stream_salsa20_xor(c, m, n, k)
1234
1235 if (res !== 0) throw new Error('status: ' + res)
1236}
1237
1238exports.crypto_stream_salsa20_xor_ic = function (c, m, n, ic, k) {
1239 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1240 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1241 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1242 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1243 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1244 assert(
1245 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1246 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1247 )
1248 assert(
1249 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1250 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1251 )
1252
1253 const res = binding.crypto_stream_salsa20_xor_ic(c, m, n, ic, k)
1254
1255 if (res !== 0) throw new Error('status: ' + res)
1256}
1257
1258// crypto_auth
1259
1260exports.crypto_auth = function (out, input, k) {
1261 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1262 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1263 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1264 assert(out.byteLength === binding.crypto_auth_BYTES, "out must be 'crypto_auth_BYTES' bytes")
1265 assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes")
1266
1267 const res = binding.crypto_auth(out, input, k)
1268
1269 if (res !== 0) throw new Error('status: ' + res)
1270}
1271
1272exports.crypto_auth_verify = function (h, input, k) {
1273 assert(ArrayBuffer.isView(h), 'h must be a typed array')
1274 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1275 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1276 assert(h.byteLength === binding.crypto_auth_BYTES, "h must be 'crypto_auth_BYTES' bytes")
1277 assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes")
1278
1279 return binding.crypto_auth_verify(h, input, k)
1280}
1281
1282// crypto_onetimeauth
1283
1284exports.crypto_onetimeauth = function (out, input, k) {
1285 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1286 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1287 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1288 assert(
1289 out.byteLength === binding.crypto_onetimeauth_BYTES,
1290 "out must be 'crypto_onetimeauth_BYTES' bytes"
1291 )
1292 assert(
1293 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1294 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1295 )
1296
1297 const res = binding.crypto_onetimeauth(out, input, k)
1298
1299 if (res !== 0) throw new Error('status: ' + res)
1300}
1301
1302exports.crypto_onetimeauth_init = function (state, k) {
1303 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1304 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1305 assert(
1306 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1307 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1308 )
1309 assert(
1310 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1311 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1312 )
1313
1314 const res = binding.crypto_onetimeauth_init(state, k)
1315
1316 if (res !== 0) throw new Error('status: ' + res)
1317}
1318
1319exports.crypto_onetimeauth_update = function (state, input) {
1320 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1321 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1322 assert(
1323 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1324 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1325 )
1326
1327 const res = binding.crypto_onetimeauth_update(state, input)
1328
1329 if (res !== 0) throw new Error('status: ' + res)
1330}
1331
1332exports.crypto_onetimeauth_final = function (state, out) {
1333 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1334 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1335 assert(
1336 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1337 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1338 )
1339 assert(
1340 out.byteLength === binding.crypto_onetimeauth_BYTES,
1341 "out must be 'crypto_onetimeauth_BYTES' bytes"
1342 )
1343
1344 const res = binding.crypto_onetimeauth_final(state, out)
1345
1346 if (res !== 0) throw new Error('status: ' + res)
1347}
1348
1349exports.crypto_onetimeauth_verify = function (h, input, k) {
1350 assert(ArrayBuffer.isView(h), 'h must be a typed array')
1351 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1352 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1353 assert(
1354 h.byteLength === binding.crypto_onetimeauth_BYTES,
1355 "h must be 'crypto_onetimeauth_BYTES' bytes"
1356 )
1357 assert(
1358 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1359 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1360 )
1361
1362 return binding.crypto_onetimeauth_verify(h, input, k)
1363}
1364
1365// crypto_pwhash
1366
1367exports.crypto_pwhash = function (out, passwd, salt, opslimit, memlimit, alg) {
1368 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1369 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1370 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1371 assert(
1372 out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
1373 "out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
1374 )
1375 assert(
1376 out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
1377 "out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
1378 )
1379 assert(
1380 salt.byteLength === binding.crypto_pwhash_SALTBYTES,
1381 "salt must be 'crypto_pwhash_SALTBYTES' bytes"
1382 )
1383 assert(
1384 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1385 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1386 )
1387 assert(
1388 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1389 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1390 )
1391 assert(
1392 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1393 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1394 )
1395 assert(
1396 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1397 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1398 )
1399 assert(alg >= 1 && alg <= 2, 'alg must be either Argon2i 1.3 or Argon2id 1.3')
1400
1401 const res = binding.crypto_pwhash(out, passwd, salt, opslimit, memlimit, alg)
1402
1403 if (res !== 0) throw new Error('status: ' + res)
1404}
1405
1406exports.crypto_pwhash_async = function (
1407 out,
1408 passwd,
1409 salt,
1410 opslimit,
1411 memlimit,
1412 alg,
1413 callback = undefined
1414) {
1415 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1416 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1417 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1418 assert(
1419 out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
1420 "out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
1421 )
1422 assert(
1423 out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
1424 "out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
1425 )
1426 assert(
1427 salt.byteLength === binding.crypto_pwhash_SALTBYTES,
1428 "salt must be 'crypto_pwhash_SALTBYTES' bytes"
1429 )
1430 assert(
1431 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1432 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1433 )
1434 assert(
1435 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1436 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1437 )
1438 assert(
1439 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1440 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1441 )
1442 assert(
1443 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1444 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1445 )
1446 assert(alg >= 1 && alg <= 2, 'alg must be either Argon2i 1.3 or Argon2id 1.3')
1447
1448 const [done, promise] = checkStatus(callback)
1449
1450 binding.crypto_pwhash_async(
1451 out.buffer,
1452 out.byteOffset,
1453 out.byteLength,
1454
1455 passwd.buffer,
1456 passwd.byteOffset,
1457 passwd.byteLength,
1458
1459 salt.buffer,
1460 salt.byteOffset,
1461 salt.byteLength,
1462
1463 opslimit,
1464 memlimit,
1465 alg,
1466
1467 done
1468 )
1469
1470 return promise
1471}
1472
1473exports.crypto_pwhash_str = function (out, passwd, opslimit, memlimit) {
1474 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1475 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1476 assert(
1477 out.byteLength === binding.crypto_pwhash_STRBYTES,
1478 "out must be 'crypto_pwhash_STRBYTES' bytes"
1479 )
1480 assert(typeof opslimit === 'number', 'opslimit must be a number')
1481 assert(
1482 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1483 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1484 )
1485 assert(
1486 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1487 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1488 )
1489 assert(typeof memlimit === 'number', 'memlimit must be a number')
1490 assert(
1491 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1492 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1493 )
1494 assert(
1495 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1496 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1497 )
1498
1499 const res = binding.crypto_pwhash_str(out, passwd, opslimit, memlimit)
1500
1501 if (res !== 0) throw new Error('status: ' + res)
1502}
1503
1504exports.crypto_pwhash_str_async = function (out, passwd, opslimit, memlimit, callback = undefined) {
1505 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1506 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1507 assert(
1508 out.byteLength === binding.crypto_pwhash_STRBYTES,
1509 "out must be 'crypto_pwhash_STRBYTES' bytes"
1510 )
1511 assert(passwd.byteLength > 0, 'passwd must not be empty')
1512 assert(typeof opslimit === 'number', 'opslimit must be a number')
1513 assert(
1514 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1515 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1516 )
1517 assert(
1518 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1519 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1520 )
1521 assert(typeof memlimit === 'number', 'memlimit must be a number')
1522 assert(
1523 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1524 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1525 )
1526 assert(
1527 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1528 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1529 )
1530
1531 const [done, promise] = checkStatus(callback)
1532
1533 binding.crypto_pwhash_str_async(
1534 out.buffer,
1535 out.byteOffset,
1536 out.byteLength,
1537
1538 passwd.buffer,
1539 passwd.byteOffset,
1540 passwd.byteLength,
1541
1542 opslimit,
1543 memlimit,
1544
1545 done
1546 )
1547
1548 return promise
1549}
1550
1551exports.crypto_pwhash_str_verify = function (str, passwd) {
1552 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1553 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1554 assert(
1555 str.byteLength === binding.crypto_pwhash_STRBYTES,
1556 "str must be 'crypto_pwhash_STRBYTES' bytes"
1557 )
1558
1559 return binding.crypto_pwhash_str_verify(str, passwd)
1560}
1561
1562exports.crypto_pwhash_str_verify_async = function (str, passwd, callback = undefined) {
1563 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1564 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1565 assert(
1566 str.byteLength === binding.crypto_pwhash_STRBYTES,
1567 "str must be 'crypto_pwhash_STRBYTES' bytes"
1568 )
1569 assert(passwd.byteLength > 0, 'passwd must not be empty')
1570
1571 const [done, promise] = checkStatus(callback, true)
1572
1573 binding.crypto_pwhash_str_verify_async(
1574 str.buffer,
1575 str.byteOffset,
1576 str.byteLength,
1577
1578 passwd.buffer,
1579 passwd.byteOffset,
1580 passwd.byteLength,
1581
1582 done
1583 )
1584
1585 return promise
1586}
1587
1588exports.crypto_pwhash_str_needs_rehash = function (str, opslimit, memlimit) {
1589 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1590 assert(
1591 str.byteLength === binding.crypto_pwhash_STRBYTES,
1592 "str must be 'crypto_pwhash_STRBYTES' bytes"
1593 )
1594 assert(
1595 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1596 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1597 )
1598 assert(
1599 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1600 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1601 )
1602 assert(
1603 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1604 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1605 )
1606 assert(
1607 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1608 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1609 )
1610
1611 return binding.crypto_pwhash_str_needs_rehash(str, opslimit, memlimit)
1612}
1613
1614exports.crypto_pwhash_scryptsalsa208sha256 = function (out, passwd, salt, opslimit, memlimit) {
1615 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1616 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1617 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1618 assert(
1619 out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
1620 "out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
1621 )
1622 assert(
1623 out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
1624 "out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
1625 )
1626 assert(
1627 salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
1628 "salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
1629 )
1630 assert(
1631 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1632 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1633 )
1634 assert(
1635 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1636 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1637 )
1638 assert(
1639 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1640 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1641 )
1642 assert(
1643 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1644 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1645 )
1646
1647 const res = binding.crypto_pwhash_scryptsalsa208sha256(out, passwd, salt, opslimit, memlimit)
1648
1649 if (res !== 0) throw new Error('status: ' + res)
1650}
1651
1652exports.crypto_pwhash_scryptsalsa208sha256_async = function (
1653 out,
1654 passwd,
1655 salt,
1656 opslimit,
1657 memlimit,
1658 callback = undefined
1659) {
1660 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1661 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1662 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1663 assert(
1664 out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
1665 "out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
1666 )
1667 assert(
1668 out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
1669 "out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
1670 )
1671 assert(passwd.byteLength > 0, 'passwd must not be empty')
1672 assert(
1673 salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
1674 "salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
1675 )
1676 assert(
1677 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1678 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1679 )
1680 assert(
1681 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1682 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1683 )
1684 assert(
1685 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1686 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1687 )
1688 assert(
1689 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1690 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1691 )
1692
1693 const [done, promise] = checkStatus(callback)
1694
1695 binding.crypto_pwhash_scryptsalsa208sha256_async(
1696 out.buffer,
1697 out.byteOffset,
1698 out.byteLength,
1699
1700 passwd.buffer,
1701 passwd.byteOffset,
1702 passwd.byteLength,
1703
1704 salt.buffer,
1705 salt.byteOffset,
1706 salt.byteLength,
1707
1708 opslimit,
1709 memlimit,
1710
1711 done
1712 )
1713
1714 return promise
1715}
1716
1717exports.crypto_pwhash_scryptsalsa208sha256_str_async = function (
1718 out,
1719 passwd,
1720 opslimit,
1721 memlimit,
1722 callback = undefined
1723) {
1724 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1725 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1726 assert(
1727 out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1728 "out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1729 )
1730 assert(passwd.byteLength > 0, 'passwd must not be empty')
1731 assert(
1732 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1733 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1734 )
1735 assert(
1736 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1737 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1738 )
1739 assert(
1740 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1741 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1742 )
1743 assert(
1744 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1745 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1746 )
1747
1748 const [done, promise] = checkStatus(callback)
1749
1750 binding.crypto_pwhash_scryptsalsa208sha256_str_async(
1751 out.buffer,
1752 out.byteOffset,
1753 out.byteLength,
1754
1755 passwd.buffer,
1756 passwd.byteOffset,
1757 passwd.byteLength,
1758
1759 opslimit,
1760 memlimit,
1761
1762 done
1763 )
1764
1765 return promise
1766}
1767
1768exports.crypto_pwhash_scryptsalsa208sha256_str = function (out, passwd, opslimit, memlimit) {
1769 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1770 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1771 assert(
1772 out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1773 "out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1774 )
1775 assert(passwd.byteLength > 0, 'passwd must not be empty')
1776 assert(
1777 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1778 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1779 )
1780 assert(
1781 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1782 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1783 )
1784 assert(
1785 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1786 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1787 )
1788 assert(
1789 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1790 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1791 )
1792
1793 const res = binding.crypto_pwhash_scryptsalsa208sha256_str(out, passwd, opslimit, memlimit)
1794
1795 if (res !== 0) throw new Error('status: ' + res)
1796}
1797
1798exports.crypto_pwhash_scryptsalsa208sha256_str_verify_async = function (
1799 str,
1800 passwd,
1801 callback = undefined
1802) {
1803 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1804 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1805 assert(
1806 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1807 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1808 )
1809 assert(passwd.byteLength > 0, 'passwd must not be empty')
1810
1811 const [done, promise] = checkStatus(callback, true)
1812
1813 binding.crypto_pwhash_scryptsalsa208sha256_str_verify_async(
1814 str.buffer,
1815 str.byteOffset,
1816 str.byteLength,
1817
1818 passwd.buffer,
1819 passwd.byteOffset,
1820 passwd.byteLength,
1821
1822 done
1823 )
1824
1825 return promise
1826}
1827
1828exports.crypto_pwhash_scryptsalsa208sha256_str_verify = function (str, passwd) {
1829 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1830 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1831 assert(
1832 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1833 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1834 )
1835 assert(passwd.byteLength > 0, 'passwd must not be empty')
1836
1837 return binding.crypto_pwhash_scryptsalsa208sha256_str_verify(str, passwd)
1838}
1839
1840exports.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash = function (str, opslimit, memlimit) {
1841 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1842 assert(
1843 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1844 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1845 )
1846 assert(
1847 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1848 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1849 )
1850 assert(
1851 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1852 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1853 )
1854 assert(
1855 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1856 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1857 )
1858 assert(
1859 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1860 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1861 )
1862
1863 return binding.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str, opslimit, memlimit)
1864}
1865
1866// crypto_kx
1867
1868exports.crypto_kx_keypair = function (pk, sk) {
1869 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
1870 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
1871 assert(
1872 pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1873 "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1874 )
1875 assert(
1876 sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1877 "sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1878 )
1879
1880 const res = binding.crypto_kx_keypair(pk, sk)
1881
1882 if (res !== 0) throw new Error('status: ' + res)
1883}
1884
1885exports.crypto_kx_seed_keypair = function (pk, sk, seed) {
1886 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
1887 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
1888 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
1889 assert(
1890 pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1891 "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1892 )
1893 assert(
1894 sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1895 "sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1896 )
1897 assert(
1898 seed.byteLength === binding.crypto_kx_SEEDBYTES,
1899 "seed must be 'crypto_kx_SEEDBYTES' bytes"
1900 )
1901
1902 const res = binding.crypto_kx_seed_keypair(pk, sk, seed)
1903
1904 if (res !== 0) throw new Error('status: ' + res)
1905}
1906
1907exports.crypto_kx_client_session_keys = function (rx, tx, clientPk, clientSk, serverPk) {
1908 if (!rx) rx = undefined
1909 if (!tx) tx = undefined
1910
1911 assert(rx || tx, 'at least one session key must be specified')
1912
1913 if (rx) {
1914 assert(ArrayBuffer.isView(rx), 'rx must be a typed array')
1915 assert(
1916 rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1917 "rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1918 )
1919 }
1920
1921 if (tx) {
1922 assert(ArrayBuffer.isView(tx), 'tx must be a typed array')
1923 assert(
1924 tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1925 "tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1926 )
1927 }
1928
1929 assert(ArrayBuffer.isView(clientPk), 'clientPk must be a typed array')
1930 assert(ArrayBuffer.isView(clientSk), 'clientSk must be a typed array')
1931 assert(ArrayBuffer.isView(serverPk), 'serverPk must be a typed array')
1932 assert(
1933 clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1934 "clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1935 )
1936 assert(
1937 clientSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1938 "clientSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1939 )
1940 assert(
1941 serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1942 "serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1943 )
1944
1945 const res = binding.crypto_kx_client_session_keys(rx, tx, clientPk, clientSk, serverPk)
1946
1947 if (res !== 0) throw new Error('status: ' + res)
1948}
1949
1950exports.crypto_kx_server_session_keys = function (rx, tx, serverPk, serverSk, clientPk) {
1951 if (!rx) rx = undefined
1952 if (!tx) tx = undefined
1953
1954 assert(rx || tx, 'at least one session key must be specified')
1955
1956 if (rx) {
1957 assert(ArrayBuffer.isView(rx), 'rx must be a typed array')
1958 assert(
1959 rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1960 "rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1961 )
1962 }
1963
1964 if (tx) {
1965 assert(ArrayBuffer.isView(tx), 'tx must be a typed array')
1966 assert(
1967 tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1968 "tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1969 )
1970 }
1971
1972 assert(ArrayBuffer.isView(serverPk), 'serverPk must be a typed array')
1973 assert(ArrayBuffer.isView(serverSk), 'serverSk must be a typed array')
1974 assert(ArrayBuffer.isView(clientPk), 'clientPk must be a typed array')
1975 assert(
1976 serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1977 "serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1978 )
1979 assert(
1980 serverSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1981 "serverSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1982 )
1983 assert(
1984 clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1985 "clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1986 )
1987
1988 const res = binding.crypto_kx_server_session_keys(rx, tx, serverPk, serverSk, clientPk)
1989
1990 if (res !== 0) throw new Error('status: ' + res)
1991}
1992
1993// crypto_scalarmult
1994
1995exports.crypto_scalarmult_base = function (q, n) {
1996 assert(ArrayBuffer.isView(q), 'q must be a typed array')
1997 assert(
1998 q.byteLength === binding.crypto_scalarmult_BYTES,
1999 "q must be 'crypto_scalarmult_BYTES' bytes"
2000 )
2001 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2002 assert(
2003 n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
2004 "n must be 'crypto_scalarmult_SCALARBYTES' bytes"
2005 )
2006
2007 const res = binding.crypto_scalarmult_base(q, n)
2008
2009 if (res !== 0) throw new Error('status: ' + res)
2010}
2011
2012exports.crypto_scalarmult = function (q, n, p) {
2013 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2014 assert(
2015 q.byteLength === binding.crypto_scalarmult_BYTES,
2016 "q must be 'crypto_scalarmult_BYTES' bytes"
2017 )
2018 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2019 assert(
2020 n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
2021 "n must be 'crypto_scalarmult_SCALARBYTES' bytes"
2022 )
2023 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2024 assert(
2025 p.byteLength === binding.crypto_scalarmult_BYTES,
2026 "p must be 'crypto_scalarmult_BYTES' bytes"
2027 )
2028
2029 const res = binding.crypto_scalarmult(q, n, p)
2030
2031 if (res !== 0) throw new Error('status: ' + res)
2032}
2033
2034exports.crypto_scalarmult_ed25519_base = function (q, n) {
2035 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2036 assert(
2037 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2038 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2039 )
2040 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2041 assert(
2042 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2043 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2044 )
2045
2046 const res = binding.crypto_scalarmult_ed25519_base(q, n)
2047
2048 if (res !== 0) throw new Error('status: ' + res)
2049}
2050
2051exports.crypto_scalarmult_ed25519 = function (q, n, p) {
2052 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2053 assert(
2054 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2055 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2056 )
2057 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2058 assert(
2059 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2060 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2061 )
2062 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2063 assert(
2064 p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2065 "p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2066 )
2067
2068 const res = binding.crypto_scalarmult_ed25519(q, n, p)
2069
2070 if (res !== 0) throw new Error('status: ' + res)
2071}
2072
2073exports.crypto_core_ed25519_is_valid_point = function (p) {
2074 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2075 assert(
2076 p.byteLength === binding.crypto_core_ed25519_BYTES,
2077 "p must be 'crypto_core_ed25519_BYTES' bytes"
2078 )
2079
2080 return binding.crypto_core_ed25519_is_valid_point(p)
2081}
2082
2083exports.crypto_core_ed25519_from_uniform = function (p, r) {
2084 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2085 assert(
2086 p.byteLength === binding.crypto_core_ed25519_BYTES,
2087 "p must be 'crypto_core_ed25519_BYTES' bytes"
2088 )
2089 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2090 assert(
2091 r.byteLength === binding.crypto_core_ed25519_UNIFORMBYTES,
2092 "r must be 'crypto_core_ed25519_UNIFORMBYTES' bytes"
2093 )
2094
2095 const res = binding.crypto_core_ed25519_from_uniform(p, r)
2096
2097 if (res !== 0) throw new Error('status: ' + res)
2098}
2099
2100exports.crypto_scalarmult_ed25519_base_noclamp = function (q, n) {
2101 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2102 assert(
2103 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2104 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2105 )
2106 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2107 assert(
2108 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2109 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2110 )
2111
2112 const res = binding.crypto_scalarmult_ed25519_base_noclamp(q, n)
2113
2114 if (res !== 0) throw new Error('status: ' + res)
2115}
2116
2117exports.crypto_scalarmult_ed25519_noclamp = function (q, n, p) {
2118 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2119 assert(
2120 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2121 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2122 )
2123 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2124 assert(
2125 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2126 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2127 )
2128 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2129 assert(
2130 p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2131 "p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2132 )
2133
2134 const res = binding.crypto_scalarmult_ed25519_noclamp(q, n, p)
2135
2136 if (res !== 0) throw new Error('status: ' + res)
2137}
2138
2139// crypto_core
2140
2141exports.crypto_core_ed25519_add = function (r, p, q) {
2142 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2143 assert(
2144 r.byteLength === binding.crypto_core_ed25519_BYTES,
2145 "r must be 'crypto_core_ed25519_BYTES' bytes"
2146 )
2147 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2148 assert(
2149 p.byteLength === binding.crypto_core_ed25519_BYTES,
2150 "p must be 'crypto_core_ed25519_BYTES' bytes"
2151 )
2152 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2153 assert(
2154 q.byteLength === binding.crypto_core_ed25519_BYTES,
2155 "q must be 'crypto_core_ed25519_BYTES' bytes"
2156 )
2157
2158 const res = binding.crypto_core_ed25519_add(r, p, q)
2159
2160 if (res !== 0) throw new Error('status: ' + res)
2161}
2162
2163exports.crypto_core_ed25519_sub = function (r, p, q) {
2164 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2165 assert(
2166 r.byteLength === binding.crypto_core_ed25519_BYTES,
2167 "r must be 'crypto_core_ed25519_BYTES' bytes"
2168 )
2169 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2170 assert(
2171 p.byteLength === binding.crypto_core_ed25519_BYTES,
2172 "p must be 'crypto_core_ed25519_BYTES' bytes"
2173 )
2174 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2175 assert(
2176 q.byteLength === binding.crypto_core_ed25519_BYTES,
2177 "q must be 'crypto_core_ed25519_BYTES' bytes"
2178 )
2179
2180 const res = binding.crypto_core_ed25519_sub(r, p, q)
2181
2182 if (res !== 0) throw new Error('status: ' + res)
2183}
2184
2185exports.crypto_core_ed25519_scalar_random = function (r) {
2186 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2187 assert(
2188 r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2189 "r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2190 )
2191
2192 binding.crypto_core_ed25519_scalar_random(r)
2193}
2194
2195exports.crypto_core_ed25519_scalar_reduce = function (r, s) {
2196 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2197 assert(
2198 r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2199 "r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2200 )
2201 assert(ArrayBuffer.isView(s), 's must be a typed array')
2202 assert(
2203 s.byteLength === binding.crypto_core_ed25519_NONREDUCEDSCALARBYTES,
2204 "s must be 'crypto_core_ed25519_NONREDUCEDSCALARBYTES' bytes"
2205 )
2206
2207 binding.crypto_core_ed25519_scalar_reduce(r, s)
2208}
2209
2210exports.crypto_core_ed25519_scalar_invert = function (recip, s) {
2211 assert(ArrayBuffer.isView(recip), 'recip must be a typed array')
2212 assert(
2213 recip.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2214 "recip must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2215 )
2216 assert(ArrayBuffer.isView(s), 's must be a typed array')
2217 assert(
2218 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2219 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2220 )
2221
2222 binding.crypto_core_ed25519_scalar_invert(recip, s)
2223}
2224
2225exports.crypto_core_ed25519_scalar_negate = function (neg, s) {
2226 assert(ArrayBuffer.isView(neg), 'neg must be a typed array')
2227 assert(
2228 neg.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2229 "neg must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2230 )
2231 assert(ArrayBuffer.isView(s), 's must be a typed array')
2232 assert(
2233 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2234 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2235 )
2236
2237 binding.crypto_core_ed25519_scalar_negate(neg, s)
2238}
2239
2240exports.crypto_core_ed25519_scalar_complement = function (comp, s) {
2241 assert(ArrayBuffer.isView(comp), 'comp must be a typed array')
2242 assert(
2243 comp.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2244 "comp must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2245 )
2246 assert(ArrayBuffer.isView(s), 's must be a typed array')
2247 assert(
2248 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2249 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2250 )
2251
2252 binding.crypto_core_ed25519_scalar_complement(comp, s)
2253}
2254
2255exports.crypto_core_ed25519_scalar_add = function (z, x, y) {
2256 assert(ArrayBuffer.isView(z), 'z must be a typed array')
2257 assert(
2258 z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2259 "z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2260 )
2261 assert(ArrayBuffer.isView(x), 'x must be a typed array')
2262 assert(
2263 x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2264 "x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2265 )
2266 assert(ArrayBuffer.isView(y), 'y must be a typed array')
2267 assert(
2268 y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2269 "y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2270 )
2271
2272 binding.crypto_core_ed25519_scalar_add(z, x, y)
2273}
2274
2275exports.crypto_core_ed25519_scalar_sub = function (z, x, y) {
2276 assert(ArrayBuffer.isView(z), 'z must be a typed array')
2277 assert(
2278 z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2279 "z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2280 )
2281 assert(ArrayBuffer.isView(x), 'x must be a typed array')
2282 assert(
2283 x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2284 "x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2285 )
2286 assert(ArrayBuffer.isView(y), 'y must be a typed array')
2287 assert(
2288 y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2289 "y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2290 )
2291
2292 binding.crypto_core_ed25519_scalar_sub(z, x, y)
2293}
2294
2295// crypto_shorthash
2296
2297exports.crypto_shorthash = function (out, input, k) {
2298 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2299 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2300 assert(
2301 out.byteLength === binding.crypto_shorthash_BYTES,
2302 "out must be 'crypto_shorthash_BYTES' bytes"
2303 )
2304 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2305 assert(
2306 k.byteLength === binding.crypto_shorthash_KEYBYTES,
2307 "k must be 'crypto_shorthash_KEYBYTES' bytes"
2308 )
2309
2310 const res = binding.crypto_shorthash(out, input, k)
2311
2312 if (res !== 0) throw new Error('status: ' + res)
2313}
2314
2315// crypto_kdf
2316
2317exports.crypto_kdf_keygen = function (key) {
2318 assert(ArrayBuffer.isView(key), 'key must be a typed array')
2319 assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes")
2320
2321 binding.crypto_kdf_keygen(key)
2322}
2323
2324exports.crypto_kdf_derive_from_key = function (subkey, subkeyId, ctx, key) {
2325 assert(ArrayBuffer.isView(subkey), 'subkey must be a typed array')
2326 assert(
2327 subkey.byteLength >= binding.crypto_kdf_BYTES_MIN,
2328 "subkey must be at least 'crypto_kdf_BYTES_MIN' bytes"
2329 )
2330 assert(
2331 subkey.byteLength <= binding.crypto_kdf_BYTES_MAX,
2332 "subkey must be at most 'crypto_kdf_BYTES_MAX' bytes"
2333 )
2334 assert(ArrayBuffer.isView(ctx), 'ctx must be a typed array')
2335 assert(
2336 ctx.byteLength === binding.crypto_kdf_CONTEXTBYTES,
2337 "ctx must be 'crypto_kdf_CONTEXTBYTES' bytes"
2338 )
2339 assert(ArrayBuffer.isView(key), 'key must be a typed array')
2340 assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes")
2341
2342 const res = binding.crypto_kdf_derive_from_key(subkey, subkeyId, ctx, key)
2343
2344 if (res !== 0) throw new Error('status: ' + res)
2345}
2346
2347// crypto_hash
2348
2349exports.crypto_hash = function (out, input) {
2350 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2351 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2352 assert(out.byteLength === binding.crypto_hash_BYTES, "out must be 'crypto_hash_BYTES' bytes")
2353
2354 const res = binding.crypto_hash(out, input)
2355
2356 if (res !== 0) throw new Error('status: ' + res)
2357}
2358
2359exports.crypto_hash_sha256 = function (out, input) {
2360 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2361 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2362 assert(
2363 out.byteLength === binding.crypto_hash_sha256_BYTES,
2364 "out must be 'crypto_hash_sha256_BYTES' bytes"
2365 )
2366
2367 const res = binding.crypto_hash_sha256(out, input)
2368
2369 if (res !== 0) throw new Error('status: ' + res)
2370}
2371
2372exports.crypto_hash_sha256_init = function (state) {
2373 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2374 assert(
2375 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2376 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2377 )
2378
2379 const res = binding.crypto_hash_sha256_init(state)
2380
2381 if (res !== 0) throw new Error('status: ' + res)
2382}
2383
2384exports.crypto_hash_sha256_update = function (state, input) {
2385 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2386 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2387 assert(
2388 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2389 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2390 )
2391
2392 const res = binding.crypto_hash_sha256_update(state, input)
2393
2394 if (res !== 0) throw new Error('status: ' + res)
2395}
2396
2397exports.crypto_hash_sha256_final = function (state, out) {
2398 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2399 assert(
2400 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2401 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2402 )
2403 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2404 assert(
2405 out.byteLength === binding.crypto_hash_sha256_BYTES,
2406 "out must be 'crypto_hash_sha256_BYTES' bytes"
2407 )
2408
2409 const res = binding.crypto_hash_sha256_final(state, out)
2410
2411 if (res !== 0) throw new Error('status: ' + res)
2412}
2413
2414exports.crypto_hash_sha512 = function (out, input) {
2415 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2416 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2417 assert(
2418 out.byteLength === binding.crypto_hash_sha512_BYTES,
2419 "out must be 'crypto_hash_sha512_BYTES' bytes"
2420 )
2421
2422 const res = binding.crypto_hash_sha512(out, input)
2423
2424 if (res !== 0) throw new Error('status: ' + res)
2425}
2426
2427exports.crypto_hash_sha512_init = function (state) {
2428 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2429 assert(
2430 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2431 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2432 )
2433
2434 const res = binding.crypto_hash_sha512_init(state)
2435
2436 if (res !== 0) throw new Error('status: ' + res)
2437}
2438
2439exports.crypto_hash_sha512_update = function (state, input) {
2440 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2441 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2442 assert(
2443 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2444 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2445 )
2446
2447 const res = binding.crypto_hash_sha512_update(state, input)
2448
2449 if (res !== 0) throw new Error('status: ' + res)
2450}
2451
2452exports.crypto_hash_sha512_final = function (state, out) {
2453 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2454 assert(
2455 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2456 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2457 )
2458 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2459 assert(
2460 out.byteLength === binding.crypto_hash_sha512_BYTES,
2461 "out must be 'crypto_hash_sha512_BYTES' bytes"
2462 )
2463
2464 const res = binding.crypto_hash_sha512_final(state, out)
2465
2466 if (res !== 0) throw new Error('status: ' + res)
2467}
2468
2469// crypto_aead
2470
2471exports.crypto_aead_xchacha20poly1305_ietf_keygen = function (k) {
2472 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2473 assert(
2474 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2475 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2476 )
2477
2478 binding.crypto_aead_xchacha20poly1305_ietf_keygen(k)
2479}
2480
2481exports.crypto_aead_xchacha20poly1305_ietf_encrypt = function (c, m, ad, nsec, npub, k) {
2482 if (!ad) ad = undefined
2483
2484 assert(nsec === null, 'nsec must always be set to null')
2485 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2486 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2487 assert(
2488 c.byteLength === m.byteLength + binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2489 "c must be 'm.byteLength + crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2490 )
2491 assert(c.byteLength <= 0xffffffff, 'c.byteLength must be a 32bit integer')
2492 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2493 assert(
2494 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2495 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2496 )
2497 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2498 assert(
2499 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2500 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2501 )
2502
2503 const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt(c, m, ad, npub, k)
2504
2505 if (res < 0) throw new Error('could not encrypt data')
2506
2507 return res
2508}
2509
2510exports.crypto_aead_xchacha20poly1305_ietf_decrypt = function (m, nsec, c, ad, npub, k) {
2511 if (!ad) ad = undefined
2512
2513 assert(nsec === null, 'nsec must always be set to null')
2514 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2515 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2516 assert(
2517 m.byteLength === c.byteLength - binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2518 "m must be 'c.byteLength - crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2519 )
2520 assert(m.byteLength <= 0xffffffff, 'm.byteLength must be a 32bit integer')
2521 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2522 assert(
2523 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2524 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2525 )
2526 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2527 assert(
2528 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2529 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2530 )
2531
2532 const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt(m, c, ad, npub, k)
2533
2534 if (res < 0) throw new Error('could not verify data')
2535
2536 return res
2537}
2538
2539exports.crypto_aead_xchacha20poly1305_ietf_encrypt_detached = function (
2540 c,
2541 mac,
2542 m,
2543 ad,
2544 nsec,
2545 npub,
2546 k
2547) {
2548 if (!ad) ad = undefined
2549
2550 assert(nsec === null, 'nsec must always be set to null')
2551 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2552 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2553 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2554 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2555 assert(
2556 mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2557 "mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2558 )
2559 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2560 assert(
2561 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2562 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2563 )
2564 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2565 assert(
2566 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2567 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2568 )
2569
2570 const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k)
2571
2572 if (res < 0) throw new Error('could not encrypt data')
2573
2574 return res
2575}
2576
2577exports.crypto_aead_xchacha20poly1305_ietf_decrypt_detached = function (
2578 m,
2579 nsec,
2580 c,
2581 mac,
2582 ad,
2583 npub,
2584 k
2585) {
2586 if (!ad) ad = undefined
2587
2588 assert(nsec === null, 'nsec must always be set to null')
2589 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2590 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2591 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
2592 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2593 assert(
2594 mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2595 "mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2596 )
2597 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2598 assert(
2599 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2600 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2601 )
2602 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2603 assert(
2604 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2605 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2606 )
2607
2608 const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k)
2609
2610 if (res !== 0) throw new Error('could not verify data')
2611}
2612
2613exports.crypto_aead_chacha20poly1305_ietf_keygen = function (k) {
2614 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2615 assert(
2616 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2617 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2618 )
2619
2620 binding.crypto_aead_chacha20poly1305_ietf_keygen(k)
2621}
2622
2623exports.crypto_aead_chacha20poly1305_ietf_encrypt = function (c, m, ad, nsec, npub, k) {
2624 if (!ad) ad = undefined
2625
2626 assert(nsec === null, 'nsec must always be set to null')
2627 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2628 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2629 assert(
2630 c.byteLength === m.byteLength + binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2631 "c must be 'm.byteLength + crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2632 )
2633 assert(c.byteLength <= 0xffffffff, 'c.byteLength must be a 32bit integer')
2634 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2635 assert(
2636 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2637 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2638 )
2639 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2640 assert(
2641 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2642 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2643 )
2644
2645 const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, ad, npub, k)
2646
2647 if (res < 0) throw new Error('could not encrypt data')
2648
2649 return res
2650}
2651
2652exports.crypto_aead_chacha20poly1305_ietf_decrypt = function (m, nsec, c, ad, npub, k) {
2653 if (!ad) ad = undefined
2654
2655 assert(nsec === null, 'nsec must always be set to null')
2656 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2657 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2658 assert(
2659 m.byteLength === c.byteLength - binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2660 "m must be 'c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2661 )
2662 assert(m.byteLength <= 0xffffffff, 'm.byteLength must be a 32bit integer')
2663 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2664 assert(
2665 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2666 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2667 )
2668 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2669 assert(
2670 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2671 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2672 )
2673
2674 const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt(m, c, ad, npub, k)
2675
2676 if (res < 0) throw new Error('could not verify data')
2677
2678 return res
2679}
2680
2681exports.crypto_aead_chacha20poly1305_ietf_encrypt_detached = function (
2682 c,
2683 mac,
2684 m,
2685 ad,
2686 nsec,
2687 npub,
2688 k
2689) {
2690 if (!ad) ad = undefined
2691
2692 assert(nsec === null, 'nsec must always be set to null')
2693 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2694 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2695 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2696 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2697 assert(
2698 mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2699 "mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2700 )
2701 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2702 assert(
2703 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2704 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2705 )
2706 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2707 assert(
2708 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2709 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2710 )
2711
2712 const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k)
2713
2714 if (res < 0) throw new Error('could not encrypt data')
2715
2716 return res
2717}
2718
2719exports.crypto_aead_chacha20poly1305_ietf_decrypt_detached = function (
2720 m,
2721 nsec,
2722 c,
2723 mac,
2724 ad,
2725 npub,
2726 k
2727) {
2728 if (!ad) ad = undefined
2729
2730 assert(nsec === null, 'nsec must always be set to null')
2731 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2732 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2733 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
2734 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2735 assert(
2736 mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2737 "mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2738 )
2739 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2740 assert(
2741 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2742 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2743 )
2744 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2745 assert(
2746 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2747 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2748 )
2749
2750 const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k)
2751
2752 if (res !== 0) throw new Error('could not verify data')
2753}
2754
2755// crypto_stream
2756
2757exports.crypto_stream_xor_wrap_init = function (state, n, k) {
2758 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2759 assert(
2760 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2761 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2762 )
2763 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2764 assert(
2765 n.byteLength === binding.crypto_stream_NONCEBYTES,
2766 "n must be 'crypto_stream_NONCEBYTES' bytes"
2767 )
2768 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2769 assert(
2770 k.byteLength === binding.crypto_stream_KEYBYTES,
2771 "k must be 'crypto_stream_KEYBYTES' bytes"
2772 )
2773
2774 binding.crypto_stream_xor_wrap_init(state, n, k)
2775}
2776
2777exports.crypto_stream_xor_wrap_update = function (state, c, m) {
2778 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2779 assert(
2780 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2781 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2782 )
2783 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2784 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2785 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2786
2787 binding.crypto_stream_xor_wrap_update(state, c, m)
2788}
2789
2790exports.crypto_stream_xor_wrap_final = function (state) {
2791 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2792 assert(
2793 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2794 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2795 )
2796
2797 binding.crypto_stream_xor_wrap_final(state)
2798}
2799
2800exports.crypto_stream_chacha20_xor_wrap_init = function (state, n, k) {
2801 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2802 assert(
2803 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2804 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2805 )
2806 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2807 assert(
2808 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
2809 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
2810 )
2811 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2812 assert(
2813 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
2814 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
2815 )
2816
2817 binding.crypto_stream_chacha20_xor_wrap_init(state, n, k)
2818}
2819
2820exports.crypto_stream_chacha20_xor_wrap_update = function (state, c, m) {
2821 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2822 assert(
2823 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2824 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2825 )
2826 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2827 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2828 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2829
2830 binding.crypto_stream_chacha20_xor_wrap_update(state, c, m)
2831}
2832
2833exports.crypto_stream_chacha20_xor_wrap_final = function (state) {
2834 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2835 assert(
2836 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2837 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2838 )
2839
2840 binding.crypto_stream_chacha20_xor_wrap_final(state)
2841}
2842
2843exports.crypto_stream_chacha20_ietf_xor_wrap_init = function (state, n, k) {
2844 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2845 assert(
2846 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2847 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2848 )
2849 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2850 assert(
2851 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
2852 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
2853 )
2854 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2855 assert(
2856 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
2857 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
2858 )
2859
2860 binding.crypto_stream_chacha20_ietf_xor_wrap_init(state, n, k)
2861}
2862
2863exports.crypto_stream_chacha20_ietf_xor_wrap_update = function (state, c, m) {
2864 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2865 assert(
2866 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2867 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2868 )
2869 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2870 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2871 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2872
2873 binding.crypto_stream_chacha20_ietf_xor_wrap_update(state, c, m)
2874}
2875
2876exports.crypto_stream_chacha20_ietf_xor_wrap_final = function (state) {
2877 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2878 assert(
2879 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2880 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2881 )
2882
2883 binding.crypto_stream_chacha20_ietf_xor_wrap_final(state)
2884}
2885
2886exports.crypto_stream_xchacha20_xor_wrap_init = function (state, n, k) {
2887 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2888 assert(
2889 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2890 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2891 )
2892 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2893 assert(
2894 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
2895 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
2896 )
2897 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2898 assert(
2899 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
2900 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
2901 )
2902
2903 binding.crypto_stream_xchacha20_xor_wrap_init(state, n, k)
2904}
2905
2906exports.crypto_stream_xchacha20_xor_wrap_update = function (state, c, m) {
2907 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2908 assert(
2909 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2910 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2911 )
2912 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2913 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2914 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2915
2916 binding.crypto_stream_xchacha20_xor_wrap_update(state, c, m)
2917}
2918
2919exports.crypto_stream_xchacha20_xor_wrap_final = function (state) {
2920 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2921 assert(
2922 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2923 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2924 )
2925
2926 binding.crypto_stream_xchacha20_xor_wrap_final(state)
2927}
2928
2929exports.crypto_stream_salsa20_xor_wrap_init = function (state, n, k) {
2930 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2931 assert(
2932 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2933 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2934 )
2935 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2936 assert(
2937 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
2938 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
2939 )
2940 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2941 assert(
2942 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
2943 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
2944 )
2945
2946 binding.crypto_stream_salsa20_xor_wrap_init(state, n, k)
2947}
2948
2949exports.crypto_stream_salsa20_xor_wrap_update = function (state, c, m) {
2950 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2951 assert(
2952 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2953 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2954 )
2955 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2956 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2957 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2958
2959 binding.crypto_stream_salsa20_xor_wrap_update(state, c, m)
2960}
2961
2962exports.crypto_stream_salsa20_xor_wrap_final = function (state) {
2963 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2964 assert(
2965 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2966 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2967 )
2968
2969 binding.crypto_stream_salsa20_xor_wrap_final(state)
2970}
2971
2972// experimental
2973
2974exports.extension_tweak_ed25519_base = function (n, p, ns) {
2975 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2976 assert(
2977 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
2978 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
2979 )
2980 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2981 assert(
2982 p.byteLength === binding.extension_tweak_ed25519_BYTES,
2983 "p must be 'extension_tweak_ed25519_BYTES' bytes"
2984 )
2985
2986 binding.extension_tweak_ed25519_base(n, p, ns)
2987}
2988
2989exports.extension_tweak_ed25519_sign_detached = function (sig, m, scalar, pk) {
2990 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
2991 assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes")
2992 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2993 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
2994 assert(
2995 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
2996 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
2997 )
2998
2999 if (pk) {
3000 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3001 assert(
3002 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3003 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3004 )
3005 }
3006
3007 const res = binding.extension_tweak_ed25519_sign_detached(sig, m, scalar, pk)
3008
3009 if (res !== 0) throw new Error('failed to compute signature')
3010}
3011
3012exports.extension_tweak_ed25519_sk_to_scalar = function (n, sk) {
3013 assert(ArrayBuffer.isView(n), 'n must be a typed array')
3014 assert(
3015 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3016 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3017 )
3018 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
3019 assert(
3020 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
3021 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
3022 )
3023
3024 binding.extension_tweak_ed25519_sk_to_scalar(n, sk)
3025}
3026
3027exports.extension_tweak_ed25519_scalar = function (scalarOut, scalar, ns) {
3028 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3029 assert(
3030 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3031 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3032 )
3033 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
3034 assert(
3035 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3036 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3037 )
3038
3039 binding.extension_tweak_ed25519_scalar(scalarOut, scalar, ns)
3040}
3041
3042exports.extension_tweak_ed25519_pk = function (tpk, pk, ns) {
3043 assert(ArrayBuffer.isView(tpk), 'tpk must be a typed array')
3044 assert(
3045 tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3046 "tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3047 )
3048 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3049 assert(
3050 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3051 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3052 )
3053
3054 const res = binding.extension_tweak_ed25519_pk(tpk, pk, ns)
3055
3056 if (res !== 0) throw new Error('failed to tweak public key')
3057}
3058
3059exports.extension_tweak_ed25519_keypair = function (pk, scalarOut, scalarIn, ns) {
3060 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3061 assert(
3062 pk.byteLength === binding.extension_tweak_ed25519_BYTES,
3063 "pk must be 'extension_tweak_ed25519_BYTES' bytes"
3064 )
3065 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3066 assert(
3067 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3068 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3069 )
3070 assert(ArrayBuffer.isView(scalarIn), 'scalarIn must be a typed array')
3071 assert(
3072 scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3073 "scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3074 )
3075
3076 binding.extension_tweak_ed25519_keypair(pk, scalarOut, scalarIn, ns)
3077}
3078
3079exports.extension_tweak_ed25519_scalar_add = function (scalarOut, scalar, n) {
3080 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3081 assert(
3082 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3083 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3084 )
3085 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
3086 assert(
3087 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3088 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3089 )
3090 assert(ArrayBuffer.isView(n), 'n must be a typed array')
3091 assert(
3092 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3093 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3094 )
3095
3096 binding.extension_tweak_ed25519_scalar_add(scalarOut, scalar, n)
3097}
3098
3099exports.extension_tweak_ed25519_pk_add = function (tpk, pk, p) {
3100 assert(ArrayBuffer.isView(tpk), 'tpk must be a typed array')
3101 assert(
3102 tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3103 "tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3104 )
3105 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3106 assert(
3107 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3108 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3109 )
3110 assert(ArrayBuffer.isView(p), 'p must be a typed array')
3111 assert(
3112 p.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3113 "p must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3114 )
3115
3116 const res = binding.extension_tweak_ed25519_pk_add(tpk, pk, p)
3117
3118 if (res !== 0) throw new Error('failed to add tweak to public key')
3119}
3120
3121exports.extension_tweak_ed25519_keypair_add = function (pk, scalarOut, scalarIn, tweak) {
3122 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3123 assert(
3124 pk.byteLength === binding.extension_tweak_ed25519_BYTES,
3125 "pk must be 'extension_tweak_ed25519_BYTES' bytes"
3126 )
3127 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3128 assert(
3129 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3130 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3131 )
3132 assert(ArrayBuffer.isView(scalarIn), 'scalarIn must be a typed array')
3133 assert(
3134 scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3135 "scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3136 )
3137 assert(ArrayBuffer.isView(tweak), 'tweak must be a typed array')
3138 assert(
3139 tweak.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3140 "tweak must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3141 )
3142
3143 const res = binding.extension_tweak_ed25519_keypair_add(pk, scalarOut, scalarIn, tweak)
3144
3145 if (res !== 0) throw new Error('failed to add tweak to keypair')
3146}
3147
3148exports.extension_pbkdf2_sha512_async = function (out, passwd, salt, iter, outlen, callback) {
3149 assert(
3150 iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
3151 "iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
3152 )
3153 assert(
3154 outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
3155 "outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
3156 )
3157 assert(ArrayBuffer.isView(out), 'out must be a typed array')
3158 assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes")
3159 assert(out.byteLength > 0, 'out must not be empty')
3160 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
3161 assert(passwd.byteLength > 0, 'passwd must not be empty')
3162 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
3163 assert(salt.byteLength > 0, 'salt must not be empty')
3164
3165 const [done, promise] = checkStatus(callback)
3166
3167 binding.extension_pbkdf2_sha512_async(
3168 out.buffer,
3169 out.byteOffset,
3170 out.byteLength,
3171
3172 passwd.buffer,
3173 passwd.byteOffset,
3174 passwd.byteLength,
3175
3176 salt.buffer,
3177 salt.byteOffset,
3178 salt.byteLength,
3179
3180 iter,
3181 outlen,
3182
3183 done
3184 )
3185
3186 return promise
3187}
3188
3189exports.extension_pbkdf2_sha512 = function (out, passwd, salt, iter, outlen) {
3190 assert(
3191 iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
3192 "iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
3193 )
3194 assert(
3195 outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
3196 "outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
3197 )
3198 assert(ArrayBuffer.isView(out), 'out must be a typed array')
3199 assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes")
3200 assert(out.byteLength > 0, 'out must not be empty')
3201 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
3202 assert(passwd.byteLength > 0, 'passwd must not be empty')
3203 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
3204 assert(salt.byteLength > 0, 'salt must not be empty')
3205
3206 const res = binding.extension_pbkdf2_sha512(out, passwd, salt, iter, outlen)
3207
3208 if (res !== 0) throw new Error('failed to add tweak to public key')
3209}
3210
3211function checkStatus(callback, booleanResult = false) {
3212 let done, promise
3213
3214 if (typeof callback === 'function') {
3215 done = function (status) {
3216 if (booleanResult) callback(null, status === 0)
3217 else if (status === 0) callback(null)
3218 else callback(new Error('status: ' + status))
3219 }
3220 } else {
3221 promise = new Promise(function (resolve, reject) {
3222 done = function (status) {
3223 if (booleanResult) resolve(status === 0)
3224 else if (status === 0) resolve()
3225 else reject(new Error('status: ' + status))
3226 }
3227 })
3228 }
3229
3230 return [done, promise]
3231}
node_modules/noise-curve-ed/node_modules/sodium-native/package.json +62 -0
……@@ -0,0 +1,62 @@
1{
2 "name": "sodium-native",
3 "version": "5.1.0",
4 "description": "Low level bindings for libsodium",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "binding.cc",
9 "binding.js",
10 "extensions",
11 "prebuilds",
12 "CMakeLists.txt"
13 ],
14 "imports": {
15 "assert": {
16 "bare": "bare-assert",
17 "node": "assert"
18 }
19 },
20 "addon": true,
21 "dependencies": {
22 "bare-assert": "^1.2.0",
23 "require-addon": "^1.1.0",
24 "which-runtime": "^1.2.1"
25 },
26 "devDependencies": {
27 "bare-compat-napi": "^1.3.5",
28 "brittle": "^3.16.2",
29 "cmake-bare": "^1.6.1",
30 "cmake-fetch": "^1.4.3",
31 "cmake-napi": "^1.2.1",
32 "prettier": "^3.6.2",
33 "prettier-config-holepunch": "^2.0.0"
34 },
35 "scripts": {
36 "test": "prettier . --check && npm run test:node && npm run test:bare",
37 "test:node": "node test/all.js",
38 "test:bare": "bare test/all.js"
39 },
40 "standard": {
41 "ignore": [
42 "/test/fixtures/*.js"
43 ]
44 },
45 "engines": {
46 "bare": ">=1.16.0"
47 },
48 "repository": {
49 "type": "git",
50 "url": "git+https://github.com/holepunchto/sodium-native.git"
51 },
52 "contributors": [
53 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
54 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
55 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
56 ],
57 "license": "MIT",
58 "bugs": {
59 "url": "https://github.com/holepunchto/sodium-native/issues"
60 },
61 "homepage": "https://github.com/holepunchto/sodium-native"
62}
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/android-arm/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/android-arm/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/android-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/android-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/android-ia32/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/android-ia32/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/android-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/android-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/ios-arm64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/ios-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/ios-x64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/win32-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-native/prebuilds/win32-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-curve-ed/node_modules/sodium-universal/LICENSE.md +7 -0
……@@ -0,0 +1,7 @@
1Copyright 2017 Mathias Buus & Emil Bay
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
node_modules/noise-curve-ed/node_modules/sodium-universal/README.md +288 -0
……@@ -0,0 +1,288 @@
1# sodium-universal
2
3Universal wrapper for `sodium-javascript` and `sodium-native` working in Node.js and the Browser
4
5```sh
6npm install sodium-universal
7```
8
9`sodium-native` ships with prebuilds for macOS, Windows, and Linux.
10
11Note that the module itself is generated on a prepublish hook.
12
13## Usage
14
15```js
16var sodium = require('sodium-universal')
17
18var rnd = Buffer.allocUnsafe(12) // Cryptographically random data
19sodium.randombytes_buf(rnd)
20
21console.log(rnd.toString('hex'))
22
23```
24
25Works seamlessly with Node.js:
26
27```sh
28$ node example.js
29c7dbd46a6cc84ff2e0d1285c
30```
31
32And the browser:
33
34First install the peer dep, `sodium-javascript`.
35
36```sh
37npm install --save sodium-javascript
38```
39
40And then browserify
41
42```sh
43browserify example.js > bundle.js
44```
45
46## Introduction
47
48[`libsodium`](https://download.libsodium.org/doc/) is a collection of cryptographic primitives, providing a low-level foundation to build higher-level cryptographic applications and protocols. It is often put in contrast to RSA based cryptography and OpenSSL, even though they all share overlapping algorithms and target slightly different audiences. Sodium is a collection of modern collection of primitives, fulfilling the same cryptographic tasks, but based on simpler and more efficient algorithms.
49
50This library provides seamless bindings to [`sodium-native`](https://github.com/sodium-friends/sodium-native), which is the original C implementation of `libsodium` exposed as a Node native module. For the browser we expose [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript), using the `package.json` [`browser`](https://github.com/defunctzombie/package-browser-field-spec) field, which is supported by most bundlers.
51
52## API
53
54Please refer to [`sodium-native`](https://github.com/sodium-friends/sodium-native#api) and [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript#api). Note that the two modules do not yet have feature parity, where `sodium-native` is the more featureful of the two.
55
56## Compatibilty
57
58<!-- Generated by build-scripts/symbols.js with
59 sodium-native@3.2.0
60 sodium-javascript@0.6.0 -->
61| C Library Symbol | `sodium-native` | `sodium-javascript` |
62|:--------------------------------------------------------:|:--------------------:|:--------------------:|
63| `crypto_aead_chacha20poly1305_ietf_ABYTES` | :white_check_mark: | :white_check_mark: |
64| `crypto_aead_chacha20poly1305_ietf_decrypt` | :white_check_mark: | :white_check_mark: |
65| `crypto_aead_chacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :white_check_mark: |
66| `crypto_aead_chacha20poly1305_ietf_encrypt` | :white_check_mark: | :white_check_mark: |
67| `crypto_aead_chacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :white_check_mark: |
68| `crypto_aead_chacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
69| `crypto_aead_chacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
70| `crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
71| `crypto_aead_chacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :white_check_mark: |
72| `crypto_aead_chacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :white_check_mark: |
73| `crypto_aead_xchacha20poly1305_ietf_ABYTES` | :white_check_mark: | :small_red_triangle: |
74| `crypto_aead_xchacha20poly1305_ietf_decrypt` | :white_check_mark: | :small_red_triangle: |
75| `crypto_aead_xchacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :small_red_triangle: |
76| `crypto_aead_xchacha20poly1305_ietf_encrypt` | :white_check_mark: | :small_red_triangle: |
77| `crypto_aead_xchacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :small_red_triangle: |
78| `crypto_aead_xchacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
79| `crypto_aead_xchacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
80| `crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
81| `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :small_red_triangle: |
82| `crypto_aead_xchacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :small_red_triangle: |
83| `crypto_auth` | :white_check_mark: | :small_red_triangle: |
84| `crypto_auth_BYTES` | :white_check_mark: | :small_red_triangle: |
85| `crypto_auth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
86| `crypto_auth_verify` | :white_check_mark: | :small_red_triangle: |
87| `crypto_box_BEFORENMBYTES` | :small_red_triangle: | :white_check_mark: |
88| `crypto_box_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
89| `crypto_box_detached` | :white_check_mark: | :small_red_triangle: |
90| `crypto_box_easy` | :white_check_mark: | :small_red_triangle: |
91| `crypto_box_keypair` | :white_check_mark: | :white_check_mark: |
92| `crypto_box_MACBYTES` | :white_check_mark: | :small_red_triangle: |
93| `crypto_box_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
94| `crypto_box_open_detached` | :white_check_mark: | :small_red_triangle: |
95| `crypto_box_open_easy` | :white_check_mark: | :small_red_triangle: |
96| `crypto_box_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
97| `crypto_box_seal` | :white_check_mark: | :white_check_mark: |
98| `crypto_box_seal_open` | :white_check_mark: | :white_check_mark: |
99| `crypto_box_SEALBYTES` | :white_check_mark: | :white_check_mark: |
100| `crypto_box_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
101| `crypto_box_seed_keypair` | :white_check_mark: | :white_check_mark: |
102| `crypto_box_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
103| `crypto_box_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
104| `crypto_core_ed25519_add` | :white_check_mark: | :small_red_triangle: |
105| `crypto_core_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
106| `crypto_core_ed25519_from_uniform` | :white_check_mark: | :small_red_triangle: |
107| `crypto_core_ed25519_is_valid_point` | :white_check_mark: | :small_red_triangle: |
108| `crypto_core_ed25519_NONREDUCEDSCALARBYTES` | :white_check_mark: | :small_red_triangle: |
109| `crypto_core_ed25519_scalar_add` | :white_check_mark: | :small_red_triangle: |
110| `crypto_core_ed25519_scalar_complement` | :white_check_mark: | :small_red_triangle: |
111| `crypto_core_ed25519_scalar_invert` | :white_check_mark: | :small_red_triangle: |
112| `crypto_core_ed25519_scalar_negate` | :white_check_mark: | :small_red_triangle: |
113| `crypto_core_ed25519_scalar_random` | :white_check_mark: | :small_red_triangle: |
114| `crypto_core_ed25519_scalar_reduce` | :white_check_mark: | :small_red_triangle: |
115| `crypto_core_ed25519_scalar_sub` | :white_check_mark: | :small_red_triangle: |
116| `crypto_core_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
117| `crypto_core_ed25519_sub` | :white_check_mark: | :small_red_triangle: |
118| `crypto_core_ed25519_UNIFORMBYTES` | :white_check_mark: | :small_red_triangle: |
119| `crypto_generichash` | :white_check_mark: | :white_check_mark: |
120| `crypto_generichash_BYTES` | :white_check_mark: | :white_check_mark: |
121| `crypto_generichash_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
122| `crypto_generichash_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
123| `crypto_generichash_final` | :white_check_mark: | :small_red_triangle: |
124| `crypto_generichash_init` | :white_check_mark: | :small_red_triangle: |
125| `crypto_generichash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
126| `crypto_generichash_KEYBYTES_MAX` | :white_check_mark: | :white_check_mark: |
127| `crypto_generichash_KEYBYTES_MIN` | :white_check_mark: | :white_check_mark: |
128| `crypto_generichash_keygen` | :white_check_mark: | :small_red_triangle: |
129| `crypto_generichash_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
130| `crypto_generichash_update` | :white_check_mark: | :small_red_triangle: |
131| `crypto_hash` | :white_check_mark: | :white_check_mark: |
132| `crypto_hash_BYTES` | :white_check_mark: | :white_check_mark: |
133| `crypto_hash_sha256` | :white_check_mark: | :white_check_mark: |
134| `crypto_hash_sha256_BYTES` | :white_check_mark: | :white_check_mark: |
135| `crypto_hash_sha256_final` | :white_check_mark: | :small_red_triangle: |
136| `crypto_hash_sha256_init` | :white_check_mark: | :small_red_triangle: |
137| `crypto_hash_sha256_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
138| `crypto_hash_sha256_update` | :white_check_mark: | :small_red_triangle: |
139| `crypto_hash_sha512` | :white_check_mark: | :white_check_mark: |
140| `crypto_hash_sha512_BYTES` | :white_check_mark: | :white_check_mark: |
141| `crypto_hash_sha512_final` | :white_check_mark: | :small_red_triangle: |
142| `crypto_hash_sha512_init` | :white_check_mark: | :small_red_triangle: |
143| `crypto_hash_sha512_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
144| `crypto_hash_sha512_update` | :white_check_mark: | :small_red_triangle: |
145| `crypto_kdf_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
146| `crypto_kdf_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
147| `crypto_kdf_CONTEXTBYTES` | :white_check_mark: | :white_check_mark: |
148| `crypto_kdf_derive_from_key` | :white_check_mark: | :white_check_mark: |
149| `crypto_kdf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
150| `crypto_kdf_keygen` | :white_check_mark: | :white_check_mark: |
151| `crypto_kx_client_session_keys` | :white_check_mark: | :small_red_triangle: |
152| `crypto_kx_keypair` | :white_check_mark: | :white_check_mark: |
153| `crypto_kx_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
154| `crypto_kx_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
155| `crypto_kx_seed_keypair` | :white_check_mark: | :white_check_mark: |
156| `crypto_kx_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
157| `crypto_kx_server_session_keys` | :white_check_mark: | :small_red_triangle: |
158| `crypto_kx_SESSIONKEYBYTES` | :white_check_mark: | :small_red_triangle: |
159| `crypto_onetimeauth` | :white_check_mark: | :white_check_mark: |
160| `crypto_onetimeauth_BYTES` | :white_check_mark: | :small_red_triangle: |
161| `crypto_onetimeauth_final` | :white_check_mark: | :small_red_triangle: |
162| `crypto_onetimeauth_init` | :white_check_mark: | :small_red_triangle: |
163| `crypto_onetimeauth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
164| `crypto_onetimeauth_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
165| `crypto_onetimeauth_update` | :white_check_mark: | :small_red_triangle: |
166| `crypto_onetimeauth_verify` | :white_check_mark: | :white_check_mark: |
167| `crypto_pwhash` | :white_check_mark: | :small_red_triangle: |
168| `crypto_pwhash_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
169| `crypto_pwhash_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
170| `crypto_pwhash_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
171| `crypto_pwhash_scryptsalsa208sha256` | :white_check_mark: | :small_red_triangle: |
172| `crypto_pwhash_scryptsalsa208sha256_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
173| `crypto_pwhash_scryptsalsa208sha256_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
174| `crypto_pwhash_scryptsalsa208sha256_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
175| `crypto_pwhash_scryptsalsa208sha256_str` | :white_check_mark: | :small_red_triangle: |
176| `crypto_pwhash_scryptsalsa208sha256_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
177| `crypto_pwhash_scryptsalsa208sha256_str_verify` | :white_check_mark: | :small_red_triangle: |
178| `crypto_pwhash_scryptsalsa208sha256_STRBYTES` | :white_check_mark: | :small_red_triangle: |
179| `crypto_pwhash_str` | :white_check_mark: | :small_red_triangle: |
180| `crypto_pwhash_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
181| `crypto_pwhash_str_verify` | :white_check_mark: | :small_red_triangle: |
182| `crypto_pwhash_STRBYTES` | :white_check_mark: | :small_red_triangle: |
183| `crypto_scalarmult` | :white_check_mark: | :white_check_mark: |
184| `crypto_scalarmult_base` | :white_check_mark: | :white_check_mark: |
185| `crypto_scalarmult_BYTES` | :white_check_mark: | :white_check_mark: |
186| `crypto_scalarmult_ed25519` | :white_check_mark: | :small_red_triangle: |
187| `crypto_scalarmult_ed25519_base` | :white_check_mark: | :small_red_triangle: |
188| `crypto_scalarmult_ed25519_base_noclamp` | :white_check_mark: | :small_red_triangle: |
189| `crypto_scalarmult_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
190| `crypto_scalarmult_ed25519_noclamp` | :white_check_mark: | :small_red_triangle: |
191| `crypto_scalarmult_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
192| `crypto_scalarmult_SCALARBYTES` | :white_check_mark: | :white_check_mark: |
193| `crypto_secretbox` | :small_red_triangle: | :white_check_mark: |
194| `crypto_secretbox_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
195| `crypto_secretbox_detached` | :white_check_mark: | :white_check_mark: |
196| `crypto_secretbox_easy` | :white_check_mark: | :white_check_mark: |
197| `crypto_secretbox_KEYBYTES` | :white_check_mark: | :white_check_mark: |
198| `crypto_secretbox_MACBYTES` | :white_check_mark: | :white_check_mark: |
199| `crypto_secretbox_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
200| `crypto_secretbox_open` | :small_red_triangle: | :white_check_mark: |
201| `crypto_secretbox_open_detached` | :white_check_mark: | :white_check_mark: |
202| `crypto_secretbox_open_easy` | :white_check_mark: | :white_check_mark: |
203| `crypto_secretbox_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
204| `crypto_secretstream_xchacha20poly1305_ABYTES` | :white_check_mark: | :small_red_triangle: |
205| `crypto_secretstream_xchacha20poly1305_HEADERBYTES` | :white_check_mark: | :small_red_triangle: |
206| `crypto_secretstream_xchacha20poly1305_init_pull` | :white_check_mark: | :small_red_triangle: |
207| `crypto_secretstream_xchacha20poly1305_init_push` | :white_check_mark: | :small_red_triangle: |
208| `crypto_secretstream_xchacha20poly1305_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
209| `crypto_secretstream_xchacha20poly1305_keygen` | :white_check_mark: | :small_red_triangle: |
210| `crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
211| `crypto_secretstream_xchacha20poly1305_pull` | :white_check_mark: | :small_red_triangle: |
212| `crypto_secretstream_xchacha20poly1305_push` | :white_check_mark: | :small_red_triangle: |
213| `crypto_secretstream_xchacha20poly1305_rekey` | :white_check_mark: | :small_red_triangle: |
214| `crypto_secretstream_xchacha20poly1305_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
215| `crypto_shorthash` | :white_check_mark: | :white_check_mark: |
216| `crypto_shorthash_BYTES` | :white_check_mark: | :white_check_mark: |
217| `crypto_shorthash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
218| `crypto_sign` | :white_check_mark: | :white_check_mark: |
219| `crypto_sign_BYTES` | :white_check_mark: | :white_check_mark: |
220| `crypto_sign_detached` | :white_check_mark: | :white_check_mark: |
221| `crypto_sign_ed25519_pk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
222| `crypto_sign_ed25519_sk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
223| `crypto_sign_ed25519_sk_to_pk` | :white_check_mark: | :small_red_triangle: |
224| `crypto_sign_keypair` | :white_check_mark: | :white_check_mark: |
225| `crypto_sign_open` | :white_check_mark: | :white_check_mark: |
226| `crypto_sign_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
227| `crypto_sign_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
228| `crypto_sign_seed_keypair` | :white_check_mark: | :white_check_mark: |
229| `crypto_sign_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
230| `crypto_sign_verify_detached` | :white_check_mark: | :white_check_mark: |
231| `crypto_stream` | :white_check_mark: | :white_check_mark: |
232| `crypto_stream_chacha20` | :white_check_mark: | :white_check_mark: |
233| `crypto_stream_chacha20_ietf` | :white_check_mark: | :white_check_mark: |
234| `crypto_stream_chacha20_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
235| `crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
236| `crypto_stream_chacha20_ietf_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
237| `crypto_stream_chacha20_ietf_xor` | :white_check_mark: | :white_check_mark: |
238| `crypto_stream_chacha20_ietf_xor_ic` | :white_check_mark: | :white_check_mark: |
239| `crypto_stream_chacha20_KEYBYTES` | :white_check_mark: | :white_check_mark: |
240| `crypto_stream_chacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
241| `crypto_stream_chacha20_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
242| `crypto_stream_chacha20_xor` | :white_check_mark: | :white_check_mark: |
243| `crypto_stream_chacha20_xor_ic` | :white_check_mark: | :white_check_mark: |
244| `crypto_stream_KEYBYTES` | :white_check_mark: | :white_check_mark: |
245| `crypto_stream_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
246| `crypto_stream_salsa20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
247| `crypto_stream_salsa20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
248| `crypto_stream_salsa20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
249| `crypto_stream_salsa20_xor` | :white_check_mark: | :small_red_triangle: |
250| `crypto_stream_salsa20_xor_ic` | :white_check_mark: | :small_red_triangle: |
251| `crypto_stream_xchacha20` | :white_check_mark: | :small_red_triangle: |
252| `crypto_stream_xchacha20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
253| `crypto_stream_xchacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
254| `crypto_stream_xchacha20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
255| `crypto_stream_xchacha20_xor` | :white_check_mark: | :small_red_triangle: |
256| `crypto_stream_xchacha20_xor_ic` | :white_check_mark: | :small_red_triangle: |
257| `crypto_stream_xor` | :white_check_mark: | :white_check_mark: |
258| `crypto_verify_16` | :small_red_triangle: | :white_check_mark: |
259| `crypto_verify_32` | :small_red_triangle: | :white_check_mark: |
260| `randombytes_buf` | :white_check_mark: | :white_check_mark: |
261| `randombytes_buf_deterministic` | :white_check_mark: | :small_red_triangle: |
262| `randombytes_random` | :white_check_mark: | :small_red_triangle: |
263| `randombytes_SEEDBYTES` | :white_check_mark: | :small_red_triangle: |
264| `randombytes_uniform` | :white_check_mark: | :small_red_triangle: |
265| `sodium_add` | :white_check_mark: | :small_red_triangle: |
266| `sodium_compare` | :white_check_mark: | :small_red_triangle: |
267| `sodium_free` | :white_check_mark: | :small_red_triangle: |
268| `sodium_increment` | :white_check_mark: | :small_red_triangle: |
269| `sodium_is_zero` | :white_check_mark: | :white_check_mark: |
270| `sodium_malloc` | :white_check_mark: | :white_check_mark: |
271| `sodium_memcmp` | :white_check_mark: | :white_check_mark: |
272| `sodium_memzero` | :white_check_mark: | :white_check_mark: |
273| `sodium_mlock` | :white_check_mark: | :small_red_triangle: |
274| `sodium_mprotect_noaccess` | :white_check_mark: | :small_red_triangle: |
275| `sodium_mprotect_readonly` | :white_check_mark: | :small_red_triangle: |
276| `sodium_mprotect_readwrite` | :white_check_mark: | :small_red_triangle: |
277| `sodium_munlock` | :white_check_mark: | :small_red_triangle: |
278| `sodium_pad` | :white_check_mark: | :small_red_triangle: |
279| `sodium_sub` | :white_check_mark: | :small_red_triangle: |
280| `sodium_unpad` | :white_check_mark: | :small_red_triangle: |
281
282### Missing altogether (Ctrl + F friendly)
283
284`crypto_aead_aes256gcm_ABYTES`, `crypto_aead_aes256gcm_beforenm`, `crypto_aead_aes256gcm_decrypt`, `crypto_aead_aes256gcm_decrypt_afternm`, `crypto_aead_aes256gcm_decrypt_detached`, `crypto_aead_aes256gcm_decrypt_detached_afternm`, `crypto_aead_aes256gcm_encrypt`, `crypto_aead_aes256gcm_encrypt_afternm`, `crypto_aead_aes256gcm_encrypt_detached`, `crypto_aead_aes256gcm_encrypt_detached_afternm`, `crypto_aead_aes256gcm_is_available`, `crypto_aead_aes256gcm_KEYBYTES`, `crypto_aead_aes256gcm_keygen`, `crypto_aead_aes256gcm_MESSAGEBYTES_MAX`, `crypto_aead_aes256gcm_NPUBBYTES`, `crypto_aead_aes256gcm_NSECBYTES`, `crypto_aead_aes256gcm_STATEBYTES`, `crypto_aead_chacha20poly1305_ABYTES`, `crypto_aead_chacha20poly1305_decrypt`, `crypto_aead_chacha20poly1305_decrypt_detached`, `crypto_aead_chacha20poly1305_encrypt`, `crypto_aead_chacha20poly1305_encrypt_detached`, `crypto_aead_chacha20poly1305_KEYBYTES`, `crypto_aead_chacha20poly1305_keygen`, `crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX`, `crypto_aead_chacha20poly1305_NPUBBYTES`, `crypto_aead_chacha20poly1305_NSECBYTES`, `crypto_auth_hmacsha256`, `crypto_auth_hmacsha256_BYTES`, `crypto_auth_hmacsha256_final`, `crypto_auth_hmacsha256_init`, `crypto_auth_hmacsha256_KEYBYTES`, `crypto_auth_hmacsha256_keygen`, `crypto_auth_hmacsha256_STATEBYTES`, `crypto_auth_hmacsha256_update`, `crypto_auth_hmacsha256_verify`, `crypto_auth_hmacsha512`, `crypto_auth_hmacsha512256`, `crypto_auth_hmacsha512256_BYTES`, `crypto_auth_hmacsha512256_final`, `crypto_auth_hmacsha512256_init`, `crypto_auth_hmacsha512256_KEYBYTES`, `crypto_auth_hmacsha512256_keygen`, `crypto_auth_hmacsha512256_STATEBYTES`, `crypto_auth_hmacsha512256_update`, `crypto_auth_hmacsha512256_verify`, `crypto_auth_hmacsha512_BYTES`, `crypto_auth_hmacsha512_final`, `crypto_auth_hmacsha512_init`, `crypto_auth_hmacsha512_KEYBYTES`, `crypto_auth_hmacsha512_keygen`, `crypto_auth_hmacsha512_STATEBYTES`, `crypto_auth_hmacsha512_update`, `crypto_auth_hmacsha512_verify`, `crypto_auth_keygen`, `crypto_auth_primitive`, `crypto_box`, `crypto_box_afternm`, `crypto_box_beforenm`, `crypto_box_curve25519xchacha20poly1305_beforenm`, `crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xchacha20poly1305_detached`, `crypto_box_curve25519xchacha20poly1305_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_easy`, `crypto_box_curve25519xchacha20poly1305_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_keypair`, `crypto_box_curve25519xchacha20poly1305_MACBYTES`, `crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xchacha20poly1305_NONCEBYTES`, `crypto_box_curve25519xchacha20poly1305_open_detached`, `crypto_box_curve25519xchacha20poly1305_open_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_open_easy`, `crypto_box_curve25519xchacha20poly1305_open_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seal`, `crypto_box_curve25519xchacha20poly1305_seal_open`, `crypto_box_curve25519xchacha20poly1305_SEALBYTES`, `crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seed_keypair`, `crypto_box_curve25519xchacha20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305`, `crypto_box_curve25519xsalsa20poly1305_afternm`, `crypto_box_curve25519xsalsa20poly1305_beforenm`, `crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES`, `crypto_box_curve25519xsalsa20poly1305_keypair`, `crypto_box_curve25519xsalsa20poly1305_MACBYTES`, `crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xsalsa20poly1305_NONCEBYTES`, `crypto_box_curve25519xsalsa20poly1305_open`, `crypto_box_curve25519xsalsa20poly1305_open_afternm`, `crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_seed_keypair`, `crypto_box_curve25519xsalsa20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305_ZEROBYTES`, `crypto_box_detached_afternm`, `crypto_box_easy_afternm`, `crypto_box_MESSAGEBYTES_MAX`, `crypto_box_open`, `crypto_box_open_afternm`, `crypto_box_open_detached_afternm`, `crypto_box_open_easy_afternm`, `crypto_box_primitive`, `crypto_core_ed25519_from_hash`, `crypto_core_ed25519_HASHBYTES`, `crypto_core_ed25519_random`, `crypto_core_ed25519_scalar_mul`, `crypto_core_hchacha20`, `crypto_core_hchacha20_CONSTBYTES`, `crypto_core_hchacha20_INPUTBYTES`, `crypto_core_hchacha20_KEYBYTES`, `crypto_core_hchacha20_OUTPUTBYTES`, `crypto_core_hsalsa20`, `crypto_core_hsalsa20_CONSTBYTES`, `crypto_core_hsalsa20_INPUTBYTES`, `crypto_core_hsalsa20_KEYBYTES`, `crypto_core_hsalsa20_OUTPUTBYTES`, `crypto_core_ristretto255_add`, `crypto_core_ristretto255_BYTES`, `crypto_core_ristretto255_from_hash`, `crypto_core_ristretto255_HASHBYTES`, `crypto_core_ristretto255_is_valid_point`, `crypto_core_ristretto255_NONREDUCEDSCALARBYTES`, `crypto_core_ristretto255_random`, `crypto_core_ristretto255_scalar_add`, `crypto_core_ristretto255_scalar_complement`, `crypto_core_ristretto255_scalar_invert`, `crypto_core_ristretto255_scalar_mul`, `crypto_core_ristretto255_scalar_negate`, `crypto_core_ristretto255_scalar_random`, `crypto_core_ristretto255_scalar_reduce`, `crypto_core_ristretto255_scalar_sub`, `crypto_core_ristretto255_SCALARBYTES`, `crypto_core_ristretto255_sub`, `crypto_core_salsa20`, `crypto_core_salsa2012`, `crypto_core_salsa2012_CONSTBYTES`, `crypto_core_salsa2012_INPUTBYTES`, `crypto_core_salsa2012_KEYBYTES`, `crypto_core_salsa2012_OUTPUTBYTES`, `crypto_core_salsa208`, `crypto_core_salsa208_CONSTBYTES`, `crypto_core_salsa208_INPUTBYTES`, `crypto_core_salsa208_KEYBYTES`, `crypto_core_salsa208_OUTPUTBYTES`, `crypto_core_salsa20_CONSTBYTES`, `crypto_core_salsa20_INPUTBYTES`, `crypto_core_salsa20_KEYBYTES`, `crypto_core_salsa20_OUTPUTBYTES`, `crypto_generichash_blake2b`, `crypto_generichash_blake2b_BYTES`, `crypto_generichash_blake2b_BYTES_MAX`, `crypto_generichash_blake2b_BYTES_MIN`, `crypto_generichash_blake2b_final`, `crypto_generichash_blake2b_init`, `crypto_generichash_blake2b_init_salt_personal`, `crypto_generichash_blake2b_KEYBYTES`, `crypto_generichash_blake2b_KEYBYTES_MAX`, `crypto_generichash_blake2b_KEYBYTES_MIN`, `crypto_generichash_blake2b_keygen`, `crypto_generichash_blake2b_PERSONALBYTES`, `crypto_generichash_blake2b_salt_personal`, `crypto_generichash_blake2b_SALTBYTES`, `crypto_generichash_blake2b_STATEBYTES`, `crypto_generichash_blake2b_update`, `crypto_generichash_primitive`, `crypto_hash_primitive`, `crypto_kdf_blake2b_BYTES_MAX`, `crypto_kdf_blake2b_BYTES_MIN`, `crypto_kdf_blake2b_CONTEXTBYTES`, `crypto_kdf_blake2b_derive_from_key`, `crypto_kdf_blake2b_KEYBYTES`, `crypto_kdf_primitive`, `crypto_kx_primitive`, `crypto_onetimeauth_keygen`, `crypto_onetimeauth_poly1305`, `crypto_onetimeauth_poly1305_BYTES`, `crypto_onetimeauth_poly1305_final`, `crypto_onetimeauth_poly1305_init`, `crypto_onetimeauth_poly1305_KEYBYTES`, `crypto_onetimeauth_poly1305_keygen`, `crypto_onetimeauth_poly1305_STATEBYTES`, `crypto_onetimeauth_poly1305_update`, `crypto_onetimeauth_poly1305_verify`, `crypto_onetimeauth_primitive`, `crypto_pwhash_alg_argon2i13`, `crypto_pwhash_alg_argon2id13`, `crypto_pwhash_alg_default`, `crypto_pwhash_argon2i`, `crypto_pwhash_argon2i_alg_argon2i13`, `crypto_pwhash_argon2i_BYTES_MAX`, `crypto_pwhash_argon2i_BYTES_MIN`, `crypto_pwhash_argon2i_memlimit_interactive`, `crypto_pwhash_argon2i_memlimit_max`, `crypto_pwhash_argon2i_memlimit_min`, `crypto_pwhash_argon2i_memlimit_moderate`, `crypto_pwhash_argon2i_memlimit_sensitive`, `crypto_pwhash_argon2i_opslimit_interactive`, `crypto_pwhash_argon2i_opslimit_max`, `crypto_pwhash_argon2i_opslimit_min`, `crypto_pwhash_argon2i_opslimit_moderate`, `crypto_pwhash_argon2i_opslimit_sensitive`, `crypto_pwhash_argon2i_passwd_max`, `crypto_pwhash_argon2i_passwd_min`, `crypto_pwhash_argon2i_SALTBYTES`, `crypto_pwhash_argon2i_str`, `crypto_pwhash_argon2i_str_needs_rehash`, `crypto_pwhash_argon2i_str_verify`, `crypto_pwhash_argon2i_STRBYTES`, `crypto_pwhash_argon2i_strprefix`, `crypto_pwhash_argon2id`, `crypto_pwhash_argon2id_alg_argon2id13`, `crypto_pwhash_argon2id_BYTES_MAX`, `crypto_pwhash_argon2id_BYTES_MIN`, `crypto_pwhash_argon2id_memlimit_interactive`, `crypto_pwhash_argon2id_memlimit_max`, `crypto_pwhash_argon2id_memlimit_min`, `crypto_pwhash_argon2id_memlimit_moderate`, `crypto_pwhash_argon2id_memlimit_sensitive`, `crypto_pwhash_argon2id_opslimit_interactive`, `crypto_pwhash_argon2id_opslimit_max`, `crypto_pwhash_argon2id_opslimit_min`, `crypto_pwhash_argon2id_opslimit_moderate`, `crypto_pwhash_argon2id_opslimit_sensitive`, `crypto_pwhash_argon2id_passwd_max`, `crypto_pwhash_argon2id_passwd_min`, `crypto_pwhash_argon2id_SALTBYTES`, `crypto_pwhash_argon2id_str`, `crypto_pwhash_argon2id_str_needs_rehash`, `crypto_pwhash_argon2id_str_verify`, `crypto_pwhash_argon2id_STRBYTES`, `crypto_pwhash_argon2id_strprefix`, `crypto_pwhash_memlimit_interactive`, `crypto_pwhash_memlimit_max`, `crypto_pwhash_memlimit_min`, `crypto_pwhash_memlimit_moderate`, `crypto_pwhash_memlimit_sensitive`, `crypto_pwhash_opslimit_interactive`, `crypto_pwhash_opslimit_max`, `crypto_pwhash_opslimit_min`, `crypto_pwhash_opslimit_moderate`, `crypto_pwhash_opslimit_sensitive`, `crypto_pwhash_passwd_max`, `crypto_pwhash_passwd_min`, `crypto_pwhash_primitive`, `crypto_pwhash_scryptsalsa208sha256_ll`, `crypto_pwhash_scryptsalsa208sha256_memlimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_memlimit_max`, `crypto_pwhash_scryptsalsa208sha256_memlimit_min`, `crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_max`, `crypto_pwhash_scryptsalsa208sha256_opslimit_min`, `crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_passwd_max`, `crypto_pwhash_scryptsalsa208sha256_passwd_min`, `crypto_pwhash_scryptsalsa208sha256_strprefix`, `crypto_pwhash_str_alg`, `crypto_pwhash_strprefix`, `crypto_scalarmult_curve25519`, `crypto_scalarmult_curve25519_base`, `crypto_scalarmult_curve25519_BYTES`, `crypto_scalarmult_curve25519_SCALARBYTES`, `crypto_scalarmult_primitive`, `crypto_scalarmult_ristretto255`, `crypto_scalarmult_ristretto255_base`, `crypto_scalarmult_ristretto255_BYTES`, `crypto_scalarmult_ristretto255_SCALARBYTES`, `crypto_secretbox_keygen`, `crypto_secretbox_MESSAGEBYTES_MAX`, `crypto_secretbox_primitive`, `crypto_secretbox_xchacha20poly1305_detached`, `crypto_secretbox_xchacha20poly1305_easy`, `crypto_secretbox_xchacha20poly1305_KEYBYTES`, `crypto_secretbox_xchacha20poly1305_MACBYTES`, `crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xchacha20poly1305_NONCEBYTES`, `crypto_secretbox_xchacha20poly1305_open_detached`, `crypto_secretbox_xchacha20poly1305_open_easy`, `crypto_secretbox_xsalsa20poly1305`, `crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES`, `crypto_secretbox_xsalsa20poly1305_KEYBYTES`, `crypto_secretbox_xsalsa20poly1305_keygen`, `crypto_secretbox_xsalsa20poly1305_MACBYTES`, `crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xsalsa20poly1305_NONCEBYTES`, `crypto_secretbox_xsalsa20poly1305_open`, `crypto_secretbox_xsalsa20poly1305_ZEROBYTES`, `crypto_secretstream_xchacha20poly1305_tag_final`, `crypto_secretstream_xchacha20poly1305_tag_message`, `crypto_secretstream_xchacha20poly1305_tag_push`, `crypto_secretstream_xchacha20poly1305_tag_rekey`, `crypto_shorthash_keygen`, `crypto_shorthash_primitive`, `crypto_shorthash_siphash24`, `crypto_shorthash_siphash24_BYTES`, `crypto_shorthash_siphash24_KEYBYTES`, `crypto_shorthash_siphashx24`, `crypto_shorthash_siphashx24_BYTES`, `crypto_shorthash_siphashx24_KEYBYTES`, `crypto_sign_ed25519`, `crypto_sign_ed25519_BYTES`, `crypto_sign_ed25519_detached`, `crypto_sign_ed25519_keypair`, `crypto_sign_ed25519_MESSAGEBYTES_MAX`, `crypto_sign_ed25519_open`, `crypto_sign_ed25519_PUBLICKEYBYTES`, `crypto_sign_ed25519_SECRETKEYBYTES`, `crypto_sign_ed25519_seed_keypair`, `crypto_sign_ed25519_SEEDBYTES`, `crypto_sign_ed25519_sk_to_seed`, `crypto_sign_ed25519_verify_detached`, `crypto_sign_ed25519ph_final_create`, `crypto_sign_ed25519ph_final_verify`, `crypto_sign_ed25519ph_init`, `crypto_sign_ed25519ph_STATEBYTES`, `crypto_sign_ed25519ph_update`, `crypto_sign_edwards25519sha512batch`, `crypto_sign_edwards25519sha512batch_keypair`, `crypto_sign_edwards25519sha512batch_open`, `crypto_sign_final_create`, `crypto_sign_final_verify`, `crypto_sign_init`, `crypto_sign_MESSAGEBYTES_MAX`, `crypto_sign_primitive`, `crypto_sign_STATEBYTES`, `crypto_sign_update`, `crypto_stream_chacha20_ietf_keygen`, `crypto_stream_chacha20_keygen`, `crypto_stream_keygen`, `crypto_stream_MESSAGEBYTES_MAX`, `crypto_stream_primitive`, `crypto_stream_salsa20`, `crypto_stream_salsa2012`, `crypto_stream_salsa2012_KEYBYTES`, `crypto_stream_salsa2012_keygen`, `crypto_stream_salsa2012_MESSAGEBYTES_MAX`, `crypto_stream_salsa2012_NONCEBYTES`, `crypto_stream_salsa2012_xor`, `crypto_stream_salsa208`, `crypto_stream_salsa208_KEYBYTES`, `crypto_stream_salsa208_keygen`, `crypto_stream_salsa208_MESSAGEBYTES_MAX`, `crypto_stream_salsa208_NONCEBYTES`, `crypto_stream_salsa208_xor`, `crypto_stream_salsa20_keygen`, `crypto_stream_xchacha20_keygen`, `crypto_stream_xsalsa20`, `crypto_stream_xsalsa20_KEYBYTES`, `crypto_stream_xsalsa20_keygen`, `crypto_stream_xsalsa20_MESSAGEBYTES_MAX`, `crypto_stream_xsalsa20_NONCEBYTES`, `crypto_stream_xsalsa20_xor`, `crypto_stream_xsalsa20_xor_ic`, `crypto_verify_16_BYTES`, `crypto_verify_32_BYTES`, `crypto_verify_64`, `crypto_verify_64_BYTES`, `randombytes`, `randombytes_close`, `randombytes_implementation_name`, `randombytes_internal_implementation`, `randombytes_set_implementation`, `randombytes_stir`, `randombytes_sysrandom_implementation`, `sodium_allocarray`, `sodium_base642bin`, `sodium_base64_encoded_len`, `sodium_bin2base64`, `sodium_bin2hex`, `sodium_hex2bin`, `sodium_init`, `sodium_library_minimal`, `sodium_library_version_major`, `sodium_library_version_minor`, `sodium_misuse`, `sodium_runtime_has_aesni`, `sodium_runtime_has_avx`, `sodium_runtime_has_avx2`, `sodium_runtime_has_avx512f`, `sodium_runtime_has_neon`, `sodium_runtime_has_pclmul`, `sodium_runtime_has_rdrand`, `sodium_runtime_has_sse2`, `sodium_runtime_has_sse3`, `sodium_runtime_has_sse41`, `sodium_runtime_has_ssse3`, `sodium_set_misuse_handler`, `sodium_stackzero`, `sodium_version_string`
285
286## License
287
288[MIT](LICENSE.md)
node_modules/noise-curve-ed/node_modules/sodium-universal/build-scripts/generate.js +33 -0
……@@ -0,0 +1,33 @@
1#!/usr/bin/env node
2
3const fs = require('fs')
4const path = require('path')
5const root = path.dirname(require.resolve('sodium-javascript/package.json'))
6
7const tmp = "module.exports = require('sodium-native')\n"
8
9function recurse (dir) {
10 const ls = fs.readdirSync(dir)
11 const subdir = path.relative(root, dir)
12 if (subdir) fs.mkdirSync(subdir, { recursive: true })
13
14 for (const file of ls) {
15 if (file === 'internal') recurse(path.join(dir, file))
16 if (!/\.js$/i.test(file)) continue
17 if (file === 'example.js') continue
18 if (file === 'test.js') continue
19
20 fs.writeFileSync(path.join(__dirname, '..', subdir, file), tmp)
21 }
22}
23
24recurse(root)
25
26const pkg = require('sodium-javascript/package.json')
27const myPkg = require('../package.json')
28
29for (const key of Object.keys(pkg.dependencies)) {
30 myPkg.dependencies[key] = pkg.dependencies[key]
31}
32
33fs.writeFileSync(path.join(__dirname, '../package.json'), JSON.stringify(myPkg, null, 2) + '\n')
node_modules/noise-curve-ed/node_modules/sodium-universal/build-scripts/symbols.js +32 -0
……@@ -0,0 +1,32 @@
1var exec = require('child_process').execSync
2var path = require('path')
3
4var symbols = exec(`nm -gU "${path.join(require.resolve('sodium-native'), '../prebuilds/darwin-x64/libsodium.dylib')}"`).toString().trim().split('\n')
5var native = new Set(Object.keys(require('sodium-native')).sort())
6var js = new Set(Object.keys(require('sodium-javascript')).sort())
7
8symbols = symbols.map(l => l.split(' ').pop().replace(/^_/, '').replace(/_[^_]*bytes.*/, (s) => s.toUpperCase()))
9
10var missing = []
11
12console.log(`
13<!-- Generated by build-scripts/symbols.js with
14 sodium-native@${require('sodium-native/package.json').version}
15 sodium-javascript@${require('sodium-javascript/package.json').version} -->\
16`)
17
18const max = symbols.filter(s => native.has(s) || js.has(s)).map(s => s.length).reduce((a, b) => Math.max(a, b))
19const lines = ':-' + ''.padEnd(max, '--') + '-:'
20const center = s => s.padStart(Math.floor((max + s.length) / 2), ' ').padEnd(max, ' ')
21
22console.log(`| ${center('C Library Symbol')} | \`sodium-native\` | \`sodium-javascript\` |`)
23console.log(`|${lines}|:--------------------:|:--------------------:|`)
24
25for (var i = 0; i < symbols.length; i++) {
26 var s = symbols[i]
27 if (!(native.has(s) || js.has(s))) missing.push(s)
28 else console.log(`| \`${(s + '`').padEnd(max + 1, ' ')} | ${native.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} | ${js.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} |`)
29}
30
31console.log('\n### Missing altogether (Ctrl + F friendly)\n')
32console.log(missing.map(s => '`' + s + '`').join(', '))
node_modules/noise-curve-ed/node_modules/sodium-universal/build-scripts/transform.js +26 -0
……@@ -0,0 +1,26 @@
1const fs = require('fs')
2const path = require('path')
3const { Transform, PassThrough } = require('stream')
4
5module.exports = function (file, opts) {
6 const basedir = path.resolve(__dirname, '..')
7 const relname = path.relative(basedir, file)
8
9 if (opts._flags.browserField === false) {
10 return new PassThrough()
11 }
12
13 return new Transform({
14 transform (data, enc, cb) {
15 cb()
16 },
17 flush (cb) {
18 const filename = require.resolve('sodium-javascript/' + relname)
19 fs.readFile(filename, (err, buf) => {
20 if (err) return cb(err)
21 this.push(buf)
22 cb(null)
23 })
24 }
25 })
26}
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_aead.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_auth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_box.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_generichash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_hash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_hash_sha256.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_kdf.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_kx.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_onetimeauth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_scalarmult.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_secretbox.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_secretstream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_shorthash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_sign.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_stream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_stream_chacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/crypto_verify.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/helpers.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/index.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/internal/ed25519.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/internal/hchacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/internal/poly1305.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/memory.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/node_modules/sodium-universal/package.json +49 -0
……@@ -0,0 +1,49 @@
1{
2 "name": "sodium-universal",
3 "version": "5.0.1",
4 "description": "Universal wrapper for sodium-javascript and sodium-native working in Node.js and the Browser",
5 "main": "index.js",
6 "dependencies": {
7 "sodium-native": "^5.0.1"
8 },
9 "peerDependencies": {
10 "sodium-javascript": "~0.8.0"
11 },
12 "peerDependenciesMeta": {
13 "sodium-javascript": {
14 "optional": true
15 }
16 },
17 "scripts": {
18 "prepublish": "./build-scripts/generate.js"
19 },
20 "browser": {
21 "sodium-native": "sodium-javascript"
22 },
23 "browserify": {
24 "transform": [
25 "./build-scripts/transform.js"
26 ]
27 },
28 "repository": {
29 "type": "git",
30 "url": "git+https://github.com/holepunchto/sodium-universal.git"
31 },
32 "keywords": [
33 "libsodium",
34 "sodium",
35 "sodium-native",
36 "sodium-javascript",
37 "browserify"
38 ],
39 "contributors": [
40 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
41 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
42 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
43 ],
44 "license": "MIT",
45 "bugs": {
46 "url": "https://github.com/holepunchto/sodium-universal/issues"
47 },
48 "homepage": "https://github.com/holepunchto/sodium-universal#readme"
49}
node_modules/noise-curve-ed/node_modules/sodium-universal/randombytes.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-curve-ed/package.json +30 -0
……@@ -0,0 +1,30 @@
1{
2 "name": "noise-curve-ed",
3 "version": "2.1.0",
4 "description": "Ed25519 elliptic curve operations for [`noise-handshake`](https://github.com/chm-diederichs/noise-handshake)",
5 "main": "index.js",
6 "scripts": {
7 "test": "npx standard && tape test.js"
8 },
9 "repository": {
10 "type": "git",
11 "url": "git+https://github.com/chm-diederichs/noise-curve-ed.git"
12 },
13 "keywords": [],
14 "author": "",
15 "license": "ISC",
16 "bugs": {
17 "url": "https://github.com/chm-diederichs/noise-curve-ed/issues"
18 },
19 "homepage": "https://github.com/chm-diederichs/noise-curve-ed#readme",
20 "dependencies": {
21 "b4a": "^1.1.0",
22 "nanoassert": "^2.0.0",
23 "sodium-universal": "^5.0.0"
24 },
25 "devDependencies": {
26 "noise-handshake": "^3.0.0",
27 "standard": "^16.0.3",
28 "tape": "^5.2.2"
29 }
30}
node_modules/noise-curve-ed/test.js +21 -0
……@@ -0,0 +1,21 @@
1const Noise = require('noise-handshake')
2const test = require('tape')
3const curve = require('./')
4
5test('XX', t => {
6 const initiator = new Noise('XX', true, null, { curve })
7 const responder = new Noise('XX', false, null, { curve })
8
9 initiator.initialise(Buffer.alloc(0))
10 responder.initialise(Buffer.alloc(0))
11
12 const message = initiator.send()
13 responder.recv(message)
14
15 const reply = responder.send()
16 initiator.recv(reply)
17
18 t.deepEqual(initiator.rx, responder.tx)
19 t.deepEqual(initiator.tx, responder.rx)
20 t.end()
21})
node_modules/noise-handshake/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/noise-handshake/README.md +95 -0
……@@ -0,0 +1,95 @@
1# noise-handshake
2
3## Usage
4```js
5const Noise = require('noise-handshake')
6const Cipher = require('noise-handshake/cipher')
7const initiator = new Noise('IK', true)
8const responder = new Noise('IK', false)
9
10const prologue = Buffer.alloc(0)
11
12// preshared key
13initiator.initialise(prologue, responder.s.publicKey)
14responder.initialise(prologue)
15
16// -> e, es, s, ss
17const message = initiator.send()
18responder.recv(message)
19
20// <- e, ee, se
21const reply = responder.send()
22initiator.recv(reply)
23
24console.log(initiator.complete) // true
25
26// convention is to use rx for
27// sending and tx for receiving
28
29// initiator.rx === responder.tx
30// responder.rx === initiator.tx
31
32// instantiate a cipher using shared secrets
33const send = new Cipher(initiator.tx)
34const recieve = new Cipher(responder.rx)
35
36const msg = Buffer.from('hello, world')
37
38const enc = send.encrypt(msg)
39console.log(recieve.decrypt(enc)) // hello, world
40```
41
42## API
43
44#### `const peer = new Noise(pattern, initiator, staticKeypair, [opts])`
45
46Create a new handshake state for a given pattern. Initiator should be either `true` or `false` depending on the role. A preexisting keypair may be passed as `staticKeypair`
47
48`opts` may be used to pass in the following:
49- `curve`: module for performing Noise over other curves.
50- `psk`: a 32-byte buffer containing a pre-shared key for patterns containing `psk0`. (Other psk positions are not currently supported.)
51
52Curve modules should export the following:
53```
54{
55 DHLEN,
56 PKLEN,
57 SKLEN,
58 ALG,
59 generateKeyPair,
60 dh
61}
62```
63
64See [dh.js](./dh) for an example.
65
66#### `peer.initialise(prologue, remoteStatic)`
67
68Initialise the handshake state with a prologue and any preshared keys.
69
70#### `const buf = send([payload])`
71
72Send the next message in the handshake, add an optional payload buffer to be included in the message, payload is a zero length buffer by default.
73
74#### `const payload = peer.recv(buf)`
75
76Receive a handshake message from the peer and return the encrypted payload.
77
78#### `peer.complete`
79
80`true` or `false`. Indicates whether `rx` and `tx` have been created yet.
81
82When complete, the working handshake state shall be cleared *only* the following state shall remain on the object:
83
84```js
85{
86 tx, // session key to decrypt messages from remote peer
87 rx, // session key to encrypt messages to remote peer
88 rs, // the remote peer's public key,
89 hash, // a hash of the entire handshake state
90}
91```
92
93## License
94
95Apache-2.0
node_modules/noise-handshake/cipher.js +93 -0
……@@ -0,0 +1,93 @@
1const sodium = require('sodium-universal')
2const b4a = require('b4a')
3
4module.exports = class CipherState {
5 constructor (key) {
6 this.key = key || null
7 this.nonce = 0
8 this.CIPHER_ALG = 'ChaChaPoly'
9 }
10
11 initialiseKey (key) {
12 this.key = key
13 this.nonce = 0
14 }
15
16 setNonce (nonce) {
17 this.nonce = nonce
18 }
19
20 encrypt (plaintext, ad) {
21 if (!this.hasKey) return plaintext
22 if (!ad) ad = b4a.alloc(0)
23
24 const ciphertext = encryptWithAD(this.key, this.nonce, ad, plaintext)
25 if (ciphertext.length > 65535) throw new Error(`ciphertext length of ${ciphertext.length} exceeds maximum Noise message length of 65535`)
26 this.nonce++
27
28 return ciphertext
29 }
30
31 decrypt (ciphertext, ad) {
32 if (!this.hasKey) return ciphertext
33 if (!ad) ad = b4a.alloc(0)
34 if (ciphertext.length > 65535) throw new Error(`ciphertext length of ${ciphertext.length} exceeds maximum Noise message length of 65535`)
35
36 const plaintext = decryptWithAD(this.key, this.nonce, ad, ciphertext)
37 this.nonce++
38
39 return plaintext
40 }
41
42 get hasKey () {
43 return this.key !== null
44 }
45
46 _clear () {
47 sodium.sodium_memzero(this.key)
48 this.key = null
49 this.nonce = null
50 }
51
52 static get MACBYTES () {
53 return 16
54 }
55
56 static get NONCEBYTES () {
57 return 8
58 }
59
60 static get KEYBYTES () {
61 return 32
62 }
63}
64
65function encryptWithAD (key, counter, additionalData, plaintext) {
66 // for our purposes, additionalData will always be a pubkey so we encode from hex
67 if (!b4a.isBuffer(additionalData)) additionalData = b4a.from(additionalData, 'hex')
68 if (!b4a.isBuffer(plaintext)) plaintext = b4a.from(plaintext, 'hex')
69
70 const nonce = b4a.alloc(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
71 const view = new DataView(nonce.buffer, nonce.byteOffset, nonce.byteLength)
72 view.setUint32(4, counter, true)
73
74 const ciphertext = b4a.alloc(plaintext.byteLength + sodium.crypto_aead_chacha20poly1305_ietf_ABYTES)
75
76 sodium.crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext, plaintext, additionalData, null, nonce, key)
77 return ciphertext
78}
79
80function decryptWithAD (key, counter, additionalData, ciphertext) {
81 // for our purposes, additionalData will always be a pubkey so we encode from hex
82 if (!b4a.isBuffer(additionalData)) additionalData = b4a.from(additionalData, 'hex')
83 if (!b4a.isBuffer(ciphertext)) ciphertext = b4a.from(ciphertext, 'hex')
84
85 const nonce = b4a.alloc(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
86 const view = new DataView(nonce.buffer, nonce.byteOffset, nonce.byteLength)
87 view.setUint32(4, counter, true)
88
89 const plaintext = b4a.alloc(ciphertext.byteLength - sodium.crypto_aead_chacha20poly1305_ietf_ABYTES)
90
91 sodium.crypto_aead_chacha20poly1305_ietf_decrypt(plaintext, null, ciphertext, additionalData, nonce, key)
92 return plaintext
93}
node_modules/noise-handshake/dh.js +71 -0
……@@ -0,0 +1,71 @@
1/* eslint-disable camelcase */
2const {
3 crypto_kx_SEEDBYTES,
4 crypto_kx_keypair,
5 crypto_kx_seed_keypair,
6 crypto_scalarmult_BYTES,
7 crypto_scalarmult_SCALARBYTES,
8 crypto_scalarmult,
9 crypto_scalarmult_base
10} = require('sodium-universal')
11
12const assert = require('nanoassert')
13const b4a = require('b4a')
14
15const DHLEN = crypto_scalarmult_BYTES
16const PKLEN = crypto_scalarmult_BYTES
17const SKLEN = crypto_scalarmult_SCALARBYTES
18const SEEDLEN = crypto_kx_SEEDBYTES
19const ALG = '25519'
20
21module.exports = {
22 DHLEN,
23 PKLEN,
24 SKLEN,
25 SEEDLEN,
26 ALG,
27 generateKeyPair,
28 generateSeedKeyPair,
29 dh
30}
31
32function generateKeyPair (privKey) {
33 const keyPair = {}
34
35 keyPair.secretKey = privKey || b4a.alloc(SKLEN)
36 keyPair.publicKey = b4a.alloc(PKLEN)
37
38 if (privKey) {
39 crypto_scalarmult_base(keyPair.publicKey, keyPair.secretKey)
40 } else {
41 crypto_kx_keypair(keyPair.publicKey, keyPair.secretKey)
42 }
43
44 return keyPair
45}
46
47function generateSeedKeyPair (seed) {
48 assert(seed.byteLength === SKLEN)
49
50 const keyPair = {}
51 keyPair.secretKey = b4a.alloc(SKLEN)
52 keyPair.publicKey = b4a.alloc(PKLEN)
53
54 crypto_kx_seed_keypair(keyPair.publicKey, keyPair.secretKey, seed)
55 return keyPair
56}
57
58function dh (publicKey, { secretKey }) {
59 assert(secretKey.byteLength === SKLEN)
60 assert(publicKey.byteLength === PKLEN)
61
62 const output = b4a.alloc(DHLEN)
63
64 crypto_scalarmult(
65 output,
66 secretKey,
67 publicKey
68 )
69
70 return output
71}
node_modules/noise-handshake/hkdf.js +47 -0
……@@ -0,0 +1,47 @@
1const hmacBlake2b = require('./hmac')
2const b4a = require('b4a')
3
4const HASHLEN = 64
5
6module.exports = {
7 hkdf,
8 HASHLEN
9}
10
11// HMAC-based Extract-and-Expand KDF
12// https://www.ietf.org/rfc/rfc5869.txt
13
14function hkdf (salt, inputKeyMaterial, info = '', length = 2 * HASHLEN) {
15 const pseudoRandomKey = hkdfExtract(salt, inputKeyMaterial)
16 return hkdfExpand(pseudoRandomKey, info, length)
17}
18
19function hkdfExtract (salt, inputKeyMaterial) {
20 const hmac = b4a.alloc(HASHLEN)
21 return hmacDigest(hmac, salt, inputKeyMaterial)
22}
23
24function hkdfExpand (key, info, length) {
25 // Put in dedicated slab to avoid keeping shared slab from being gc'ed
26 const buffer = b4a.allocUnsafeSlow(length)
27
28 const infoBuf = b4a.from(info)
29 let prev = infoBuf
30
31 const result = []
32 for (let i = 0; i < length; i += HASHLEN) {
33 const pos = b4a.from([(i / HASHLEN) + 1])
34
35 const out = buffer.subarray(i, i + HASHLEN)
36 result.push(out)
37
38 prev = hmacDigest(out, key, [prev, infoBuf, pos])
39 }
40
41 return result
42}
43
44function hmacDigest (out, key, input) {
45 hmacBlake2b(out, input, key)
46 return out
47}
node_modules/noise-handshake/hmac.js +38 -0
……@@ -0,0 +1,38 @@
1/* eslint-disable camelcase */
2const b4a = require('b4a')
3const { sodium_memzero, crypto_generichash, crypto_generichash_batch } = require('sodium-universal')
4
5const HASHLEN = 64
6const BLOCKLEN = 128
7const scratch = b4a.alloc(BLOCKLEN * 3)
8const HMACKey = scratch.subarray(BLOCKLEN * 0, BLOCKLEN * 1)
9const OuterKeyPad = scratch.subarray(BLOCKLEN * 1, BLOCKLEN * 2)
10const InnerKeyPad = scratch.subarray(BLOCKLEN * 2, BLOCKLEN * 3)
11
12// Post-fill is done in the cases where someone caught an exception that
13// happened before we were able to clear data at the end
14
15module.exports = function hmac (out, batch, key) {
16 if (key.byteLength > BLOCKLEN) {
17 crypto_generichash(HMACKey.subarray(0, HASHLEN), key)
18 sodium_memzero(HMACKey.subarray(HASHLEN))
19 } else {
20 // Covers key <= BLOCKLEN
21 HMACKey.set(key)
22 sodium_memzero(HMACKey.subarray(key.byteLength))
23 }
24
25 for (let i = 0; i < HMACKey.byteLength; i++) {
26 OuterKeyPad[i] = 0x5c ^ HMACKey[i]
27 InnerKeyPad[i] = 0x36 ^ HMACKey[i]
28 }
29 sodium_memzero(HMACKey)
30
31 crypto_generichash_batch(out, [InnerKeyPad].concat(batch))
32 sodium_memzero(InnerKeyPad)
33 crypto_generichash_batch(out, [OuterKeyPad, out])
34 sodium_memzero(OuterKeyPad)
35}
36
37module.exports.BYTES = HASHLEN
38module.exports.KEYBYTES = BLOCKLEN
node_modules/noise-handshake/node_modules/sodium-native/CMakeLists.txt +279 -0
……@@ -0,0 +1,279 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6find_package(cmake-npm REQUIRED PATHS node_modules/cmake-npm)
7
8set(CMAKE_POSITION_INDEPENDENT_CODE ON)
9
10project(sodium_native C ASM CXX)
11
12fetch_package("github:jedisct1/libsodium#e18eee6" SOURCE_DIR sodium)
13
14fetch_package("github:holepunchto/libjstl#098664c")
15
16bare_target(target)
17
18if(target MATCHES "win32")
19 add_compile_options(/MT$<$<CONFIG:Debug>:d>)
20endif()
21
22file(COPY_FILE "${sodium}/builds/msvc/version.h" "${sodium}/src/libsodium/include/sodium/version.h")
23
24file(GLOB_RECURSE sodium_headers CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.h")
25file(GLOB_RECURSE sodium_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.c")
26file(GLOB_RECURSE sodium_asm_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.S")
27
28add_library(sodium OBJECT)
29
30target_sources(
31 sodium
32 INTERFACE
33 ${sodium_headers}
34 PRIVATE
35 ${sodium_sources}
36)
37
38target_include_directories(
39 sodium
40 INTERFACE
41 "${sodium}/src/libsodium/include"
42 PRIVATE
43 "${sodium}/src/libsodium/include/sodium"
44)
45
46if(NOT target MATCHES "win32")
47 target_compile_options(
48 sodium
49 PRIVATE
50 -fvisibility=hidden
51 -fno-strict-aliasing
52 -fwrapv
53 -flax-vector-conversions
54 )
55endif()
56
57target_compile_definitions(
58 sodium
59 PUBLIC
60 SODIUM_STATIC=1
61 PRIVATE
62 _GNU_SOURCE=1
63 CONFIGURED=1
64 DEV_MODE=1
65 HAVE_ATOMIC_OPS=1
66 HAVE_C11_MEMORY_FENCES=1
67 HAVE_CET_H=1
68 HAVE_GCC_MEMORY_FENCES=1
69 HAVE_INLINE_ASM=1
70 HAVE_INTTYPES_H=1
71 HAVE_STDINT_H=1
72 HAVE_TI_MODE=1
73)
74
75if(target MATCHES "darwin|ios")
76 target_compile_definitions(
77 sodium
78 PRIVATE
79 ASM_HIDE_SYMBOL=.private_extern
80 TLS=_Thread_local
81 HAVE_ARC4RANDOM=1
82 HAVE_ARC4RANDOM_BUF=1
83 HAVE_CATCHABLE_ABRT=1
84 HAVE_CATCHABLE_SEGV=1
85 HAVE_CLOCK_GETTIME=1
86 HAVE_GETPID=1
87 HAVE_MADVISE=1
88 HAVE_MEMSET_S=1
89 HAVE_MLOCK=1
90 HAVE_MMAP=1
91 HAVE_MPROTECT=1
92 HAVE_NANOSLEEP=1
93 HAVE_POSIX_MEMALIGN=1
94 HAVE_PTHREAD=1
95 HAVE_PTHREAD_PRIO_INHERIT=1
96 HAVE_RAISE=1
97 HAVE_SYSCONF=1
98 HAVE_SYS_MMAN_H=1
99 HAVE_SYS_PARAM_H=1
100 HAVE_WEAK_SYMBOLS=1
101 )
102
103 if(NOT target MATCHES "ios")
104 target_compile_definitions(
105 sodium
106 PRIVATE
107 HAVE_GETENTROPY=1
108 HAVE_SYS_RANDOM_H=1
109 )
110 endif()
111endif()
112
113if(target MATCHES "linux")
114 target_compile_definitions(
115 sodium
116 PRIVATE
117 ASM_HIDE_SYMBOL=.hidden
118 TLS=_Thread_local
119 HAVE_CATCHABLE_ABRT=1
120 HAVE_CATCHABLE_SEGV=1
121 HAVE_CLOCK_GETTIME=1
122 HAVE_GETPID=1
123 HAVE_MADVISE=1
124 HAVE_MLOCK=1
125 HAVE_MMAP=1
126 HAVE_MPROTECT=1
127 HAVE_NANOSLEEP=1
128 HAVE_POSIX_MEMALIGN=1
129 HAVE_PTHREAD_PRIO_INHERIT=1
130 HAVE_PTHREAD=1
131 HAVE_RAISE=1
132 HAVE_SYSCONF=1
133 HAVE_SYS_AUXV_H=1
134 HAVE_SYS_MMAN_H=1
135 HAVE_SYS_PARAM_H=1
136 HAVE_SYS_RANDOM_H=1
137 HAVE_WEAK_SYMBOLS=1
138 )
139endif()
140
141if(target MATCHES "win32")
142 target_compile_definitions(
143 sodium
144 PRIVATE
145 _CRT_SECURE_NO_WARNINGS=1
146 HAVE_RAISE=1
147 )
148endif()
149
150if(target MATCHES "x64")
151 target_compile_definitions(
152 sodium
153 PRIVATE
154 HAVE_CPUID=1
155 HAVE_RDRAND=1
156 HAVE_EMMINTRIN_H=1 # SSE2
157 HAVE_PMMINTRIN_H=1 # SSE3
158 HAVE_TMMINTRIN_H=1 # SSSE3
159 HAVE_SMMINTRIN_H=1 # SSE4.1
160 HAVE_WMMINTRIN_H=1 # AES
161 HAVE_AVXINTRIN_H=1 # AVX
162 HAVE_AVX2INTRIN_H=1 # AVX2
163 HAVE_AVX512FINTRIN_H # AVX512F
164 )
165
166 if(NOT target MATCHES "win32")
167 target_compile_definitions(
168 sodium
169 PRIVATE
170 HAVE_AMD64_ASM=1
171 HAVE_AVX_ASM=1
172 )
173
174 target_sources(
175 sodium
176 PRIVATE
177 ${sodium_asm_sources}
178 )
179 endif()
180endif()
181
182if(target MATCHES "arm64")
183 target_compile_definitions(
184 sodium
185 PRIVATE
186 HAVE_ARMCRYPTO=1
187 )
188endif()
189
190if(CMAKE_C_BYTE_ORDER MATCHES "BIG_ENDIAN")
191 target_compile_definitions(
192 sodium
193 PRIVATE
194 NATIVE_BIG_ENDIAN=1
195 )
196else()
197 target_compile_definitions(
198 sodium
199 PRIVATE
200 NATIVE_LITTLE_ENDIAN=1
201 )
202endif()
203
204if(target MATCHES "linux|android")
205 target_link_options(
206 sodium
207 PUBLIC
208 -Wl,-z,noexecstack
209 )
210endif()
211
212add_library(sodium_extensions OBJECT)
213
214target_sources(
215 sodium_extensions
216 PRIVATE
217 extensions/tweak/tweak.c
218 extensions/tweak/tweak.h
219 extensions/pbkdf2/pbkdf2.c
220 extensions/pbkdf2/pbkdf2.h
221)
222
223target_link_libraries(
224 sodium_extensions
225 PUBLIC
226 sodium
227)
228
229add_bare_module(sodium_native_bare)
230
231target_sources(
232 ${sodium_native_bare}
233 PRIVATE
234 binding.cc
235)
236
237target_link_libraries(
238 ${sodium_native_bare}
239 PRIVATE
240 $<TARGET_OBJECTS:sodium>
241 $<TARGET_OBJECTS:sodium_extensions>
242 jstl
243 PUBLIC
244 sodium
245 sodium_extensions
246)
247
248add_napi_module(sodium_native_node)
249
250target_sources(
251 ${sodium_native_node}
252 PRIVATE
253 binding.cc
254)
255
256target_compile_definitions(
257 ${sodium_native_node}
258 PRIVATE
259 NAPI_VERSION=9
260)
261
262target_link_libraries(
263 ${sodium_native_node}
264 PRIVATE
265 $<TARGET_OBJECTS:sodium>
266 $<TARGET_OBJECTS:sodium_extensions>
267 jstl
268 PUBLIC
269 sodium
270 sodium_extensions
271)
272
273resolve_node_module(bare-compat-napi compat)
274
275target_include_directories(
276 ${sodium_native_node}
277 PRIVATE
278 "${compat}/include"
279)
node_modules/noise-handshake/node_modules/sodium-native/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2016 Mathias Buus and Emil Bay
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/noise-handshake/node_modules/sodium-native/README.md +51 -0
……@@ -0,0 +1,51 @@
1# sodium-native
2
3Low level bindings for [libsodium](https://github.com/jedisct1/libsodium).
4
5```
6npm install sodium-native
7```
8
9The goal of this project is to be thin, stable, unopionated wrapper around libsodium.
10
11All methods exposed are more or less a direct translation of the libsodium c-api.
12This means that most data types are buffers and you have to manage allocating return values and passing them in as arguments instead of receiving them as return values.
13
14This makes this API harder to use than other libsodium wrappers out there, but also means that you'll be able to get a lot of perf / memory improvements as you can do stuff like inline encryption / decryption, reuse buffers etc.
15
16This also makes this library useful as a foundation for more high level crypto abstractions that you want to make.
17
18## Usage
19
20```js
21var sodium = require('sodium-native')
22
23var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
24var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) // secure buffer
25var message = Buffer.from('Hello, World!')
26var ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
27
28sodium.randombytes_buf(nonce) // insert random data into nonce
29sodium.randombytes_buf(key) // insert random data into key
30
31// encrypted message is stored in ciphertext.
32sodium.crypto_secretbox_easy(ciphertext, message, nonce, key)
33
34console.log('Encrypted message:', ciphertext)
35
36var plainText = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES)
37
38if (!sodium.crypto_secretbox_open_easy(plainText, ciphertext, nonce, key)) {
39 console.log('Decryption failed!')
40} else {
41 console.log('Decrypted message:', plainText, '(' + plainText.toString() + ')')
42}
43```
44
45## Documentation
46
47Complete documentation may be found on the [sodium-friends website](https://sodium-friends.github.io/docs/docs/getstarted)
48
49## License
50
51MIT
node_modules/noise-handshake/node_modules/sodium-native/binding.cc +4094 -0
……@@ -0,0 +1,4094 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4#include <jstl.h>
5#include <sodium.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <string.h>
9#include <uv.h>
10
11#include "extensions/pbkdf2/pbkdf2.h"
12#include "extensions/tweak/tweak.h"
13
14#define assert_bounds(arraybuffer) \
15 assert(arraybuffer##_offset + arraybuffer##_len <= arraybuffer.size())
16
17static inline void
18sn_sodium_memzero(
19 js_env_t *,
20 js_receiver_t,
21 js_typedarray_span_t<> buf
22) {
23 sodium_memzero(buf.data(), buf.size_bytes());
24}
25
26static inline int
27sn_sodium_mlock(
28 js_env_t *,
29 js_receiver_t,
30 js_typedarray_span_t<> buf
31) {
32 return sodium_mlock(buf.data(), buf.size_bytes());
33}
34
35static inline int
36sn_sodium_munlock(
37 js_env_t *,
38 js_receiver_t,
39 js_typedarray_span_t<> buf
40) {
41 return sodium_munlock(buf.data(), buf.size_bytes());
42}
43
44static void
45sn_external_arraybuffer_finalize(js_env_t *env, uint8_t *ptr) {
46 sodium_free(ptr);
47}
48
49static js_arraybuffer_t
50sn_sodium_malloc(js_env_t *env, js_receiver_t, uint32_t len) {
51 int err;
52
53 auto ptr = reinterpret_cast<uint8_t *>(sodium_malloc(len));
54
55 js_arraybuffer_t buffer;
56
57 err = js_create_external_arraybuffer<sn_external_arraybuffer_finalize>(env, ptr, len, buffer);
58 assert(err == 0);
59
60 return buffer;
61}
62
63static void
64sn_sodium_free(js_env_t *env, js_receiver_t, js_arraybuffer_t buf) {
65 int err;
66
67 std::span<uint8_t> view;
68 err = js_get_arraybuffer_info(env, buf, view);
69 assert(err == 0);
70
71 if (view.empty()) return;
72
73 err = js_detach_arraybuffer(env, buf);
74 assert(err == 0);
75}
76
77static inline int
78sn_sodium_mprotect_noaccess(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
79 return sodium_mprotect_noaccess(buf.data());
80}
81
82static inline int
83sn_sodium_mprotect_readonly(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
84 return sodium_mprotect_readonly(buf.data());
85}
86
87static inline int
88sn_sodium_mprotect_readwrite(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
89 return sodium_mprotect_readwrite(buf.data());
90}
91
92static inline uint32_t // TODO: test envless
93sn_randombytes_random(js_env_t *env, js_receiver_t) {
94 return randombytes_random();
95}
96
97static inline uint32_t // TODO: test envless
98sn_randombytes_uniform(js_env_t *env, js_receiver_t, uint32_t upper_bound) {
99 return randombytes_uniform(upper_bound);
100}
101
102static inline void
103sn_randombytes_buf(
104 js_env_t *env,
105 js_receiver_t,
106 js_arraybuffer_span_t buf,
107 uint32_t buf_offset,
108 uint32_t buf_len
109) {
110 assert_bounds(buf);
111
112 randombytes_buf(&buf[buf_offset], buf_len);
113}
114
115static inline void
116sn_randombytes_buf_deterministic(
117 js_env_t *env,
118 js_receiver_t,
119
120 js_arraybuffer_span_t buf,
121 uint32_t buf_offset,
122 uint32_t buf_len,
123
124 js_arraybuffer_span_t seed,
125 uint32_t seed_offset,
126 uint32_t seed_len
127) {
128 assert_bounds(buf);
129 assert_bounds(seed);
130
131 assert(seed_len == randombytes_SEEDBYTES);
132
133 randombytes_buf_deterministic(&buf[buf_offset], buf_len, &seed[seed_offset]);
134}
135
136static inline bool
137sn_sodium_memcmp(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
138 if (a.size_bytes() != b.size_bytes()) return false;
139
140 return sodium_memcmp(a.data(), b.data(), a.size_bytes()) == 0;
141}
142
143static inline void
144sn_sodium_increment(js_env_t *, js_receiver_t, js_typedarray_span_t<> n) {
145 sodium_increment(n.data(), n.size_bytes());
146}
147
148static inline void
149sn_sodium_add(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
150 sodium_add(a.data(), b.data(), a.size_bytes());
151}
152
153static inline void
154sn_sodium_sub(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
155 sodium_sub(a.data(), b.data(), a.size_bytes());
156}
157
158static inline int32_t
159sn_sodium_compare(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
160 return sodium_compare(a.data(), b.data(), a.size_bytes());
161}
162
163static inline bool
164sn_sodium_is_zero(js_env_t *, js_receiver_t, js_typedarray_span_t<> buffer, uint32_t len) {
165 assert(len <= buffer.size_bytes());
166
167 return sodium_is_zero(buffer.data(), len) != 0;
168}
169
170static inline uint32_t
171sn_sodium_pad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t unpadded_buflen, uint32_t blocksize) {
172 size_t padded_buflen;
173
174 sodium_pad(&padded_buflen, buf.data(), unpadded_buflen, blocksize, buf.size_bytes());
175
176 return padded_buflen;
177}
178
179static inline uint32_t
180sn_sodium_unpad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t padded_buflen, uint32_t blocksize) {
181 size_t unpadded_buflen;
182
183 sodium_unpad(&unpadded_buflen, buf.data(), padded_buflen, blocksize);
184
185 return unpadded_buflen;
186}
187
188static inline int
189sn_crypto_sign_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
190 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
191 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
192
193 return crypto_sign_keypair(pk.data(), sk.data());
194}
195
196static inline int
197sn_crypto_sign_seed_keypair(
198 js_env_t *,
199 js_receiver_t,
200 js_typedarray_span_t<> pk,
201 js_typedarray_span_t<> sk,
202 js_typedarray_span_t<> seed
203) {
204 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
205 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
206 assert(seed.size_bytes() == crypto_sign_SEEDBYTES);
207
208 return crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data());
209}
210
211static inline int
212sn_crypto_sign(
213 js_env_t *,
214 js_receiver_t,
215 js_typedarray_span_t<> sm,
216 js_typedarray_span_t<> m,
217 js_typedarray_span_t<> sk
218) {
219 assert(sm.size_bytes() == crypto_sign_BYTES + m.size_bytes());
220 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
221
222 return crypto_sign(sm.data(), NULL, m.data(), m.size_bytes(), sk.data());
223}
224
225static inline bool
226sn_crypto_sign_open(
227 js_env_t *,
228 js_receiver_t,
229 js_typedarray_span_t<> m,
230 js_typedarray_span_t<> sm,
231 js_typedarray_span_t<> pk
232) {
233 assert(m.size_bytes() == sm.size_bytes() - crypto_sign_BYTES);
234 assert(sm.size_bytes() >= crypto_sign_BYTES);
235 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
236
237 return crypto_sign_open(m.data(), NULL, sm.data(), sm.size_bytes(), pk.data()) == 0;
238}
239
240static inline int
241sn_crypto_sign_detached(
242 js_env_t *env,
243 js_receiver_t,
244 js_typedarray_span_t<> sig,
245 js_typedarray_span_t<> m,
246 js_typedarray_span_t<> sk
247) {
248 assert(sig.size_bytes() == crypto_sign_BYTES);
249 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
250
251 return crypto_sign_detached(sig.data(), NULL, m.data(), m.size_bytes(), sk.data());
252}
253
254static inline bool
255sn_crypto_sign_verify_detached(
256 js_env_t *env,
257 js_receiver_t,
258
259 js_arraybuffer_span_t sig,
260 uint32_t sig_offset,
261 uint32_t sig_len,
262
263 js_arraybuffer_span_t m,
264 uint32_t m_offset,
265 uint32_t m_len,
266
267 js_arraybuffer_span_t pk,
268 uint32_t pk_offset,
269 uint32_t pk_len
270) {
271 assert_bounds(sig);
272 assert_bounds(m);
273 assert_bounds(pk);
274
275 assert(sig_len >= crypto_sign_BYTES);
276 assert(pk_len == crypto_sign_PUBLICKEYBYTES);
277
278 return crypto_sign_verify_detached(&sig[sig_offset], &m[m_offset], m_len, &pk[pk_offset]) == 0;
279}
280
281static inline int
282sn_crypto_sign_ed25519_sk_to_pk(
283 js_env_t *,
284 js_receiver_t,
285 js_typedarray_span_t<> pk,
286 js_typedarray_span_t<> sk
287) {
288 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
289 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
290
291 return crypto_sign_ed25519_sk_to_pk(pk.data(), sk.data());
292}
293
294static inline int
295sn_crypto_sign_ed25519_pk_to_curve25519(
296 js_env_t *,
297 js_receiver_t,
298 js_typedarray_span_t<> x25519_pk,
299 js_typedarray_span_t<> ed25519_pk
300) {
301 assert(x25519_pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
302 assert(ed25519_pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
303
304 return crypto_sign_ed25519_pk_to_curve25519(x25519_pk.data(), ed25519_pk.data());
305}
306
307static inline int
308sn_crypto_sign_ed25519_sk_to_curve25519(
309 js_env_t *,
310 js_receiver_t,
311 js_typedarray_span_t<> x25519_sk,
312 js_typedarray_span_t<> ed25519_sk
313) {
314 assert(x25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES);
315 assert(
316 ed25519_sk.size_bytes() == crypto_sign_SECRETKEYBYTES ||
317 ed25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES
318 );
319
320 return crypto_sign_ed25519_sk_to_curve25519(x25519_sk.data(), ed25519_sk.data());
321}
322
323static inline int
324sn_crypto_generichash(
325 js_env_t *env,
326 js_receiver_t,
327
328 js_arraybuffer_span_t out,
329 uint32_t out_offset,
330 uint32_t out_len,
331
332 js_arraybuffer_span_t in,
333 uint32_t in_offset,
334 uint32_t in_len,
335
336 js_arraybuffer_span_t key,
337 uint32_t key_offset,
338 uint32_t key_len
339) {
340 assert_bounds(out);
341 assert(
342 out_len >= crypto_generichash_BYTES_MIN &&
343 out_len <= crypto_generichash_BYTES_MAX
344 );
345
346 assert_bounds(in);
347
348 uint8_t *key_data = NULL;
349 if (key_len) {
350 assert_bounds(key);
351 assert(
352 key_len >= crypto_generichash_KEYBYTES_MIN &&
353 key_len <= crypto_generichash_KEYBYTES_MAX
354 );
355 key_data = &key[key_offset];
356 }
357
358 return crypto_generichash(&out[out_offset], out_len, &in[in_offset], in_len, key_data, key_len);
359}
360
361static inline int
362sn_crypto_generichash_batch(
363 js_env_t *env,
364 js_receiver_t,
365 js_typedarray_t<uint8_t> out,
366 std::vector<js_typedarray_span_t<>> batch,
367 bool use_key,
368 js_typedarray_t<uint8_t> key
369) {
370 int err;
371
372 uint8_t *out_data;
373 size_t out_len;
374 err = js_get_typedarray_info(env, out, out_data, out_len);
375 assert(err == 0);
376 assert(
377 out_len >= crypto_generichash_BYTES_MIN &&
378 out_len <= crypto_generichash_BYTES_MAX
379 );
380
381 uint8_t *key_data = NULL;
382 size_t key_len = 0;
383 if (use_key) {
384 err = js_get_typedarray_info(env, key, key_data, key_len);
385 assert(err == 0);
386 assert(
387 key_len >= crypto_generichash_KEYBYTES_MIN &&
388 key_len <= crypto_generichash_KEYBYTES_MAX
389 );
390 }
391
392 crypto_generichash_state state;
393 err = crypto_generichash_init(&state, key_data, key_len, out_len);
394 if (err != 0) return err;
395
396 for (auto &buf : batch) {
397 err = crypto_generichash_update(&state, buf.data(), buf.size());
398 if (err != 0) return err;
399 }
400
401 return crypto_generichash_final(&state, out_data, out_len);
402}
403
404static inline void
405sn_crypto_generichash_keygen(
406 js_env_t *env,
407 js_receiver_t,
408
409 js_arraybuffer_span_t key,
410 uint32_t key_offset,
411 uint32_t key_len
412) {
413 assert_bounds(key);
414 assert(key_len == crypto_generichash_KEYBYTES);
415
416 crypto_generichash_keygen(&key[key_offset]);
417}
418
419static inline int
420sn_crypto_generichash_init(
421 js_env_t *env,
422 js_receiver_t,
423
424 js_arraybuffer_span_t state,
425 uint32_t state_offset,
426 uint32_t state_len,
427
428 js_arraybuffer_span_t key,
429 uint32_t key_offset,
430 uint32_t key_len,
431
432 uint32_t out_len
433) {
434 assert_bounds(state);
435
436 assert(state_len == sizeof(crypto_generichash_state));
437
438 uint8_t *key_data = NULL;
439 if (key_len) {
440 assert_bounds(key);
441 assert(
442 key_len >= crypto_generichash_KEYBYTES_MIN &&
443 key_len <= crypto_generichash_KEYBYTES_MAX
444 );
445 key_data = &key[key_offset];
446 }
447
448 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
449
450 return crypto_generichash_init(state_data, key_data, key_len, out_len);
451}
452
453static inline int
454sn_crypto_generichash_update(
455 js_env_t *env,
456 js_receiver_t,
457
458 js_arraybuffer_span_t state,
459 uint32_t state_offset,
460 uint32_t state_len,
461
462 js_arraybuffer_span_t in,
463 uint32_t in_offset,
464 uint32_t in_len
465) {
466 assert_bounds(state);
467 assert_bounds(in);
468
469 assert(state_len == sizeof(crypto_generichash_state));
470
471 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
472
473 return crypto_generichash_update(state_data, &in[in_offset], in_len);
474}
475
476static inline int
477sn_crypto_generichash_final(
478 js_env_t *env,
479 js_receiver_t,
480
481 js_arraybuffer_span_t state,
482 uint32_t state_offset,
483 uint32_t state_len,
484
485 js_arraybuffer_span_t out,
486 uint32_t out_offset,
487 uint32_t out_len
488) {
489 assert_bounds(state);
490 assert_bounds(out);
491
492 assert(state_len == sizeof(crypto_generichash_state));
493
494 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
495
496 return crypto_generichash_final(state_data, &out[out_offset], out_len);
497}
498
499static inline int
500sn_crypto_box_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
501 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
502 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
503
504 return crypto_box_keypair(pk.data(), sk.data());
505}
506
507static inline int
508sn_crypto_box_seed_keypair(
509 js_env_t *,
510 js_receiver_t,
511 js_typedarray_span_t<> pk,
512 js_typedarray_span_t<> sk,
513 js_typedarray_span_t<> seed
514) {
515 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
516 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
517 assert(seed.size_bytes() == crypto_box_SEEDBYTES);
518
519 return crypto_box_seed_keypair(pk.data(), sk.data(), seed.data());
520}
521
522static inline int
523sn_crypto_box_easy(
524 js_env_t *,
525 js_receiver_t,
526 js_typedarray_span_t<> c,
527 js_typedarray_span_t<> m,
528 js_typedarray_span_t<> n,
529 js_typedarray_span_t<> pk,
530 js_typedarray_span_t<> sk
531) {
532 assert(c.size_bytes() == m.size_bytes() + crypto_box_MACBYTES);
533 assert(n.size_bytes() == crypto_box_NONCEBYTES);
534 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
535 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
536
537 return crypto_box_easy(c.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
538}
539
540static inline bool
541sn_crypto_box_open_easy(
542 js_env_t *,
543 js_receiver_t,
544 js_typedarray_span_t<> m,
545 js_typedarray_span_t<> c,
546 js_typedarray_span_t<> n,
547 js_typedarray_span_t<> pk,
548 js_typedarray_span_t<> sk
549) {
550 assert(c.size_bytes() >= crypto_box_MACBYTES);
551 assert(m.size_bytes() == c.size_bytes() - crypto_box_MACBYTES);
552 assert(n.size_bytes() == crypto_box_NONCEBYTES);
553 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
554 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
555
556 return crypto_box_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
557}
558
559static inline int
560sn_crypto_box_detached(
561 js_env_t *,
562 js_receiver_t,
563 js_typedarray_span_t<> c,
564 js_typedarray_span_t<> mac,
565 js_typedarray_span_t<> m,
566 js_typedarray_span_t<> n,
567 js_typedarray_span_t<> pk,
568 js_typedarray_span_t<> sk
569) {
570 assert(c.size_bytes() == m.size_bytes());
571 assert(mac.size_bytes() == crypto_box_MACBYTES);
572 assert(n.size_bytes() == crypto_box_NONCEBYTES);
573 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
574 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
575
576 return crypto_box_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
577}
578
579static inline bool
580sn_crypto_box_open_detached(
581 js_env_t *,
582 js_receiver_t,
583 js_typedarray_span_t<> m,
584 js_typedarray_span_t<> c,
585 js_typedarray_span_t<> mac,
586 js_typedarray_span_t<> n,
587 js_typedarray_span_t<> pk,
588 js_typedarray_span_t<> sk
589) {
590 assert(m.size_bytes() == c.size_bytes());
591 assert(mac.size_bytes() == crypto_box_MACBYTES);
592 assert(n.size_bytes() == crypto_box_NONCEBYTES);
593 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
594 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
595
596 return crypto_box_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
597}
598
599static inline int
600sn_crypto_box_seal(
601 js_env_t *,
602 js_receiver_t,
603 js_typedarray_span_t<> c,
604 js_typedarray_span_t<> m,
605 js_typedarray_span_t<> pk
606) {
607 assert(c.size_bytes() == m.size_bytes() + crypto_box_SEALBYTES);
608 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
609
610 return crypto_box_seal(c.data(), m.data(), m.size_bytes(), pk.data());
611}
612
613static inline bool
614sn_crypto_box_seal_open(
615 js_env_t *env,
616 js_receiver_t,
617
618 js_arraybuffer_span_t m,
619 uint32_t m_offset,
620 uint32_t m_len,
621
622 js_arraybuffer_span_t c,
623 uint32_t c_offset,
624 uint32_t c_len,
625
626 js_arraybuffer_span_t pk,
627 uint32_t pk_offset,
628 uint32_t pk_len,
629
630 js_arraybuffer_span_t sk,
631 uint32_t sk_offset,
632 uint32_t sk_len
633) {
634 assert_bounds(m);
635 assert_bounds(c);
636 assert_bounds(pk);
637 assert_bounds(sk);
638
639 assert(m_len == c_len - crypto_box_SEALBYTES);
640 assert(c_len >= crypto_box_SEALBYTES);
641 assert(sk_len == crypto_box_SECRETKEYBYTES);
642 assert(pk_len == crypto_box_PUBLICKEYBYTES);
643
644 return crypto_box_seal_open(&m[m_offset], &c[c_offset], c_len, &pk[pk_offset], &sk[sk_offset]) == 0;
645}
646
647static inline int
648sn_crypto_secretbox_easy(
649 js_env_t *,
650 js_receiver_t,
651 js_typedarray_span_t<> c,
652 js_typedarray_span_t<> m,
653 js_typedarray_span_t<> n,
654 js_typedarray_span_t<> k
655) {
656 assert(c.size_bytes() == m.size_bytes() + crypto_secretbox_MACBYTES);
657 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
658 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
659
660 return crypto_secretbox_easy(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
661}
662
663static inline bool
664sn_crypto_secretbox_open_easy(
665 js_env_t *,
666 js_receiver_t,
667 js_typedarray_span_t<> m,
668 js_typedarray_span_t<> c,
669 js_typedarray_span_t<> n,
670 js_typedarray_span_t<> k
671) {
672 assert(m.size_bytes() == c.size_bytes() - crypto_secretbox_MACBYTES);
673 assert(c.size_bytes() >= crypto_secretbox_MACBYTES);
674 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
675 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
676
677 return crypto_secretbox_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), k.data()) == 0;
678}
679
680static inline int
681sn_crypto_secretbox_detached(
682 js_env_t *,
683 js_receiver_t,
684 js_typedarray_span_t<> c,
685 js_typedarray_span_t<> mac,
686 js_typedarray_span_t<> m,
687 js_typedarray_span_t<> n,
688 js_typedarray_span_t<> k
689) {
690 assert(c.size_bytes() == m.size_bytes());
691 assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
692 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
693 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
694
695 return crypto_secretbox_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), k.data());
696}
697
698static inline bool
699sn_crypto_secretbox_open_detached(
700 js_env_t *,
701 js_receiver_t,
702 js_typedarray_span_t<> m,
703 js_typedarray_span_t<> c,
704 js_typedarray_span_t<> mac,
705 js_typedarray_span_t<> n,
706 js_typedarray_span_t<> k
707) {
708 assert(m.size_bytes() == c.size_bytes());
709 assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
710 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
711 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
712
713 return crypto_secretbox_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), k.data()) == 0;
714}
715
716static inline int
717sn_crypto_stream(
718 js_env_t *,
719 js_receiver_t,
720 js_typedarray_span_t<> c,
721 js_typedarray_span_t<> n,
722 js_typedarray_span_t<> k
723) {
724 assert(n.size_bytes() == crypto_stream_NONCEBYTES);
725 assert(k.size_bytes() == crypto_stream_KEYBYTES);
726
727 return crypto_stream(c.data(), c.size_bytes(), n.data(), k.data());
728}
729
730static inline int
731sn_crypto_stream_xor(
732 js_env_t *env,
733 js_receiver_t,
734
735 js_arraybuffer_span_t c,
736 uint32_t c_offset,
737 uint32_t c_len,
738
739 js_arraybuffer_span_t m,
740 uint32_t m_offset,
741 uint32_t m_len,
742
743 js_arraybuffer_span_t n,
744 uint32_t n_offset,
745 uint32_t n_len,
746
747 js_arraybuffer_span_t k,
748 uint32_t k_offset,
749 uint32_t k_len
750) {
751 assert_bounds(c);
752 assert_bounds(m);
753 assert_bounds(n);
754 assert_bounds(k);
755
756 assert(c_len == m_len);
757 assert(n_len == crypto_stream_NONCEBYTES);
758 assert(k_len == crypto_stream_KEYBYTES);
759
760 return crypto_stream_xor(&c[c_offset], &m[m_offset], m_len, &n[n_offset], &k[k_offset]);
761}
762
763static inline int
764sn_crypto_stream_chacha20(
765 js_env_t *,
766 js_receiver_t,
767 js_typedarray_span_t<> c,
768 js_typedarray_span_t<> n,
769 js_typedarray_span_t<> k
770) {
771 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
772 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
773
774 return crypto_stream_chacha20(c.data(), c.size_bytes(), n.data(), k.data());
775}
776
777static inline int
778sn_crypto_stream_chacha20_xor(
779 js_env_t *,
780 js_receiver_t,
781 js_typedarray_span_t<> c,
782 js_typedarray_span_t<> m,
783 js_typedarray_span_t<> n,
784 js_typedarray_span_t<> k
785) {
786 assert(c.size_bytes() == m.size_bytes());
787 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
788 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
789
790 return crypto_stream_chacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
791}
792
793static inline int
794sn_crypto_stream_chacha20_xor_ic(
795 js_env_t *,
796 js_receiver_t,
797 js_typedarray_span_t<> c,
798 js_typedarray_span_t<> m,
799 js_typedarray_span_t<> n,
800 uint32_t ic,
801 js_typedarray_span_t<> k
802) {
803 assert(c.size_bytes() == m.size_bytes());
804 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
805 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
806
807 return crypto_stream_chacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
808}
809
810static inline int
811sn_crypto_stream_chacha20_ietf(
812 js_env_t *,
813 js_receiver_t,
814 js_typedarray_span_t<> c,
815 js_typedarray_span_t<> n,
816 js_typedarray_span_t<> k
817) {
818 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
819 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
820
821 return crypto_stream_chacha20_ietf(c.data(), c.size_bytes(), n.data(), k.data());
822}
823
824static inline int
825sn_crypto_stream_chacha20_ietf_xor(
826 js_env_t *,
827 js_receiver_t,
828 js_typedarray_span_t<> c,
829 js_typedarray_span_t<> m,
830 js_typedarray_span_t<> n,
831 js_typedarray_span_t<> k
832) {
833 assert(c.size_bytes() == m.size_bytes());
834 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
835 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
836
837 return crypto_stream_chacha20_ietf_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
838}
839
840static inline int
841sn_crypto_stream_chacha20_ietf_xor_ic(
842 js_env_t *,
843 js_receiver_t,
844 js_typedarray_span_t<> c,
845 js_typedarray_span_t<> m,
846 js_typedarray_span_t<> n,
847 uint32_t ic,
848 js_typedarray_span_t<> k
849) {
850 assert(c.size_bytes() == m.size_bytes());
851 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
852 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
853
854 return crypto_stream_chacha20_ietf_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
855}
856
857static inline int
858sn_crypto_stream_xchacha20(
859 js_env_t *,
860 js_receiver_t,
861 js_typedarray_span_t<> c,
862 js_typedarray_span_t<> n,
863 js_typedarray_span_t<> k
864) {
865 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
866 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
867
868 return crypto_stream_xchacha20(c.data(), c.size_bytes(), n.data(), k.data());
869}
870
871static inline int
872sn_crypto_stream_xchacha20_xor(
873 js_env_t *,
874 js_receiver_t,
875 js_typedarray_span_t<> c,
876 js_typedarray_span_t<> m,
877 js_typedarray_span_t<> n,
878 js_typedarray_span_t<> k
879) {
880 assert(c.size_bytes() == m.size_bytes());
881 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
882 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
883
884 return crypto_stream_xchacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
885}
886
887static inline int
888sn_crypto_stream_xchacha20_xor_ic(
889 js_env_t *,
890 js_receiver_t,
891 js_typedarray_span_t<> c,
892 js_typedarray_span_t<> m,
893 js_typedarray_span_t<> n,
894 uint32_t ic,
895 js_typedarray_span_t<> k
896) {
897 assert(c.size_bytes() == m.size_bytes());
898 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
899 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
900
901 return crypto_stream_xchacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
902}
903
904static inline int
905sn_crypto_stream_salsa20(
906 js_env_t *,
907 js_receiver_t,
908 js_typedarray_span_t<> c,
909 js_typedarray_span_t<> n,
910 js_typedarray_span_t<> k
911) {
912 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
913 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
914
915 return crypto_stream_salsa20(c.data(), c.size_bytes(), n.data(), k.data());
916}
917
918static inline int
919sn_crypto_stream_salsa20_xor(
920 js_env_t *,
921 js_receiver_t,
922 js_typedarray_span_t<> c,
923 js_typedarray_span_t<> m,
924 js_typedarray_span_t<> n,
925 js_typedarray_span_t<> k
926) {
927 assert(c.size_bytes() == m.size_bytes());
928 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
929 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
930
931 return crypto_stream_salsa20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
932}
933
934static inline int
935sn_crypto_stream_salsa20_xor_ic(
936 js_env_t *,
937 js_receiver_t,
938 js_typedarray_span_t<> c,
939 js_typedarray_span_t<> m,
940 js_typedarray_span_t<> n,
941 uint32_t ic,
942 js_typedarray_span_t<> k
943) {
944 assert(c.size_bytes() == m.size_bytes());
945 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
946 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
947
948 return crypto_stream_salsa20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
949}
950
951static inline int
952sn_crypto_auth(
953 js_env_t *,
954 js_receiver_t,
955 js_typedarray_span_t<> out,
956 js_typedarray_span_t<> in,
957 js_typedarray_span_t<> k
958) {
959 assert(out.size_bytes() == crypto_auth_BYTES);
960 assert(k.size_bytes() == crypto_auth_KEYBYTES);
961
962 return crypto_auth(out.data(), in.data(), in.size_bytes(), k.data());
963}
964
965static inline bool
966sn_crypto_auth_verify(
967 js_env_t *,
968 js_receiver_t,
969 js_typedarray_span_t<> h,
970 js_typedarray_span_t<> in,
971 js_typedarray_span_t<> k
972) {
973 assert(h.size_bytes() == crypto_auth_BYTES);
974 assert(k.size_bytes() == crypto_auth_KEYBYTES);
975
976 return crypto_auth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
977}
978
979static inline int
980sn_crypto_onetimeauth(
981 js_env_t *,
982 js_receiver_t,
983 js_typedarray_span_t<> out,
984 js_typedarray_span_t<> in,
985 js_typedarray_span_t<> k
986) {
987 assert(out.size_bytes() == crypto_onetimeauth_BYTES);
988 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
989
990 return crypto_onetimeauth(out.data(), in.data(), in.size_bytes(), k.data());
991}
992
993static inline int
994sn_crypto_onetimeauth_init(
995 js_env_t *,
996 js_receiver_t,
997 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
998 js_typedarray_span_t<> k
999) {
1000 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
1001
1002 return crypto_onetimeauth_init(&*state, k.data());
1003}
1004
1005static inline int
1006sn_crypto_onetimeauth_update(
1007 js_env_t *,
1008 js_receiver_t,
1009 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
1010 js_typedarray_span_t<> in
1011) {
1012 return crypto_onetimeauth_update(&*state, in.data(), in.size_bytes());
1013}
1014
1015static inline int
1016sn_crypto_onetimeauth_final(
1017 js_env_t *,
1018 js_receiver_t,
1019 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
1020 js_typedarray_span_t<> out
1021) {
1022 assert(out.size_bytes() == crypto_onetimeauth_BYTES);
1023
1024 return crypto_onetimeauth_final(&*state, out.data());
1025}
1026
1027static inline bool
1028sn_crypto_onetimeauth_verify(
1029 js_env_t *,
1030 js_receiver_t,
1031 js_typedarray_span_t<> h,
1032 js_typedarray_span_t<> in,
1033 js_typedarray_span_t<> k
1034) {
1035 assert(h.size_bytes() == crypto_onetimeauth_BYTES);
1036 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
1037
1038 return crypto_onetimeauth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
1039}
1040
1041// CHECK: memlimit can be >32bit
1042static inline int
1043sn_crypto_pwhash(
1044 js_env_t *,
1045 js_receiver_t,
1046 js_typedarray_span_t<> out,
1047 js_typedarray_span_of_t<char> passwd,
1048 js_typedarray_span_t<> salt,
1049 uint64_t opslimit,
1050 uint64_t memlimit,
1051 int32_t alg
1052) {
1053 assert(out.size_bytes() >= crypto_pwhash_BYTES_MIN);
1054 assert(out.size_bytes() <= crypto_pwhash_BYTES_MAX);
1055 assert(salt.size_bytes() == crypto_pwhash_SALTBYTES);
1056 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1057 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1058 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1059 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1060 assert(alg == 1 || alg == 2); // Argon2i or Argon2id
1061
1062 return crypto_pwhash(
1063 out.data(),
1064 out.size_bytes(),
1065 passwd.data(),
1066 passwd.size_bytes(),
1067 salt.data(),
1068 opslimit,
1069 memlimit,
1070 alg
1071 );
1072}
1073
1074static inline int
1075sn_crypto_pwhash_str(
1076 js_env_t *,
1077 js_receiver_t,
1078 js_typedarray_span_of_t<char> out,
1079 js_typedarray_span_of_t<char> passwd,
1080 uint64_t opslimit,
1081 uint64_t memlimit
1082) {
1083 assert(out.size_bytes() == crypto_pwhash_STRBYTES);
1084 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1085 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1086 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1087 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1088
1089 return crypto_pwhash_str(
1090 out.data(),
1091 passwd.data(),
1092 passwd.size_bytes(),
1093 opslimit,
1094 memlimit
1095 );
1096}
1097
1098static inline bool
1099sn_crypto_pwhash_str_verify(
1100 js_env_t *,
1101 js_receiver_t,
1102 js_typedarray_span_of_t<char> str,
1103 js_typedarray_span_of_t<char> passwd
1104) {
1105 assert(str.size_bytes() == crypto_pwhash_STRBYTES);
1106
1107 return crypto_pwhash_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
1108}
1109
1110// CHECK: returns 1, 0, -1
1111static inline bool
1112sn_crypto_pwhash_str_needs_rehash(
1113 js_env_t *,
1114 js_receiver_t,
1115 js_typedarray_span_of_t<char> str,
1116 uint64_t opslimit,
1117 uint64_t memlimit
1118) {
1119 assert(str.size_bytes() == crypto_pwhash_STRBYTES);
1120 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1121 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1122 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1123 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1124
1125 return crypto_pwhash_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
1126}
1127
1128// CHECK: memlimit can be >32bit
1129static inline int
1130sn_crypto_pwhash_scryptsalsa208sha256(
1131 js_env_t *,
1132 js_receiver_t,
1133 js_typedarray_span_t<> out,
1134 js_typedarray_span_of_t<char> passwd,
1135 js_typedarray_span_t<> salt,
1136 uint64_t opslimit,
1137 uint64_t memlimit
1138) {
1139 assert(out.size_bytes() >= crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
1140 assert(out.size_bytes() <= crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
1141 assert(salt.size_bytes() == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
1142 assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
1143 assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
1144 assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
1145 assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
1146
1147 return crypto_pwhash_scryptsalsa208sha256(
1148 out.data(),
1149 out.size_bytes(),
1150 passwd.data(),
1151 passwd.size_bytes(),
1152 salt.data(),
1153 opslimit,
1154 memlimit
1155 );
1156}
1157
1158static inline int
1159sn_crypto_pwhash_scryptsalsa208sha256_str(
1160 js_env_t *,
1161 js_receiver_t,
1162 js_typedarray_span_of_t<char> out,
1163 js_typedarray_span_of_t<char> passwd,
1164 uint64_t opslimit,
1165 uint64_t memlimit
1166) {
1167 assert(out.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1168 assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
1169 assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
1170 assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
1171 assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
1172
1173 return crypto_pwhash_scryptsalsa208sha256_str(
1174 out.data(),
1175 passwd.data(),
1176 passwd.size_bytes(),
1177 opslimit,
1178 memlimit
1179 );
1180}
1181
1182static inline bool
1183sn_crypto_pwhash_scryptsalsa208sha256_str_verify(
1184 js_env_t *,
1185 js_receiver_t,
1186 js_typedarray_span_of_t<char> str,
1187 js_typedarray_span_of_t<char> passwd
1188) {
1189 assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1190
1191 return crypto_pwhash_scryptsalsa208sha256_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
1192}
1193
1194static inline bool
1195sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
1196 js_env_t *,
1197 js_receiver_t,
1198 js_typedarray_span_of_t<char> str,
1199 uint64_t opslimit,
1200 uint64_t memlimit
1201) {
1202 assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1203 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1204 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1205 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1206 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1207
1208 return crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
1209}
1210
1211static inline int
1212sn_crypto_kx_keypair(
1213 js_env_t *,
1214 js_receiver_t,
1215 js_typedarray_span_t<> pk,
1216 js_typedarray_span_t<> sk
1217) {
1218 assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1219 assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1220
1221 return crypto_kx_keypair(pk.data(), sk.data());
1222}
1223
1224static inline int
1225sn_crypto_kx_seed_keypair(
1226 js_env_t *,
1227 js_receiver_t,
1228 js_typedarray_span_t<> pk,
1229 js_typedarray_span_t<> sk,
1230 js_typedarray_span_t<> seed
1231) {
1232 assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1233 assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1234 assert(seed.size_bytes() == crypto_kx_SEEDBYTES);
1235
1236 return crypto_kx_seed_keypair(pk.data(), sk.data(), seed.data());
1237}
1238
1239static inline int
1240sn_crypto_kx_client_session_keys(
1241 js_env_t *,
1242 js_receiver_t,
1243 std::optional<js_typedarray_span_t<>> rx,
1244 std::optional<js_typedarray_span_t<>> tx,
1245 js_typedarray_span_t<> client_pk,
1246 js_typedarray_span_t<> client_sk,
1247 js_typedarray_span_t<> server_pk
1248) {
1249 assert(rx.has_value() || tx.has_value());
1250
1251 if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1252 if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1253
1254 assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1255 assert(client_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1256 assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1257
1258 return crypto_kx_client_session_keys(
1259 rx ? rx->data() : nullptr,
1260 tx ? tx->data() : nullptr,
1261 client_pk.data(),
1262 client_sk.data(),
1263 server_pk.data()
1264 );
1265}
1266
1267static inline int
1268sn_crypto_kx_server_session_keys(
1269 js_env_t *,
1270 js_receiver_t,
1271 std::optional<js_typedarray_span_t<>> rx,
1272 std::optional<js_typedarray_span_t<>> tx,
1273 js_typedarray_span_t<> server_pk,
1274 js_typedarray_span_t<> server_sk,
1275 js_typedarray_span_t<> client_pk
1276) {
1277 assert(rx.has_value() || tx.has_value());
1278
1279 if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1280 if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1281
1282 assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1283 assert(server_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1284 assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1285
1286 return crypto_kx_server_session_keys(
1287 rx ? rx->data() : nullptr,
1288 tx ? tx->data() : nullptr,
1289 server_pk.data(),
1290 server_sk.data(),
1291 client_pk.data()
1292 );
1293}
1294
1295static inline int
1296sn_crypto_scalarmult_base(
1297 js_env_t *,
1298 js_receiver_t,
1299 js_typedarray_span_t<> q,
1300 js_typedarray_span_t<> n
1301) {
1302 assert(q.size_bytes() == crypto_scalarmult_BYTES);
1303 assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
1304
1305 return crypto_scalarmult_base(q.data(), n.data());
1306}
1307
1308static inline int
1309sn_crypto_scalarmult(
1310 js_env_t *,
1311 js_receiver_t,
1312 js_typedarray_span_t<> q,
1313 js_typedarray_span_t<> n,
1314 js_typedarray_span_t<> p
1315) {
1316 assert(q.size_bytes() == crypto_scalarmult_BYTES);
1317 assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
1318 assert(p.size_bytes() == crypto_scalarmult_BYTES);
1319
1320 return crypto_scalarmult(q.data(), n.data(), p.data());
1321}
1322
1323static inline int
1324sn_crypto_scalarmult_ed25519_base(
1325 js_env_t *,
1326 js_receiver_t,
1327 js_typedarray_span_t<> q,
1328 js_typedarray_span_t<> n
1329) {
1330 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1331 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1332
1333 return crypto_scalarmult_ed25519_base(q.data(), n.data());
1334}
1335
1336static inline int
1337sn_crypto_scalarmult_ed25519(
1338 js_env_t *,
1339 js_receiver_t,
1340 js_typedarray_span_t<> q,
1341 js_typedarray_span_t<> n,
1342 js_typedarray_span_t<> p
1343) {
1344 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1345 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1346 assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1347
1348 return crypto_scalarmult_ed25519(q.data(), n.data(), p.data());
1349}
1350
1351static inline bool
1352sn_crypto_core_ed25519_is_valid_point(
1353 js_env_t *,
1354 js_receiver_t,
1355 js_typedarray_span_t<> p
1356) {
1357 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1358
1359 return crypto_core_ed25519_is_valid_point(p.data()) != 0;
1360}
1361
1362static inline int
1363sn_crypto_core_ed25519_from_uniform(
1364 js_env_t *,
1365 js_receiver_t,
1366 js_typedarray_span_t<> p,
1367 js_typedarray_span_t<> r
1368) {
1369 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1370 assert(r.size_bytes() == crypto_core_ed25519_UNIFORMBYTES);
1371
1372 return crypto_core_ed25519_from_uniform(p.data(), r.data());
1373}
1374
1375static inline int
1376sn_crypto_scalarmult_ed25519_base_noclamp(
1377 js_env_t *,
1378 js_receiver_t,
1379 js_typedarray_span_t<> q,
1380 js_typedarray_span_t<> n
1381) {
1382 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1383 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1384
1385 return crypto_scalarmult_ed25519_base_noclamp(q.data(), n.data());
1386}
1387
1388static inline int
1389sn_crypto_scalarmult_ed25519_noclamp(
1390 js_env_t *,
1391 js_receiver_t,
1392 js_typedarray_span_t<> q,
1393 js_typedarray_span_t<> n,
1394 js_typedarray_span_t<> p
1395) {
1396 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1397 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1398 assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1399
1400 return crypto_scalarmult_ed25519_noclamp(q.data(), n.data(), p.data());
1401}
1402
1403static inline int
1404sn_crypto_core_ed25519_add(
1405 js_env_t *,
1406 js_receiver_t,
1407 js_typedarray_span_t<> r,
1408 js_typedarray_span_t<> p,
1409 js_typedarray_span_t<> q
1410) {
1411 assert(r.size_bytes() == crypto_core_ed25519_BYTES);
1412 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1413 assert(q.size_bytes() == crypto_core_ed25519_BYTES);
1414
1415 return crypto_core_ed25519_add(r.data(), p.data(), q.data());
1416}
1417
1418static inline int
1419sn_crypto_core_ed25519_sub(
1420 js_env_t *,
1421 js_receiver_t,
1422 js_typedarray_span_t<> r,
1423 js_typedarray_span_t<> p,
1424 js_typedarray_span_t<> q
1425) {
1426 assert(r.size_bytes() == crypto_core_ed25519_BYTES);
1427 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1428 assert(q.size_bytes() == crypto_core_ed25519_BYTES);
1429
1430 return crypto_core_ed25519_sub(r.data(), p.data(), q.data());
1431}
1432
1433static inline void
1434sn_crypto_core_ed25519_scalar_random(
1435 js_env_t *,
1436 js_receiver_t,
1437 js_typedarray_span_t<> r
1438) {
1439 assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1440
1441 crypto_core_ed25519_scalar_random(r.data());
1442}
1443
1444static inline void
1445sn_crypto_core_ed25519_scalar_reduce(
1446 js_env_t *,
1447 js_receiver_t,
1448 js_typedarray_span_t<> r,
1449 js_typedarray_span_t<> s
1450) {
1451 assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1452 assert(s.size_bytes() == crypto_core_ed25519_NONREDUCEDSCALARBYTES);
1453
1454 crypto_core_ed25519_scalar_reduce(r.data(), s.data());
1455}
1456
1457static inline void
1458sn_crypto_core_ed25519_scalar_invert(
1459 js_env_t *,
1460 js_receiver_t,
1461 js_typedarray_span_t<> recip,
1462 js_typedarray_span_t<> s
1463) {
1464 assert(recip.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1465 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1466
1467 crypto_core_ed25519_scalar_invert(recip.data(), s.data());
1468}
1469
1470static inline void
1471sn_crypto_core_ed25519_scalar_negate(
1472 js_env_t *,
1473 js_receiver_t,
1474 js_typedarray_span_t<> neg,
1475 js_typedarray_span_t<> s
1476) {
1477 assert(neg.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1478 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1479
1480 crypto_core_ed25519_scalar_negate(neg.data(), s.data());
1481}
1482
1483static inline void
1484sn_crypto_core_ed25519_scalar_complement(
1485 js_env_t *,
1486 js_receiver_t,
1487 js_typedarray_span_t<> comp,
1488 js_typedarray_span_t<> s
1489) {
1490 assert(comp.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1491 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1492
1493 crypto_core_ed25519_scalar_complement(comp.data(), s.data());
1494}
1495
1496static inline void
1497sn_crypto_core_ed25519_scalar_add(
1498 js_env_t *,
1499 js_receiver_t,
1500 js_typedarray_span_t<> z,
1501 js_typedarray_span_t<> x,
1502 js_typedarray_span_t<> y
1503) {
1504 assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1505 assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1506 assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1507
1508 crypto_core_ed25519_scalar_add(z.data(), x.data(), y.data());
1509}
1510
1511static inline void
1512sn_crypto_core_ed25519_scalar_sub(
1513 js_env_t *,
1514 js_receiver_t,
1515 js_typedarray_span_t<> z,
1516 js_typedarray_span_t<> x,
1517 js_typedarray_span_t<> y
1518) {
1519 assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1520 assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1521 assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1522
1523 crypto_core_ed25519_scalar_sub(z.data(), x.data(), y.data());
1524}
1525
1526static inline int
1527sn_crypto_shorthash(
1528 js_env_t *,
1529 js_receiver_t,
1530 js_typedarray_span_t<> out,
1531 js_typedarray_span_t<> in,
1532 js_typedarray_span_t<> k
1533) {
1534 assert(out.size_bytes() == crypto_shorthash_BYTES);
1535 assert(k.size_bytes() == crypto_shorthash_KEYBYTES);
1536
1537 return crypto_shorthash(out.data(), in.data(), in.size_bytes(), k.data());
1538}
1539
1540static inline void
1541sn_crypto_kdf_keygen(
1542 js_env_t *,
1543 js_receiver_t,
1544 js_typedarray_span_t<> key
1545) {
1546 assert(key.size_bytes() == crypto_kdf_KEYBYTES);
1547
1548 crypto_kdf_keygen(key.data());
1549}
1550
1551static inline int
1552sn_crypto_kdf_derive_from_key(
1553 js_env_t *,
1554 js_receiver_t,
1555 js_typedarray_span_t<> subkey,
1556 uint64_t subkey_id,
1557 js_typedarray_span_of_t<char> ctx,
1558 js_typedarray_span_t<> key
1559) {
1560 assert(subkey.size_bytes() >= crypto_kdf_BYTES_MIN);
1561 assert(subkey.size_bytes() <= crypto_kdf_BYTES_MAX);
1562 assert(ctx.size_bytes() == crypto_kdf_CONTEXTBYTES);
1563 assert(key.size_bytes() == crypto_kdf_KEYBYTES);
1564
1565 return crypto_kdf_derive_from_key(
1566 subkey.data(),
1567 subkey.size_bytes(),
1568 subkey_id,
1569 ctx.data(),
1570 key.data()
1571 );
1572}
1573
1574static inline int
1575sn_crypto_hash(
1576 js_env_t *,
1577 js_receiver_t,
1578 js_typedarray_span_t<> out,
1579 js_typedarray_span_t<> in
1580) {
1581 assert(out.size_bytes() == crypto_hash_BYTES);
1582
1583 return crypto_hash(out.data(), in.data(), in.size_bytes());
1584}
1585
1586static inline int
1587sn_crypto_hash_sha256(
1588 js_env_t *,
1589 js_receiver_t,
1590 js_typedarray_span_t<> out,
1591 js_typedarray_span_t<> in
1592) {
1593 assert(out.size_bytes() == crypto_hash_sha256_BYTES);
1594
1595 return crypto_hash_sha256(out.data(), in.data(), in.size_bytes());
1596}
1597
1598static inline int
1599sn_crypto_hash_sha256_init(
1600 js_env_t *,
1601 js_receiver_t,
1602 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state
1603) {
1604 return crypto_hash_sha256_init(&*state);
1605}
1606
1607static inline int
1608sn_crypto_hash_sha256_update(
1609 js_env_t *,
1610 js_receiver_t,
1611 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
1612 js_typedarray_span_t<> in
1613) {
1614 return crypto_hash_sha256_update(&*state, in.data(), in.size_bytes());
1615}
1616
1617static inline int
1618sn_crypto_hash_sha256_final(
1619 js_env_t *,
1620 js_receiver_t,
1621 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
1622 js_typedarray_span_t<> out
1623) {
1624 assert(out.size_bytes() == crypto_hash_sha256_BYTES);
1625
1626 return crypto_hash_sha256_final(&*state, out.data());
1627}
1628
1629static inline int
1630sn_crypto_hash_sha512(
1631 js_env_t *,
1632 js_receiver_t,
1633 js_typedarray_span_t<> out,
1634 js_typedarray_span_t<> in
1635) {
1636 assert(out.size_bytes() == crypto_hash_sha512_BYTES);
1637
1638 return crypto_hash_sha512(out.data(), in.data(), in.size_bytes());
1639}
1640
1641static inline int
1642sn_crypto_hash_sha512_init(
1643 js_env_t *,
1644 js_receiver_t,
1645 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state
1646) {
1647 return crypto_hash_sha512_init(&*state);
1648}
1649
1650static inline int
1651sn_crypto_hash_sha512_update(
1652 js_env_t *,
1653 js_receiver_t,
1654 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
1655 js_typedarray_span_t<> in
1656) {
1657 return crypto_hash_sha512_update(&*state, in.data(), in.size_bytes());
1658}
1659
1660static inline int
1661sn_crypto_hash_sha512_final(
1662 js_env_t *,
1663 js_receiver_t,
1664 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
1665 js_typedarray_span_t<> out
1666) {
1667 assert(out.size_bytes() == crypto_hash_sha512_BYTES);
1668
1669 return crypto_hash_sha512_final(&*state, out.data());
1670}
1671
1672static inline void
1673sn_crypto_aead_xchacha20poly1305_ietf_keygen(
1674 js_env_t *,
1675 js_receiver_t,
1676 js_typedarray_span_t<> k
1677) {
1678 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1679
1680 crypto_aead_xchacha20poly1305_ietf_keygen(k.data());
1681}
1682
1683static inline uint64_t
1684sn_crypto_aead_xchacha20poly1305_ietf_encrypt(
1685 js_env_t *,
1686 js_receiver_t,
1687 js_typedarray_span_t<> c,
1688 js_typedarray_span_t<> m,
1689 std::optional<js_typedarray_span_t<>> ad,
1690 js_typedarray_span_t<> npub,
1691 js_typedarray_span_t<> k
1692) {
1693 assert(c.size_bytes() == m.size_bytes() + crypto_aead_xchacha20poly1305_ietf_ABYTES);
1694 assert(c.size_bytes() <= 0xffffffff);
1695 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1696 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1697
1698 uint8_t *ad_data = nullptr;
1699 size_t ad_size = 0;
1700 if (ad) {
1701 ad_data = ad->data();
1702 ad_size = ad->size_bytes();
1703 }
1704
1705 unsigned long long clen = 0;
1706 int status = crypto_aead_xchacha20poly1305_ietf_encrypt(
1707 c.data(),
1708 &clen,
1709 m.data(),
1710 m.size_bytes(),
1711 ad_data,
1712 ad_size,
1713 nullptr,
1714 npub.data(),
1715 k.data()
1716 );
1717
1718 if (status < 0) return status;
1719
1720 return clen;
1721}
1722
1723static inline uint64_t
1724sn_crypto_aead_xchacha20poly1305_ietf_decrypt(
1725 js_env_t *,
1726 js_receiver_t,
1727 js_typedarray_span_t<> m,
1728 js_typedarray_span_t<> c,
1729 std::optional<js_typedarray_span_t<>> ad,
1730 js_typedarray_span_t<> npub,
1731 js_typedarray_span_t<> k
1732) {
1733 assert(m.size_bytes() == c.size_bytes() - crypto_aead_xchacha20poly1305_ietf_ABYTES);
1734 assert(m.size_bytes() <= 0xffffffff);
1735 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1736 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1737
1738 uint8_t *ad_data = nullptr;
1739 size_t ad_size = 0;
1740 if (ad) {
1741 ad_data = ad->data();
1742 ad_size = ad->size_bytes();
1743 }
1744
1745 unsigned long long mlen = 0;
1746 int status = crypto_aead_xchacha20poly1305_ietf_decrypt(
1747 m.data(),
1748 &mlen,
1749 nullptr,
1750 c.data(),
1751 c.size_bytes(),
1752 ad_data,
1753 ad_size,
1754 npub.data(),
1755 k.data()
1756 );
1757
1758 if (status < 0) return status;
1759
1760 return mlen;
1761}
1762
1763static inline uint64_t
1764sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
1765 js_env_t *,
1766 js_receiver_t,
1767 js_typedarray_span_t<> c,
1768 js_typedarray_span_t<> mac,
1769 js_typedarray_span_t<> m,
1770 std::optional<js_typedarray_span_t<>> ad,
1771 js_typedarray_span_t<> npub,
1772 js_typedarray_span_t<> k
1773) {
1774 assert(c.size_bytes() == m.size_bytes());
1775 assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
1776 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1777 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1778
1779 uint8_t *ad_data = nullptr;
1780 size_t ad_size = 0;
1781 if (ad) {
1782 ad_data = ad->data();
1783 ad_size = ad->size_bytes();
1784 }
1785
1786 unsigned long long maclen = 0;
1787 int status = crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
1788 c.data(),
1789 mac.data(),
1790 &maclen,
1791 m.data(),
1792 m.size_bytes(),
1793 ad_data,
1794 ad_size,
1795 nullptr,
1796 npub.data(),
1797 k.data()
1798 );
1799
1800 if (status < 0) return status;
1801
1802 return maclen;
1803}
1804
1805static inline int
1806sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
1807 js_env_t *,
1808 js_receiver_t,
1809 js_typedarray_span_t<> m,
1810 js_typedarray_span_t<> c,
1811 js_typedarray_span_t<> mac,
1812 std::optional<js_typedarray_span_t<>> ad,
1813 js_typedarray_span_t<> npub,
1814 js_typedarray_span_t<> k
1815) {
1816 assert(m.size_bytes() == c.size_bytes());
1817 assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
1818 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1819 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1820
1821 uint8_t *ad_data = nullptr;
1822 size_t ad_size = 0;
1823 if (ad) {
1824 ad_data = ad->data();
1825 ad_size = ad->size_bytes();
1826 }
1827
1828 return crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
1829 m.data(),
1830 nullptr,
1831 c.data(),
1832 c.size_bytes(),
1833 mac.data(),
1834 ad_data,
1835 ad_size,
1836 npub.data(),
1837 k.data()
1838 );
1839}
1840
1841static inline void
1842sn_crypto_aead_chacha20poly1305_ietf_keygen(
1843 js_env_t *,
1844 js_receiver_t,
1845 js_typedarray_span_t<> k
1846) {
1847 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1848
1849 crypto_aead_chacha20poly1305_ietf_keygen(k.data());
1850}
1851
1852static inline uint64_t
1853sn_crypto_aead_chacha20poly1305_ietf_encrypt(
1854 js_env_t *,
1855 js_receiver_t,
1856 js_typedarray_span_t<> c,
1857 js_typedarray_span_t<> m,
1858 std::optional<js_typedarray_span_t<>> ad,
1859 js_typedarray_span_t<> npub,
1860 js_typedarray_span_t<> k
1861) {
1862 assert(c.size_bytes() == m.size_bytes() + crypto_aead_chacha20poly1305_ietf_ABYTES);
1863 assert(c.size_bytes() <= 0xffffffff);
1864 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1865 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1866
1867 uint8_t *ad_data = nullptr;
1868 size_t ad_size = 0;
1869 if (ad) {
1870 ad_data = ad->data();
1871 ad_size = ad->size_bytes();
1872 }
1873
1874 unsigned long long clen = 0;
1875 int status = crypto_aead_chacha20poly1305_ietf_encrypt(
1876 c.data(),
1877 &clen,
1878 m.data(),
1879 m.size_bytes(),
1880 ad_data,
1881 ad_size,
1882 nullptr,
1883 npub.data(),
1884 k.data()
1885 );
1886
1887 if (status < 0) return status;
1888
1889 return clen;
1890}
1891
1892static inline uint64_t
1893sn_crypto_aead_chacha20poly1305_ietf_decrypt(
1894 js_env_t *,
1895 js_receiver_t,
1896 js_typedarray_span_t<> m,
1897 js_typedarray_span_t<> c,
1898 std::optional<js_typedarray_span_t<>> ad,
1899 js_typedarray_span_t<> npub,
1900 js_typedarray_span_t<> k
1901) {
1902 assert(m.size_bytes() == c.size_bytes() - crypto_aead_chacha20poly1305_ietf_ABYTES);
1903 assert(m.size_bytes() <= 0xffffffff);
1904 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1905 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1906
1907 uint8_t *ad_data = nullptr;
1908 size_t ad_size = 0;
1909 if (ad) {
1910 ad_data = ad->data();
1911 ad_size = ad->size_bytes();
1912 }
1913
1914 unsigned long long mlen = 0;
1915 int status = crypto_aead_chacha20poly1305_ietf_decrypt(
1916 m.data(),
1917 &mlen,
1918 nullptr,
1919 c.data(),
1920 c.size_bytes(),
1921 ad_data,
1922 ad_size,
1923 npub.data(),
1924 k.data()
1925 );
1926
1927 if (status < 0) return status;
1928
1929 return mlen;
1930}
1931
1932static inline uint64_t
1933sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached(
1934 js_env_t *,
1935 js_receiver_t,
1936 js_typedarray_span_t<> c,
1937 js_typedarray_span_t<> mac,
1938 js_typedarray_span_t<> m,
1939 std::optional<js_typedarray_span_t<>> ad,
1940 js_typedarray_span_t<> npub,
1941 js_typedarray_span_t<> k
1942) {
1943 assert(c.size_bytes() == m.size_bytes());
1944 assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
1945 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1946 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1947
1948 uint8_t *ad_data = nullptr;
1949 size_t ad_size = 0;
1950 if (ad) {
1951 ad_data = ad->data();
1952 ad_size = ad->size_bytes();
1953 }
1954
1955 unsigned long long maclen = 0;
1956 int status = crypto_aead_chacha20poly1305_ietf_encrypt_detached(
1957 c.data(),
1958 mac.data(),
1959 &maclen,
1960 m.data(),
1961 m.size_bytes(),
1962 ad_data,
1963 ad_size,
1964 nullptr,
1965 npub.data(),
1966 k.data()
1967 );
1968
1969 if (status < 0) return status;
1970
1971 return maclen;
1972}
1973
1974static inline int
1975sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached(
1976 js_env_t *,
1977 js_receiver_t,
1978 js_typedarray_span_t<> m,
1979 js_typedarray_span_t<> c,
1980 js_typedarray_span_t<> mac,
1981 std::optional<js_typedarray_span_t<>> ad,
1982 js_typedarray_span_t<> npub,
1983 js_typedarray_span_t<> k
1984) {
1985 assert(m.size_bytes() == c.size_bytes());
1986 assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
1987 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1988 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1989
1990 uint8_t *ad_data = nullptr;
1991 size_t ad_size = 0;
1992 if (ad) {
1993 ad_data = ad->data();
1994 ad_size = ad->size_bytes();
1995 }
1996
1997 return crypto_aead_chacha20poly1305_ietf_decrypt_detached(
1998 m.data(),
1999 nullptr,
2000 c.data(),
2001 c.size_bytes(),
2002 mac.data(),
2003 ad_data,
2004 ad_size,
2005 npub.data(),
2006 k.data()
2007 );
2008}
2009
2010static inline void
2011sn_crypto_secretstream_xchacha20poly1305_keygen(
2012 js_env_t *env,
2013 js_receiver_t,
2014
2015 js_arraybuffer_span_t k,
2016 uint32_t k_offset,
2017 uint32_t k_len
2018) {
2019 assert_bounds(k);
2020 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2021
2022 crypto_secretstream_xchacha20poly1305_keygen(&k[k_offset]);
2023}
2024
2025static inline int
2026sn_crypto_secretstream_xchacha20poly1305_init_push(
2027 js_env_t *env,
2028 js_receiver_t,
2029
2030 js_arraybuffer_span_t state,
2031 uint32_t state_offset,
2032 uint32_t state_len,
2033
2034 js_arraybuffer_span_t header,
2035 uint32_t header_offset,
2036 uint32_t header_len,
2037
2038 js_arraybuffer_span_t k,
2039 uint32_t k_offset,
2040 uint32_t k_len
2041) {
2042 assert_bounds(state);
2043 assert_bounds(header);
2044 assert_bounds(k);
2045
2046 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2047 assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
2048 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2049
2050 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2051
2052 return crypto_secretstream_xchacha20poly1305_init_push(state_data, &header[header_offset], &k[k_offset]);
2053}
2054
2055static inline uint64_t
2056sn_crypto_secretstream_xchacha20poly1305_push(
2057 js_env_t *env,
2058 js_receiver_t,
2059
2060 js_arraybuffer_span_t state,
2061 uint32_t state_offset,
2062 uint32_t state_len,
2063
2064 js_arraybuffer_span_t c,
2065 uint32_t c_offset,
2066 uint32_t c_len,
2067
2068 js_arraybuffer_span_t m,
2069 uint32_t m_offset,
2070 uint32_t m_len,
2071
2072 js_arraybuffer_span_t ad,
2073 uint32_t ad_offset,
2074 uint32_t ad_len,
2075
2076 uint32_t tag
2077) {
2078 assert_bounds(state);
2079 assert_bounds(c);
2080 assert_bounds(m);
2081
2082 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2083 assert(c_len == m_len + crypto_secretstream_xchacha20poly1305_ABYTES);
2084 assert(c_len <= 0xffffffff && "32bit integer");
2085
2086 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2087
2088 uint8_t *ad_data = NULL;
2089 if (ad_len) {
2090 assert_bounds(ad);
2091 ad_data = &ad[ad_offset];
2092 }
2093
2094 unsigned long long clen = 0;
2095 int status = crypto_secretstream_xchacha20poly1305_push(
2096 state_data,
2097 &c[c_offset],
2098 &clen,
2099 &m[m_offset],
2100 m_len,
2101 ad_data,
2102 ad_len,
2103 tag
2104 );
2105
2106 if (status < 0) return status;
2107
2108 return clen;
2109}
2110
2111static inline int
2112sn_crypto_secretstream_xchacha20poly1305_init_pull(
2113 js_env_t *,
2114 js_receiver_t,
2115
2116 js_arraybuffer_span_t state,
2117 uint32_t state_offset,
2118 uint32_t state_len,
2119
2120 js_arraybuffer_span_t header,
2121 uint32_t header_offset,
2122 uint32_t header_len,
2123
2124 js_arraybuffer_span_t k,
2125 uint32_t k_offset,
2126 uint32_t k_len
2127) {
2128 assert_bounds(state);
2129 assert_bounds(header);
2130 assert_bounds(k);
2131
2132 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2133 assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
2134 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2135
2136 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2137
2138 return crypto_secretstream_xchacha20poly1305_init_pull(state_data, &header[header_offset], &k[k_offset]);
2139}
2140
2141static inline uint64_t
2142sn_crypto_secretstream_xchacha20poly1305_pull(
2143 js_env_t *env,
2144 js_receiver_t,
2145
2146 js_arraybuffer_span_t state,
2147 uint32_t state_offset,
2148 uint32_t state_len,
2149
2150 js_arraybuffer_span_t m,
2151 uint32_t m_offset,
2152 uint32_t m_len,
2153
2154 js_arraybuffer_span_t tag,
2155 uint32_t tag_offset,
2156 uint32_t tag_len,
2157
2158 js_arraybuffer_span_t c,
2159 uint32_t c_offset,
2160 uint32_t c_len,
2161
2162 js_arraybuffer_span_t ad,
2163 uint32_t ad_offset,
2164 uint32_t ad_len
2165) {
2166 assert_bounds(state);
2167 assert_bounds(m);
2168 assert_bounds(tag);
2169 assert_bounds(c);
2170
2171 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2172 assert(c_len >= crypto_secretstream_xchacha20poly1305_ABYTES);
2173 assert(tag_len == 1);
2174 assert(m_len == c_len - crypto_secretstream_xchacha20poly1305_ABYTES);
2175 assert(m_len <= 0xffffffff);
2176
2177 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2178
2179 uint8_t *ad_data = NULL;
2180 if (ad_len) {
2181 assert_bounds(ad);
2182 ad_data = &ad[ad_offset];
2183 }
2184
2185 unsigned long long mlen = 0;
2186 int status = crypto_secretstream_xchacha20poly1305_pull(
2187 state_data,
2188 &m[m_offset],
2189 &mlen,
2190 &tag[tag_offset],
2191 &c[c_offset],
2192 c_len,
2193 ad_data,
2194 ad_len
2195 );
2196
2197 if (status < 0) return status;
2198
2199 return mlen;
2200}
2201
2202static inline void
2203sn_crypto_secretstream_xchacha20poly1305_rekey(
2204 js_env_t *,
2205 js_receiver_t,
2206
2207 js_arraybuffer_span_t state,
2208 uint32_t state_offset,
2209 uint32_t state_len
2210) {
2211 assert_bounds(state);
2212
2213 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2214
2215 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2216
2217 crypto_secretstream_xchacha20poly1305_rekey(state_data);
2218}
2219
2220struct sn_async_task {
2221 uv_work_t task;
2222 js_env_t *env;
2223 js_persistent_t<js_function_t<void, int>> cb;
2224 js_deferred_teardown_t *teardown;
2225 int code = 0;
2226 bool exiting = false;
2227
2228 sn_async_task(js_env_t *env) : env(env) {
2229 int err;
2230 err = js_add_teardown_callback<on_teardown, sn_async_task>(env, this, teardown);
2231 assert(err == 0);
2232 }
2233
2234 ~sn_async_task() {
2235 int err;
2236 err = js_finish_teardown_callback(teardown);
2237 assert(err == 0);
2238 }
2239
2240private:
2241 static void
2242 on_teardown(js_deferred_teardown_t *teardown, sn_async_task *req) {
2243 req->exiting = true;
2244 }
2245};
2246
2247struct sn_async_pwhash_request : sn_async_task {
2248 js_persistent_t<js_arraybuffer_t> out_ref;
2249 std::span<uint8_t> out;
2250
2251 js_persistent_t<js_arraybuffer_t> pwd_ref;
2252 std::span<char> pwd;
2253
2254 js_persistent_t<js_arraybuffer_t> salt_ref;
2255 std::span<uint8_t> salt;
2256
2257 uint64_t opslimit;
2258 size_t memlimit;
2259 int alg;
2260
2261 sn_async_pwhash_request(js_env_t *env) : sn_async_task(env) {}
2262};
2263
2264static void
2265async_pwhash_execute(uv_work_t *uv_req) {
2266 auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
2267
2268 req->code = crypto_pwhash(
2269 req->out.data(),
2270 req->out.size(),
2271 req->pwd.data(),
2272 req->pwd.size(),
2273 req->salt.data(),
2274 req->opslimit,
2275 req->memlimit,
2276 req->alg
2277 );
2278}
2279
2280static void
2281async_pwhash_complete(uv_work_t *uv_req, int status) {
2282 int err;
2283
2284 auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
2285
2286 if (req->exiting) return delete req;
2287
2288 js_handle_scope_t *scope;
2289 err = js_open_handle_scope(req->env, &scope);
2290 assert(err == 0);
2291
2292 js_function_t<void, int> callback;
2293 err = js_get_reference_value(req->env, req->cb, callback);
2294 assert(err == 0);
2295
2296 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2297 assert(err != js_pending_exception);
2298
2299 err = js_close_handle_scope(req->env, scope);
2300 assert(err == 0);
2301
2302 delete req;
2303}
2304
2305static inline void
2306sn_crypto_pwhash_async(
2307 js_env_t *env,
2308 js_receiver_t,
2309
2310 js_arraybuffer_t out,
2311 uint32_t out_offset,
2312 uint32_t out_len,
2313
2314 js_arraybuffer_t pwd,
2315 uint32_t pwd_offset,
2316 uint32_t pwd_len,
2317
2318 js_arraybuffer_t salt,
2319 uint32_t salt_offset,
2320 uint32_t salt_len,
2321
2322 uint64_t opslimit,
2323 uint64_t memlimit,
2324 uint32_t alg,
2325
2326 js_function_t<void, int> callback
2327) {
2328 int err;
2329
2330 auto *req = new sn_async_pwhash_request(env);
2331
2332 std::span<uint8_t> out_view;
2333 err = js_get_arraybuffer_info(env, out, out_view);
2334 assert(err == 0);
2335 assert(out_offset + out_len <= out_view.size());
2336
2337 req->out = {&out_view[out_offset], out_len};
2338
2339 std::span<char> pwd_view;
2340 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2341 assert(err == 0);
2342 assert(pwd_offset + pwd_len <= pwd_view.size());
2343
2344 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2345
2346 std::span<uint8_t> salt_view;
2347 err = js_get_arraybuffer_info(env, salt, salt_view);
2348 assert(err == 0);
2349 assert(salt_offset + salt_len <= salt_view.size());
2350
2351 req->salt = {&salt_view[salt_offset], salt_len};
2352
2353 req->opslimit = opslimit;
2354 req->memlimit = memlimit;
2355 req->alg = alg;
2356
2357 err = js_create_reference(env, out, req->out_ref);
2358 assert(err == 0);
2359
2360 err = js_create_reference(env, pwd, req->pwd_ref);
2361 assert(err == 0);
2362
2363 err = js_create_reference(env, salt, req->salt_ref);
2364 assert(err == 0);
2365
2366 err = js_create_reference(env, callback, req->cb);
2367 assert(err == 0);
2368
2369 uv_loop_t *loop;
2370 err = js_get_env_loop(env, &loop);
2371 assert(err == 0);
2372
2373 err = uv_queue_work(loop, &req->task, async_pwhash_execute, async_pwhash_complete);
2374 assert(err == 0);
2375}
2376
2377struct sn_async_pwhash_str_request : sn_async_task {
2378 js_persistent_t<js_arraybuffer_t> out_ref;
2379 std::span<char> out;
2380
2381 js_persistent_t<js_arraybuffer_t> pwd_ref;
2382 std::span<char> pwd;
2383
2384 uint64_t opslimit;
2385 size_t memlimit;
2386
2387 sn_async_pwhash_str_request(js_env_t *env) : sn_async_task(env) {}
2388};
2389
2390static void
2391async_pwhash_str_execute(uv_work_t *uv_req) {
2392 auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
2393
2394 req->code = crypto_pwhash_str(
2395 req->out.data(),
2396 req->pwd.data(),
2397 req->pwd.size(),
2398 req->opslimit,
2399 req->memlimit
2400 );
2401}
2402
2403static void
2404async_pwhash_str_complete(uv_work_t *uv_req, int status) {
2405 int err;
2406
2407 auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
2408
2409 if (req->exiting) return delete req;
2410
2411 js_handle_scope_t *scope;
2412 err = js_open_handle_scope(req->env, &scope);
2413 assert(err == 0);
2414
2415 js_function_t<void, int> callback;
2416 err = js_get_reference_value(req->env, req->cb, callback);
2417 assert(err == 0);
2418
2419 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2420 assert(err != js_pending_exception);
2421
2422 err = js_close_handle_scope(req->env, scope);
2423 assert(err == 0);
2424
2425 delete req;
2426}
2427
2428static inline void
2429sn_crypto_pwhash_str_async(
2430 js_env_t *env,
2431 js_receiver_t,
2432
2433 js_arraybuffer_t out,
2434 uint32_t out_offset,
2435 uint32_t out_len,
2436
2437 js_arraybuffer_t pwd,
2438 uint32_t pwd_offset,
2439 uint32_t pwd_len,
2440
2441 uint64_t opslimit,
2442 uint64_t memlimit,
2443 js_function_t<void, int> callback
2444) {
2445 int err;
2446
2447 auto *req = new sn_async_pwhash_str_request(env);
2448
2449 std::span<char> out_view;
2450 err = js_get_arraybuffer_info(env, out, out_view);
2451 assert(err == 0);
2452 assert(out_offset + out_len <= out_view.size());
2453
2454 req->out = {&out_view[out_offset], out_len};
2455
2456 std::span<char> pwd_view;
2457 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2458 assert(err == 0);
2459 assert(pwd_offset + pwd_len <= pwd_view.size());
2460
2461 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2462
2463 req->opslimit = opslimit;
2464 req->memlimit = memlimit;
2465
2466 err = js_create_reference(env, out, req->out_ref);
2467 assert(err == 0);
2468
2469 err = js_create_reference(env, pwd, req->pwd_ref);
2470 assert(err == 0);
2471
2472 err = js_create_reference(env, callback, req->cb);
2473 assert(err == 0);
2474
2475 uv_loop_t *loop;
2476 err = js_get_env_loop(env, &loop);
2477 assert(err == 0);
2478
2479 err = uv_queue_work(loop, &req->task, async_pwhash_str_execute, async_pwhash_str_complete);
2480 assert(err == 0);
2481}
2482
2483struct sn_async_pwhash_str_verify_request : sn_async_task {
2484 js_persistent_t<js_arraybuffer_t> str_ref;
2485 std::span<char> str;
2486
2487 js_persistent_t<js_arraybuffer_t> pwd_ref;
2488 std::span<char> pwd;
2489
2490 sn_async_pwhash_str_verify_request(js_env_t *env) : sn_async_task(env) {}
2491};
2492
2493static void
2494async_pwhash_str_verify_execute(uv_work_t *uv_req) {
2495 auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
2496
2497 req->code = crypto_pwhash_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
2498}
2499
2500static void
2501async_pwhash_str_verify_complete(uv_work_t *uv_req, int status) {
2502 int err;
2503
2504 auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
2505
2506 if (req->exiting) return delete req;
2507
2508 js_handle_scope_t *scope;
2509 err = js_open_handle_scope(req->env, &scope);
2510 assert(err == 0);
2511
2512 js_function_t<void, int> callback;
2513 err = js_get_reference_value(req->env, req->cb, callback);
2514 assert(err == 0);
2515
2516 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2517 assert(err != js_pending_exception);
2518
2519 err = js_close_handle_scope(req->env, scope);
2520 assert(err == 0);
2521
2522 delete req;
2523}
2524
2525static inline void
2526sn_crypto_pwhash_str_verify_async(
2527 js_env_t *env,
2528 js_receiver_t,
2529
2530 js_arraybuffer_t str,
2531 uint32_t str_offset,
2532 uint32_t str_len,
2533
2534 js_arraybuffer_t pwd,
2535 uint32_t pwd_offset,
2536 uint32_t pwd_len,
2537
2538 js_function_t<void, int> callback
2539) {
2540 int err;
2541
2542 auto *req = new sn_async_pwhash_str_verify_request(env);
2543
2544 std::span<char> str_view;
2545 err = js_get_arraybuffer_info(env, str, str_view);
2546 assert(err == 0);
2547 assert(str_offset + str_len <= str_view.size());
2548
2549 req->str = {&str_view[str_offset], str_len};
2550
2551 std::span<char> pwd_view;
2552 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2553 assert(err == 0);
2554 assert(pwd_offset + pwd_len <= pwd_view.size());
2555
2556 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2557
2558 err = js_create_reference(env, str, req->str_ref);
2559 assert(err == 0);
2560
2561 err = js_create_reference(env, pwd, req->pwd_ref);
2562 assert(err == 0);
2563
2564 err = js_create_reference(env, callback, req->cb);
2565 assert(err == 0);
2566
2567 uv_loop_t *loop;
2568 err = js_get_env_loop(env, &loop);
2569 assert(err == 0);
2570
2571 err = uv_queue_work(loop, &req->task, async_pwhash_str_verify_execute, async_pwhash_str_verify_complete);
2572 assert(err == 0);
2573}
2574
2575struct sn_async_pwhash_scryptsalsa208sha256_request : sn_async_task {
2576 js_persistent_t<js_arraybuffer_t> out_ref;
2577 std::span<uint8_t> out;
2578
2579 js_persistent_t<js_arraybuffer_t> pwd_ref;
2580 std::span<char> pwd;
2581
2582 js_persistent_t<js_arraybuffer_t> salt_ref;
2583 std::span<uint8_t> salt;
2584
2585 uint64_t opslimit;
2586 size_t memlimit;
2587
2588 sn_async_pwhash_scryptsalsa208sha256_request(js_env_t *env) : sn_async_task(env) {}
2589};
2590
2591static void
2592async_pwhash_scryptsalsa208sha256_execute(uv_work_t *uv_req) {
2593 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
2594
2595 req->code = crypto_pwhash_scryptsalsa208sha256(
2596 req->out.data(),
2597 req->out.size(),
2598 req->pwd.data(),
2599 req->pwd.size(),
2600 req->salt.data(),
2601 req->opslimit,
2602 req->memlimit
2603 );
2604}
2605
2606static void
2607async_pwhash_scryptsalsa208sha256_complete(uv_work_t *uv_req, int status) {
2608 int err;
2609
2610 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
2611
2612 if (req->exiting) return delete req;
2613
2614 js_handle_scope_t *scope;
2615 err = js_open_handle_scope(req->env, &scope);
2616 assert(err == 0);
2617
2618 js_function_t<void, int> callback;
2619 err = js_get_reference_value(req->env, req->cb, callback);
2620 assert(err == 0);
2621
2622 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2623 assert(err != js_pending_exception);
2624
2625 err = js_close_handle_scope(req->env, scope);
2626 assert(err == 0);
2627
2628 delete req;
2629}
2630
2631static inline void
2632sn_crypto_pwhash_scryptsalsa208sha256_async(
2633 js_env_t *env,
2634 js_receiver_t,
2635
2636 js_arraybuffer_t out,
2637 uint32_t out_offset,
2638 uint32_t out_len,
2639
2640 js_arraybuffer_t pwd,
2641 uint32_t pwd_offset,
2642 uint32_t pwd_len,
2643
2644 js_arraybuffer_t salt,
2645 uint32_t salt_offset,
2646 uint32_t salt_len,
2647
2648 uint64_t opslimit,
2649 uint64_t memlimit,
2650
2651 js_function_t<void, int> callback
2652) {
2653 int err;
2654
2655 auto *req = new sn_async_pwhash_scryptsalsa208sha256_request(env);
2656
2657 std::span<uint8_t> out_view;
2658 err = js_get_arraybuffer_info(env, out, out_view);
2659 assert(err == 0);
2660 assert(out_offset + out_len <= out_view.size());
2661
2662 req->out = {&out_view[out_offset], out_len};
2663
2664 std::span<char> pwd_view;
2665 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2666 assert(err == 0);
2667 assert(pwd_offset + pwd_len <= pwd_view.size());
2668
2669 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2670
2671 std::span<uint8_t> salt_view;
2672 err = js_get_arraybuffer_info(env, salt, salt_view);
2673 assert(err == 0);
2674 assert(salt_offset + salt_len <= salt_view.size());
2675 assert(salt_len == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
2676
2677 req->salt = {&salt_view[salt_offset], salt_len};
2678
2679 req->opslimit = opslimit;
2680 req->memlimit = memlimit;
2681
2682 err = js_create_reference(env, out, req->out_ref);
2683 assert(err == 0);
2684
2685 err = js_create_reference(env, pwd, req->pwd_ref);
2686 assert(err == 0);
2687
2688 err = js_create_reference(env, salt, req->salt_ref);
2689 assert(err == 0);
2690
2691 err = js_create_reference(env, callback, req->cb);
2692 assert(err == 0);
2693
2694 uv_loop_t *loop;
2695 err = js_get_env_loop(env, &loop);
2696 assert(err == 0);
2697
2698 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_execute, async_pwhash_scryptsalsa208sha256_complete);
2699 assert(err == 0);
2700}
2701
2702struct sn_async_pwhash_scryptsalsa208sha256_str_request : sn_async_task {
2703 js_persistent_t<js_arraybuffer_t> out_ref;
2704 std::span<char> out;
2705
2706 js_persistent_t<js_arraybuffer_t> pwd_ref;
2707 std::span<char> pwd;
2708
2709 uint64_t opslimit;
2710 size_t memlimit;
2711
2712 sn_async_pwhash_scryptsalsa208sha256_str_request(js_env_t *env) : sn_async_task(env) {}
2713};
2714
2715static void
2716async_pwhash_scryptsalsa208sha256_str_execute(uv_work_t *uv_req) {
2717 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
2718
2719 req->code = crypto_pwhash_scryptsalsa208sha256_str(
2720 req->out.data(),
2721 req->pwd.data(),
2722 req->pwd.size(),
2723 req->opslimit,
2724 req->memlimit
2725 );
2726}
2727
2728static void
2729async_pwhash_scryptsalsa208sha256_str_complete(uv_work_t *uv_req, int status) {
2730 int err;
2731
2732 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
2733
2734 if (req->exiting) return delete req;
2735
2736 js_handle_scope_t *scope;
2737 err = js_open_handle_scope(req->env, &scope);
2738 assert(err == 0);
2739
2740 js_function_t<void, int> callback;
2741 err = js_get_reference_value(req->env, req->cb, callback);
2742 assert(err == 0);
2743
2744 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2745 assert(err != js_pending_exception);
2746
2747 err = js_close_handle_scope(req->env, scope);
2748 assert(err == 0);
2749
2750 delete req;
2751}
2752
2753static inline void
2754sn_crypto_pwhash_scryptsalsa208sha256_str_async(
2755 js_env_t *env,
2756 js_receiver_t,
2757
2758 js_arraybuffer_t out,
2759 uint32_t out_offset,
2760 uint32_t out_len,
2761
2762 js_arraybuffer_t pwd,
2763 uint32_t pwd_offset,
2764 uint32_t pwd_len,
2765
2766 uint64_t opslimit,
2767 uint64_t memlimit,
2768
2769 js_function_t<void, int> callback
2770) {
2771 int err;
2772
2773 auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_request(env);
2774
2775 std::span<char> out_view;
2776 err = js_get_arraybuffer_info(env, out, out_view);
2777 assert(err == 0);
2778 assert(out_offset + out_len <= out_view.size());
2779
2780 req->out = {&out_view[out_offset], out_len};
2781
2782 std::span<char> pwd_view;
2783 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2784 assert(err == 0);
2785 assert(pwd_offset + pwd_len <= pwd_view.size());
2786
2787 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2788
2789 req->opslimit = opslimit;
2790 req->memlimit = memlimit;
2791
2792 err = js_create_reference(env, out, req->out_ref);
2793 assert(err == 0);
2794
2795 err = js_create_reference(env, pwd, req->pwd_ref);
2796 assert(err == 0);
2797
2798 err = js_create_reference(env, callback, req->cb);
2799 assert(err == 0);
2800
2801 uv_loop_t *loop;
2802 err = js_get_env_loop(env, &loop);
2803 assert(err == 0);
2804
2805 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_execute, async_pwhash_scryptsalsa208sha256_str_complete);
2806 assert(err == 0);
2807}
2808
2809struct sn_async_pwhash_scryptsalsa208sha256_str_verify_request : sn_async_task {
2810 js_persistent_t<js_arraybuffer_t> str_ref;
2811 std::span<char> str;
2812
2813 js_persistent_t<js_arraybuffer_t> pwd_ref;
2814 std::span<char> pwd;
2815
2816 sn_async_pwhash_scryptsalsa208sha256_str_verify_request(js_env_t *env) : sn_async_task(env) {}
2817};
2818
2819static void
2820async_pwhash_scryptsalsa208sha256_str_verify_execute(uv_work_t *uv_req) {
2821 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
2822
2823 req->code = crypto_pwhash_scryptsalsa208sha256_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
2824}
2825
2826static void
2827async_pwhash_scryptsalsa208sha256_str_verify_complete(uv_work_t *uv_req, int status) {
2828 int err;
2829
2830 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
2831
2832 if (req->exiting) return delete req;
2833
2834 js_handle_scope_t *scope;
2835 err = js_open_handle_scope(req->env, &scope);
2836 assert(err == 0);
2837
2838 js_function_t<void, int> callback;
2839 err = js_get_reference_value(req->env, req->cb, callback);
2840 assert(err == 0);
2841
2842 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2843 assert(err != js_pending_exception);
2844
2845 err = js_close_handle_scope(req->env, scope);
2846 assert(err == 0);
2847
2848 delete req;
2849}
2850
2851static inline void
2852sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async(
2853 js_env_t *env,
2854 js_receiver_t,
2855
2856 js_arraybuffer_t str,
2857 uint32_t str_offset,
2858 uint32_t str_len,
2859
2860 js_arraybuffer_t pwd,
2861 uint32_t pwd_offset,
2862 uint32_t pwd_len,
2863
2864 js_function_t<void, int> callback
2865) {
2866 int err;
2867
2868 auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_verify_request(env);
2869
2870 std::span<char> str_view;
2871 err = js_get_arraybuffer_info(env, str, str_view);
2872 assert(err == 0);
2873 assert(str_offset + str_len <= str_view.size());
2874
2875 req->str = {&str_view[str_offset], str_len};
2876
2877 std::span<char> pwd_view;
2878 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2879 assert(err == 0);
2880 assert(pwd_offset + pwd_len <= pwd_view.size());
2881
2882 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2883
2884 err = js_create_reference(env, str, req->str_ref);
2885 assert(err == 0);
2886
2887 err = js_create_reference(env, pwd, req->pwd_ref);
2888 assert(err == 0);
2889
2890 err = js_create_reference(env, callback, req->cb);
2891 assert(err == 0);
2892
2893 uv_loop_t *loop;
2894 err = js_get_env_loop(env, &loop);
2895 assert(err == 0);
2896
2897 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_verify_execute, async_pwhash_scryptsalsa208sha256_str_verify_complete);
2898 assert(err == 0);
2899}
2900
2901struct sn_crypto_stream_xor_state {
2902 unsigned char n[crypto_stream_NONCEBYTES];
2903 unsigned char k[crypto_stream_KEYBYTES];
2904 unsigned char next_block[64];
2905 int remainder;
2906 uint64_t block_counter;
2907};
2908
2909static inline void
2910sn_crypto_stream_xor_wrap_init(
2911 js_env_t *,
2912 js_receiver_t,
2913 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
2914 js_typedarray_span_t<> n,
2915 js_typedarray_span_t<> k
2916) {
2917 assert(n.size_bytes() == crypto_stream_NONCEBYTES);
2918 assert(k.size_bytes() == crypto_stream_KEYBYTES);
2919
2920 state->remainder = 0;
2921 state->block_counter = 0;
2922 memcpy(state->n, n.data(), crypto_stream_NONCEBYTES);
2923 memcpy(state->k, k.data(), crypto_stream_KEYBYTES);
2924}
2925
2926static inline void
2927sn_crypto_stream_xor_wrap_update(
2928 js_env_t *,
2929 js_receiver_t,
2930 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
2931 js_typedarray_span_t<> c,
2932 js_typedarray_span_t<> m
2933) {
2934 assert(c.size_bytes() == m.size_bytes());
2935
2936 auto next_block = state->next_block;
2937
2938 size_t m_size = m.size_bytes();
2939 auto *c_ptr = c.data();
2940 auto *m_ptr = m.data();
2941
2942 if (state->remainder) {
2943 uint64_t offset = 0;
2944 int rem = state->remainder;
2945
2946 while (rem < 64 && offset < m_size) {
2947 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
2948 ++offset;
2949 ++rem;
2950 }
2951
2952 c_ptr += offset;
2953 m_ptr += offset;
2954 m_size -= offset;
2955 state->remainder = (rem == 64) ? 0 : rem;
2956
2957 if (m_size == 0) return;
2958 }
2959
2960 state->remainder = m_size & 63;
2961 size_t main_len = m_size - state->remainder;
2962
2963 crypto_stream_xsalsa20_xor_ic(c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k);
2964 state->block_counter += main_len / 64;
2965
2966 if (state->remainder) {
2967 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
2968 memcpy(next_block, m_ptr + main_len, state->remainder);
2969
2970 crypto_stream_xsalsa20_xor_ic(
2971 next_block, next_block, 64, state->n, state->block_counter, state->k
2972 );
2973 memcpy(c_ptr + main_len, next_block, state->remainder);
2974
2975 state->block_counter++;
2976 }
2977}
2978
2979static inline void
2980sn_crypto_stream_xor_wrap_final(
2981 js_env_t *,
2982 js_receiver_t,
2983 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state
2984) {
2985 sodium_memzero(state->n, sizeof(state->n));
2986 sodium_memzero(state->k, sizeof(state->k));
2987 sodium_memzero(state->next_block, sizeof(state->next_block));
2988 state->remainder = 0;
2989}
2990
2991struct sn_crypto_stream_chacha20_xor_state {
2992 unsigned char n[crypto_stream_chacha20_NONCEBYTES];
2993 unsigned char k[crypto_stream_chacha20_KEYBYTES];
2994 unsigned char next_block[64];
2995 int remainder;
2996 uint64_t block_counter;
2997};
2998
2999static inline void
3000sn_crypto_stream_chacha20_xor_wrap_init(
3001 js_env_t *,
3002 js_receiver_t,
3003 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
3004 js_typedarray_span_t<> n,
3005 js_typedarray_span_t<> k
3006) {
3007 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
3008 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
3009
3010 state->remainder = 0;
3011 state->block_counter = 0;
3012 memcpy(state->n, n.data(), crypto_stream_chacha20_NONCEBYTES);
3013 memcpy(state->k, k.data(), crypto_stream_chacha20_KEYBYTES);
3014}
3015
3016static inline void
3017sn_crypto_stream_chacha20_xor_wrap_update(
3018 js_env_t *,
3019 js_receiver_t,
3020 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
3021 js_typedarray_span_t<> c,
3022 js_typedarray_span_t<> m
3023) {
3024 assert(c.size_bytes() == m.size_bytes());
3025
3026 auto *next_block = state->next_block;
3027
3028 size_t m_size = m.size_bytes();
3029 auto *c_ptr = c.data();
3030 auto *m_ptr = m.data();
3031
3032 if (state->remainder) {
3033 uint64_t offset = 0;
3034 int rem = state->remainder;
3035
3036 while (rem < 64 && offset < m_size) {
3037 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3038 offset++;
3039 rem++;
3040 }
3041
3042 c_ptr += offset;
3043 m_ptr += offset;
3044 m_size -= offset;
3045 state->remainder = (rem == 64) ? 0 : rem;
3046
3047 if (m_size == 0) return;
3048 }
3049
3050 state->remainder = m_size & 63;
3051 size_t main_len = m_size - state->remainder;
3052
3053 crypto_stream_chacha20_xor_ic(
3054 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3055 );
3056
3057 state->block_counter += main_len / 64;
3058
3059 if (state->remainder) {
3060 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3061 memcpy(next_block, m_ptr + main_len, state->remainder);
3062
3063 crypto_stream_chacha20_xor_ic(
3064 next_block, next_block, 64, state->n, state->block_counter, state->k
3065 );
3066 memcpy(c_ptr + main_len, next_block, state->remainder);
3067
3068 state->block_counter++;
3069 }
3070}
3071
3072static inline void
3073sn_crypto_stream_chacha20_xor_wrap_final(
3074 js_env_t *,
3075 js_receiver_t,
3076 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state
3077) {
3078 sodium_memzero(state->n, sizeof(state->n));
3079 sodium_memzero(state->k, sizeof(state->k));
3080 sodium_memzero(state->next_block, sizeof(state->next_block));
3081 state->remainder = 0;
3082}
3083
3084struct sn_crypto_stream_chacha20_ietf_xor_state {
3085 unsigned char n[crypto_stream_chacha20_ietf_NONCEBYTES];
3086 unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES];
3087 unsigned char next_block[64];
3088 int remainder;
3089 uint64_t block_counter;
3090};
3091
3092static inline void
3093sn_crypto_stream_chacha20_ietf_xor_wrap_init(
3094 js_env_t *,
3095 js_receiver_t,
3096 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
3097 js_typedarray_span_t<> n,
3098 js_typedarray_span_t<> k
3099) {
3100 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
3101 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
3102
3103 state->remainder = 0;
3104 state->block_counter = 0;
3105 memcpy(state->n, n.data(), crypto_stream_chacha20_ietf_NONCEBYTES);
3106 memcpy(state->k, k.data(), crypto_stream_chacha20_ietf_KEYBYTES);
3107}
3108
3109static inline void
3110sn_crypto_stream_chacha20_ietf_xor_wrap_update(
3111 js_env_t *,
3112 js_receiver_t,
3113 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
3114 js_typedarray_span_t<> c,
3115 js_typedarray_span_t<> m
3116) {
3117 assert(c.size_bytes() == m.size_bytes());
3118
3119 auto *next_block = state->next_block;
3120
3121 size_t m_size = m.size_bytes();
3122 auto *c_ptr = c.data();
3123 auto *m_ptr = m.data();
3124
3125 if (state->remainder) {
3126 uint64_t offset = 0;
3127 int rem = state->remainder;
3128
3129 while (rem < 64 && offset < m_size) {
3130 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3131 offset++;
3132 rem++;
3133 }
3134
3135 c_ptr += offset;
3136 m_ptr += offset;
3137 m_size -= offset;
3138 state->remainder = (rem == 64) ? 0 : rem;
3139
3140 if (m_size == 0) return;
3141 }
3142
3143 state->remainder = m_size & 63;
3144 size_t main_len = m_size - state->remainder;
3145
3146 crypto_stream_chacha20_ietf_xor_ic(
3147 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3148 );
3149
3150 state->block_counter += main_len / 64;
3151
3152 if (state->remainder) {
3153 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3154 memcpy(next_block, m_ptr + main_len, state->remainder);
3155
3156 crypto_stream_chacha20_ietf_xor_ic(
3157 next_block, next_block, 64, state->n, state->block_counter, state->k
3158 );
3159 memcpy(c_ptr + main_len, next_block, state->remainder);
3160
3161 state->block_counter++;
3162 }
3163}
3164
3165static inline void
3166sn_crypto_stream_chacha20_ietf_xor_wrap_final(
3167 js_env_t *,
3168 js_receiver_t,
3169 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state
3170) {
3171 sodium_memzero(state->n, sizeof(state->n));
3172 sodium_memzero(state->k, sizeof(state->k));
3173 sodium_memzero(state->next_block, sizeof(state->next_block));
3174 state->remainder = 0;
3175}
3176
3177struct sn_crypto_stream_xchacha20_xor_state {
3178 unsigned char n[crypto_stream_xchacha20_NONCEBYTES];
3179 unsigned char k[crypto_stream_xchacha20_KEYBYTES];
3180 unsigned char next_block[64];
3181 int remainder;
3182 uint64_t block_counter;
3183};
3184
3185static inline void
3186sn_crypto_stream_xchacha20_xor_wrap_init(
3187 js_env_t *,
3188 js_receiver_t,
3189 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
3190 js_typedarray_span_t<> n,
3191 js_typedarray_span_t<> k
3192) {
3193 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
3194 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
3195
3196 state->remainder = 0;
3197 state->block_counter = 0;
3198 memcpy(state->n, n.data(), crypto_stream_xchacha20_NONCEBYTES);
3199 memcpy(state->k, k.data(), crypto_stream_xchacha20_KEYBYTES);
3200}
3201
3202static inline void
3203sn_crypto_stream_xchacha20_xor_wrap_update(
3204 js_env_t *,
3205 js_receiver_t,
3206 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
3207 js_typedarray_span_t<> c,
3208 js_typedarray_span_t<> m
3209) {
3210 assert(c.size_bytes() == m.size_bytes());
3211
3212 auto *next_block = state->next_block;
3213
3214 size_t m_size = m.size_bytes();
3215 auto *c_ptr = c.data();
3216 auto *m_ptr = m.data();
3217
3218 if (state->remainder) {
3219 uint64_t offset = 0;
3220 int rem = state->remainder;
3221
3222 while (rem < 64 && offset < m_size) {
3223 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3224 ++offset;
3225 ++rem;
3226 }
3227
3228 c_ptr += offset;
3229 m_ptr += offset;
3230 m_size -= offset;
3231 state->remainder = (rem == 64) ? 0 : rem;
3232
3233 if (m_size == 0) return;
3234 }
3235
3236 state->remainder = m_size & 63;
3237 size_t main_len = m_size - state->remainder;
3238
3239 crypto_stream_xchacha20_xor_ic(
3240 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3241 );
3242
3243 state->block_counter += main_len / 64;
3244
3245 if (state->remainder) {
3246 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3247 memcpy(next_block, m_ptr + main_len, state->remainder);
3248
3249 crypto_stream_xchacha20_xor_ic(
3250 next_block, next_block, 64, state->n, state->block_counter, state->k
3251 );
3252 memcpy(c_ptr + main_len, next_block, state->remainder);
3253
3254 state->block_counter++;
3255 }
3256}
3257
3258static inline void
3259sn_crypto_stream_xchacha20_xor_wrap_final(
3260 js_env_t *,
3261 js_receiver_t,
3262 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state
3263) {
3264 sodium_memzero(state->n, sizeof(state->n));
3265 sodium_memzero(state->k, sizeof(state->k));
3266 sodium_memzero(state->next_block, sizeof(state->next_block));
3267 state->remainder = 0;
3268}
3269
3270struct sn_crypto_stream_salsa20_xor_state {
3271 unsigned char n[crypto_stream_salsa20_NONCEBYTES];
3272 unsigned char k[crypto_stream_salsa20_KEYBYTES];
3273 unsigned char next_block[64];
3274 int remainder;
3275 uint64_t block_counter;
3276};
3277
3278static inline void
3279sn_crypto_stream_salsa20_xor_wrap_init(
3280 js_env_t *,
3281 js_receiver_t,
3282 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
3283 js_typedarray_span_t<> n,
3284 js_typedarray_span_t<> k
3285) {
3286 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
3287 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
3288
3289 state->remainder = 0;
3290 state->block_counter = 0;
3291 memcpy(state->n, n.data(), crypto_stream_salsa20_NONCEBYTES);
3292 memcpy(state->k, k.data(), crypto_stream_salsa20_KEYBYTES);
3293}
3294
3295static inline void
3296sn_crypto_stream_salsa20_xor_wrap_update(
3297 js_env_t *,
3298 js_receiver_t,
3299 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
3300 js_typedarray_span_t<> c,
3301 js_typedarray_span_t<> m
3302) {
3303 assert(c.size_bytes() == m.size_bytes());
3304
3305 auto *next_block = state->next_block;
3306
3307 size_t m_size = m.size_bytes();
3308 auto *c_ptr = c.data();
3309 auto *m_ptr = m.data();
3310
3311 if (state->remainder) {
3312 uint64_t offset = 0;
3313 int rem = state->remainder;
3314
3315 while (rem < 64 && offset < m_size) {
3316 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3317 ++offset;
3318 ++rem;
3319 }
3320
3321 c_ptr += offset;
3322 m_ptr += offset;
3323 m_size -= offset;
3324 state->remainder = (rem == 64) ? 0 : rem;
3325
3326 if (m_size == 0) return;
3327 }
3328
3329 state->remainder = m_size & 63;
3330 size_t main_len = m_size - state->remainder;
3331
3332 crypto_stream_salsa20_xor_ic(
3333 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3334 );
3335
3336 state->block_counter += main_len / 64;
3337
3338 if (state->remainder) {
3339 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3340 memcpy(next_block, m_ptr + main_len, state->remainder);
3341
3342 crypto_stream_salsa20_xor_ic(
3343 next_block, next_block, 64, state->n, state->block_counter, state->k
3344 );
3345 memcpy(c_ptr + main_len, next_block, state->remainder);
3346
3347 state->block_counter++;
3348 }
3349}
3350
3351static inline void
3352sn_crypto_stream_salsa20_xor_wrap_final(
3353 js_env_t *,
3354 js_receiver_t,
3355 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state
3356) {
3357 sodium_memzero(state->n, sizeof(state->n));
3358 sodium_memzero(state->k, sizeof(state->k));
3359 sodium_memzero(state->next_block, sizeof(state->next_block));
3360 state->remainder = 0;
3361}
3362
3363// Experimental API
3364
3365static inline void
3366sn_extension_tweak_ed25519_base(
3367 js_env_t *,
3368 js_receiver_t,
3369 js_typedarray_span_t<> n,
3370 js_typedarray_span_t<> p,
3371 js_typedarray_span_t<> ns
3372) {
3373 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3374 assert(p.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3375
3376 sn__extension_tweak_ed25519_base(p.data(), n.data(), ns.data(), ns.size_bytes());
3377}
3378
3379static inline int
3380sn_extension_tweak_ed25519_sign_detached(
3381 js_env_t *,
3382 js_receiver_t,
3383 js_typedarray_span_t<> sig,
3384 js_typedarray_span_t<> m,
3385 js_typedarray_span_t<> scalar,
3386 std::optional<js_typedarray_span_t<>> pk
3387) {
3388 assert(sig.size_bytes() == crypto_sign_BYTES);
3389 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3390
3391 uint8_t *pk_data = nullptr;
3392 if (pk) {
3393 assert(pk->size_bytes() == crypto_sign_PUBLICKEYBYTES);
3394 pk_data = pk->data();
3395 }
3396
3397 return sn__extension_tweak_ed25519_sign_detached(
3398 sig.data(),
3399 nullptr,
3400 m.data(),
3401 m.size_bytes(),
3402 scalar.data(),
3403 pk_data
3404 );
3405}
3406
3407static inline void
3408sn_extension_tweak_ed25519_sk_to_scalar(
3409 js_env_t *,
3410 js_receiver_t,
3411 js_typedarray_span_t<> n,
3412 js_typedarray_span_t<> sk
3413) {
3414 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3415 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
3416
3417 sn__extension_tweak_ed25519_sk_to_scalar(n.data(), sk.data());
3418}
3419
3420static inline void
3421sn_extension_tweak_ed25519_scalar(
3422 js_env_t *,
3423 js_receiver_t,
3424 js_typedarray_span_t<> scalar_out,
3425 js_typedarray_span_t<> scalar,
3426 js_typedarray_span_t<> ns
3427) {
3428 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3429 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3430
3431 sn__extension_tweak_ed25519_scalar(scalar_out.data(), scalar.data(), ns.data(), ns.size_bytes());
3432}
3433
3434static inline int
3435sn_extension_tweak_ed25519_pk(
3436 js_env_t *,
3437 js_receiver_t,
3438 js_typedarray_span_t<> tpk,
3439 js_typedarray_span_t<> pk,
3440 js_typedarray_span_t<> ns
3441) {
3442 assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3443 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3444
3445 return sn__extension_tweak_ed25519_pk(tpk.data(), pk.data(), ns.data(), ns.size_bytes());
3446}
3447
3448static inline void
3449sn_extension_tweak_ed25519_keypair(
3450 js_env_t *,
3451 js_receiver_t,
3452 js_typedarray_span_t<> pk,
3453 js_typedarray_span_t<> scalar_out,
3454 js_typedarray_span_t<> scalar_in,
3455 js_typedarray_span_t<> ns
3456) {
3457 assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3458 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3459 assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3460
3461 sn__extension_tweak_ed25519_keypair(
3462 pk.data(),
3463 scalar_out.data(),
3464 scalar_in.data(),
3465 ns.data(),
3466 ns.size_bytes()
3467 );
3468}
3469
3470static inline void
3471sn_extension_tweak_ed25519_scalar_add(
3472 js_env_t *,
3473 js_receiver_t,
3474 js_typedarray_span_t<> scalar_out,
3475 js_typedarray_span_t<> scalar,
3476 js_typedarray_span_t<> n
3477) {
3478 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3479 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3480 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3481
3482 sn__extension_tweak_ed25519_scalar_add(scalar_out.data(), scalar.data(), n.data());
3483}
3484
3485static inline int
3486sn_extension_tweak_ed25519_pk_add(
3487 js_env_t *,
3488 js_receiver_t,
3489 js_typedarray_span_t<> tpk,
3490 js_typedarray_span_t<> pk,
3491 js_typedarray_span_t<> p
3492) {
3493 assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3494 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3495 assert(p.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3496
3497 return sn__extension_tweak_ed25519_pk_add(tpk.data(), pk.data(), p.data());
3498}
3499
3500static inline int
3501sn_extension_tweak_ed25519_keypair_add(
3502 js_env_t *,
3503 js_receiver_t,
3504 js_typedarray_span_t<> pk,
3505 js_typedarray_span_t<> scalar_out,
3506 js_typedarray_span_t<> scalar_in,
3507 js_typedarray_span_t<> tweak
3508) {
3509 assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3510 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3511 assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3512 assert(tweak.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3513
3514 return sn__extension_tweak_ed25519_keypair_add(
3515 pk.data(),
3516 scalar_out.data(),
3517 scalar_in.data(),
3518 tweak.data()
3519 );
3520}
3521
3522static inline int
3523sn_extension_pbkdf2_sha512(
3524 js_env_t *,
3525 js_receiver_t,
3526 js_typedarray_span_t<> out,
3527 js_typedarray_span_t<> passwd,
3528 js_typedarray_span_t<> salt,
3529 uint64_t iter,
3530 uint64_t outlen
3531) {
3532
3533 assert(iter >= sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
3534 assert(outlen <= sn__extension_pbkdf2_sha512_BYTES_MAX);
3535 assert(out.size_bytes() >= static_cast<size_t>(outlen));
3536
3537 return sn__extension_pbkdf2_sha512(
3538 passwd.data(),
3539 passwd.size_bytes(),
3540 salt.data(),
3541 salt.size_bytes(),
3542 iter,
3543 out.data(),
3544 outlen
3545 );
3546}
3547
3548struct sn_async_pbkdf2_sha512_request : sn_async_task {
3549 js_persistent_t<js_arraybuffer_t> out_ref;
3550 std::span<uint8_t> out;
3551
3552 size_t outlen;
3553
3554 js_persistent_t<js_arraybuffer_t> pwd_ref;
3555 std::span<uint8_t> pwd;
3556
3557 js_persistent_t<js_arraybuffer_t> salt_ref;
3558 std::span<uint8_t> salt;
3559
3560 uint64_t iter;
3561
3562 sn_async_pbkdf2_sha512_request(js_env_t *env) : sn_async_task(env) {}
3563};
3564
3565static void
3566async_pbkdf2_sha512_execute(uv_work_t *uv_req) {
3567 auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
3568
3569 req->code = sn__extension_pbkdf2_sha512(
3570 req->pwd.data(),
3571 req->pwd.size(),
3572 req->salt.data(),
3573 req->salt.size(),
3574 req->iter,
3575 req->out.data(),
3576 req->outlen
3577 );
3578}
3579
3580static void
3581async_pbkdf2_sha512_complete(uv_work_t *uv_req, int status) {
3582 int err;
3583
3584 auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
3585
3586 if (req->exiting) return delete req;
3587
3588 js_handle_scope_t *scope;
3589 err = js_open_handle_scope(req->env, &scope);
3590 assert(err == 0);
3591
3592 js_function_t<void, int> callback;
3593 err = js_get_reference_value(req->env, req->cb, callback);
3594 assert(err == 0);
3595
3596 err = js_call_function_with_checkpoint(req->env, callback, req->code);
3597 assert(err != js_pending_exception);
3598
3599 err = js_close_handle_scope(req->env, scope);
3600 assert(err == 0);
3601
3602 delete req;
3603}
3604
3605static inline void
3606sn_extension_pbkdf2_sha512_async(
3607 js_env_t *env,
3608 js_receiver_t,
3609
3610 js_arraybuffer_t out,
3611 uint32_t out_offset,
3612 uint32_t out_len,
3613
3614 js_arraybuffer_t pwd,
3615 uint32_t pwd_offset,
3616 uint32_t pwd_len,
3617
3618 js_arraybuffer_t salt,
3619 uint32_t salt_offset,
3620 uint32_t salt_len,
3621
3622 uint64_t iter,
3623 uint64_t outlen,
3624
3625 js_function_t<void, int> callback
3626) {
3627 int err;
3628
3629 auto *req = new sn_async_pbkdf2_sha512_request(env);
3630
3631 std::span<uint8_t> out_view;
3632 err = js_get_arraybuffer_info(env, out, out_view);
3633 assert(err == 0);
3634 assert(out_offset + out_len <= out_view.size());
3635
3636 req->out = {&out_view[out_offset], out_len};
3637
3638 std::span<uint8_t> pwd_view;
3639 err = js_get_arraybuffer_info(env, pwd, pwd_view);
3640 assert(err == 0);
3641 assert(pwd_offset + pwd_len <= pwd_view.size());
3642
3643 req->pwd = {&pwd_view[pwd_offset], pwd_len};
3644
3645 std::span<uint8_t> salt_view;
3646 err = js_get_arraybuffer_info(env, salt, salt_view);
3647 assert(err == 0);
3648 assert(salt_offset + salt_len <= salt_view.size());
3649
3650 req->salt = {&salt_view[salt_offset], salt_len};
3651
3652 req->iter = iter;
3653 req->outlen = outlen;
3654
3655 err = js_create_reference(env, out, req->out_ref);
3656 assert(err == 0);
3657
3658 err = js_create_reference(env, pwd, req->pwd_ref);
3659 assert(err == 0);
3660
3661 err = js_create_reference(env, salt, req->salt_ref);
3662 assert(err == 0);
3663
3664 err = js_create_reference(env, callback, req->cb);
3665 assert(err == 0);
3666
3667 uv_loop_t *loop;
3668 err = js_get_env_loop(env, &loop);
3669 assert(err == 0);
3670
3671 err = uv_queue_work(loop, &req->task, async_pbkdf2_sha512_execute, async_pbkdf2_sha512_complete);
3672 assert(err == 0);
3673}
3674
3675static js_value_t *
3676sodium_native_exports(js_env_t *env, js_value_t *exports) {
3677 int err;
3678
3679 err = sodium_init();
3680 assert(err >= 0);
3681
3682#define V_FUNCTION(name, fn) \
3683 err = js_set_property<fn>(env, exports, name); \
3684 assert(err == 0);
3685
3686#define V_FUNCTION_NOSCOPE(name, fn) \
3687 err = js_set_property<fn, js_function_options_t{.scoped = false}>(env, exports, name); \
3688 assert(err == 0);
3689
3690#define V_UINT32(name, constant) \
3691 err = js_set_property(env, exports, name, static_cast<uint32_t>(constant)); \
3692 assert(err == 0);
3693
3694#define V_UINT64(name, constant) \
3695 err = js_set_property(env, exports, name, static_cast<int64_t>(std::min<uint64_t>(constant, js_max_safe_integer))); \
3696 assert(err == 0);
3697
3698#define V_STRING(name, str) \
3699 err = js_set_property(env, exports, name, str); \
3700 assert(err == 0);
3701
3702 // memory
3703
3704 V_FUNCTION("sodium_memzero", sn_sodium_memzero);
3705 V_FUNCTION("sodium_mlock", sn_sodium_mlock);
3706 V_FUNCTION("sodium_munlock", sn_sodium_munlock);
3707 V_FUNCTION("sodium_malloc", sn_sodium_malloc);
3708 V_FUNCTION("sodium_free", sn_sodium_free);
3709 V_FUNCTION("sodium_mprotect_noaccess", sn_sodium_mprotect_noaccess);
3710 V_FUNCTION("sodium_mprotect_readonly", sn_sodium_mprotect_readonly);
3711 V_FUNCTION("sodium_mprotect_readwrite", sn_sodium_mprotect_readwrite);
3712
3713 // randombytes
3714
3715 V_FUNCTION_NOSCOPE("randombytes_buf", sn_randombytes_buf);
3716 V_FUNCTION_NOSCOPE("randombytes_buf_deterministic", sn_randombytes_buf_deterministic);
3717 V_FUNCTION_NOSCOPE("randombytes_random", sn_randombytes_random);
3718 V_FUNCTION_NOSCOPE("randombytes_uniform", sn_randombytes_uniform);
3719
3720 V_UINT32("randombytes_SEEDBYTES", randombytes_SEEDBYTES);
3721
3722 // sodium helpers
3723
3724 V_FUNCTION("sodium_memcmp", sn_sodium_memcmp);
3725 V_FUNCTION("sodium_increment", sn_sodium_increment);
3726 V_FUNCTION("sodium_add", sn_sodium_add);
3727 V_FUNCTION("sodium_sub", sn_sodium_sub);
3728 V_FUNCTION("sodium_compare", sn_sodium_compare);
3729 V_FUNCTION("sodium_is_zero", sn_sodium_is_zero);
3730 V_FUNCTION("sodium_pad", sn_sodium_pad);
3731 V_FUNCTION("sodium_unpad", sn_sodium_unpad);
3732
3733 // crypto_aead
3734
3735 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_keygen", sn_crypto_aead_xchacha20poly1305_ietf_keygen);
3736 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt", sn_crypto_aead_xchacha20poly1305_ietf_encrypt);
3737 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt", sn_crypto_aead_xchacha20poly1305_ietf_decrypt);
3738 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached);
3739 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached);
3740 V_UINT32("crypto_aead_xchacha20poly1305_ietf_ABYTES", crypto_aead_xchacha20poly1305_ietf_ABYTES);
3741 V_UINT32("crypto_aead_xchacha20poly1305_ietf_KEYBYTES", crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
3742 V_UINT32("crypto_aead_xchacha20poly1305_ietf_NPUBBYTES", crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
3743 V_UINT32("crypto_aead_xchacha20poly1305_ietf_NSECBYTES", crypto_aead_xchacha20poly1305_ietf_NSECBYTES);
3744 V_UINT64("crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX);
3745
3746 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_keygen", sn_crypto_aead_chacha20poly1305_ietf_keygen);
3747 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt", sn_crypto_aead_chacha20poly1305_ietf_encrypt);
3748 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt", sn_crypto_aead_chacha20poly1305_ietf_decrypt);
3749 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached);
3750 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached);
3751 V_UINT32("crypto_aead_chacha20poly1305_ietf_ABYTES", crypto_aead_chacha20poly1305_ietf_ABYTES);
3752 V_UINT32("crypto_aead_chacha20poly1305_ietf_KEYBYTES", crypto_aead_chacha20poly1305_ietf_KEYBYTES);
3753 V_UINT32("crypto_aead_chacha20poly1305_ietf_NPUBBYTES", crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
3754 V_UINT32("crypto_aead_chacha20poly1305_ietf_NSECBYTES", crypto_aead_chacha20poly1305_ietf_NSECBYTES);
3755 V_UINT64("crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
3756
3757 // crypto_auth
3758
3759 V_FUNCTION("crypto_auth", sn_crypto_auth);
3760 V_FUNCTION("crypto_auth_verify", sn_crypto_auth_verify);
3761 V_UINT32("crypto_auth_BYTES", crypto_auth_BYTES);
3762 V_UINT32("crypto_auth_KEYBYTES", crypto_auth_KEYBYTES);
3763 V_STRING("crypto_auth_PRIMITIVE", crypto_auth_PRIMITIVE);
3764
3765 // crypto_box
3766
3767 V_FUNCTION("crypto_box_keypair", sn_crypto_box_keypair);
3768 V_FUNCTION("crypto_box_seed_keypair", sn_crypto_box_seed_keypair);
3769 V_FUNCTION("crypto_box_easy", sn_crypto_box_easy);
3770 V_FUNCTION("crypto_box_open_easy", sn_crypto_box_open_easy);
3771 V_FUNCTION("crypto_box_detached", sn_crypto_box_detached);
3772 V_FUNCTION("crypto_box_open_detached", sn_crypto_box_open_detached);
3773 V_FUNCTION("crypto_box_seal", sn_crypto_box_seal);
3774 V_FUNCTION_NOSCOPE("crypto_box_seal_open", sn_crypto_box_seal_open);
3775
3776 V_UINT32("crypto_box_SEEDBYTES", crypto_box_SEEDBYTES);
3777 V_UINT32("crypto_box_PUBLICKEYBYTES", crypto_box_PUBLICKEYBYTES);
3778 V_UINT32("crypto_box_SECRETKEYBYTES", crypto_box_SECRETKEYBYTES);
3779 V_UINT32("crypto_box_NONCEBYTES", crypto_box_NONCEBYTES);
3780 V_UINT32("crypto_box_MACBYTES", crypto_box_MACBYTES);
3781 V_UINT32("crypto_box_SEALBYTES", crypto_box_SEALBYTES);
3782 V_STRING("crypto_box_PRIMITIVE", crypto_box_PRIMITIVE);
3783
3784 // crypto_core
3785
3786 V_FUNCTION("crypto_core_ed25519_is_valid_point", sn_crypto_core_ed25519_is_valid_point);
3787 V_FUNCTION("crypto_core_ed25519_from_uniform", sn_crypto_core_ed25519_from_uniform);
3788 V_FUNCTION("crypto_core_ed25519_add", sn_crypto_core_ed25519_add);
3789 V_FUNCTION("crypto_core_ed25519_sub", sn_crypto_core_ed25519_sub);
3790 V_FUNCTION("crypto_core_ed25519_scalar_random", sn_crypto_core_ed25519_scalar_random);
3791 V_FUNCTION("crypto_core_ed25519_scalar_reduce", sn_crypto_core_ed25519_scalar_reduce);
3792 V_FUNCTION("crypto_core_ed25519_scalar_invert", sn_crypto_core_ed25519_scalar_invert);
3793 V_FUNCTION("crypto_core_ed25519_scalar_negate", sn_crypto_core_ed25519_scalar_negate);
3794 V_FUNCTION("crypto_core_ed25519_scalar_complement", sn_crypto_core_ed25519_scalar_complement);
3795 V_FUNCTION("crypto_core_ed25519_scalar_add", sn_crypto_core_ed25519_scalar_add);
3796 V_FUNCTION("crypto_core_ed25519_scalar_sub", sn_crypto_core_ed25519_scalar_sub);
3797 V_UINT32("crypto_core_ed25519_BYTES", crypto_core_ed25519_BYTES);
3798 V_UINT32("crypto_core_ed25519_UNIFORMBYTES", crypto_core_ed25519_UNIFORMBYTES);
3799 V_UINT32("crypto_core_ed25519_SCALARBYTES", crypto_core_ed25519_SCALARBYTES);
3800 V_UINT32("crypto_core_ed25519_NONREDUCEDSCALARBYTES", crypto_core_ed25519_NONREDUCEDSCALARBYTES);
3801
3802 // crypto_kdf
3803
3804 V_FUNCTION("crypto_kdf_keygen", sn_crypto_kdf_keygen);
3805 V_FUNCTION("crypto_kdf_derive_from_key", sn_crypto_kdf_derive_from_key);
3806 V_UINT32("crypto_kdf_BYTES_MIN", crypto_kdf_BYTES_MIN);
3807 V_UINT32("crypto_kdf_BYTES_MAX", crypto_kdf_BYTES_MAX);
3808 V_UINT32("crypto_kdf_CONTEXTBYTES", crypto_kdf_CONTEXTBYTES);
3809 V_UINT32("crypto_kdf_KEYBYTES", crypto_kdf_KEYBYTES);
3810 V_STRING("crypto_kdf_PRIMITIVE", crypto_kdf_PRIMITIVE);
3811
3812 // crypto_kx
3813
3814 V_FUNCTION("crypto_kx_keypair", sn_crypto_kx_keypair);
3815 V_FUNCTION("crypto_kx_seed_keypair", sn_crypto_kx_seed_keypair);
3816 V_FUNCTION("crypto_kx_client_session_keys", sn_crypto_kx_client_session_keys);
3817 V_FUNCTION("crypto_kx_server_session_keys", sn_crypto_kx_server_session_keys);
3818 V_UINT32("crypto_kx_PUBLICKEYBYTES", crypto_kx_PUBLICKEYBYTES);
3819 V_UINT32("crypto_kx_SECRETKEYBYTES", crypto_kx_SECRETKEYBYTES);
3820 V_UINT32("crypto_kx_SEEDBYTES", crypto_kx_SEEDBYTES);
3821 V_UINT32("crypto_kx_SESSIONKEYBYTES", crypto_kx_SESSIONKEYBYTES);
3822 V_STRING("crypto_kx_PRIMITIVE", crypto_kx_PRIMITIVE);
3823
3824 // crypto_generichash
3825
3826 V_FUNCTION_NOSCOPE("crypto_generichash", sn_crypto_generichash);
3827 V_FUNCTION("crypto_generichash_batch", sn_crypto_generichash_batch);
3828 V_FUNCTION_NOSCOPE("crypto_generichash_keygen", sn_crypto_generichash_keygen);
3829 V_FUNCTION_NOSCOPE("crypto_generichash_init", sn_crypto_generichash_init);
3830 V_FUNCTION_NOSCOPE("crypto_generichash_update", sn_crypto_generichash_update);
3831 V_FUNCTION_NOSCOPE("crypto_generichash_final", sn_crypto_generichash_final);
3832
3833 V_UINT32("crypto_generichash_STATEBYTES", sizeof(crypto_generichash_state));
3834 V_STRING("crypto_generichash_PRIMITIVE", crypto_generichash_PRIMITIVE);
3835 V_UINT32("crypto_generichash_BYTES_MIN", crypto_generichash_BYTES_MIN);
3836 V_UINT32("crypto_generichash_BYTES_MAX", crypto_generichash_BYTES_MAX);
3837 V_UINT32("crypto_generichash_BYTES", crypto_generichash_BYTES);
3838 V_UINT32("crypto_generichash_KEYBYTES_MIN", crypto_generichash_KEYBYTES_MIN);
3839 V_UINT32("crypto_generichash_KEYBYTES_MAX", crypto_generichash_KEYBYTES_MAX);
3840 V_UINT32("crypto_generichash_KEYBYTES", crypto_generichash_KEYBYTES);
3841
3842 // crypto_hash
3843
3844 V_FUNCTION("crypto_hash", sn_crypto_hash);
3845 V_UINT32("crypto_hash_BYTES", crypto_hash_BYTES);
3846 V_STRING("crypto_hash_PRIMITIVE", crypto_hash_PRIMITIVE);
3847
3848 V_FUNCTION("crypto_hash_sha256", sn_crypto_hash_sha256);
3849 V_FUNCTION("crypto_hash_sha256_init", sn_crypto_hash_sha256_init);
3850 V_FUNCTION("crypto_hash_sha256_update", sn_crypto_hash_sha256_update);
3851 V_FUNCTION("crypto_hash_sha256_final", sn_crypto_hash_sha256_final);
3852 V_UINT32("crypto_hash_sha256_STATEBYTES", sizeof(crypto_hash_sha256_state));
3853 V_UINT32("crypto_hash_sha256_BYTES", crypto_hash_sha256_BYTES);
3854
3855 V_FUNCTION("crypto_hash_sha512", sn_crypto_hash_sha512);
3856 V_FUNCTION("crypto_hash_sha512_init", sn_crypto_hash_sha512_init);
3857 V_FUNCTION("crypto_hash_sha512_update", sn_crypto_hash_sha512_update);
3858 V_FUNCTION("crypto_hash_sha512_final", sn_crypto_hash_sha512_final);
3859 V_UINT32("crypto_hash_sha512_STATEBYTES", sizeof(crypto_hash_sha512_state));
3860 V_UINT32("crypto_hash_sha512_BYTES", crypto_hash_sha512_BYTES);
3861
3862 // crypto_onetimeauth
3863
3864 V_FUNCTION("crypto_onetimeauth", sn_crypto_onetimeauth);
3865 V_FUNCTION("crypto_onetimeauth_verify", sn_crypto_onetimeauth_verify);
3866 V_FUNCTION("crypto_onetimeauth_init", sn_crypto_onetimeauth_init);
3867 V_FUNCTION("crypto_onetimeauth_update", sn_crypto_onetimeauth_update);
3868 V_FUNCTION("crypto_onetimeauth_final", sn_crypto_onetimeauth_final);
3869 V_UINT32("crypto_onetimeauth_STATEBYTES", sizeof(crypto_onetimeauth_state));
3870 V_UINT32("crypto_onetimeauth_BYTES", crypto_onetimeauth_BYTES);
3871 V_UINT32("crypto_onetimeauth_KEYBYTES", crypto_onetimeauth_KEYBYTES);
3872 V_STRING("crypto_onetimeauth_PRIMITIVE", crypto_onetimeauth_PRIMITIVE);
3873
3874 // crypto_pwhash
3875
3876 V_FUNCTION("crypto_pwhash", sn_crypto_pwhash);
3877 V_FUNCTION("crypto_pwhash_str", sn_crypto_pwhash_str);
3878 V_FUNCTION("crypto_pwhash_str_verify", sn_crypto_pwhash_str_verify);
3879 V_FUNCTION("crypto_pwhash_str_needs_rehash", sn_crypto_pwhash_str_needs_rehash);
3880 V_FUNCTION("crypto_pwhash_async", sn_crypto_pwhash_async);
3881 V_FUNCTION("crypto_pwhash_str_async", sn_crypto_pwhash_str_async);
3882 V_FUNCTION("crypto_pwhash_str_verify_async", sn_crypto_pwhash_str_verify_async);
3883 V_UINT32("crypto_pwhash_ALG_ARGON2I13", crypto_pwhash_ALG_ARGON2I13);
3884 V_UINT32("crypto_pwhash_ALG_ARGON2ID13", crypto_pwhash_ALG_ARGON2ID13);
3885 V_UINT32("crypto_pwhash_ALG_DEFAULT", crypto_pwhash_ALG_DEFAULT);
3886 V_UINT32("crypto_pwhash_BYTES_MIN", crypto_pwhash_BYTES_MIN);
3887 V_UINT32("crypto_pwhash_BYTES_MAX", crypto_pwhash_BYTES_MAX);
3888 V_UINT32("crypto_pwhash_PASSWD_MIN", crypto_pwhash_PASSWD_MIN);
3889 V_UINT32("crypto_pwhash_PASSWD_MAX", crypto_pwhash_PASSWD_MAX);
3890 V_UINT32("crypto_pwhash_SALTBYTES", crypto_pwhash_SALTBYTES);
3891 V_UINT32("crypto_pwhash_STRBYTES", crypto_pwhash_STRBYTES);
3892 V_STRING("crypto_pwhash_STRPREFIX", crypto_pwhash_STRPREFIX);
3893 V_UINT32("crypto_pwhash_OPSLIMIT_MIN", crypto_pwhash_OPSLIMIT_MIN);
3894 V_UINT32("crypto_pwhash_OPSLIMIT_MAX", crypto_pwhash_OPSLIMIT_MAX);
3895 V_UINT64("crypto_pwhash_MEMLIMIT_MIN", crypto_pwhash_MEMLIMIT_MIN);
3896 V_UINT64("crypto_pwhash_MEMLIMIT_MAX", crypto_pwhash_MEMLIMIT_MAX);
3897 V_UINT32("crypto_pwhash_OPSLIMIT_INTERACTIVE", crypto_pwhash_OPSLIMIT_INTERACTIVE);
3898 V_UINT64("crypto_pwhash_MEMLIMIT_INTERACTIVE", crypto_pwhash_MEMLIMIT_INTERACTIVE);
3899 V_UINT32("crypto_pwhash_OPSLIMIT_MODERATE", crypto_pwhash_OPSLIMIT_MODERATE);
3900 V_UINT64("crypto_pwhash_MEMLIMIT_MODERATE", crypto_pwhash_MEMLIMIT_MODERATE);
3901 V_UINT32("crypto_pwhash_OPSLIMIT_SENSITIVE", crypto_pwhash_OPSLIMIT_SENSITIVE);
3902 V_UINT64("crypto_pwhash_MEMLIMIT_SENSITIVE", crypto_pwhash_MEMLIMIT_SENSITIVE);
3903 V_STRING("crypto_pwhash_PRIMITIVE", crypto_pwhash_PRIMITIVE);
3904
3905 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256", sn_crypto_pwhash_scryptsalsa208sha256);
3906 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str", sn_crypto_pwhash_scryptsalsa208sha256_str);
3907 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify", sn_crypto_pwhash_scryptsalsa208sha256_str_verify);
3908 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_needs_rehash", sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash);
3909 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_async", sn_crypto_pwhash_scryptsalsa208sha256_async);
3910 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_async", sn_crypto_pwhash_scryptsalsa208sha256_str_async)
3911 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify_async", sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async);
3912 V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MIN", crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
3913 V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MAX", crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
3914 V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN", crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN);
3915 V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX", crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX);
3916 V_UINT64("crypto_pwhash_scryptsalsa208sha256_SALTBYTES", crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
3917 V_UINT64("crypto_pwhash_scryptsalsa208sha256_STRBYTES", crypto_pwhash_scryptsalsa208sha256_STRBYTES);
3918 V_STRING("crypto_pwhash_scryptsalsa208sha256_STRPREFIX", crypto_pwhash_scryptsalsa208sha256_STRPREFIX);
3919 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
3920 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
3921 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
3922 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
3923 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
3924 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
3925 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE);
3926 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE);
3927
3928 // crypto_scalarmult
3929
3930 V_FUNCTION("crypto_scalarmult_base", sn_crypto_scalarmult_base);
3931 V_FUNCTION("crypto_scalarmult", sn_crypto_scalarmult);
3932 V_STRING("crypto_scalarmult_PRIMITIVE", crypto_scalarmult_PRIMITIVE);
3933 V_UINT32("crypto_scalarmult_BYTES", crypto_scalarmult_BYTES);
3934 V_UINT32("crypto_scalarmult_SCALARBYTES", crypto_scalarmult_SCALARBYTES);
3935
3936 V_FUNCTION("crypto_scalarmult_ed25519_base", sn_crypto_scalarmult_ed25519_base);
3937 V_FUNCTION("crypto_scalarmult_ed25519", sn_crypto_scalarmult_ed25519);
3938 V_FUNCTION("crypto_scalarmult_ed25519_base_noclamp", sn_crypto_scalarmult_ed25519_base_noclamp);
3939 V_FUNCTION("crypto_scalarmult_ed25519_noclamp", sn_crypto_scalarmult_ed25519_noclamp);
3940 V_UINT32("crypto_scalarmult_ed25519_BYTES", crypto_scalarmult_ed25519_BYTES);
3941 V_UINT32("crypto_scalarmult_ed25519_SCALARBYTES", crypto_scalarmult_ed25519_SCALARBYTES);
3942
3943 // crypto_secretbox
3944
3945 V_FUNCTION("crypto_secretbox_easy", sn_crypto_secretbox_easy);
3946 V_FUNCTION("crypto_secretbox_open_easy", sn_crypto_secretbox_open_easy);
3947 V_FUNCTION("crypto_secretbox_detached", sn_crypto_secretbox_detached);
3948 V_FUNCTION("crypto_secretbox_open_detached", sn_crypto_secretbox_open_detached);
3949 V_UINT32("crypto_secretbox_KEYBYTES", crypto_secretbox_KEYBYTES);
3950 V_UINT32("crypto_secretbox_NONCEBYTES", crypto_secretbox_NONCEBYTES);
3951 V_UINT32("crypto_secretbox_MACBYTES", crypto_secretbox_MACBYTES);
3952 V_STRING("crypto_secretbox_PRIMITIVE", crypto_secretbox_PRIMITIVE);
3953
3954 // crypto_secretstream
3955
3956 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_keygen", sn_crypto_secretstream_xchacha20poly1305_keygen);
3957 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_push", sn_crypto_secretstream_xchacha20poly1305_init_push);
3958 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_pull", sn_crypto_secretstream_xchacha20poly1305_init_pull);
3959 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_push", sn_crypto_secretstream_xchacha20poly1305_push);
3960 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_pull", sn_crypto_secretstream_xchacha20poly1305_pull);
3961 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_rekey", sn_crypto_secretstream_xchacha20poly1305_rekey);
3962
3963 V_UINT32("crypto_secretstream_xchacha20poly1305_STATEBYTES", sizeof(crypto_secretstream_xchacha20poly1305_state));
3964 V_UINT32("crypto_secretstream_xchacha20poly1305_ABYTES", crypto_secretstream_xchacha20poly1305_ABYTES);
3965 V_UINT32("crypto_secretstream_xchacha20poly1305_HEADERBYTES", crypto_secretstream_xchacha20poly1305_HEADERBYTES);
3966 V_UINT32("crypto_secretstream_xchacha20poly1305_KEYBYTES", crypto_secretstream_xchacha20poly1305_KEYBYTES);
3967 V_UINT32("crypto_secretstream_xchacha20poly1305_TAGBYTES", 1);
3968 V_UINT64("crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX", crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX);
3969 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_MESSAGE", crypto_secretstream_xchacha20poly1305_TAG_MESSAGE);
3970 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_PUSH", crypto_secretstream_xchacha20poly1305_TAG_PUSH);
3971 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_REKEY", crypto_secretstream_xchacha20poly1305_TAG_REKEY);
3972 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_FINAL", crypto_secretstream_xchacha20poly1305_TAG_FINAL);
3973
3974 // crypto_shorthash
3975
3976 V_FUNCTION("crypto_shorthash", sn_crypto_shorthash);
3977 V_UINT32("crypto_shorthash_BYTES", crypto_shorthash_BYTES);
3978 V_UINT32("crypto_shorthash_KEYBYTES", crypto_shorthash_KEYBYTES);
3979 V_STRING("crypto_shorthash_PRIMITIVE", crypto_shorthash_PRIMITIVE);
3980
3981 // crypto_sign
3982
3983 V_FUNCTION("crypto_sign_keypair", sn_crypto_sign_keypair);
3984 V_FUNCTION("crypto_sign_seed_keypair", sn_crypto_sign_seed_keypair);
3985 V_FUNCTION("crypto_sign", sn_crypto_sign);
3986 V_FUNCTION("crypto_sign_open", sn_crypto_sign_open);
3987 V_FUNCTION("crypto_sign_detached", sn_crypto_sign_detached);
3988 V_FUNCTION_NOSCOPE("crypto_sign_verify_detached", sn_crypto_sign_verify_detached);
3989 V_FUNCTION("crypto_sign_ed25519_sk_to_pk", sn_crypto_sign_ed25519_sk_to_pk);
3990 V_FUNCTION("crypto_sign_ed25519_pk_to_curve25519", sn_crypto_sign_ed25519_pk_to_curve25519);
3991 V_FUNCTION("crypto_sign_ed25519_sk_to_curve25519", sn_crypto_sign_ed25519_sk_to_curve25519);
3992
3993 V_UINT32("crypto_sign_SEEDBYTES", crypto_sign_SEEDBYTES);
3994 V_UINT32("crypto_sign_PUBLICKEYBYTES", crypto_sign_PUBLICKEYBYTES);
3995 V_UINT32("crypto_sign_SECRETKEYBYTES", crypto_sign_SECRETKEYBYTES);
3996 V_UINT32("crypto_sign_BYTES", crypto_sign_BYTES);
3997
3998 // crypto_stream
3999
4000 V_FUNCTION("crypto_stream", sn_crypto_stream);
4001 V_UINT32("crypto_stream_KEYBYTES", crypto_stream_KEYBYTES);
4002 V_UINT32("crypto_stream_NONCEBYTES", crypto_stream_NONCEBYTES);
4003 V_STRING("crypto_stream_PRIMITIVE", crypto_stream_PRIMITIVE);
4004
4005 V_FUNCTION_NOSCOPE("crypto_stream_xor", sn_crypto_stream_xor);
4006 V_FUNCTION("crypto_stream_xor_init", sn_crypto_stream_xor_wrap_init);
4007 V_FUNCTION("crypto_stream_xor_update", sn_crypto_stream_xor_wrap_update);
4008 V_FUNCTION("crypto_stream_xor_final", sn_crypto_stream_xor_wrap_final);
4009 V_UINT32("crypto_stream_xor_STATEBYTES", sizeof(sn_crypto_stream_xor_state));
4010
4011 V_FUNCTION("crypto_stream_chacha20", sn_crypto_stream_chacha20);
4012 V_UINT32("crypto_stream_chacha20_KEYBYTES", crypto_stream_chacha20_KEYBYTES);
4013 V_UINT32("crypto_stream_chacha20_NONCEBYTES", crypto_stream_chacha20_NONCEBYTES);
4014 V_UINT64("crypto_stream_chacha20_MESSAGEBYTES_MAX", crypto_stream_chacha20_MESSAGEBYTES_MAX);
4015
4016 V_FUNCTION("crypto_stream_chacha20_xor", sn_crypto_stream_chacha20_xor);
4017 V_FUNCTION("crypto_stream_chacha20_xor_ic", sn_crypto_stream_chacha20_xor_ic);
4018 V_FUNCTION("crypto_stream_chacha20_xor_init", sn_crypto_stream_chacha20_xor_wrap_init);
4019 V_FUNCTION("crypto_stream_chacha20_xor_update", sn_crypto_stream_chacha20_xor_wrap_update);
4020 V_FUNCTION("crypto_stream_chacha20_xor_final", sn_crypto_stream_chacha20_xor_wrap_final);
4021 V_UINT32("crypto_stream_chacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_xor_state));
4022
4023 V_FUNCTION("crypto_stream_chacha20_ietf", sn_crypto_stream_chacha20_ietf);
4024 V_UINT32("crypto_stream_chacha20_ietf_KEYBYTES", crypto_stream_chacha20_ietf_KEYBYTES);
4025 V_UINT32("crypto_stream_chacha20_ietf_NONCEBYTES", crypto_stream_chacha20_ietf_NONCEBYTES);
4026 V_UINT64("crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX", crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX);
4027 V_UINT32("crypto_stream_chacha20_ietf_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_ietf_xor_state));
4028
4029 V_FUNCTION("crypto_stream_chacha20_ietf_xor", sn_crypto_stream_chacha20_ietf_xor);
4030 V_FUNCTION("crypto_stream_chacha20_ietf_xor_ic", sn_crypto_stream_chacha20_ietf_xor_ic);
4031 V_FUNCTION("crypto_stream_chacha20_ietf_xor_init", sn_crypto_stream_chacha20_ietf_xor_wrap_init);
4032 V_FUNCTION("crypto_stream_chacha20_ietf_xor_update", sn_crypto_stream_chacha20_ietf_xor_wrap_update);
4033 V_FUNCTION("crypto_stream_chacha20_ietf_xor_final", sn_crypto_stream_chacha20_ietf_xor_wrap_final);
4034
4035 V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
4036 V_UINT32("crypto_stream_xchacha20_KEYBYTES", crypto_stream_xchacha20_KEYBYTES);
4037 V_UINT32("crypto_stream_xchacha20_NONCEBYTES", crypto_stream_xchacha20_NONCEBYTES);
4038 V_UINT64("crypto_stream_xchacha20_MESSAGEBYTES_MAX", crypto_stream_xchacha20_MESSAGEBYTES_MAX);
4039
4040 V_FUNCTION("crypto_stream_xchacha20_xor", sn_crypto_stream_xchacha20_xor);
4041 V_FUNCTION("crypto_stream_xchacha20_xor_ic", sn_crypto_stream_xchacha20_xor_ic);
4042 V_FUNCTION("crypto_stream_xchacha20_xor_init", sn_crypto_stream_xchacha20_xor_wrap_init);
4043 V_FUNCTION("crypto_stream_xchacha20_xor_update", sn_crypto_stream_xchacha20_xor_wrap_update);
4044 V_FUNCTION("crypto_stream_xchacha20_xor_final", sn_crypto_stream_xchacha20_xor_wrap_final);
4045 V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
4046 V_UINT32("crypto_stream_xchacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_xchacha20_xor_state));
4047
4048 V_FUNCTION("crypto_stream_salsa20", sn_crypto_stream_salsa20);
4049 V_UINT32("crypto_stream_salsa20_KEYBYTES", crypto_stream_salsa20_KEYBYTES);
4050 V_UINT32("crypto_stream_salsa20_NONCEBYTES", crypto_stream_salsa20_NONCEBYTES);
4051 V_UINT64("crypto_stream_salsa20_MESSAGEBYTES_MAX", crypto_stream_salsa20_MESSAGEBYTES_MAX);
4052
4053 V_FUNCTION("crypto_stream_salsa20_xor", sn_crypto_stream_salsa20_xor);
4054 V_FUNCTION("crypto_stream_salsa20_xor_ic", sn_crypto_stream_salsa20_xor_ic);
4055 V_FUNCTION("crypto_stream_salsa20_xor_init", sn_crypto_stream_salsa20_xor_wrap_init);
4056 V_FUNCTION("crypto_stream_salsa20_xor_update", sn_crypto_stream_salsa20_xor_wrap_update);
4057 V_FUNCTION("crypto_stream_salsa20_xor_final", sn_crypto_stream_salsa20_xor_wrap_final);
4058 V_UINT32("crypto_stream_salsa20_xor_STATEBYTES", sizeof(sn_crypto_stream_salsa20_xor_state));
4059
4060 // extensions
4061
4062 // tweak
4063
4064 V_FUNCTION("extension_tweak_ed25519_base", sn_extension_tweak_ed25519_base);
4065 V_FUNCTION("extension_tweak_ed25519_sign_detached", sn_extension_tweak_ed25519_sign_detached);
4066 V_FUNCTION("extension_tweak_ed25519_sk_to_scalar", sn_extension_tweak_ed25519_sk_to_scalar);
4067 V_FUNCTION("extension_tweak_ed25519_scalar", sn_extension_tweak_ed25519_scalar);
4068 V_FUNCTION("extension_tweak_ed25519_pk", sn_extension_tweak_ed25519_pk);
4069 V_FUNCTION("extension_tweak_ed25519_keypair", sn_extension_tweak_ed25519_keypair);
4070 V_FUNCTION("extension_tweak_ed25519_scalar_add", sn_extension_tweak_ed25519_scalar_add);
4071 V_FUNCTION("extension_tweak_ed25519_pk_add", sn_extension_tweak_ed25519_pk_add);
4072 V_FUNCTION("extension_tweak_ed25519_keypair_add", sn_extension_tweak_ed25519_keypair_add);
4073 V_UINT32("extension_tweak_ed25519_BYTES", sn__extension_tweak_ed25519_BYTES);
4074 V_UINT32("extension_tweak_ed25519_SCALARBYTES", sn__extension_tweak_ed25519_SCALARBYTES);
4075
4076 // pbkdf2
4077
4078 V_FUNCTION("extension_pbkdf2_sha512", sn_extension_pbkdf2_sha512);
4079 V_FUNCTION("extension_pbkdf2_sha512_async", sn_extension_pbkdf2_sha512_async);
4080 V_UINT32("extension_pbkdf2_sha512_SALTBYTES", sn__extension_pbkdf2_sha512_SALTBYTES);
4081 V_UINT32("extension_pbkdf2_sha512_HASHBYTES", sn__extension_pbkdf2_sha512_HASHBYTES);
4082 V_UINT32("extension_pbkdf2_sha512_ITERATIONS_MIN", sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
4083 V_UINT64("extension_pbkdf2_sha512_BYTES_MAX", sn__extension_pbkdf2_sha512_BYTES_MAX);
4084
4085#undef V_FUNCTION
4086#undef V_FUNCTION_NOSCOPE
4087#undef V_UINT32
4088#undef V_UINT64
4089#undef V_STRING
4090
4091 return exports;
4092}
4093
4094BARE_MODULE(sodium_native, sodium_native_exports)
node_modules/noise-handshake/node_modules/sodium-native/binding.js +2 -0
……@@ -0,0 +1,2 @@
1require.addon = require('require-addon')
2module.exports = require.addon('.', __filename)
node_modules/noise-handshake/node_modules/sodium-native/extensions/pbkdf2/pbkdf2.c +90 -0
……@@ -0,0 +1,90 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
29 */
30
31#include <string.h>
32#include <sodium.h>
33
34#include "pbkdf2.h"
35
36/**
37 * pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
38 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
39 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
40 */
41int
42sn__extension_pbkdf2_sha512(const unsigned char *passwd, size_t passwdlen,
43 const unsigned char *salt, size_t saltlen, uint64_t c,
44 unsigned char *buf, size_t dkLen)
45{
46 crypto_auth_hmacsha512_state PShctx, hctx;
47 size_t i;
48 unsigned char ivec[4];
49 unsigned char U[64];
50 unsigned char T[64];
51 uint64_t j;
52 unsigned int k;
53 size_t clen;
54
55 if (dkLen > sn__extension_pbkdf2_sha512_BYTES_MAX) {
56 return -1;
57 }
58
59 crypto_auth_hmacsha512_init(&PShctx, passwd, passwdlen);
60 crypto_auth_hmacsha512_update(&PShctx, salt, saltlen);
61
62 for (i = 0; i * crypto_auth_hmacsha512_BYTES < dkLen; i++) {
63 SN_PBKDF2_STORE32_BE(ivec, (uint32_t)(i + 1));
64 memcpy(&hctx, &PShctx, sizeof(crypto_auth_hmacsha512_state));
65 crypto_auth_hmacsha512_update(&hctx, ivec, 4);
66 crypto_auth_hmacsha512_final(&hctx, U);
67
68 memcpy(T, U, crypto_auth_hmacsha512_BYTES);
69 /* LCOV_EXCL_START */
70 for (j = 2; j <= c; j++) {
71 crypto_auth_hmacsha512_init(&hctx, passwd, passwdlen);
72 crypto_auth_hmacsha512_update(&hctx, U, crypto_auth_hmacsha512_BYTES);
73 crypto_auth_hmacsha512_final(&hctx, U);
74
75 for (k = 0; k < crypto_auth_hmacsha512_BYTES; k++) {
76 T[k] ^= U[k];
77 }
78 }
79 /* LCOV_EXCL_STOP */
80
81 clen = dkLen - i * crypto_auth_hmacsha512_BYTES;
82 if (clen > crypto_auth_hmacsha512_BYTES) {
83 clen = crypto_auth_hmacsha512_BYTES;
84 }
85 memcpy(&buf[i * crypto_auth_hmacsha512_BYTES], T, clen);
86 }
87 sodium_memzero((void *) &PShctx, sizeof PShctx);
88
89 return 0;
90}
node_modules/noise-handshake/node_modules/sodium-native/extensions/pbkdf2/pbkdf2.h +60 -0
……@@ -0,0 +1,60 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28/*
29 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
30 */
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35#include <sodium.h>
36
37#define SN_PBKDF2_STORE32_BE(buf, n32) \
38 buf[0] = n32 >> 24 & 0xff; \
39 buf[1] = n32 >> 16 & 0xff; \
40 buf[2] = n32 >> 8 & 0xff; \
41 buf[3] = n32 >> 0 & 0xff;
42
43#define sn__extension_pbkdf2_sha512_SALTBYTES 16U
44
45#define sn__extension_pbkdf2_sha512_HASHBYTES crypto_hash_sha512_BYTES
46
47#define sn__extension_pbkdf2_sha512_ITERATIONS_MIN 1U
48
49#define sn__extension_pbkdf2_sha512_BYTES_MAX 0x3fffffffc0ULL
50
51/**
52 * extension_pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
53 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
54 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
55 */
56int sn__extension_pbkdf2_sha512(const unsigned char *, size_t, const unsigned char *, size_t,
57 uint64_t, unsigned char *, size_t);
58#ifdef __cplusplus
59};
60#endif
node_modules/noise-handshake/node_modules/sodium-native/extensions/tweak/tweak.c +206 -0
……@@ -0,0 +1,206 @@
1#include "tweak.h"
2
3/*
4 *EXPERIMENTAL API*
5
6 This module is an experimental implementation of a key tweaking protocol
7 over ed25519 keys. The signature algorithm has been reimplemented from
8 libsodium, but the nonce generation algorithm is *non-standard*.
9
10 Use at your own risk
11*/
12
13static void _extension_tweak_nonce (unsigned char *nonce, const unsigned char *n,
14 const unsigned char *m, unsigned long long mlen)
15{
16 // dom2(x, y) with x = 0 (not prehashed) and y = "crypto_tweak_ed25519"
17 static const unsigned char TWEAK_PREFIX[32 + 2 + 20] = {
18 'S', 'i', 'g', 'E', 'd', '2', '5', '5', '1', '9', ' ',
19 'n', 'o', ' ', 'E', 'd', '2', '5', '5', '1', '9', ' ',
20 'c', 'o', 'l', 'l', 'i', 's', 'i', 'o', 'n', 's', 0,
21 20, 'c', 'r', 'y', 'p', 't', 'o', '_', 't', 'w', 'e',
22 'a', 'k', '_', 'e', 'd', '2', '5', '5', '1', '9'
23 };
24
25 crypto_hash_sha512_state hs;
26
27 crypto_hash_sha512_init(&hs);
28 crypto_hash_sha512_update(&hs, TWEAK_PREFIX, sizeof TWEAK_PREFIX);
29 crypto_hash_sha512_update(&hs, n, 32);
30 crypto_hash_sha512_update(&hs, m, mlen);
31 crypto_hash_sha512_final(&hs, nonce);
32}
33
34static inline void
35_crypto_sign_ed25519_clamp(unsigned char k[32])
36{
37 k[0] &= 248;
38 k[31] &= 127;
39 k[31] |= 64;
40}
41
42static void _extension_tweak_ed25519(unsigned char *q, unsigned char *n,
43 const unsigned char *ns, unsigned long long nslen)
44{
45 sodium_memzero(q, sizeof q);
46
47 crypto_hash(n, ns, nslen);
48 n[31] &= 127; // clear highest bit
49
50 crypto_scalarmult_ed25519_base_noclamp(q, n);
51
52 // hash tweak until we get a valid tweaked q
53 while (crypto_core_ed25519_is_valid_point(q) != 1) {
54 crypto_hash(n, n, 32);
55 n[31] &= 127; // clear highest bit
56
57 crypto_scalarmult_ed25519_base_noclamp(q, n);
58 }
59}
60
61void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
62 const unsigned char *ns, unsigned long long nslen)
63{
64 unsigned char n64[64];
65
66 _extension_tweak_ed25519(pk, n64, ns, nslen);
67
68 SN_TWEAK_COPY_32(scalar, n64)
69}
70
71int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
72 const unsigned char *m, unsigned long long mlen,
73 const unsigned char *n, unsigned char *pk)
74{
75 crypto_hash_sha512_state hs;
76
77 unsigned char nonce[64];
78 unsigned char R[32];
79 unsigned char hram[64];
80 unsigned char _pk[32];
81
82 // check if pk was passed
83 if (pk == NULL) {
84 pk = _pk;
85
86 // derive pk from scalar
87 if (crypto_scalarmult_ed25519_base_noclamp(pk, n) != 0) {
88 return -1;
89 }
90 }
91
92 _extension_tweak_nonce(nonce, n, m, mlen);
93 crypto_core_ed25519_scalar_reduce(nonce, nonce);
94
95 // R = G ^ nonce : curve point from nonce
96 if (crypto_scalarmult_ed25519_base_noclamp(R, nonce) != 0) {
97 return -1;
98 }
99
100 // generate challenge as h(ram) = hash(R, pk, message)
101 crypto_hash_sha512_init(&hs);
102 crypto_hash_sha512_update(&hs, R, 32);
103 crypto_hash_sha512_update(&hs, pk, 32);
104 crypto_hash_sha512_update(&hs, m, mlen);
105
106 crypto_hash_sha512_final(&hs, hram);
107
108 crypto_core_ed25519_scalar_reduce(hram, hram);
109
110 // sig = nonce + n * h(ram)
111 crypto_core_ed25519_scalar_mul(sig, hram, n);
112 crypto_core_ed25519_scalar_add(sig + 32, nonce, sig);
113
114 SN_TWEAK_COPY_32(sig, R)
115
116 if (siglen_p != NULL) {
117 *siglen_p = 64U;
118 }
119
120 return 0;
121}
122
123// tweak a secret key
124void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *n, const unsigned char *sk)
125{
126 unsigned char n64[64];
127
128 // get sk scalar from seed, cf. crypto_sign_keypair_seed
129 crypto_hash(n64, sk, 32);
130 _crypto_sign_ed25519_clamp(n64);
131
132 SN_TWEAK_COPY_32(n, n64)
133}
134
135// tweak a secret key
136void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
137 const unsigned char *scalar,
138 const unsigned char *ns,
139 unsigned long long nslen)
140{
141 unsigned char n[64];
142 unsigned char q[32];
143
144 _extension_tweak_ed25519(q, n, ns, nslen);
145 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
146}
147
148// tweak a public key
149int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
150 const unsigned char *pk,
151 const unsigned char *ns,
152 unsigned long long nslen)
153{
154 unsigned char n[64];
155 unsigned char q[32];
156
157 _extension_tweak_ed25519(q, n, ns, nslen);
158 return crypto_core_ed25519_add(tpk, q, pk);
159}
160
161
162void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
163 unsigned char *scalar, const unsigned char *ns,
164 unsigned long long nslen)
165{
166 unsigned char n64[64];
167
168 crypto_hash(n64, ns, nslen);
169 n64[31] &= 127; // clear highest bit
170
171 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
172 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
173
174 // hash tweak until we get a valid tweaked point
175 while (crypto_core_ed25519_is_valid_point(pk) != 1) {
176 crypto_hash(n64, n64, 32);
177 n64[31] &= 127; // clear highest bit
178
179 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
180 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
181 }
182}
183
184// add tweak to scalar
185void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
186 const unsigned char *scalar,
187 const unsigned char *n)
188{
189 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
190}
191
192// add tweak point to public key
193int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
194 const unsigned char *pk,
195 const unsigned char *q)
196{
197 return crypto_core_ed25519_add(tpk, pk, q);
198}
199
200
201int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
202 unsigned char *scalar, const unsigned char *tweak)
203{
204 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, tweak);
205 return crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
206}
node_modules/noise-handshake/node_modules/sodium-native/extensions/tweak/tweak.h +62 -0
……@@ -0,0 +1,62 @@
1#ifdef __cplusplus
2extern "C" {
3#endif
4
5#include <sodium.h>
6
7// copy 32 bytes using int64_t pointers
8#define SN_TWEAK_COPY_32(a, b) \
9 { \
10 long long *dst = (long long *) a; \
11 long long *src = (long long *) b; \
12 dst[0] = src[0]; \
13 dst[1] = src[1]; \
14 dst[2] = src[2]; \
15 dst[3] = src[3]; \
16 }
17
18#define sn__extension_tweak_ed25519_BYTES crypto_sign_ed25519_PUBLICKEYBYTES
19
20#define sn__extension_tweak_ed25519_SCALARBYTES crypto_scalarmult_ed25519_SCALARBYTES
21
22int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
23 const unsigned char *m, unsigned long long mlen,
24 const unsigned char *n, unsigned char *pk);
25
26void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
27 const unsigned char *ns, unsigned long long nslen);
28
29void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *scalar, const unsigned char *sk);
30
31// tweak a secret key
32void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
33 const unsigned char *scalar,
34 const unsigned char *ns,
35 unsigned long long nslen);
36
37// tweak a public key
38int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
39 const unsigned char *pk,
40 const unsigned char *ns,
41 unsigned long long nslen);
42
43void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
44 unsigned char *scalar, const unsigned char *ns,
45 unsigned long long nslen);
46
47// add tweak scalar to private key
48void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
49 const unsigned char *scalar,
50 const unsigned char *n);
51
52// add tweak point to public key
53int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
54 const unsigned char *pk,
55 const unsigned char *q);
56
57int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
58 unsigned char *scalar, const unsigned char *tweak);
59
60#ifdef __cplusplus
61};
62#endif
node_modules/noise-handshake/node_modules/sodium-native/index.js +3231 -0
……@@ -0,0 +1,3231 @@
1const assert = require('assert')
2const binding = require('./binding')
3const { isNode } = require('which-runtime')
4
5const OPTIONAL = Buffer.from(new ArrayBuffer(0))
6
7module.exports = exports = { ...binding }
8
9// memory
10
11exports.sodium_memzero = function (buf) {
12 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
13
14 binding.sodium_memzero(buf)
15}
16
17exports.sodium_mlock = function (buf) {
18 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
19
20 const res = binding.sodium_mlock(buf)
21
22 if (res !== 0) throw new Error('memory lock failed')
23}
24
25exports.sodium_munlock = function (buf) {
26 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
27
28 const res = binding.sodium_munlock(buf)
29
30 if (res !== 0) throw new Error('memory unlock failed')
31}
32
33exports.sodium_malloc = function (size) {
34 assert(size >= 0, 'invalid size')
35
36 const buf = Buffer.from(binding.sodium_malloc(size))
37 buf.secure = true
38 return buf
39}
40
41exports.sodium_free = function (buf) {
42 if (!buf || !buf.secure) return
43
44 binding.sodium_free(buf.buffer)
45}
46
47exports.sodium_mprotect_noaccess = function (buf) {
48 const res = binding.sodium_mprotect_noaccess(buf.buffer)
49
50 if (res !== 0) throw new Error('failed to lock buffer')
51}
52
53exports.sodium_mprotect_readonly = function (buf) {
54 const res = binding.sodium_mprotect_readonly(buf.buffer)
55
56 if (res !== 0) throw new Error('failed to unlock buffer')
57}
58
59exports.sodium_mprotect_readwrite = function (buf) {
60 const res = binding.sodium_mprotect_readwrite(buf.buffer)
61
62 if (res !== 0) throw new Error('failed to unlock buffer')
63}
64
65// crypto_randombytes
66
67exports.randombytes_buf = function (buffer) {
68 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
69
70 binding.randombytes_buf(buffer.buffer, buffer.byteOffset, buffer.byteLength)
71}
72
73exports.randombytes_buf_deterministic = function (buffer, seed) {
74 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
75 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
76 assert(
77 seed.byteLength === binding.randombytes_SEEDBYTES,
78 "seed must be 'randombytes_SEEDBYTES' bytes"
79 )
80
81 binding.randombytes_buf_deterministic(
82 buffer.buffer,
83 buffer.byteOffset,
84 buffer.byteLength,
85
86 seed.buffer,
87 seed.byteOffset,
88 seed.byteLength
89 )
90}
91
92// sodium_helpers
93
94exports.sodium_memcmp = function (a, b) {
95 assert(ArrayBuffer.isView(a), 'a must be a typed array')
96 assert(ArrayBuffer.isView(b), 'b must be a typed array')
97 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
98
99 return binding.sodium_memcmp(a, b)
100}
101
102exports.sodium_add = function (a, b) {
103 assert(ArrayBuffer.isView(a), 'a must be a typed array')
104 assert(ArrayBuffer.isView(b), 'b must be a typed array')
105 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
106
107 binding.sodium_add(a, b)
108}
109
110exports.sodium_sub = function (a, b) {
111 assert(ArrayBuffer.isView(a), 'a must be a typed array')
112 assert(ArrayBuffer.isView(b), 'b must be a typed array')
113 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
114
115 binding.sodium_sub(a, b)
116}
117
118exports.sodium_compare = function (a, b) {
119 assert(ArrayBuffer.isView(a), 'a must be a typed array')
120 assert(ArrayBuffer.isView(b), 'b must be a typed array')
121 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
122
123 return binding.sodium_compare(a, b)
124}
125
126exports.sodium_is_zero = function (buffer, length) {
127 if (length === undefined) length = buffer.byteLength
128
129 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
130 assert(length >= 0 && length <= buffer.byteLength, 'invalid length')
131
132 return binding.sodium_is_zero(buffer, length)
133}
134
135exports.sodium_pad = function (buffer, unpaddedBuflen, blockSize) {
136 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
137 assert(unpaddedBuflen <= buffer.byteLength, 'unpadded length cannot exceed buffer length')
138 assert(blockSize <= buffer.byteLength, 'block size cannot exceed buffer length')
139 assert(blockSize >= 1, 'block size must be at least 1 byte')
140 assert(
141 buffer.byteLength >= unpaddedBuflen + (blockSize - (unpaddedBuflen % blockSize)),
142 'buf not long enough'
143 )
144
145 return binding.sodium_pad(buffer, unpaddedBuflen, blockSize)
146}
147
148exports.sodium_unpad = function (buffer, paddedBuflen, blockSize) {
149 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
150 assert(paddedBuflen <= buffer.byteLength, 'unpadded length cannot exceed buffer length')
151 assert(blockSize <= buffer.byteLength, 'block size cannot exceed buffer length')
152 assert(blockSize >= 1, 'block size must be at least 1 byte')
153
154 return binding.sodium_unpad(buffer, paddedBuflen, blockSize)
155}
156
157// crypto_sign
158
159exports.crypto_sign_keypair = function (pk, sk) {
160 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
161 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
162 assert(
163 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
164 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
165 )
166 assert(
167 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
168 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
169 )
170
171 const res = binding.crypto_sign_keypair(pk, sk)
172
173 if (res !== 0) throw new Error('status: ' + res)
174}
175
176exports.crypto_sign_seed_keypair = function (pk, sk, seed) {
177 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
178 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
179 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
180 assert(
181 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
182 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
183 )
184 assert(
185 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
186 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
187 )
188 assert(
189 seed.byteLength === binding.crypto_sign_SEEDBYTES,
190 "seed must be 'crypto_sign_SEEDBYTES' bytes"
191 )
192
193 const res = binding.crypto_sign_seed_keypair(pk, sk, seed)
194
195 if (res !== 0) throw new Error('status: ' + res)
196}
197
198exports.crypto_sign = function (sm, m, sk) {
199 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
200 assert(ArrayBuffer.isView(m), 'm must be a typed array')
201 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
202 assert(
203 sm.byteLength === binding.crypto_sign_BYTES + m.byteLength,
204 "sm must be 'm.byteLength + crypto_sign_BYTES' bytes"
205 )
206 assert(
207 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
208 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
209 )
210
211 const res = binding.crypto_sign(sm, m, sk)
212
213 if (res !== 0) throw new Error('status: ' + res)
214}
215
216exports.crypto_sign_open = function (m, sm, pk) {
217 assert(ArrayBuffer.isView(m), 'm must be a typed array')
218 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
219 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
220 assert(
221 sm.byteLength >= binding.crypto_sign_BYTES,
222 "sm must be at least 'crypto_sign_BYTES' bytes"
223 )
224 assert(
225 m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
226 "m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
227 )
228 assert(
229 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
230 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
231 )
232
233 const res = binding.crypto_sign_open(m, sm, pk)
234
235 if (res !== 0) throw new Error('status: ' + res)
236}
237
238exports.crypto_sign_open = function (m, sm, pk) {
239 assert(ArrayBuffer.isView(m), 'm must be a typed array')
240 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
241 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
242 assert(
243 sm.byteLength >= binding.crypto_sign_BYTES,
244 "sm must be at least 'crypto_sign_BYTES' bytes"
245 )
246 assert(
247 m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
248 "m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
249 )
250 assert(
251 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
252 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
253 )
254
255 return binding.crypto_sign_open(m, sm, pk)
256}
257
258exports.crypto_sign_detached = function (sig, m, sk) {
259 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
260 assert(ArrayBuffer.isView(m), 'm must be a typed array')
261 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
262 assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes")
263 assert(
264 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
265 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
266 )
267
268 const res = binding.crypto_sign_detached(sig, m, sk)
269
270 if (res !== 0) throw new Error('status: ' + res)
271}
272
273exports.crypto_sign_verify_detached = function (sig, m, pk) {
274 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
275 assert(ArrayBuffer.isView(m), 'm must be a typed array')
276 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
277 assert(
278 sig.byteLength >= binding.crypto_sign_BYTES,
279 "sig must be at least 'crypto_sign_BYTES' bytes"
280 )
281 assert(
282 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
283 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
284 )
285
286 return binding.crypto_sign_verify_detached(
287 sig.buffer,
288 sig.byteOffset,
289 sig.byteLength,
290
291 m.buffer,
292 m.byteOffset,
293 m.byteLength,
294
295 pk.buffer,
296 pk.byteOffset,
297 pk.byteLength
298 )
299}
300
301exports.crypto_sign_ed25519_sk_to_pk = function (pk, sk) {
302 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
303 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
304 assert(
305 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
306 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
307 )
308 assert(
309 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
310 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
311 )
312
313 const res = binding.crypto_sign_ed25519_sk_to_pk(pk, sk)
314
315 if (res !== 0) throw new Error('status: ' + res)
316}
317
318exports.crypto_sign_ed25519_pk_to_curve25519 = function (x25519pk, ed25519pk) {
319 assert(ArrayBuffer.isView(x25519pk), 'x25519pk must be a typed array')
320 assert(ArrayBuffer.isView(ed25519pk), 'ed25519pk must be a typed array')
321 assert(
322 x25519pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
323 "x25519pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
324 )
325 assert(
326 ed25519pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
327 "ed25519pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
328 )
329
330 const res = binding.crypto_sign_ed25519_pk_to_curve25519(x25519pk, ed25519pk)
331
332 if (res !== 0) throw new Error('status: ' + res)
333}
334
335exports.crypto_sign_ed25519_sk_to_curve25519 = function (x25519sk, ed25519sk) {
336 assert(ArrayBuffer.isView(x25519sk), 'x25519sk must be a typed array')
337 assert(ArrayBuffer.isView(ed25519sk), 'ed25519sk must be a typed array')
338 assert(
339 x25519sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
340 "x25519sk must be 'crypto_box_SECRETKEYBYTES' bytes"
341 )
342
343 const edLen = ed25519sk.byteLength
344
345 assert(
346 edLen === binding.crypto_sign_SECRETKEYBYTES || edLen === binding.crypto_box_SECRETKEYBYTES,
347 "ed25519sk must be 'crypto_sign_SECRETKEYBYTES' or 'crypto_sign_SECRETKEYBYTES - crypto_sign_PUBLICKEYBYTES' bytes"
348 )
349
350 const res = binding.crypto_sign_ed25519_sk_to_curve25519(x25519sk, ed25519sk)
351
352 if (res !== 0) throw new Error('status: ' + res)
353}
354
355// crypto_box
356
357exports.crypto_box_keypair = function (pk, sk) {
358 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
359 assert(
360 pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
361 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
362 )
363 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
364 assert(
365 sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
366 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
367 )
368
369 const res = binding.crypto_box_keypair(pk, sk)
370
371 if (res !== 0) throw new Error('status: ' + res)
372}
373
374exports.crypto_box_seed_keypair = function (pk, sk, seed) {
375 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
376 assert(
377 pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
378 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
379 )
380 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
381 assert(
382 sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
383 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
384 )
385 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
386 assert(
387 seed.byteLength === binding.crypto_box_SEEDBYTES,
388 "seed must be 'crypto_box_SEEDBYTES' bytes"
389 )
390
391 const res = binding.crypto_box_seed_keypair(pk, sk, seed)
392
393 if (res !== 0) throw new Error('status: ' + res)
394}
395
396exports.crypto_box_easy = function (c, m, n, pk, sk) {
397 assert(ArrayBuffer.isView(c), 'c must be a typed array')
398 assert(ArrayBuffer.isView(m), 'm must be a typed array')
399 assert(ArrayBuffer.isView(n), 'n must be a typed array')
400 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
401 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
402 assert(
403 c.byteLength === m.byteLength + exports.crypto_box_MACBYTES,
404 "c must be 'm.byteLength + crypto_box_MACBYTES' bytes"
405 )
406 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
407 assert(
408 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
409 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
410 )
411 assert(
412 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
413 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
414 )
415
416 const res = binding.crypto_box_easy(c, m, n, pk, sk)
417
418 if (res !== 0) throw new Error('status: ' + res)
419}
420
421exports.crypto_box_detached = function (c, mac, m, n, pk, sk) {
422 assert(ArrayBuffer.isView(c), 'c must be a typed array')
423 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
424 assert(ArrayBuffer.isView(m), 'm must be a typed array')
425 assert(ArrayBuffer.isView(n), 'n must be a typed array')
426 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
427 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
428 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
429 assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes")
430 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
431 assert(
432 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
433 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
434 )
435 assert(
436 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
437 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
438 )
439
440 const res = binding.crypto_box_detached(c, mac, m, n, pk, sk)
441
442 if (res !== 0) throw new Error('status: ' + res)
443}
444
445exports.crypto_box_open_easy = function (m, c, n, pk, sk) {
446 assert(ArrayBuffer.isView(m), 'm must be a typed array')
447 assert(ArrayBuffer.isView(c), 'c must be a typed array')
448 assert(ArrayBuffer.isView(n), 'n must be a typed array')
449 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
450 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
451 assert(
452 c.byteLength >= exports.crypto_box_MACBYTES,
453 "c must be at least 'crypto_box_MACBYTES' bytes"
454 )
455 assert(
456 m.byteLength === c.byteLength - exports.crypto_box_MACBYTES,
457 "m must be 'c.byteLength - crypto_box_MACBYTES' bytes"
458 )
459 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
460 assert(
461 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
462 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
463 )
464 assert(
465 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
466 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
467 )
468
469 return binding.crypto_box_open_easy(m, c, n, pk, sk)
470}
471
472exports.crypto_box_open_detached = function (m, c, mac, n, pk, sk) {
473 assert(ArrayBuffer.isView(m), 'm must be a typed array')
474 assert(ArrayBuffer.isView(c), 'c must be a typed array')
475 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
476 assert(ArrayBuffer.isView(n), 'n must be a typed array')
477 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
478 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
479 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
480 assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes")
481 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
482 assert(
483 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
484 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
485 )
486 assert(
487 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
488 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
489 )
490
491 return binding.crypto_box_open_detached(m, c, mac, n, pk, sk)
492}
493
494exports.crypto_box_seal = function (c, m, pk) {
495 assert(ArrayBuffer.isView(c), 'c must be a typed array')
496 assert(ArrayBuffer.isView(m), 'm must be a typed array')
497 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
498 assert(
499 c.byteLength === m.byteLength + exports.crypto_box_SEALBYTES,
500 "c must be 'm.byteLength + crypto_box_SEALBYTES' bytes"
501 )
502 assert(
503 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
504 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
505 )
506
507 const res = binding.crypto_box_seal(c, m, pk)
508
509 if (res !== 0) throw new Error('status: ' + res)
510}
511
512exports.crypto_box_seal_open = function (m, c, pk, sk) {
513 assert(ArrayBuffer.isView(m), 'm must be a typed array')
514 assert(ArrayBuffer.isView(c), 'c must be a typed array')
515 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
516 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
517 assert(
518 c.byteLength >= exports.crypto_box_SEALBYTES,
519 "c must be at least 'crypto_box_SEALBYTES' bytes"
520 )
521 assert(
522 m.byteLength === c.byteLength - exports.crypto_box_SEALBYTES,
523 "m must be 'c.byteLength - crypto_box_SEALBYTES' bytes"
524 )
525 assert(
526 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
527 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
528 )
529 assert(
530 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
531 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
532 )
533
534 return binding.crypto_box_seal_open(
535 m.buffer,
536 m.byteOffset,
537 m.byteLength,
538
539 c.buffer,
540 c.byteOffset,
541 c.byteLength,
542
543 pk.buffer,
544 pk.byteOffset,
545 pk.byteLength,
546
547 sk.buffer,
548 sk.byteOffset,
549 sk.byteLength
550 )
551}
552
553// crypto_secretbox
554
555exports.crypto_secretbox_easy = function (c, m, n, k) {
556 assert(ArrayBuffer.isView(c), 'c must be a typed array')
557 assert(ArrayBuffer.isView(m), 'm must be a typed array')
558 assert(ArrayBuffer.isView(n), 'n must be a typed array')
559 assert(ArrayBuffer.isView(k), 'k must be a typed array')
560 assert(
561 c.byteLength === m.byteLength + binding.crypto_secretbox_MACBYTES,
562 "c must be 'm.byteLength + crypto_secretbox_MACBYTES' bytes"
563 )
564 assert(
565 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
566 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
567 )
568 assert(
569 k.byteLength === binding.crypto_secretbox_KEYBYTES,
570 "k must be 'crypto_secretbox_KEYBYTES' bytes"
571 )
572
573 const res = binding.crypto_secretbox_easy(c, m, n, k)
574
575 if (res !== 0) throw new Error('status: ' + res)
576}
577
578exports.crypto_secretbox_open_easy = function (m, c, n, k) {
579 assert(ArrayBuffer.isView(m), 'm must be a typed array')
580 assert(ArrayBuffer.isView(c), 'c must be a typed array')
581 assert(ArrayBuffer.isView(n), 'n must be a typed array')
582 assert(ArrayBuffer.isView(k), 'k must be a typed array')
583 assert(
584 c.byteLength >= binding.crypto_secretbox_MACBYTES,
585 "c must be at least 'crypto_secretbox_MACBYTES' bytes"
586 )
587 assert(
588 m.byteLength === c.byteLength - binding.crypto_secretbox_MACBYTES,
589 "m must be 'c.byteLength - crypto_secretbox_MACBYTES' bytes"
590 )
591 assert(
592 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
593 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
594 )
595 assert(
596 k.byteLength === binding.crypto_secretbox_KEYBYTES,
597 "k must be 'crypto_secretbox_KEYBYTES' bytes"
598 )
599
600 return binding.crypto_secretbox_open_easy(m, c, n, k)
601}
602
603exports.crypto_secretbox_detached = function (c, mac, m, n, k) {
604 assert(ArrayBuffer.isView(c), 'c must be a typed array')
605 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
606 assert(ArrayBuffer.isView(m), 'm must be a typed array')
607 assert(ArrayBuffer.isView(n), 'n must be a typed array')
608 assert(ArrayBuffer.isView(k), 'k must be a typed array')
609 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
610 assert(
611 mac.byteLength === binding.crypto_secretbox_MACBYTES,
612 "mac must be 'crypto_secretbox_MACBYTES' bytes"
613 )
614 assert(
615 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
616 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
617 )
618 assert(
619 k.byteLength === binding.crypto_secretbox_KEYBYTES,
620 "k must be 'crypto_secretbox_KEYBYTES' bytes"
621 )
622
623 const res = binding.crypto_secretbox_detached(c, mac, m, n, k)
624
625 if (res !== 0) throw new Error('status: ' + res)
626}
627
628exports.crypto_secretbox_open_detached = function (m, c, mac, n, k) {
629 assert(ArrayBuffer.isView(m), 'm must be a typed array')
630 assert(ArrayBuffer.isView(c), 'c must be a typed array')
631 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
632 assert(ArrayBuffer.isView(n), 'n must be a typed array')
633 assert(ArrayBuffer.isView(k), 'k must be a typed array')
634 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
635 assert(
636 mac.byteLength === binding.crypto_secretbox_MACBYTES,
637 "mac must be 'crypto_secretbox_MACBYTES' bytes"
638 )
639 assert(
640 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
641 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
642 )
643 assert(
644 k.byteLength === binding.crypto_secretbox_KEYBYTES,
645 "k must be 'crypto_secretbox_KEYBYTES' bytes"
646 )
647
648 return binding.crypto_secretbox_open_detached(m, c, mac, n, k)
649}
650
651// crypto_generichash
652
653exports.crypto_generichash = function (output, input, key) {
654 if (!key) key = OPTIONAL
655
656 assert(ArrayBuffer.isView(output), 'output must be a typed array')
657 assert(ArrayBuffer.isView(input), 'input must be a typed array')
658 assert(
659 output.byteLength >= binding.crypto_generichash_BYTES_MIN &&
660 output.byteLength <= binding.crypto_generichash_BYTES_MAX,
661 'output must be between crypto_generichash_BYTES_MIN and crypto_generichash_BYTES_MAX bytes'
662 )
663
664 if (key !== OPTIONAL) {
665 assert(ArrayBuffer.isView(key), 'key must be a typed array')
666 assert(
667 key.byteLength >= binding.crypto_generichash_KEYBYTES_MIN &&
668 key.byteLength <= binding.crypto_generichash_KEYBYTES_MAX,
669 'key must be between crypto_generichash_KEYBYTES_MIN and crypto_generichash_KEYBYTES_MAX bytes'
670 )
671 }
672
673 const res = binding.crypto_generichash(
674 output.buffer,
675 output.byteOffset,
676 output.byteLength,
677
678 input.buffer,
679 input.byteOffset,
680 input.byteLength,
681
682 key.buffer,
683 key.byteOffset,
684 key.byteLength
685 )
686
687 if (res !== 0) throw new Error('status: ' + res)
688}
689
690exports.crypto_generichash_batch = function (output, batch, key) {
691 assert(ArrayBuffer.isView(output), 'output must be a typed array')
692
693 if (isNode || batch.length < 4) {
694 const res = binding.crypto_generichash_batch(output, batch, !!key, key || OPTIONAL)
695 if (res !== 0) throw new Error('status: ' + res)
696 } else {
697 const state = Buffer.alloc(binding.crypto_generichash_STATEBYTES)
698
699 exports.crypto_generichash_init(state, key, output.byteLength)
700
701 for (const buf of batch) {
702 exports.crypto_generichash_update(state, buf)
703 }
704
705 exports.crypto_generichash_final(state, output)
706 }
707}
708
709exports.crypto_generichash_keygen = function (key) {
710 assert(ArrayBuffer.isView(key), 'key must be a typed array')
711 assert(
712 key.byteLength === binding.crypto_generichash_KEYBYTES,
713 "key must be 'crypto_generichash_KEYBYTES' bytes"
714 )
715
716 const res = binding.crypto_generichash_keygen(key.buffer, key.byteOffset, key.byteLength)
717
718 if (res !== 0) throw new Error('status: ' + res)
719}
720
721exports.crypto_generichash_init = function (state, key, outputLength) {
722 if (!key) key = OPTIONAL
723
724 assert(ArrayBuffer.isView(state), 'state must be a typed array')
725 assert(
726 state.byteLength === binding.crypto_generichash_STATEBYTES,
727 "state must be 'crypto_generichash_STATEBYTES' bytes"
728 )
729
730 const res = binding.crypto_generichash_init(
731 state.buffer,
732 state.byteOffset,
733 state.byteLength,
734
735 key.buffer,
736 key.byteOffset,
737 key.byteLength,
738
739 outputLength
740 )
741
742 if (res !== 0) throw new Error('status: ' + res)
743}
744
745exports.crypto_generichash_update = function (state, input) {
746 assert(ArrayBuffer.isView(state), 'state must be a typed array')
747 assert(ArrayBuffer.isView(input), 'input must be a typed array')
748 assert(
749 state.byteLength === binding.crypto_generichash_STATEBYTES,
750 "state must be 'crypto_generichash_STATEBYTES' bytes"
751 )
752
753 const res = binding.crypto_generichash_update(
754 state.buffer,
755 state.byteOffset,
756 state.byteLength,
757
758 input.buffer,
759 input.byteOffset,
760 input.byteLength
761 )
762
763 if (res !== 0) throw new Error('status: ' + res)
764}
765
766exports.crypto_generichash_final = function (state, output) {
767 assert(ArrayBuffer.isView(state), 'state must be a typed array')
768 assert(ArrayBuffer.isView(output), 'output must be a typed array')
769 assert(
770 state.byteLength === binding.crypto_generichash_STATEBYTES,
771 "state must be 'crypto_generichash_STATEBYTES' bytes"
772 )
773
774 const res = binding.crypto_generichash_final(
775 state.buffer,
776 state.byteOffset,
777 state.byteLength,
778
779 output.buffer,
780 output.byteOffset,
781 output.byteLength
782 )
783
784 if (res !== 0) throw new Error('status: ' + res)
785}
786
787// secretstream
788
789exports.crypto_secretstream_xchacha20poly1305_keygen = function (k) {
790 assert(ArrayBuffer.isView(k), 'k must be a typed array')
791 assert(
792 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
793 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
794 )
795
796 binding.crypto_secretstream_xchacha20poly1305_keygen(k.buffer, k.byteOffset, k.byteLength)
797}
798
799exports.crypto_secretstream_xchacha20poly1305_init_push = function (state, header, k) {
800 assert(ArrayBuffer.isView(state), 'state must be a typed array')
801 assert(ArrayBuffer.isView(header), 'header must be a typed array')
802 assert(ArrayBuffer.isView(k), 'k must be a typed array')
803 assert(
804 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
805 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
806 )
807 assert(
808 header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
809 "header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
810 )
811 assert(
812 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
813 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
814 )
815
816 const res = binding.crypto_secretstream_xchacha20poly1305_init_push(
817 state.buffer,
818 state.byteOffset,
819 state.byteLength,
820
821 header.buffer,
822 header.byteOffset,
823 header.byteLength,
824
825 k.buffer,
826 k.byteOffset,
827 k.byteLength
828 )
829
830 if (res !== 0) throw new Error('status: ' + res)
831}
832
833exports.crypto_secretstream_xchacha20poly1305_init_pull = function (state, header, k) {
834 assert(ArrayBuffer.isView(state), 'state must be a typed array')
835 assert(ArrayBuffer.isView(header), 'header must be a typed array')
836 assert(ArrayBuffer.isView(k), 'k must be a typed array')
837 assert(
838 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
839 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
840 )
841 assert(
842 header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
843 "header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
844 )
845 assert(
846 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
847 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
848 )
849
850 const res = binding.crypto_secretstream_xchacha20poly1305_init_pull(
851 state.buffer,
852 state.byteOffset,
853 state.byteLength,
854
855 header.buffer,
856 header.byteOffset,
857 header.byteLength,
858
859 k.buffer,
860 k.byteOffset,
861 k.byteLength
862 )
863
864 if (res !== 0) throw new Error('status: ' + res)
865}
866
867exports.crypto_secretstream_xchacha20poly1305_push = function (state, c, m, ad, tag) {
868 if (!ad) ad = OPTIONAL
869
870 assert(ArrayBuffer.isView(state), 'state must be a typed array')
871 assert(ArrayBuffer.isView(c), 'c must be a typed array')
872 assert(ArrayBuffer.isView(m), 'm must be a typed array')
873 assert(
874 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
875 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
876 )
877 assert(
878 c.byteLength === m.byteLength + binding.crypto_secretstream_xchacha20poly1305_ABYTES,
879 "c must be 'm.byteLength + crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
880 )
881
882 const res = binding.crypto_secretstream_xchacha20poly1305_push(
883 state.buffer,
884 state.byteOffset,
885 state.byteLength,
886
887 c.buffer,
888 c.byteOffset,
889 c.byteLength,
890
891 m.buffer,
892 m.byteOffset,
893 m.byteLength,
894
895 ad.buffer,
896 ad.byteOffset,
897 ad.byteLength,
898
899 tag
900 )
901
902 if (res < 0) throw new Error('push failed')
903
904 return res
905}
906
907exports.crypto_secretstream_xchacha20poly1305_pull = function (state, m, tag, c, ad) {
908 if (!ad) ad = OPTIONAL
909
910 assert(ArrayBuffer.isView(state), 'state must be a typed array')
911 assert(
912 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
913 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
914 )
915 assert(ArrayBuffer.isView(tag), 'tag must be a typed array')
916 assert(tag.byteLength === 1, 'tag must be 1 byte')
917
918 assert(ArrayBuffer.isView(c), 'c must be a typed array')
919 assert(
920 c.byteLength >= binding.crypto_secretstream_xchacha20poly1305_ABYTES,
921 "c must be at least 'crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
922 )
923 assert(ArrayBuffer.isView(m), 'm must be a typed array')
924 assert(
925 m.byteLength === c.byteLength - binding.crypto_secretstream_xchacha20poly1305_ABYTES,
926 "m must be 'c.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
927 )
928
929 const res = binding.crypto_secretstream_xchacha20poly1305_pull(
930 state.buffer,
931 state.byteOffset,
932 state.byteLength,
933
934 m.buffer,
935 m.byteOffset,
936 m.byteLength,
937
938 tag.buffer,
939 tag.byteOffset,
940 tag.byteLength,
941
942 c.buffer,
943 c.byteOffset,
944 c.byteLength,
945
946 ad.buffer,
947 ad.byteOffset,
948 ad.byteLength
949 )
950
951 if (res < 0) throw new Error('pull failed')
952
953 return res
954}
955
956exports.crypto_secretstream_xchacha20poly1305_rekey = function (state) {
957 assert(ArrayBuffer.isView(state), 'state must be a typed array')
958 assert(
959 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
960 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
961 )
962
963 binding.crypto_secretstream_xchacha20poly1305_rekey(
964 state.buffer,
965 state.byteOffset,
966 state.byteLength
967 )
968}
969
970// crypto_stream
971
972exports.crypto_stream = function (c, n, k) {
973 assert(ArrayBuffer.isView(c), 'c must be a typed array')
974 assert(ArrayBuffer.isView(n), 'n must be a typed array')
975 assert(ArrayBuffer.isView(k), 'k must be a typed array')
976 assert(
977 n.byteLength === binding.crypto_stream_NONCEBYTES,
978 "n must be 'crypto_stream_NONCEBYTES' bytes"
979 )
980 assert(
981 k.byteLength === binding.crypto_stream_KEYBYTES,
982 "k must be 'crypto_stream_KEYBYTES' bytes"
983 )
984
985 const res = binding.crypto_stream(c, n, k)
986
987 if (res !== 0) throw new Error('status: ' + res)
988}
989
990exports.crypto_stream_xor = function (c, m, n, k) {
991 assert(ArrayBuffer.isView(c), 'c must be a typed array')
992 assert(ArrayBuffer.isView(m), 'm must be a typed array')
993 assert(ArrayBuffer.isView(n), 'n must be a typed array')
994 assert(ArrayBuffer.isView(k), 'k must be a typed array')
995 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
996 assert(
997 n.byteLength === binding.crypto_stream_NONCEBYTES,
998 "n must be 'crypto_stream_NONCEBYTES' bytes"
999 )
1000 assert(
1001 k.byteLength === binding.crypto_stream_KEYBYTES,
1002 "k must be 'crypto_stream_KEYBYTES' bytes"
1003 )
1004
1005 const res = binding.crypto_stream_xor(
1006 c.buffer,
1007 c.byteOffset,
1008 c.byteLength,
1009
1010 m.buffer,
1011 m.byteOffset,
1012 m.byteLength,
1013
1014 n.buffer,
1015 n.byteOffset,
1016 n.byteLength,
1017
1018 k.buffer,
1019 k.byteOffset,
1020 k.byteLength
1021 )
1022
1023 if (res !== 0) throw new Error('status: ' + res)
1024}
1025
1026exports.crypto_stream_chacha20 = function (c, n, k) {
1027 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1028 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1029 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1030 assert(
1031 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1032 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1033 )
1034 assert(
1035 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1036 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1037 )
1038
1039 const res = binding.crypto_stream_chacha20(c, n, k)
1040
1041 if (res !== 0) throw new Error('status: ' + res)
1042}
1043
1044exports.crypto_stream_chacha20_xor = function (c, m, n, k) {
1045 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1046 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1047 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1048 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1049 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1050 assert(
1051 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1052 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1053 )
1054 assert(
1055 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1056 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1057 )
1058
1059 const res = binding.crypto_stream_chacha20_xor(c, m, n, k)
1060
1061 if (res !== 0) throw new Error('status: ' + res)
1062}
1063
1064exports.crypto_stream_chacha20_xor_ic = function (c, m, n, ic, k) {
1065 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1066 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1067 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1068 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1069 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1070 assert(
1071 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1072 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1073 )
1074 assert(
1075 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1076 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1077 )
1078
1079 const res = binding.crypto_stream_chacha20_xor_ic(c, m, n, ic, k)
1080
1081 if (res !== 0) throw new Error('status: ' + res)
1082}
1083
1084exports.crypto_stream_chacha20_ietf = function (c, n, k) {
1085 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1086 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1087 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1088 assert(
1089 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1090 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1091 )
1092 assert(
1093 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1094 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1095 )
1096
1097 const res = binding.crypto_stream_chacha20_ietf(c, n, k)
1098
1099 if (res !== 0) throw new Error('status: ' + res)
1100}
1101
1102exports.crypto_stream_chacha20_ietf_xor = function (c, m, n, k) {
1103 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1104 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1105 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1106 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1107 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1108 assert(
1109 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1110 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1111 )
1112 assert(
1113 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1114 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1115 )
1116
1117 const res = binding.crypto_stream_chacha20_ietf_xor(c, m, n, k)
1118
1119 if (res !== 0) throw new Error('status: ' + res)
1120}
1121
1122exports.crypto_stream_chacha20_ietf_xor_ic = function (c, m, n, ic, k) {
1123 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1124 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1125 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1126 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1127 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1128 assert(
1129 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1130 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1131 )
1132 assert(
1133 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1134 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1135 )
1136
1137 const res = binding.crypto_stream_chacha20_ietf_xor_ic(c, m, n, ic, k)
1138
1139 if (res !== 0) throw new Error('status: ' + res)
1140}
1141
1142exports.crypto_stream_xchacha20 = function (c, n, k) {
1143 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1144 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1145 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1146 assert(
1147 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1148 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1149 )
1150 assert(
1151 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1152 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1153 )
1154
1155 const res = binding.crypto_stream_xchacha20(c, n, k)
1156
1157 if (res !== 0) throw new Error('status: ' + res)
1158}
1159
1160exports.crypto_stream_xchacha20_xor = function (c, m, n, k) {
1161 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1162 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1163 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1164 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1165 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1166 assert(
1167 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1168 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1169 )
1170 assert(
1171 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1172 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1173 )
1174
1175 const res = binding.crypto_stream_xchacha20_xor(c, m, n, k)
1176
1177 if (res !== 0) throw new Error('status: ' + res)
1178}
1179
1180exports.crypto_stream_xchacha20_xor_ic = function (c, m, n, ic, k) {
1181 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1182 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1183 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1184 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1185 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1186 assert(
1187 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1188 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1189 )
1190 assert(
1191 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1192 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1193 )
1194
1195 const res = binding.crypto_stream_xchacha20_xor_ic(c, m, n, ic, k)
1196
1197 if (res !== 0) throw new Error('status: ' + res)
1198}
1199
1200exports.crypto_stream_salsa20 = function (c, n, k) {
1201 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1202 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1203 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1204 assert(
1205 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1206 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1207 )
1208 assert(
1209 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1210 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1211 )
1212
1213 const res = binding.crypto_stream_salsa20(c, n, k)
1214
1215 if (res !== 0) throw new Error('status: ' + res)
1216}
1217
1218exports.crypto_stream_salsa20_xor = function (c, m, n, k) {
1219 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1220 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1221 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1222 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1223 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1224 assert(
1225 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1226 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1227 )
1228 assert(
1229 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1230 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1231 )
1232
1233 const res = binding.crypto_stream_salsa20_xor(c, m, n, k)
1234
1235 if (res !== 0) throw new Error('status: ' + res)
1236}
1237
1238exports.crypto_stream_salsa20_xor_ic = function (c, m, n, ic, k) {
1239 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1240 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1241 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1242 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1243 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1244 assert(
1245 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1246 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1247 )
1248 assert(
1249 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1250 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1251 )
1252
1253 const res = binding.crypto_stream_salsa20_xor_ic(c, m, n, ic, k)
1254
1255 if (res !== 0) throw new Error('status: ' + res)
1256}
1257
1258// crypto_auth
1259
1260exports.crypto_auth = function (out, input, k) {
1261 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1262 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1263 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1264 assert(out.byteLength === binding.crypto_auth_BYTES, "out must be 'crypto_auth_BYTES' bytes")
1265 assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes")
1266
1267 const res = binding.crypto_auth(out, input, k)
1268
1269 if (res !== 0) throw new Error('status: ' + res)
1270}
1271
1272exports.crypto_auth_verify = function (h, input, k) {
1273 assert(ArrayBuffer.isView(h), 'h must be a typed array')
1274 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1275 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1276 assert(h.byteLength === binding.crypto_auth_BYTES, "h must be 'crypto_auth_BYTES' bytes")
1277 assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes")
1278
1279 return binding.crypto_auth_verify(h, input, k)
1280}
1281
1282// crypto_onetimeauth
1283
1284exports.crypto_onetimeauth = function (out, input, k) {
1285 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1286 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1287 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1288 assert(
1289 out.byteLength === binding.crypto_onetimeauth_BYTES,
1290 "out must be 'crypto_onetimeauth_BYTES' bytes"
1291 )
1292 assert(
1293 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1294 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1295 )
1296
1297 const res = binding.crypto_onetimeauth(out, input, k)
1298
1299 if (res !== 0) throw new Error('status: ' + res)
1300}
1301
1302exports.crypto_onetimeauth_init = function (state, k) {
1303 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1304 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1305 assert(
1306 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1307 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1308 )
1309 assert(
1310 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1311 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1312 )
1313
1314 const res = binding.crypto_onetimeauth_init(state, k)
1315
1316 if (res !== 0) throw new Error('status: ' + res)
1317}
1318
1319exports.crypto_onetimeauth_update = function (state, input) {
1320 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1321 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1322 assert(
1323 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1324 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1325 )
1326
1327 const res = binding.crypto_onetimeauth_update(state, input)
1328
1329 if (res !== 0) throw new Error('status: ' + res)
1330}
1331
1332exports.crypto_onetimeauth_final = function (state, out) {
1333 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1334 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1335 assert(
1336 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1337 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1338 )
1339 assert(
1340 out.byteLength === binding.crypto_onetimeauth_BYTES,
1341 "out must be 'crypto_onetimeauth_BYTES' bytes"
1342 )
1343
1344 const res = binding.crypto_onetimeauth_final(state, out)
1345
1346 if (res !== 0) throw new Error('status: ' + res)
1347}
1348
1349exports.crypto_onetimeauth_verify = function (h, input, k) {
1350 assert(ArrayBuffer.isView(h), 'h must be a typed array')
1351 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1352 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1353 assert(
1354 h.byteLength === binding.crypto_onetimeauth_BYTES,
1355 "h must be 'crypto_onetimeauth_BYTES' bytes"
1356 )
1357 assert(
1358 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1359 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1360 )
1361
1362 return binding.crypto_onetimeauth_verify(h, input, k)
1363}
1364
1365// crypto_pwhash
1366
1367exports.crypto_pwhash = function (out, passwd, salt, opslimit, memlimit, alg) {
1368 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1369 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1370 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1371 assert(
1372 out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
1373 "out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
1374 )
1375 assert(
1376 out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
1377 "out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
1378 )
1379 assert(
1380 salt.byteLength === binding.crypto_pwhash_SALTBYTES,
1381 "salt must be 'crypto_pwhash_SALTBYTES' bytes"
1382 )
1383 assert(
1384 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1385 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1386 )
1387 assert(
1388 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1389 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1390 )
1391 assert(
1392 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1393 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1394 )
1395 assert(
1396 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1397 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1398 )
1399 assert(alg >= 1 && alg <= 2, 'alg must be either Argon2i 1.3 or Argon2id 1.3')
1400
1401 const res = binding.crypto_pwhash(out, passwd, salt, opslimit, memlimit, alg)
1402
1403 if (res !== 0) throw new Error('status: ' + res)
1404}
1405
1406exports.crypto_pwhash_async = function (
1407 out,
1408 passwd,
1409 salt,
1410 opslimit,
1411 memlimit,
1412 alg,
1413 callback = undefined
1414) {
1415 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1416 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1417 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1418 assert(
1419 out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
1420 "out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
1421 )
1422 assert(
1423 out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
1424 "out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
1425 )
1426 assert(
1427 salt.byteLength === binding.crypto_pwhash_SALTBYTES,
1428 "salt must be 'crypto_pwhash_SALTBYTES' bytes"
1429 )
1430 assert(
1431 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1432 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1433 )
1434 assert(
1435 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1436 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1437 )
1438 assert(
1439 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1440 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1441 )
1442 assert(
1443 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1444 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1445 )
1446 assert(alg >= 1 && alg <= 2, 'alg must be either Argon2i 1.3 or Argon2id 1.3')
1447
1448 const [done, promise] = checkStatus(callback)
1449
1450 binding.crypto_pwhash_async(
1451 out.buffer,
1452 out.byteOffset,
1453 out.byteLength,
1454
1455 passwd.buffer,
1456 passwd.byteOffset,
1457 passwd.byteLength,
1458
1459 salt.buffer,
1460 salt.byteOffset,
1461 salt.byteLength,
1462
1463 opslimit,
1464 memlimit,
1465 alg,
1466
1467 done
1468 )
1469
1470 return promise
1471}
1472
1473exports.crypto_pwhash_str = function (out, passwd, opslimit, memlimit) {
1474 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1475 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1476 assert(
1477 out.byteLength === binding.crypto_pwhash_STRBYTES,
1478 "out must be 'crypto_pwhash_STRBYTES' bytes"
1479 )
1480 assert(typeof opslimit === 'number', 'opslimit must be a number')
1481 assert(
1482 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1483 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1484 )
1485 assert(
1486 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1487 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1488 )
1489 assert(typeof memlimit === 'number', 'memlimit must be a number')
1490 assert(
1491 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1492 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1493 )
1494 assert(
1495 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1496 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1497 )
1498
1499 const res = binding.crypto_pwhash_str(out, passwd, opslimit, memlimit)
1500
1501 if (res !== 0) throw new Error('status: ' + res)
1502}
1503
1504exports.crypto_pwhash_str_async = function (out, passwd, opslimit, memlimit, callback = undefined) {
1505 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1506 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1507 assert(
1508 out.byteLength === binding.crypto_pwhash_STRBYTES,
1509 "out must be 'crypto_pwhash_STRBYTES' bytes"
1510 )
1511 assert(passwd.byteLength > 0, 'passwd must not be empty')
1512 assert(typeof opslimit === 'number', 'opslimit must be a number')
1513 assert(
1514 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1515 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1516 )
1517 assert(
1518 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1519 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1520 )
1521 assert(typeof memlimit === 'number', 'memlimit must be a number')
1522 assert(
1523 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1524 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1525 )
1526 assert(
1527 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1528 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1529 )
1530
1531 const [done, promise] = checkStatus(callback)
1532
1533 binding.crypto_pwhash_str_async(
1534 out.buffer,
1535 out.byteOffset,
1536 out.byteLength,
1537
1538 passwd.buffer,
1539 passwd.byteOffset,
1540 passwd.byteLength,
1541
1542 opslimit,
1543 memlimit,
1544
1545 done
1546 )
1547
1548 return promise
1549}
1550
1551exports.crypto_pwhash_str_verify = function (str, passwd) {
1552 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1553 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1554 assert(
1555 str.byteLength === binding.crypto_pwhash_STRBYTES,
1556 "str must be 'crypto_pwhash_STRBYTES' bytes"
1557 )
1558
1559 return binding.crypto_pwhash_str_verify(str, passwd)
1560}
1561
1562exports.crypto_pwhash_str_verify_async = function (str, passwd, callback = undefined) {
1563 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1564 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1565 assert(
1566 str.byteLength === binding.crypto_pwhash_STRBYTES,
1567 "str must be 'crypto_pwhash_STRBYTES' bytes"
1568 )
1569 assert(passwd.byteLength > 0, 'passwd must not be empty')
1570
1571 const [done, promise] = checkStatus(callback, true)
1572
1573 binding.crypto_pwhash_str_verify_async(
1574 str.buffer,
1575 str.byteOffset,
1576 str.byteLength,
1577
1578 passwd.buffer,
1579 passwd.byteOffset,
1580 passwd.byteLength,
1581
1582 done
1583 )
1584
1585 return promise
1586}
1587
1588exports.crypto_pwhash_str_needs_rehash = function (str, opslimit, memlimit) {
1589 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1590 assert(
1591 str.byteLength === binding.crypto_pwhash_STRBYTES,
1592 "str must be 'crypto_pwhash_STRBYTES' bytes"
1593 )
1594 assert(
1595 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1596 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1597 )
1598 assert(
1599 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1600 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1601 )
1602 assert(
1603 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1604 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1605 )
1606 assert(
1607 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1608 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1609 )
1610
1611 return binding.crypto_pwhash_str_needs_rehash(str, opslimit, memlimit)
1612}
1613
1614exports.crypto_pwhash_scryptsalsa208sha256 = function (out, passwd, salt, opslimit, memlimit) {
1615 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1616 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1617 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1618 assert(
1619 out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
1620 "out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
1621 )
1622 assert(
1623 out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
1624 "out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
1625 )
1626 assert(
1627 salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
1628 "salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
1629 )
1630 assert(
1631 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1632 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1633 )
1634 assert(
1635 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1636 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1637 )
1638 assert(
1639 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1640 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1641 )
1642 assert(
1643 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1644 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1645 )
1646
1647 const res = binding.crypto_pwhash_scryptsalsa208sha256(out, passwd, salt, opslimit, memlimit)
1648
1649 if (res !== 0) throw new Error('status: ' + res)
1650}
1651
1652exports.crypto_pwhash_scryptsalsa208sha256_async = function (
1653 out,
1654 passwd,
1655 salt,
1656 opslimit,
1657 memlimit,
1658 callback = undefined
1659) {
1660 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1661 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1662 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1663 assert(
1664 out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
1665 "out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
1666 )
1667 assert(
1668 out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
1669 "out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
1670 )
1671 assert(passwd.byteLength > 0, 'passwd must not be empty')
1672 assert(
1673 salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
1674 "salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
1675 )
1676 assert(
1677 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1678 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1679 )
1680 assert(
1681 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1682 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1683 )
1684 assert(
1685 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1686 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1687 )
1688 assert(
1689 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1690 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1691 )
1692
1693 const [done, promise] = checkStatus(callback)
1694
1695 binding.crypto_pwhash_scryptsalsa208sha256_async(
1696 out.buffer,
1697 out.byteOffset,
1698 out.byteLength,
1699
1700 passwd.buffer,
1701 passwd.byteOffset,
1702 passwd.byteLength,
1703
1704 salt.buffer,
1705 salt.byteOffset,
1706 salt.byteLength,
1707
1708 opslimit,
1709 memlimit,
1710
1711 done
1712 )
1713
1714 return promise
1715}
1716
1717exports.crypto_pwhash_scryptsalsa208sha256_str_async = function (
1718 out,
1719 passwd,
1720 opslimit,
1721 memlimit,
1722 callback = undefined
1723) {
1724 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1725 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1726 assert(
1727 out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1728 "out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1729 )
1730 assert(passwd.byteLength > 0, 'passwd must not be empty')
1731 assert(
1732 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1733 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1734 )
1735 assert(
1736 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1737 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1738 )
1739 assert(
1740 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1741 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1742 )
1743 assert(
1744 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1745 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1746 )
1747
1748 const [done, promise] = checkStatus(callback)
1749
1750 binding.crypto_pwhash_scryptsalsa208sha256_str_async(
1751 out.buffer,
1752 out.byteOffset,
1753 out.byteLength,
1754
1755 passwd.buffer,
1756 passwd.byteOffset,
1757 passwd.byteLength,
1758
1759 opslimit,
1760 memlimit,
1761
1762 done
1763 )
1764
1765 return promise
1766}
1767
1768exports.crypto_pwhash_scryptsalsa208sha256_str = function (out, passwd, opslimit, memlimit) {
1769 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1770 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1771 assert(
1772 out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1773 "out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1774 )
1775 assert(passwd.byteLength > 0, 'passwd must not be empty')
1776 assert(
1777 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1778 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1779 )
1780 assert(
1781 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1782 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1783 )
1784 assert(
1785 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1786 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1787 )
1788 assert(
1789 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1790 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1791 )
1792
1793 const res = binding.crypto_pwhash_scryptsalsa208sha256_str(out, passwd, opslimit, memlimit)
1794
1795 if (res !== 0) throw new Error('status: ' + res)
1796}
1797
1798exports.crypto_pwhash_scryptsalsa208sha256_str_verify_async = function (
1799 str,
1800 passwd,
1801 callback = undefined
1802) {
1803 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1804 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1805 assert(
1806 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1807 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1808 )
1809 assert(passwd.byteLength > 0, 'passwd must not be empty')
1810
1811 const [done, promise] = checkStatus(callback, true)
1812
1813 binding.crypto_pwhash_scryptsalsa208sha256_str_verify_async(
1814 str.buffer,
1815 str.byteOffset,
1816 str.byteLength,
1817
1818 passwd.buffer,
1819 passwd.byteOffset,
1820 passwd.byteLength,
1821
1822 done
1823 )
1824
1825 return promise
1826}
1827
1828exports.crypto_pwhash_scryptsalsa208sha256_str_verify = function (str, passwd) {
1829 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1830 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1831 assert(
1832 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1833 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1834 )
1835 assert(passwd.byteLength > 0, 'passwd must not be empty')
1836
1837 return binding.crypto_pwhash_scryptsalsa208sha256_str_verify(str, passwd)
1838}
1839
1840exports.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash = function (str, opslimit, memlimit) {
1841 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1842 assert(
1843 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1844 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1845 )
1846 assert(
1847 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1848 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1849 )
1850 assert(
1851 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1852 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1853 )
1854 assert(
1855 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1856 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1857 )
1858 assert(
1859 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1860 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1861 )
1862
1863 return binding.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str, opslimit, memlimit)
1864}
1865
1866// crypto_kx
1867
1868exports.crypto_kx_keypair = function (pk, sk) {
1869 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
1870 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
1871 assert(
1872 pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1873 "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1874 )
1875 assert(
1876 sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1877 "sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1878 )
1879
1880 const res = binding.crypto_kx_keypair(pk, sk)
1881
1882 if (res !== 0) throw new Error('status: ' + res)
1883}
1884
1885exports.crypto_kx_seed_keypair = function (pk, sk, seed) {
1886 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
1887 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
1888 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
1889 assert(
1890 pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1891 "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1892 )
1893 assert(
1894 sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1895 "sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1896 )
1897 assert(
1898 seed.byteLength === binding.crypto_kx_SEEDBYTES,
1899 "seed must be 'crypto_kx_SEEDBYTES' bytes"
1900 )
1901
1902 const res = binding.crypto_kx_seed_keypair(pk, sk, seed)
1903
1904 if (res !== 0) throw new Error('status: ' + res)
1905}
1906
1907exports.crypto_kx_client_session_keys = function (rx, tx, clientPk, clientSk, serverPk) {
1908 if (!rx) rx = undefined
1909 if (!tx) tx = undefined
1910
1911 assert(rx || tx, 'at least one session key must be specified')
1912
1913 if (rx) {
1914 assert(ArrayBuffer.isView(rx), 'rx must be a typed array')
1915 assert(
1916 rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1917 "rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1918 )
1919 }
1920
1921 if (tx) {
1922 assert(ArrayBuffer.isView(tx), 'tx must be a typed array')
1923 assert(
1924 tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1925 "tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1926 )
1927 }
1928
1929 assert(ArrayBuffer.isView(clientPk), 'clientPk must be a typed array')
1930 assert(ArrayBuffer.isView(clientSk), 'clientSk must be a typed array')
1931 assert(ArrayBuffer.isView(serverPk), 'serverPk must be a typed array')
1932 assert(
1933 clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1934 "clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1935 )
1936 assert(
1937 clientSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1938 "clientSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1939 )
1940 assert(
1941 serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1942 "serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1943 )
1944
1945 const res = binding.crypto_kx_client_session_keys(rx, tx, clientPk, clientSk, serverPk)
1946
1947 if (res !== 0) throw new Error('status: ' + res)
1948}
1949
1950exports.crypto_kx_server_session_keys = function (rx, tx, serverPk, serverSk, clientPk) {
1951 if (!rx) rx = undefined
1952 if (!tx) tx = undefined
1953
1954 assert(rx || tx, 'at least one session key must be specified')
1955
1956 if (rx) {
1957 assert(ArrayBuffer.isView(rx), 'rx must be a typed array')
1958 assert(
1959 rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1960 "rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1961 )
1962 }
1963
1964 if (tx) {
1965 assert(ArrayBuffer.isView(tx), 'tx must be a typed array')
1966 assert(
1967 tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1968 "tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1969 )
1970 }
1971
1972 assert(ArrayBuffer.isView(serverPk), 'serverPk must be a typed array')
1973 assert(ArrayBuffer.isView(serverSk), 'serverSk must be a typed array')
1974 assert(ArrayBuffer.isView(clientPk), 'clientPk must be a typed array')
1975 assert(
1976 serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1977 "serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1978 )
1979 assert(
1980 serverSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1981 "serverSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1982 )
1983 assert(
1984 clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1985 "clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1986 )
1987
1988 const res = binding.crypto_kx_server_session_keys(rx, tx, serverPk, serverSk, clientPk)
1989
1990 if (res !== 0) throw new Error('status: ' + res)
1991}
1992
1993// crypto_scalarmult
1994
1995exports.crypto_scalarmult_base = function (q, n) {
1996 assert(ArrayBuffer.isView(q), 'q must be a typed array')
1997 assert(
1998 q.byteLength === binding.crypto_scalarmult_BYTES,
1999 "q must be 'crypto_scalarmult_BYTES' bytes"
2000 )
2001 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2002 assert(
2003 n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
2004 "n must be 'crypto_scalarmult_SCALARBYTES' bytes"
2005 )
2006
2007 const res = binding.crypto_scalarmult_base(q, n)
2008
2009 if (res !== 0) throw new Error('status: ' + res)
2010}
2011
2012exports.crypto_scalarmult = function (q, n, p) {
2013 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2014 assert(
2015 q.byteLength === binding.crypto_scalarmult_BYTES,
2016 "q must be 'crypto_scalarmult_BYTES' bytes"
2017 )
2018 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2019 assert(
2020 n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
2021 "n must be 'crypto_scalarmult_SCALARBYTES' bytes"
2022 )
2023 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2024 assert(
2025 p.byteLength === binding.crypto_scalarmult_BYTES,
2026 "p must be 'crypto_scalarmult_BYTES' bytes"
2027 )
2028
2029 const res = binding.crypto_scalarmult(q, n, p)
2030
2031 if (res !== 0) throw new Error('status: ' + res)
2032}
2033
2034exports.crypto_scalarmult_ed25519_base = function (q, n) {
2035 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2036 assert(
2037 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2038 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2039 )
2040 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2041 assert(
2042 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2043 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2044 )
2045
2046 const res = binding.crypto_scalarmult_ed25519_base(q, n)
2047
2048 if (res !== 0) throw new Error('status: ' + res)
2049}
2050
2051exports.crypto_scalarmult_ed25519 = function (q, n, p) {
2052 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2053 assert(
2054 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2055 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2056 )
2057 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2058 assert(
2059 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2060 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2061 )
2062 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2063 assert(
2064 p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2065 "p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2066 )
2067
2068 const res = binding.crypto_scalarmult_ed25519(q, n, p)
2069
2070 if (res !== 0) throw new Error('status: ' + res)
2071}
2072
2073exports.crypto_core_ed25519_is_valid_point = function (p) {
2074 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2075 assert(
2076 p.byteLength === binding.crypto_core_ed25519_BYTES,
2077 "p must be 'crypto_core_ed25519_BYTES' bytes"
2078 )
2079
2080 return binding.crypto_core_ed25519_is_valid_point(p)
2081}
2082
2083exports.crypto_core_ed25519_from_uniform = function (p, r) {
2084 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2085 assert(
2086 p.byteLength === binding.crypto_core_ed25519_BYTES,
2087 "p must be 'crypto_core_ed25519_BYTES' bytes"
2088 )
2089 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2090 assert(
2091 r.byteLength === binding.crypto_core_ed25519_UNIFORMBYTES,
2092 "r must be 'crypto_core_ed25519_UNIFORMBYTES' bytes"
2093 )
2094
2095 const res = binding.crypto_core_ed25519_from_uniform(p, r)
2096
2097 if (res !== 0) throw new Error('status: ' + res)
2098}
2099
2100exports.crypto_scalarmult_ed25519_base_noclamp = function (q, n) {
2101 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2102 assert(
2103 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2104 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2105 )
2106 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2107 assert(
2108 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2109 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2110 )
2111
2112 const res = binding.crypto_scalarmult_ed25519_base_noclamp(q, n)
2113
2114 if (res !== 0) throw new Error('status: ' + res)
2115}
2116
2117exports.crypto_scalarmult_ed25519_noclamp = function (q, n, p) {
2118 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2119 assert(
2120 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2121 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2122 )
2123 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2124 assert(
2125 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2126 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2127 )
2128 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2129 assert(
2130 p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2131 "p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2132 )
2133
2134 const res = binding.crypto_scalarmult_ed25519_noclamp(q, n, p)
2135
2136 if (res !== 0) throw new Error('status: ' + res)
2137}
2138
2139// crypto_core
2140
2141exports.crypto_core_ed25519_add = function (r, p, q) {
2142 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2143 assert(
2144 r.byteLength === binding.crypto_core_ed25519_BYTES,
2145 "r must be 'crypto_core_ed25519_BYTES' bytes"
2146 )
2147 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2148 assert(
2149 p.byteLength === binding.crypto_core_ed25519_BYTES,
2150 "p must be 'crypto_core_ed25519_BYTES' bytes"
2151 )
2152 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2153 assert(
2154 q.byteLength === binding.crypto_core_ed25519_BYTES,
2155 "q must be 'crypto_core_ed25519_BYTES' bytes"
2156 )
2157
2158 const res = binding.crypto_core_ed25519_add(r, p, q)
2159
2160 if (res !== 0) throw new Error('status: ' + res)
2161}
2162
2163exports.crypto_core_ed25519_sub = function (r, p, q) {
2164 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2165 assert(
2166 r.byteLength === binding.crypto_core_ed25519_BYTES,
2167 "r must be 'crypto_core_ed25519_BYTES' bytes"
2168 )
2169 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2170 assert(
2171 p.byteLength === binding.crypto_core_ed25519_BYTES,
2172 "p must be 'crypto_core_ed25519_BYTES' bytes"
2173 )
2174 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2175 assert(
2176 q.byteLength === binding.crypto_core_ed25519_BYTES,
2177 "q must be 'crypto_core_ed25519_BYTES' bytes"
2178 )
2179
2180 const res = binding.crypto_core_ed25519_sub(r, p, q)
2181
2182 if (res !== 0) throw new Error('status: ' + res)
2183}
2184
2185exports.crypto_core_ed25519_scalar_random = function (r) {
2186 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2187 assert(
2188 r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2189 "r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2190 )
2191
2192 binding.crypto_core_ed25519_scalar_random(r)
2193}
2194
2195exports.crypto_core_ed25519_scalar_reduce = function (r, s) {
2196 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2197 assert(
2198 r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2199 "r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2200 )
2201 assert(ArrayBuffer.isView(s), 's must be a typed array')
2202 assert(
2203 s.byteLength === binding.crypto_core_ed25519_NONREDUCEDSCALARBYTES,
2204 "s must be 'crypto_core_ed25519_NONREDUCEDSCALARBYTES' bytes"
2205 )
2206
2207 binding.crypto_core_ed25519_scalar_reduce(r, s)
2208}
2209
2210exports.crypto_core_ed25519_scalar_invert = function (recip, s) {
2211 assert(ArrayBuffer.isView(recip), 'recip must be a typed array')
2212 assert(
2213 recip.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2214 "recip must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2215 )
2216 assert(ArrayBuffer.isView(s), 's must be a typed array')
2217 assert(
2218 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2219 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2220 )
2221
2222 binding.crypto_core_ed25519_scalar_invert(recip, s)
2223}
2224
2225exports.crypto_core_ed25519_scalar_negate = function (neg, s) {
2226 assert(ArrayBuffer.isView(neg), 'neg must be a typed array')
2227 assert(
2228 neg.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2229 "neg must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2230 )
2231 assert(ArrayBuffer.isView(s), 's must be a typed array')
2232 assert(
2233 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2234 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2235 )
2236
2237 binding.crypto_core_ed25519_scalar_negate(neg, s)
2238}
2239
2240exports.crypto_core_ed25519_scalar_complement = function (comp, s) {
2241 assert(ArrayBuffer.isView(comp), 'comp must be a typed array')
2242 assert(
2243 comp.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2244 "comp must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2245 )
2246 assert(ArrayBuffer.isView(s), 's must be a typed array')
2247 assert(
2248 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2249 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2250 )
2251
2252 binding.crypto_core_ed25519_scalar_complement(comp, s)
2253}
2254
2255exports.crypto_core_ed25519_scalar_add = function (z, x, y) {
2256 assert(ArrayBuffer.isView(z), 'z must be a typed array')
2257 assert(
2258 z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2259 "z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2260 )
2261 assert(ArrayBuffer.isView(x), 'x must be a typed array')
2262 assert(
2263 x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2264 "x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2265 )
2266 assert(ArrayBuffer.isView(y), 'y must be a typed array')
2267 assert(
2268 y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2269 "y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2270 )
2271
2272 binding.crypto_core_ed25519_scalar_add(z, x, y)
2273}
2274
2275exports.crypto_core_ed25519_scalar_sub = function (z, x, y) {
2276 assert(ArrayBuffer.isView(z), 'z must be a typed array')
2277 assert(
2278 z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2279 "z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2280 )
2281 assert(ArrayBuffer.isView(x), 'x must be a typed array')
2282 assert(
2283 x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2284 "x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2285 )
2286 assert(ArrayBuffer.isView(y), 'y must be a typed array')
2287 assert(
2288 y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2289 "y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2290 )
2291
2292 binding.crypto_core_ed25519_scalar_sub(z, x, y)
2293}
2294
2295// crypto_shorthash
2296
2297exports.crypto_shorthash = function (out, input, k) {
2298 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2299 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2300 assert(
2301 out.byteLength === binding.crypto_shorthash_BYTES,
2302 "out must be 'crypto_shorthash_BYTES' bytes"
2303 )
2304 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2305 assert(
2306 k.byteLength === binding.crypto_shorthash_KEYBYTES,
2307 "k must be 'crypto_shorthash_KEYBYTES' bytes"
2308 )
2309
2310 const res = binding.crypto_shorthash(out, input, k)
2311
2312 if (res !== 0) throw new Error('status: ' + res)
2313}
2314
2315// crypto_kdf
2316
2317exports.crypto_kdf_keygen = function (key) {
2318 assert(ArrayBuffer.isView(key), 'key must be a typed array')
2319 assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes")
2320
2321 binding.crypto_kdf_keygen(key)
2322}
2323
2324exports.crypto_kdf_derive_from_key = function (subkey, subkeyId, ctx, key) {
2325 assert(ArrayBuffer.isView(subkey), 'subkey must be a typed array')
2326 assert(
2327 subkey.byteLength >= binding.crypto_kdf_BYTES_MIN,
2328 "subkey must be at least 'crypto_kdf_BYTES_MIN' bytes"
2329 )
2330 assert(
2331 subkey.byteLength <= binding.crypto_kdf_BYTES_MAX,
2332 "subkey must be at most 'crypto_kdf_BYTES_MAX' bytes"
2333 )
2334 assert(ArrayBuffer.isView(ctx), 'ctx must be a typed array')
2335 assert(
2336 ctx.byteLength === binding.crypto_kdf_CONTEXTBYTES,
2337 "ctx must be 'crypto_kdf_CONTEXTBYTES' bytes"
2338 )
2339 assert(ArrayBuffer.isView(key), 'key must be a typed array')
2340 assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes")
2341
2342 const res = binding.crypto_kdf_derive_from_key(subkey, subkeyId, ctx, key)
2343
2344 if (res !== 0) throw new Error('status: ' + res)
2345}
2346
2347// crypto_hash
2348
2349exports.crypto_hash = function (out, input) {
2350 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2351 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2352 assert(out.byteLength === binding.crypto_hash_BYTES, "out must be 'crypto_hash_BYTES' bytes")
2353
2354 const res = binding.crypto_hash(out, input)
2355
2356 if (res !== 0) throw new Error('status: ' + res)
2357}
2358
2359exports.crypto_hash_sha256 = function (out, input) {
2360 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2361 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2362 assert(
2363 out.byteLength === binding.crypto_hash_sha256_BYTES,
2364 "out must be 'crypto_hash_sha256_BYTES' bytes"
2365 )
2366
2367 const res = binding.crypto_hash_sha256(out, input)
2368
2369 if (res !== 0) throw new Error('status: ' + res)
2370}
2371
2372exports.crypto_hash_sha256_init = function (state) {
2373 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2374 assert(
2375 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2376 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2377 )
2378
2379 const res = binding.crypto_hash_sha256_init(state)
2380
2381 if (res !== 0) throw new Error('status: ' + res)
2382}
2383
2384exports.crypto_hash_sha256_update = function (state, input) {
2385 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2386 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2387 assert(
2388 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2389 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2390 )
2391
2392 const res = binding.crypto_hash_sha256_update(state, input)
2393
2394 if (res !== 0) throw new Error('status: ' + res)
2395}
2396
2397exports.crypto_hash_sha256_final = function (state, out) {
2398 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2399 assert(
2400 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2401 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2402 )
2403 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2404 assert(
2405 out.byteLength === binding.crypto_hash_sha256_BYTES,
2406 "out must be 'crypto_hash_sha256_BYTES' bytes"
2407 )
2408
2409 const res = binding.crypto_hash_sha256_final(state, out)
2410
2411 if (res !== 0) throw new Error('status: ' + res)
2412}
2413
2414exports.crypto_hash_sha512 = function (out, input) {
2415 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2416 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2417 assert(
2418 out.byteLength === binding.crypto_hash_sha512_BYTES,
2419 "out must be 'crypto_hash_sha512_BYTES' bytes"
2420 )
2421
2422 const res = binding.crypto_hash_sha512(out, input)
2423
2424 if (res !== 0) throw new Error('status: ' + res)
2425}
2426
2427exports.crypto_hash_sha512_init = function (state) {
2428 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2429 assert(
2430 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2431 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2432 )
2433
2434 const res = binding.crypto_hash_sha512_init(state)
2435
2436 if (res !== 0) throw new Error('status: ' + res)
2437}
2438
2439exports.crypto_hash_sha512_update = function (state, input) {
2440 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2441 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2442 assert(
2443 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2444 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2445 )
2446
2447 const res = binding.crypto_hash_sha512_update(state, input)
2448
2449 if (res !== 0) throw new Error('status: ' + res)
2450}
2451
2452exports.crypto_hash_sha512_final = function (state, out) {
2453 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2454 assert(
2455 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2456 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2457 )
2458 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2459 assert(
2460 out.byteLength === binding.crypto_hash_sha512_BYTES,
2461 "out must be 'crypto_hash_sha512_BYTES' bytes"
2462 )
2463
2464 const res = binding.crypto_hash_sha512_final(state, out)
2465
2466 if (res !== 0) throw new Error('status: ' + res)
2467}
2468
2469// crypto_aead
2470
2471exports.crypto_aead_xchacha20poly1305_ietf_keygen = function (k) {
2472 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2473 assert(
2474 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2475 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2476 )
2477
2478 binding.crypto_aead_xchacha20poly1305_ietf_keygen(k)
2479}
2480
2481exports.crypto_aead_xchacha20poly1305_ietf_encrypt = function (c, m, ad, nsec, npub, k) {
2482 if (!ad) ad = undefined
2483
2484 assert(nsec === null, 'nsec must always be set to null')
2485 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2486 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2487 assert(
2488 c.byteLength === m.byteLength + binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2489 "c must be 'm.byteLength + crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2490 )
2491 assert(c.byteLength <= 0xffffffff, 'c.byteLength must be a 32bit integer')
2492 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2493 assert(
2494 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2495 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2496 )
2497 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2498 assert(
2499 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2500 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2501 )
2502
2503 const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt(c, m, ad, npub, k)
2504
2505 if (res < 0) throw new Error('could not encrypt data')
2506
2507 return res
2508}
2509
2510exports.crypto_aead_xchacha20poly1305_ietf_decrypt = function (m, nsec, c, ad, npub, k) {
2511 if (!ad) ad = undefined
2512
2513 assert(nsec === null, 'nsec must always be set to null')
2514 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2515 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2516 assert(
2517 m.byteLength === c.byteLength - binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2518 "m must be 'c.byteLength - crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2519 )
2520 assert(m.byteLength <= 0xffffffff, 'm.byteLength must be a 32bit integer')
2521 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2522 assert(
2523 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2524 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2525 )
2526 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2527 assert(
2528 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2529 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2530 )
2531
2532 const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt(m, c, ad, npub, k)
2533
2534 if (res < 0) throw new Error('could not verify data')
2535
2536 return res
2537}
2538
2539exports.crypto_aead_xchacha20poly1305_ietf_encrypt_detached = function (
2540 c,
2541 mac,
2542 m,
2543 ad,
2544 nsec,
2545 npub,
2546 k
2547) {
2548 if (!ad) ad = undefined
2549
2550 assert(nsec === null, 'nsec must always be set to null')
2551 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2552 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2553 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2554 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2555 assert(
2556 mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2557 "mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2558 )
2559 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2560 assert(
2561 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2562 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2563 )
2564 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2565 assert(
2566 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2567 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2568 )
2569
2570 const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k)
2571
2572 if (res < 0) throw new Error('could not encrypt data')
2573
2574 return res
2575}
2576
2577exports.crypto_aead_xchacha20poly1305_ietf_decrypt_detached = function (
2578 m,
2579 nsec,
2580 c,
2581 mac,
2582 ad,
2583 npub,
2584 k
2585) {
2586 if (!ad) ad = undefined
2587
2588 assert(nsec === null, 'nsec must always be set to null')
2589 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2590 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2591 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
2592 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2593 assert(
2594 mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2595 "mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2596 )
2597 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2598 assert(
2599 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2600 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2601 )
2602 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2603 assert(
2604 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2605 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2606 )
2607
2608 const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k)
2609
2610 if (res !== 0) throw new Error('could not verify data')
2611}
2612
2613exports.crypto_aead_chacha20poly1305_ietf_keygen = function (k) {
2614 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2615 assert(
2616 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2617 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2618 )
2619
2620 binding.crypto_aead_chacha20poly1305_ietf_keygen(k)
2621}
2622
2623exports.crypto_aead_chacha20poly1305_ietf_encrypt = function (c, m, ad, nsec, npub, k) {
2624 if (!ad) ad = undefined
2625
2626 assert(nsec === null, 'nsec must always be set to null')
2627 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2628 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2629 assert(
2630 c.byteLength === m.byteLength + binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2631 "c must be 'm.byteLength + crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2632 )
2633 assert(c.byteLength <= 0xffffffff, 'c.byteLength must be a 32bit integer')
2634 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2635 assert(
2636 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2637 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2638 )
2639 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2640 assert(
2641 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2642 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2643 )
2644
2645 const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, ad, npub, k)
2646
2647 if (res < 0) throw new Error('could not encrypt data')
2648
2649 return res
2650}
2651
2652exports.crypto_aead_chacha20poly1305_ietf_decrypt = function (m, nsec, c, ad, npub, k) {
2653 if (!ad) ad = undefined
2654
2655 assert(nsec === null, 'nsec must always be set to null')
2656 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2657 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2658 assert(
2659 m.byteLength === c.byteLength - binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2660 "m must be 'c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2661 )
2662 assert(m.byteLength <= 0xffffffff, 'm.byteLength must be a 32bit integer')
2663 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2664 assert(
2665 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2666 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2667 )
2668 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2669 assert(
2670 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2671 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2672 )
2673
2674 const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt(m, c, ad, npub, k)
2675
2676 if (res < 0) throw new Error('could not verify data')
2677
2678 return res
2679}
2680
2681exports.crypto_aead_chacha20poly1305_ietf_encrypt_detached = function (
2682 c,
2683 mac,
2684 m,
2685 ad,
2686 nsec,
2687 npub,
2688 k
2689) {
2690 if (!ad) ad = undefined
2691
2692 assert(nsec === null, 'nsec must always be set to null')
2693 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2694 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2695 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2696 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2697 assert(
2698 mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2699 "mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2700 )
2701 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2702 assert(
2703 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2704 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2705 )
2706 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2707 assert(
2708 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2709 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2710 )
2711
2712 const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k)
2713
2714 if (res < 0) throw new Error('could not encrypt data')
2715
2716 return res
2717}
2718
2719exports.crypto_aead_chacha20poly1305_ietf_decrypt_detached = function (
2720 m,
2721 nsec,
2722 c,
2723 mac,
2724 ad,
2725 npub,
2726 k
2727) {
2728 if (!ad) ad = undefined
2729
2730 assert(nsec === null, 'nsec must always be set to null')
2731 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2732 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2733 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
2734 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2735 assert(
2736 mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2737 "mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2738 )
2739 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2740 assert(
2741 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2742 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2743 )
2744 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2745 assert(
2746 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2747 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2748 )
2749
2750 const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k)
2751
2752 if (res !== 0) throw new Error('could not verify data')
2753}
2754
2755// crypto_stream
2756
2757exports.crypto_stream_xor_wrap_init = function (state, n, k) {
2758 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2759 assert(
2760 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2761 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2762 )
2763 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2764 assert(
2765 n.byteLength === binding.crypto_stream_NONCEBYTES,
2766 "n must be 'crypto_stream_NONCEBYTES' bytes"
2767 )
2768 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2769 assert(
2770 k.byteLength === binding.crypto_stream_KEYBYTES,
2771 "k must be 'crypto_stream_KEYBYTES' bytes"
2772 )
2773
2774 binding.crypto_stream_xor_wrap_init(state, n, k)
2775}
2776
2777exports.crypto_stream_xor_wrap_update = function (state, c, m) {
2778 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2779 assert(
2780 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2781 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2782 )
2783 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2784 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2785 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2786
2787 binding.crypto_stream_xor_wrap_update(state, c, m)
2788}
2789
2790exports.crypto_stream_xor_wrap_final = function (state) {
2791 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2792 assert(
2793 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2794 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2795 )
2796
2797 binding.crypto_stream_xor_wrap_final(state)
2798}
2799
2800exports.crypto_stream_chacha20_xor_wrap_init = function (state, n, k) {
2801 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2802 assert(
2803 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2804 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2805 )
2806 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2807 assert(
2808 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
2809 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
2810 )
2811 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2812 assert(
2813 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
2814 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
2815 )
2816
2817 binding.crypto_stream_chacha20_xor_wrap_init(state, n, k)
2818}
2819
2820exports.crypto_stream_chacha20_xor_wrap_update = function (state, c, m) {
2821 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2822 assert(
2823 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2824 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2825 )
2826 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2827 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2828 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2829
2830 binding.crypto_stream_chacha20_xor_wrap_update(state, c, m)
2831}
2832
2833exports.crypto_stream_chacha20_xor_wrap_final = function (state) {
2834 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2835 assert(
2836 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2837 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2838 )
2839
2840 binding.crypto_stream_chacha20_xor_wrap_final(state)
2841}
2842
2843exports.crypto_stream_chacha20_ietf_xor_wrap_init = function (state, n, k) {
2844 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2845 assert(
2846 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2847 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2848 )
2849 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2850 assert(
2851 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
2852 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
2853 )
2854 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2855 assert(
2856 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
2857 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
2858 )
2859
2860 binding.crypto_stream_chacha20_ietf_xor_wrap_init(state, n, k)
2861}
2862
2863exports.crypto_stream_chacha20_ietf_xor_wrap_update = function (state, c, m) {
2864 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2865 assert(
2866 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2867 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2868 )
2869 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2870 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2871 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2872
2873 binding.crypto_stream_chacha20_ietf_xor_wrap_update(state, c, m)
2874}
2875
2876exports.crypto_stream_chacha20_ietf_xor_wrap_final = function (state) {
2877 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2878 assert(
2879 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2880 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2881 )
2882
2883 binding.crypto_stream_chacha20_ietf_xor_wrap_final(state)
2884}
2885
2886exports.crypto_stream_xchacha20_xor_wrap_init = function (state, n, k) {
2887 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2888 assert(
2889 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2890 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2891 )
2892 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2893 assert(
2894 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
2895 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
2896 )
2897 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2898 assert(
2899 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
2900 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
2901 )
2902
2903 binding.crypto_stream_xchacha20_xor_wrap_init(state, n, k)
2904}
2905
2906exports.crypto_stream_xchacha20_xor_wrap_update = function (state, c, m) {
2907 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2908 assert(
2909 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2910 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2911 )
2912 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2913 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2914 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2915
2916 binding.crypto_stream_xchacha20_xor_wrap_update(state, c, m)
2917}
2918
2919exports.crypto_stream_xchacha20_xor_wrap_final = function (state) {
2920 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2921 assert(
2922 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2923 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2924 )
2925
2926 binding.crypto_stream_xchacha20_xor_wrap_final(state)
2927}
2928
2929exports.crypto_stream_salsa20_xor_wrap_init = function (state, n, k) {
2930 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2931 assert(
2932 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2933 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2934 )
2935 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2936 assert(
2937 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
2938 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
2939 )
2940 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2941 assert(
2942 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
2943 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
2944 )
2945
2946 binding.crypto_stream_salsa20_xor_wrap_init(state, n, k)
2947}
2948
2949exports.crypto_stream_salsa20_xor_wrap_update = function (state, c, m) {
2950 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2951 assert(
2952 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2953 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2954 )
2955 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2956 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2957 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2958
2959 binding.crypto_stream_salsa20_xor_wrap_update(state, c, m)
2960}
2961
2962exports.crypto_stream_salsa20_xor_wrap_final = function (state) {
2963 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2964 assert(
2965 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2966 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2967 )
2968
2969 binding.crypto_stream_salsa20_xor_wrap_final(state)
2970}
2971
2972// experimental
2973
2974exports.extension_tweak_ed25519_base = function (n, p, ns) {
2975 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2976 assert(
2977 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
2978 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
2979 )
2980 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2981 assert(
2982 p.byteLength === binding.extension_tweak_ed25519_BYTES,
2983 "p must be 'extension_tweak_ed25519_BYTES' bytes"
2984 )
2985
2986 binding.extension_tweak_ed25519_base(n, p, ns)
2987}
2988
2989exports.extension_tweak_ed25519_sign_detached = function (sig, m, scalar, pk) {
2990 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
2991 assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes")
2992 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2993 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
2994 assert(
2995 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
2996 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
2997 )
2998
2999 if (pk) {
3000 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3001 assert(
3002 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3003 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3004 )
3005 }
3006
3007 const res = binding.extension_tweak_ed25519_sign_detached(sig, m, scalar, pk)
3008
3009 if (res !== 0) throw new Error('failed to compute signature')
3010}
3011
3012exports.extension_tweak_ed25519_sk_to_scalar = function (n, sk) {
3013 assert(ArrayBuffer.isView(n), 'n must be a typed array')
3014 assert(
3015 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3016 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3017 )
3018 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
3019 assert(
3020 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
3021 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
3022 )
3023
3024 binding.extension_tweak_ed25519_sk_to_scalar(n, sk)
3025}
3026
3027exports.extension_tweak_ed25519_scalar = function (scalarOut, scalar, ns) {
3028 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3029 assert(
3030 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3031 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3032 )
3033 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
3034 assert(
3035 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3036 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3037 )
3038
3039 binding.extension_tweak_ed25519_scalar(scalarOut, scalar, ns)
3040}
3041
3042exports.extension_tweak_ed25519_pk = function (tpk, pk, ns) {
3043 assert(ArrayBuffer.isView(tpk), 'tpk must be a typed array')
3044 assert(
3045 tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3046 "tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3047 )
3048 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3049 assert(
3050 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3051 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3052 )
3053
3054 const res = binding.extension_tweak_ed25519_pk(tpk, pk, ns)
3055
3056 if (res !== 0) throw new Error('failed to tweak public key')
3057}
3058
3059exports.extension_tweak_ed25519_keypair = function (pk, scalarOut, scalarIn, ns) {
3060 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3061 assert(
3062 pk.byteLength === binding.extension_tweak_ed25519_BYTES,
3063 "pk must be 'extension_tweak_ed25519_BYTES' bytes"
3064 )
3065 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3066 assert(
3067 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3068 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3069 )
3070 assert(ArrayBuffer.isView(scalarIn), 'scalarIn must be a typed array')
3071 assert(
3072 scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3073 "scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3074 )
3075
3076 binding.extension_tweak_ed25519_keypair(pk, scalarOut, scalarIn, ns)
3077}
3078
3079exports.extension_tweak_ed25519_scalar_add = function (scalarOut, scalar, n) {
3080 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3081 assert(
3082 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3083 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3084 )
3085 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
3086 assert(
3087 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3088 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3089 )
3090 assert(ArrayBuffer.isView(n), 'n must be a typed array')
3091 assert(
3092 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3093 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3094 )
3095
3096 binding.extension_tweak_ed25519_scalar_add(scalarOut, scalar, n)
3097}
3098
3099exports.extension_tweak_ed25519_pk_add = function (tpk, pk, p) {
3100 assert(ArrayBuffer.isView(tpk), 'tpk must be a typed array')
3101 assert(
3102 tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3103 "tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3104 )
3105 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3106 assert(
3107 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3108 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3109 )
3110 assert(ArrayBuffer.isView(p), 'p must be a typed array')
3111 assert(
3112 p.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3113 "p must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3114 )
3115
3116 const res = binding.extension_tweak_ed25519_pk_add(tpk, pk, p)
3117
3118 if (res !== 0) throw new Error('failed to add tweak to public key')
3119}
3120
3121exports.extension_tweak_ed25519_keypair_add = function (pk, scalarOut, scalarIn, tweak) {
3122 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3123 assert(
3124 pk.byteLength === binding.extension_tweak_ed25519_BYTES,
3125 "pk must be 'extension_tweak_ed25519_BYTES' bytes"
3126 )
3127 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3128 assert(
3129 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3130 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3131 )
3132 assert(ArrayBuffer.isView(scalarIn), 'scalarIn must be a typed array')
3133 assert(
3134 scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3135 "scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3136 )
3137 assert(ArrayBuffer.isView(tweak), 'tweak must be a typed array')
3138 assert(
3139 tweak.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3140 "tweak must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3141 )
3142
3143 const res = binding.extension_tweak_ed25519_keypair_add(pk, scalarOut, scalarIn, tweak)
3144
3145 if (res !== 0) throw new Error('failed to add tweak to keypair')
3146}
3147
3148exports.extension_pbkdf2_sha512_async = function (out, passwd, salt, iter, outlen, callback) {
3149 assert(
3150 iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
3151 "iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
3152 )
3153 assert(
3154 outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
3155 "outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
3156 )
3157 assert(ArrayBuffer.isView(out), 'out must be a typed array')
3158 assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes")
3159 assert(out.byteLength > 0, 'out must not be empty')
3160 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
3161 assert(passwd.byteLength > 0, 'passwd must not be empty')
3162 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
3163 assert(salt.byteLength > 0, 'salt must not be empty')
3164
3165 const [done, promise] = checkStatus(callback)
3166
3167 binding.extension_pbkdf2_sha512_async(
3168 out.buffer,
3169 out.byteOffset,
3170 out.byteLength,
3171
3172 passwd.buffer,
3173 passwd.byteOffset,
3174 passwd.byteLength,
3175
3176 salt.buffer,
3177 salt.byteOffset,
3178 salt.byteLength,
3179
3180 iter,
3181 outlen,
3182
3183 done
3184 )
3185
3186 return promise
3187}
3188
3189exports.extension_pbkdf2_sha512 = function (out, passwd, salt, iter, outlen) {
3190 assert(
3191 iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
3192 "iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
3193 )
3194 assert(
3195 outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
3196 "outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
3197 )
3198 assert(ArrayBuffer.isView(out), 'out must be a typed array')
3199 assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes")
3200 assert(out.byteLength > 0, 'out must not be empty')
3201 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
3202 assert(passwd.byteLength > 0, 'passwd must not be empty')
3203 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
3204 assert(salt.byteLength > 0, 'salt must not be empty')
3205
3206 const res = binding.extension_pbkdf2_sha512(out, passwd, salt, iter, outlen)
3207
3208 if (res !== 0) throw new Error('failed to add tweak to public key')
3209}
3210
3211function checkStatus(callback, booleanResult = false) {
3212 let done, promise
3213
3214 if (typeof callback === 'function') {
3215 done = function (status) {
3216 if (booleanResult) callback(null, status === 0)
3217 else if (status === 0) callback(null)
3218 else callback(new Error('status: ' + status))
3219 }
3220 } else {
3221 promise = new Promise(function (resolve, reject) {
3222 done = function (status) {
3223 if (booleanResult) resolve(status === 0)
3224 else if (status === 0) resolve()
3225 else reject(new Error('status: ' + status))
3226 }
3227 })
3228 }
3229
3230 return [done, promise]
3231}
node_modules/noise-handshake/node_modules/sodium-native/package.json +62 -0
……@@ -0,0 +1,62 @@
1{
2 "name": "sodium-native",
3 "version": "5.1.0",
4 "description": "Low level bindings for libsodium",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "binding.cc",
9 "binding.js",
10 "extensions",
11 "prebuilds",
12 "CMakeLists.txt"
13 ],
14 "imports": {
15 "assert": {
16 "bare": "bare-assert",
17 "node": "assert"
18 }
19 },
20 "addon": true,
21 "dependencies": {
22 "bare-assert": "^1.2.0",
23 "require-addon": "^1.1.0",
24 "which-runtime": "^1.2.1"
25 },
26 "devDependencies": {
27 "bare-compat-napi": "^1.3.5",
28 "brittle": "^3.16.2",
29 "cmake-bare": "^1.6.1",
30 "cmake-fetch": "^1.4.3",
31 "cmake-napi": "^1.2.1",
32 "prettier": "^3.6.2",
33 "prettier-config-holepunch": "^2.0.0"
34 },
35 "scripts": {
36 "test": "prettier . --check && npm run test:node && npm run test:bare",
37 "test:node": "node test/all.js",
38 "test:bare": "bare test/all.js"
39 },
40 "standard": {
41 "ignore": [
42 "/test/fixtures/*.js"
43 ]
44 },
45 "engines": {
46 "bare": ">=1.16.0"
47 },
48 "repository": {
49 "type": "git",
50 "url": "git+https://github.com/holepunchto/sodium-native.git"
51 },
52 "contributors": [
53 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
54 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
55 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
56 ],
57 "license": "MIT",
58 "bugs": {
59 "url": "https://github.com/holepunchto/sodium-native/issues"
60 },
61 "homepage": "https://github.com/holepunchto/sodium-native"
62}
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/android-arm/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/android-arm/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/android-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/android-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/android-ia32/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/android-ia32/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/android-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/android-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/ios-arm64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/ios-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/ios-x64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/win32-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-native/prebuilds/win32-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/noise-handshake/node_modules/sodium-universal/LICENSE.md +7 -0
……@@ -0,0 +1,7 @@
1Copyright 2017 Mathias Buus & Emil Bay
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
node_modules/noise-handshake/node_modules/sodium-universal/README.md +288 -0
……@@ -0,0 +1,288 @@
1# sodium-universal
2
3Universal wrapper for `sodium-javascript` and `sodium-native` working in Node.js and the Browser
4
5```sh
6npm install sodium-universal
7```
8
9`sodium-native` ships with prebuilds for macOS, Windows, and Linux.
10
11Note that the module itself is generated on a prepublish hook.
12
13## Usage
14
15```js
16var sodium = require('sodium-universal')
17
18var rnd = Buffer.allocUnsafe(12) // Cryptographically random data
19sodium.randombytes_buf(rnd)
20
21console.log(rnd.toString('hex'))
22
23```
24
25Works seamlessly with Node.js:
26
27```sh
28$ node example.js
29c7dbd46a6cc84ff2e0d1285c
30```
31
32And the browser:
33
34First install the peer dep, `sodium-javascript`.
35
36```sh
37npm install --save sodium-javascript
38```
39
40And then browserify
41
42```sh
43browserify example.js > bundle.js
44```
45
46## Introduction
47
48[`libsodium`](https://download.libsodium.org/doc/) is a collection of cryptographic primitives, providing a low-level foundation to build higher-level cryptographic applications and protocols. It is often put in contrast to RSA based cryptography and OpenSSL, even though they all share overlapping algorithms and target slightly different audiences. Sodium is a collection of modern collection of primitives, fulfilling the same cryptographic tasks, but based on simpler and more efficient algorithms.
49
50This library provides seamless bindings to [`sodium-native`](https://github.com/sodium-friends/sodium-native), which is the original C implementation of `libsodium` exposed as a Node native module. For the browser we expose [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript), using the `package.json` [`browser`](https://github.com/defunctzombie/package-browser-field-spec) field, which is supported by most bundlers.
51
52## API
53
54Please refer to [`sodium-native`](https://github.com/sodium-friends/sodium-native#api) and [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript#api). Note that the two modules do not yet have feature parity, where `sodium-native` is the more featureful of the two.
55
56## Compatibilty
57
58<!-- Generated by build-scripts/symbols.js with
59 sodium-native@3.2.0
60 sodium-javascript@0.6.0 -->
61| C Library Symbol | `sodium-native` | `sodium-javascript` |
62|:--------------------------------------------------------:|:--------------------:|:--------------------:|
63| `crypto_aead_chacha20poly1305_ietf_ABYTES` | :white_check_mark: | :white_check_mark: |
64| `crypto_aead_chacha20poly1305_ietf_decrypt` | :white_check_mark: | :white_check_mark: |
65| `crypto_aead_chacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :white_check_mark: |
66| `crypto_aead_chacha20poly1305_ietf_encrypt` | :white_check_mark: | :white_check_mark: |
67| `crypto_aead_chacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :white_check_mark: |
68| `crypto_aead_chacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
69| `crypto_aead_chacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
70| `crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
71| `crypto_aead_chacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :white_check_mark: |
72| `crypto_aead_chacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :white_check_mark: |
73| `crypto_aead_xchacha20poly1305_ietf_ABYTES` | :white_check_mark: | :small_red_triangle: |
74| `crypto_aead_xchacha20poly1305_ietf_decrypt` | :white_check_mark: | :small_red_triangle: |
75| `crypto_aead_xchacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :small_red_triangle: |
76| `crypto_aead_xchacha20poly1305_ietf_encrypt` | :white_check_mark: | :small_red_triangle: |
77| `crypto_aead_xchacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :small_red_triangle: |
78| `crypto_aead_xchacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
79| `crypto_aead_xchacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
80| `crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
81| `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :small_red_triangle: |
82| `crypto_aead_xchacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :small_red_triangle: |
83| `crypto_auth` | :white_check_mark: | :small_red_triangle: |
84| `crypto_auth_BYTES` | :white_check_mark: | :small_red_triangle: |
85| `crypto_auth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
86| `crypto_auth_verify` | :white_check_mark: | :small_red_triangle: |
87| `crypto_box_BEFORENMBYTES` | :small_red_triangle: | :white_check_mark: |
88| `crypto_box_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
89| `crypto_box_detached` | :white_check_mark: | :small_red_triangle: |
90| `crypto_box_easy` | :white_check_mark: | :small_red_triangle: |
91| `crypto_box_keypair` | :white_check_mark: | :white_check_mark: |
92| `crypto_box_MACBYTES` | :white_check_mark: | :small_red_triangle: |
93| `crypto_box_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
94| `crypto_box_open_detached` | :white_check_mark: | :small_red_triangle: |
95| `crypto_box_open_easy` | :white_check_mark: | :small_red_triangle: |
96| `crypto_box_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
97| `crypto_box_seal` | :white_check_mark: | :white_check_mark: |
98| `crypto_box_seal_open` | :white_check_mark: | :white_check_mark: |
99| `crypto_box_SEALBYTES` | :white_check_mark: | :white_check_mark: |
100| `crypto_box_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
101| `crypto_box_seed_keypair` | :white_check_mark: | :white_check_mark: |
102| `crypto_box_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
103| `crypto_box_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
104| `crypto_core_ed25519_add` | :white_check_mark: | :small_red_triangle: |
105| `crypto_core_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
106| `crypto_core_ed25519_from_uniform` | :white_check_mark: | :small_red_triangle: |
107| `crypto_core_ed25519_is_valid_point` | :white_check_mark: | :small_red_triangle: |
108| `crypto_core_ed25519_NONREDUCEDSCALARBYTES` | :white_check_mark: | :small_red_triangle: |
109| `crypto_core_ed25519_scalar_add` | :white_check_mark: | :small_red_triangle: |
110| `crypto_core_ed25519_scalar_complement` | :white_check_mark: | :small_red_triangle: |
111| `crypto_core_ed25519_scalar_invert` | :white_check_mark: | :small_red_triangle: |
112| `crypto_core_ed25519_scalar_negate` | :white_check_mark: | :small_red_triangle: |
113| `crypto_core_ed25519_scalar_random` | :white_check_mark: | :small_red_triangle: |
114| `crypto_core_ed25519_scalar_reduce` | :white_check_mark: | :small_red_triangle: |
115| `crypto_core_ed25519_scalar_sub` | :white_check_mark: | :small_red_triangle: |
116| `crypto_core_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
117| `crypto_core_ed25519_sub` | :white_check_mark: | :small_red_triangle: |
118| `crypto_core_ed25519_UNIFORMBYTES` | :white_check_mark: | :small_red_triangle: |
119| `crypto_generichash` | :white_check_mark: | :white_check_mark: |
120| `crypto_generichash_BYTES` | :white_check_mark: | :white_check_mark: |
121| `crypto_generichash_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
122| `crypto_generichash_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
123| `crypto_generichash_final` | :white_check_mark: | :small_red_triangle: |
124| `crypto_generichash_init` | :white_check_mark: | :small_red_triangle: |
125| `crypto_generichash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
126| `crypto_generichash_KEYBYTES_MAX` | :white_check_mark: | :white_check_mark: |
127| `crypto_generichash_KEYBYTES_MIN` | :white_check_mark: | :white_check_mark: |
128| `crypto_generichash_keygen` | :white_check_mark: | :small_red_triangle: |
129| `crypto_generichash_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
130| `crypto_generichash_update` | :white_check_mark: | :small_red_triangle: |
131| `crypto_hash` | :white_check_mark: | :white_check_mark: |
132| `crypto_hash_BYTES` | :white_check_mark: | :white_check_mark: |
133| `crypto_hash_sha256` | :white_check_mark: | :white_check_mark: |
134| `crypto_hash_sha256_BYTES` | :white_check_mark: | :white_check_mark: |
135| `crypto_hash_sha256_final` | :white_check_mark: | :small_red_triangle: |
136| `crypto_hash_sha256_init` | :white_check_mark: | :small_red_triangle: |
137| `crypto_hash_sha256_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
138| `crypto_hash_sha256_update` | :white_check_mark: | :small_red_triangle: |
139| `crypto_hash_sha512` | :white_check_mark: | :white_check_mark: |
140| `crypto_hash_sha512_BYTES` | :white_check_mark: | :white_check_mark: |
141| `crypto_hash_sha512_final` | :white_check_mark: | :small_red_triangle: |
142| `crypto_hash_sha512_init` | :white_check_mark: | :small_red_triangle: |
143| `crypto_hash_sha512_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
144| `crypto_hash_sha512_update` | :white_check_mark: | :small_red_triangle: |
145| `crypto_kdf_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
146| `crypto_kdf_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
147| `crypto_kdf_CONTEXTBYTES` | :white_check_mark: | :white_check_mark: |
148| `crypto_kdf_derive_from_key` | :white_check_mark: | :white_check_mark: |
149| `crypto_kdf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
150| `crypto_kdf_keygen` | :white_check_mark: | :white_check_mark: |
151| `crypto_kx_client_session_keys` | :white_check_mark: | :small_red_triangle: |
152| `crypto_kx_keypair` | :white_check_mark: | :white_check_mark: |
153| `crypto_kx_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
154| `crypto_kx_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
155| `crypto_kx_seed_keypair` | :white_check_mark: | :white_check_mark: |
156| `crypto_kx_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
157| `crypto_kx_server_session_keys` | :white_check_mark: | :small_red_triangle: |
158| `crypto_kx_SESSIONKEYBYTES` | :white_check_mark: | :small_red_triangle: |
159| `crypto_onetimeauth` | :white_check_mark: | :white_check_mark: |
160| `crypto_onetimeauth_BYTES` | :white_check_mark: | :small_red_triangle: |
161| `crypto_onetimeauth_final` | :white_check_mark: | :small_red_triangle: |
162| `crypto_onetimeauth_init` | :white_check_mark: | :small_red_triangle: |
163| `crypto_onetimeauth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
164| `crypto_onetimeauth_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
165| `crypto_onetimeauth_update` | :white_check_mark: | :small_red_triangle: |
166| `crypto_onetimeauth_verify` | :white_check_mark: | :white_check_mark: |
167| `crypto_pwhash` | :white_check_mark: | :small_red_triangle: |
168| `crypto_pwhash_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
169| `crypto_pwhash_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
170| `crypto_pwhash_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
171| `crypto_pwhash_scryptsalsa208sha256` | :white_check_mark: | :small_red_triangle: |
172| `crypto_pwhash_scryptsalsa208sha256_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
173| `crypto_pwhash_scryptsalsa208sha256_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
174| `crypto_pwhash_scryptsalsa208sha256_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
175| `crypto_pwhash_scryptsalsa208sha256_str` | :white_check_mark: | :small_red_triangle: |
176| `crypto_pwhash_scryptsalsa208sha256_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
177| `crypto_pwhash_scryptsalsa208sha256_str_verify` | :white_check_mark: | :small_red_triangle: |
178| `crypto_pwhash_scryptsalsa208sha256_STRBYTES` | :white_check_mark: | :small_red_triangle: |
179| `crypto_pwhash_str` | :white_check_mark: | :small_red_triangle: |
180| `crypto_pwhash_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
181| `crypto_pwhash_str_verify` | :white_check_mark: | :small_red_triangle: |
182| `crypto_pwhash_STRBYTES` | :white_check_mark: | :small_red_triangle: |
183| `crypto_scalarmult` | :white_check_mark: | :white_check_mark: |
184| `crypto_scalarmult_base` | :white_check_mark: | :white_check_mark: |
185| `crypto_scalarmult_BYTES` | :white_check_mark: | :white_check_mark: |
186| `crypto_scalarmult_ed25519` | :white_check_mark: | :small_red_triangle: |
187| `crypto_scalarmult_ed25519_base` | :white_check_mark: | :small_red_triangle: |
188| `crypto_scalarmult_ed25519_base_noclamp` | :white_check_mark: | :small_red_triangle: |
189| `crypto_scalarmult_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
190| `crypto_scalarmult_ed25519_noclamp` | :white_check_mark: | :small_red_triangle: |
191| `crypto_scalarmult_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
192| `crypto_scalarmult_SCALARBYTES` | :white_check_mark: | :white_check_mark: |
193| `crypto_secretbox` | :small_red_triangle: | :white_check_mark: |
194| `crypto_secretbox_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
195| `crypto_secretbox_detached` | :white_check_mark: | :white_check_mark: |
196| `crypto_secretbox_easy` | :white_check_mark: | :white_check_mark: |
197| `crypto_secretbox_KEYBYTES` | :white_check_mark: | :white_check_mark: |
198| `crypto_secretbox_MACBYTES` | :white_check_mark: | :white_check_mark: |
199| `crypto_secretbox_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
200| `crypto_secretbox_open` | :small_red_triangle: | :white_check_mark: |
201| `crypto_secretbox_open_detached` | :white_check_mark: | :white_check_mark: |
202| `crypto_secretbox_open_easy` | :white_check_mark: | :white_check_mark: |
203| `crypto_secretbox_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
204| `crypto_secretstream_xchacha20poly1305_ABYTES` | :white_check_mark: | :small_red_triangle: |
205| `crypto_secretstream_xchacha20poly1305_HEADERBYTES` | :white_check_mark: | :small_red_triangle: |
206| `crypto_secretstream_xchacha20poly1305_init_pull` | :white_check_mark: | :small_red_triangle: |
207| `crypto_secretstream_xchacha20poly1305_init_push` | :white_check_mark: | :small_red_triangle: |
208| `crypto_secretstream_xchacha20poly1305_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
209| `crypto_secretstream_xchacha20poly1305_keygen` | :white_check_mark: | :small_red_triangle: |
210| `crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
211| `crypto_secretstream_xchacha20poly1305_pull` | :white_check_mark: | :small_red_triangle: |
212| `crypto_secretstream_xchacha20poly1305_push` | :white_check_mark: | :small_red_triangle: |
213| `crypto_secretstream_xchacha20poly1305_rekey` | :white_check_mark: | :small_red_triangle: |
214| `crypto_secretstream_xchacha20poly1305_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
215| `crypto_shorthash` | :white_check_mark: | :white_check_mark: |
216| `crypto_shorthash_BYTES` | :white_check_mark: | :white_check_mark: |
217| `crypto_shorthash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
218| `crypto_sign` | :white_check_mark: | :white_check_mark: |
219| `crypto_sign_BYTES` | :white_check_mark: | :white_check_mark: |
220| `crypto_sign_detached` | :white_check_mark: | :white_check_mark: |
221| `crypto_sign_ed25519_pk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
222| `crypto_sign_ed25519_sk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
223| `crypto_sign_ed25519_sk_to_pk` | :white_check_mark: | :small_red_triangle: |
224| `crypto_sign_keypair` | :white_check_mark: | :white_check_mark: |
225| `crypto_sign_open` | :white_check_mark: | :white_check_mark: |
226| `crypto_sign_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
227| `crypto_sign_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
228| `crypto_sign_seed_keypair` | :white_check_mark: | :white_check_mark: |
229| `crypto_sign_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
230| `crypto_sign_verify_detached` | :white_check_mark: | :white_check_mark: |
231| `crypto_stream` | :white_check_mark: | :white_check_mark: |
232| `crypto_stream_chacha20` | :white_check_mark: | :white_check_mark: |
233| `crypto_stream_chacha20_ietf` | :white_check_mark: | :white_check_mark: |
234| `crypto_stream_chacha20_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
235| `crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
236| `crypto_stream_chacha20_ietf_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
237| `crypto_stream_chacha20_ietf_xor` | :white_check_mark: | :white_check_mark: |
238| `crypto_stream_chacha20_ietf_xor_ic` | :white_check_mark: | :white_check_mark: |
239| `crypto_stream_chacha20_KEYBYTES` | :white_check_mark: | :white_check_mark: |
240| `crypto_stream_chacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
241| `crypto_stream_chacha20_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
242| `crypto_stream_chacha20_xor` | :white_check_mark: | :white_check_mark: |
243| `crypto_stream_chacha20_xor_ic` | :white_check_mark: | :white_check_mark: |
244| `crypto_stream_KEYBYTES` | :white_check_mark: | :white_check_mark: |
245| `crypto_stream_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
246| `crypto_stream_salsa20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
247| `crypto_stream_salsa20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
248| `crypto_stream_salsa20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
249| `crypto_stream_salsa20_xor` | :white_check_mark: | :small_red_triangle: |
250| `crypto_stream_salsa20_xor_ic` | :white_check_mark: | :small_red_triangle: |
251| `crypto_stream_xchacha20` | :white_check_mark: | :small_red_triangle: |
252| `crypto_stream_xchacha20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
253| `crypto_stream_xchacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
254| `crypto_stream_xchacha20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
255| `crypto_stream_xchacha20_xor` | :white_check_mark: | :small_red_triangle: |
256| `crypto_stream_xchacha20_xor_ic` | :white_check_mark: | :small_red_triangle: |
257| `crypto_stream_xor` | :white_check_mark: | :white_check_mark: |
258| `crypto_verify_16` | :small_red_triangle: | :white_check_mark: |
259| `crypto_verify_32` | :small_red_triangle: | :white_check_mark: |
260| `randombytes_buf` | :white_check_mark: | :white_check_mark: |
261| `randombytes_buf_deterministic` | :white_check_mark: | :small_red_triangle: |
262| `randombytes_random` | :white_check_mark: | :small_red_triangle: |
263| `randombytes_SEEDBYTES` | :white_check_mark: | :small_red_triangle: |
264| `randombytes_uniform` | :white_check_mark: | :small_red_triangle: |
265| `sodium_add` | :white_check_mark: | :small_red_triangle: |
266| `sodium_compare` | :white_check_mark: | :small_red_triangle: |
267| `sodium_free` | :white_check_mark: | :small_red_triangle: |
268| `sodium_increment` | :white_check_mark: | :small_red_triangle: |
269| `sodium_is_zero` | :white_check_mark: | :white_check_mark: |
270| `sodium_malloc` | :white_check_mark: | :white_check_mark: |
271| `sodium_memcmp` | :white_check_mark: | :white_check_mark: |
272| `sodium_memzero` | :white_check_mark: | :white_check_mark: |
273| `sodium_mlock` | :white_check_mark: | :small_red_triangle: |
274| `sodium_mprotect_noaccess` | :white_check_mark: | :small_red_triangle: |
275| `sodium_mprotect_readonly` | :white_check_mark: | :small_red_triangle: |
276| `sodium_mprotect_readwrite` | :white_check_mark: | :small_red_triangle: |
277| `sodium_munlock` | :white_check_mark: | :small_red_triangle: |
278| `sodium_pad` | :white_check_mark: | :small_red_triangle: |
279| `sodium_sub` | :white_check_mark: | :small_red_triangle: |
280| `sodium_unpad` | :white_check_mark: | :small_red_triangle: |
281
282### Missing altogether (Ctrl + F friendly)
283
284`crypto_aead_aes256gcm_ABYTES`, `crypto_aead_aes256gcm_beforenm`, `crypto_aead_aes256gcm_decrypt`, `crypto_aead_aes256gcm_decrypt_afternm`, `crypto_aead_aes256gcm_decrypt_detached`, `crypto_aead_aes256gcm_decrypt_detached_afternm`, `crypto_aead_aes256gcm_encrypt`, `crypto_aead_aes256gcm_encrypt_afternm`, `crypto_aead_aes256gcm_encrypt_detached`, `crypto_aead_aes256gcm_encrypt_detached_afternm`, `crypto_aead_aes256gcm_is_available`, `crypto_aead_aes256gcm_KEYBYTES`, `crypto_aead_aes256gcm_keygen`, `crypto_aead_aes256gcm_MESSAGEBYTES_MAX`, `crypto_aead_aes256gcm_NPUBBYTES`, `crypto_aead_aes256gcm_NSECBYTES`, `crypto_aead_aes256gcm_STATEBYTES`, `crypto_aead_chacha20poly1305_ABYTES`, `crypto_aead_chacha20poly1305_decrypt`, `crypto_aead_chacha20poly1305_decrypt_detached`, `crypto_aead_chacha20poly1305_encrypt`, `crypto_aead_chacha20poly1305_encrypt_detached`, `crypto_aead_chacha20poly1305_KEYBYTES`, `crypto_aead_chacha20poly1305_keygen`, `crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX`, `crypto_aead_chacha20poly1305_NPUBBYTES`, `crypto_aead_chacha20poly1305_NSECBYTES`, `crypto_auth_hmacsha256`, `crypto_auth_hmacsha256_BYTES`, `crypto_auth_hmacsha256_final`, `crypto_auth_hmacsha256_init`, `crypto_auth_hmacsha256_KEYBYTES`, `crypto_auth_hmacsha256_keygen`, `crypto_auth_hmacsha256_STATEBYTES`, `crypto_auth_hmacsha256_update`, `crypto_auth_hmacsha256_verify`, `crypto_auth_hmacsha512`, `crypto_auth_hmacsha512256`, `crypto_auth_hmacsha512256_BYTES`, `crypto_auth_hmacsha512256_final`, `crypto_auth_hmacsha512256_init`, `crypto_auth_hmacsha512256_KEYBYTES`, `crypto_auth_hmacsha512256_keygen`, `crypto_auth_hmacsha512256_STATEBYTES`, `crypto_auth_hmacsha512256_update`, `crypto_auth_hmacsha512256_verify`, `crypto_auth_hmacsha512_BYTES`, `crypto_auth_hmacsha512_final`, `crypto_auth_hmacsha512_init`, `crypto_auth_hmacsha512_KEYBYTES`, `crypto_auth_hmacsha512_keygen`, `crypto_auth_hmacsha512_STATEBYTES`, `crypto_auth_hmacsha512_update`, `crypto_auth_hmacsha512_verify`, `crypto_auth_keygen`, `crypto_auth_primitive`, `crypto_box`, `crypto_box_afternm`, `crypto_box_beforenm`, `crypto_box_curve25519xchacha20poly1305_beforenm`, `crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xchacha20poly1305_detached`, `crypto_box_curve25519xchacha20poly1305_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_easy`, `crypto_box_curve25519xchacha20poly1305_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_keypair`, `crypto_box_curve25519xchacha20poly1305_MACBYTES`, `crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xchacha20poly1305_NONCEBYTES`, `crypto_box_curve25519xchacha20poly1305_open_detached`, `crypto_box_curve25519xchacha20poly1305_open_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_open_easy`, `crypto_box_curve25519xchacha20poly1305_open_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seal`, `crypto_box_curve25519xchacha20poly1305_seal_open`, `crypto_box_curve25519xchacha20poly1305_SEALBYTES`, `crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seed_keypair`, `crypto_box_curve25519xchacha20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305`, `crypto_box_curve25519xsalsa20poly1305_afternm`, `crypto_box_curve25519xsalsa20poly1305_beforenm`, `crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES`, `crypto_box_curve25519xsalsa20poly1305_keypair`, `crypto_box_curve25519xsalsa20poly1305_MACBYTES`, `crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xsalsa20poly1305_NONCEBYTES`, `crypto_box_curve25519xsalsa20poly1305_open`, `crypto_box_curve25519xsalsa20poly1305_open_afternm`, `crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_seed_keypair`, `crypto_box_curve25519xsalsa20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305_ZEROBYTES`, `crypto_box_detached_afternm`, `crypto_box_easy_afternm`, `crypto_box_MESSAGEBYTES_MAX`, `crypto_box_open`, `crypto_box_open_afternm`, `crypto_box_open_detached_afternm`, `crypto_box_open_easy_afternm`, `crypto_box_primitive`, `crypto_core_ed25519_from_hash`, `crypto_core_ed25519_HASHBYTES`, `crypto_core_ed25519_random`, `crypto_core_ed25519_scalar_mul`, `crypto_core_hchacha20`, `crypto_core_hchacha20_CONSTBYTES`, `crypto_core_hchacha20_INPUTBYTES`, `crypto_core_hchacha20_KEYBYTES`, `crypto_core_hchacha20_OUTPUTBYTES`, `crypto_core_hsalsa20`, `crypto_core_hsalsa20_CONSTBYTES`, `crypto_core_hsalsa20_INPUTBYTES`, `crypto_core_hsalsa20_KEYBYTES`, `crypto_core_hsalsa20_OUTPUTBYTES`, `crypto_core_ristretto255_add`, `crypto_core_ristretto255_BYTES`, `crypto_core_ristretto255_from_hash`, `crypto_core_ristretto255_HASHBYTES`, `crypto_core_ristretto255_is_valid_point`, `crypto_core_ristretto255_NONREDUCEDSCALARBYTES`, `crypto_core_ristretto255_random`, `crypto_core_ristretto255_scalar_add`, `crypto_core_ristretto255_scalar_complement`, `crypto_core_ristretto255_scalar_invert`, `crypto_core_ristretto255_scalar_mul`, `crypto_core_ristretto255_scalar_negate`, `crypto_core_ristretto255_scalar_random`, `crypto_core_ristretto255_scalar_reduce`, `crypto_core_ristretto255_scalar_sub`, `crypto_core_ristretto255_SCALARBYTES`, `crypto_core_ristretto255_sub`, `crypto_core_salsa20`, `crypto_core_salsa2012`, `crypto_core_salsa2012_CONSTBYTES`, `crypto_core_salsa2012_INPUTBYTES`, `crypto_core_salsa2012_KEYBYTES`, `crypto_core_salsa2012_OUTPUTBYTES`, `crypto_core_salsa208`, `crypto_core_salsa208_CONSTBYTES`, `crypto_core_salsa208_INPUTBYTES`, `crypto_core_salsa208_KEYBYTES`, `crypto_core_salsa208_OUTPUTBYTES`, `crypto_core_salsa20_CONSTBYTES`, `crypto_core_salsa20_INPUTBYTES`, `crypto_core_salsa20_KEYBYTES`, `crypto_core_salsa20_OUTPUTBYTES`, `crypto_generichash_blake2b`, `crypto_generichash_blake2b_BYTES`, `crypto_generichash_blake2b_BYTES_MAX`, `crypto_generichash_blake2b_BYTES_MIN`, `crypto_generichash_blake2b_final`, `crypto_generichash_blake2b_init`, `crypto_generichash_blake2b_init_salt_personal`, `crypto_generichash_blake2b_KEYBYTES`, `crypto_generichash_blake2b_KEYBYTES_MAX`, `crypto_generichash_blake2b_KEYBYTES_MIN`, `crypto_generichash_blake2b_keygen`, `crypto_generichash_blake2b_PERSONALBYTES`, `crypto_generichash_blake2b_salt_personal`, `crypto_generichash_blake2b_SALTBYTES`, `crypto_generichash_blake2b_STATEBYTES`, `crypto_generichash_blake2b_update`, `crypto_generichash_primitive`, `crypto_hash_primitive`, `crypto_kdf_blake2b_BYTES_MAX`, `crypto_kdf_blake2b_BYTES_MIN`, `crypto_kdf_blake2b_CONTEXTBYTES`, `crypto_kdf_blake2b_derive_from_key`, `crypto_kdf_blake2b_KEYBYTES`, `crypto_kdf_primitive`, `crypto_kx_primitive`, `crypto_onetimeauth_keygen`, `crypto_onetimeauth_poly1305`, `crypto_onetimeauth_poly1305_BYTES`, `crypto_onetimeauth_poly1305_final`, `crypto_onetimeauth_poly1305_init`, `crypto_onetimeauth_poly1305_KEYBYTES`, `crypto_onetimeauth_poly1305_keygen`, `crypto_onetimeauth_poly1305_STATEBYTES`, `crypto_onetimeauth_poly1305_update`, `crypto_onetimeauth_poly1305_verify`, `crypto_onetimeauth_primitive`, `crypto_pwhash_alg_argon2i13`, `crypto_pwhash_alg_argon2id13`, `crypto_pwhash_alg_default`, `crypto_pwhash_argon2i`, `crypto_pwhash_argon2i_alg_argon2i13`, `crypto_pwhash_argon2i_BYTES_MAX`, `crypto_pwhash_argon2i_BYTES_MIN`, `crypto_pwhash_argon2i_memlimit_interactive`, `crypto_pwhash_argon2i_memlimit_max`, `crypto_pwhash_argon2i_memlimit_min`, `crypto_pwhash_argon2i_memlimit_moderate`, `crypto_pwhash_argon2i_memlimit_sensitive`, `crypto_pwhash_argon2i_opslimit_interactive`, `crypto_pwhash_argon2i_opslimit_max`, `crypto_pwhash_argon2i_opslimit_min`, `crypto_pwhash_argon2i_opslimit_moderate`, `crypto_pwhash_argon2i_opslimit_sensitive`, `crypto_pwhash_argon2i_passwd_max`, `crypto_pwhash_argon2i_passwd_min`, `crypto_pwhash_argon2i_SALTBYTES`, `crypto_pwhash_argon2i_str`, `crypto_pwhash_argon2i_str_needs_rehash`, `crypto_pwhash_argon2i_str_verify`, `crypto_pwhash_argon2i_STRBYTES`, `crypto_pwhash_argon2i_strprefix`, `crypto_pwhash_argon2id`, `crypto_pwhash_argon2id_alg_argon2id13`, `crypto_pwhash_argon2id_BYTES_MAX`, `crypto_pwhash_argon2id_BYTES_MIN`, `crypto_pwhash_argon2id_memlimit_interactive`, `crypto_pwhash_argon2id_memlimit_max`, `crypto_pwhash_argon2id_memlimit_min`, `crypto_pwhash_argon2id_memlimit_moderate`, `crypto_pwhash_argon2id_memlimit_sensitive`, `crypto_pwhash_argon2id_opslimit_interactive`, `crypto_pwhash_argon2id_opslimit_max`, `crypto_pwhash_argon2id_opslimit_min`, `crypto_pwhash_argon2id_opslimit_moderate`, `crypto_pwhash_argon2id_opslimit_sensitive`, `crypto_pwhash_argon2id_passwd_max`, `crypto_pwhash_argon2id_passwd_min`, `crypto_pwhash_argon2id_SALTBYTES`, `crypto_pwhash_argon2id_str`, `crypto_pwhash_argon2id_str_needs_rehash`, `crypto_pwhash_argon2id_str_verify`, `crypto_pwhash_argon2id_STRBYTES`, `crypto_pwhash_argon2id_strprefix`, `crypto_pwhash_memlimit_interactive`, `crypto_pwhash_memlimit_max`, `crypto_pwhash_memlimit_min`, `crypto_pwhash_memlimit_moderate`, `crypto_pwhash_memlimit_sensitive`, `crypto_pwhash_opslimit_interactive`, `crypto_pwhash_opslimit_max`, `crypto_pwhash_opslimit_min`, `crypto_pwhash_opslimit_moderate`, `crypto_pwhash_opslimit_sensitive`, `crypto_pwhash_passwd_max`, `crypto_pwhash_passwd_min`, `crypto_pwhash_primitive`, `crypto_pwhash_scryptsalsa208sha256_ll`, `crypto_pwhash_scryptsalsa208sha256_memlimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_memlimit_max`, `crypto_pwhash_scryptsalsa208sha256_memlimit_min`, `crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_max`, `crypto_pwhash_scryptsalsa208sha256_opslimit_min`, `crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_passwd_max`, `crypto_pwhash_scryptsalsa208sha256_passwd_min`, `crypto_pwhash_scryptsalsa208sha256_strprefix`, `crypto_pwhash_str_alg`, `crypto_pwhash_strprefix`, `crypto_scalarmult_curve25519`, `crypto_scalarmult_curve25519_base`, `crypto_scalarmult_curve25519_BYTES`, `crypto_scalarmult_curve25519_SCALARBYTES`, `crypto_scalarmult_primitive`, `crypto_scalarmult_ristretto255`, `crypto_scalarmult_ristretto255_base`, `crypto_scalarmult_ristretto255_BYTES`, `crypto_scalarmult_ristretto255_SCALARBYTES`, `crypto_secretbox_keygen`, `crypto_secretbox_MESSAGEBYTES_MAX`, `crypto_secretbox_primitive`, `crypto_secretbox_xchacha20poly1305_detached`, `crypto_secretbox_xchacha20poly1305_easy`, `crypto_secretbox_xchacha20poly1305_KEYBYTES`, `crypto_secretbox_xchacha20poly1305_MACBYTES`, `crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xchacha20poly1305_NONCEBYTES`, `crypto_secretbox_xchacha20poly1305_open_detached`, `crypto_secretbox_xchacha20poly1305_open_easy`, `crypto_secretbox_xsalsa20poly1305`, `crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES`, `crypto_secretbox_xsalsa20poly1305_KEYBYTES`, `crypto_secretbox_xsalsa20poly1305_keygen`, `crypto_secretbox_xsalsa20poly1305_MACBYTES`, `crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xsalsa20poly1305_NONCEBYTES`, `crypto_secretbox_xsalsa20poly1305_open`, `crypto_secretbox_xsalsa20poly1305_ZEROBYTES`, `crypto_secretstream_xchacha20poly1305_tag_final`, `crypto_secretstream_xchacha20poly1305_tag_message`, `crypto_secretstream_xchacha20poly1305_tag_push`, `crypto_secretstream_xchacha20poly1305_tag_rekey`, `crypto_shorthash_keygen`, `crypto_shorthash_primitive`, `crypto_shorthash_siphash24`, `crypto_shorthash_siphash24_BYTES`, `crypto_shorthash_siphash24_KEYBYTES`, `crypto_shorthash_siphashx24`, `crypto_shorthash_siphashx24_BYTES`, `crypto_shorthash_siphashx24_KEYBYTES`, `crypto_sign_ed25519`, `crypto_sign_ed25519_BYTES`, `crypto_sign_ed25519_detached`, `crypto_sign_ed25519_keypair`, `crypto_sign_ed25519_MESSAGEBYTES_MAX`, `crypto_sign_ed25519_open`, `crypto_sign_ed25519_PUBLICKEYBYTES`, `crypto_sign_ed25519_SECRETKEYBYTES`, `crypto_sign_ed25519_seed_keypair`, `crypto_sign_ed25519_SEEDBYTES`, `crypto_sign_ed25519_sk_to_seed`, `crypto_sign_ed25519_verify_detached`, `crypto_sign_ed25519ph_final_create`, `crypto_sign_ed25519ph_final_verify`, `crypto_sign_ed25519ph_init`, `crypto_sign_ed25519ph_STATEBYTES`, `crypto_sign_ed25519ph_update`, `crypto_sign_edwards25519sha512batch`, `crypto_sign_edwards25519sha512batch_keypair`, `crypto_sign_edwards25519sha512batch_open`, `crypto_sign_final_create`, `crypto_sign_final_verify`, `crypto_sign_init`, `crypto_sign_MESSAGEBYTES_MAX`, `crypto_sign_primitive`, `crypto_sign_STATEBYTES`, `crypto_sign_update`, `crypto_stream_chacha20_ietf_keygen`, `crypto_stream_chacha20_keygen`, `crypto_stream_keygen`, `crypto_stream_MESSAGEBYTES_MAX`, `crypto_stream_primitive`, `crypto_stream_salsa20`, `crypto_stream_salsa2012`, `crypto_stream_salsa2012_KEYBYTES`, `crypto_stream_salsa2012_keygen`, `crypto_stream_salsa2012_MESSAGEBYTES_MAX`, `crypto_stream_salsa2012_NONCEBYTES`, `crypto_stream_salsa2012_xor`, `crypto_stream_salsa208`, `crypto_stream_salsa208_KEYBYTES`, `crypto_stream_salsa208_keygen`, `crypto_stream_salsa208_MESSAGEBYTES_MAX`, `crypto_stream_salsa208_NONCEBYTES`, `crypto_stream_salsa208_xor`, `crypto_stream_salsa20_keygen`, `crypto_stream_xchacha20_keygen`, `crypto_stream_xsalsa20`, `crypto_stream_xsalsa20_KEYBYTES`, `crypto_stream_xsalsa20_keygen`, `crypto_stream_xsalsa20_MESSAGEBYTES_MAX`, `crypto_stream_xsalsa20_NONCEBYTES`, `crypto_stream_xsalsa20_xor`, `crypto_stream_xsalsa20_xor_ic`, `crypto_verify_16_BYTES`, `crypto_verify_32_BYTES`, `crypto_verify_64`, `crypto_verify_64_BYTES`, `randombytes`, `randombytes_close`, `randombytes_implementation_name`, `randombytes_internal_implementation`, `randombytes_set_implementation`, `randombytes_stir`, `randombytes_sysrandom_implementation`, `sodium_allocarray`, `sodium_base642bin`, `sodium_base64_encoded_len`, `sodium_bin2base64`, `sodium_bin2hex`, `sodium_hex2bin`, `sodium_init`, `sodium_library_minimal`, `sodium_library_version_major`, `sodium_library_version_minor`, `sodium_misuse`, `sodium_runtime_has_aesni`, `sodium_runtime_has_avx`, `sodium_runtime_has_avx2`, `sodium_runtime_has_avx512f`, `sodium_runtime_has_neon`, `sodium_runtime_has_pclmul`, `sodium_runtime_has_rdrand`, `sodium_runtime_has_sse2`, `sodium_runtime_has_sse3`, `sodium_runtime_has_sse41`, `sodium_runtime_has_ssse3`, `sodium_set_misuse_handler`, `sodium_stackzero`, `sodium_version_string`
285
286## License
287
288[MIT](LICENSE.md)
node_modules/noise-handshake/node_modules/sodium-universal/build-scripts/generate.js +33 -0
……@@ -0,0 +1,33 @@
1#!/usr/bin/env node
2
3const fs = require('fs')
4const path = require('path')
5const root = path.dirname(require.resolve('sodium-javascript/package.json'))
6
7const tmp = "module.exports = require('sodium-native')\n"
8
9function recurse (dir) {
10 const ls = fs.readdirSync(dir)
11 const subdir = path.relative(root, dir)
12 if (subdir) fs.mkdirSync(subdir, { recursive: true })
13
14 for (const file of ls) {
15 if (file === 'internal') recurse(path.join(dir, file))
16 if (!/\.js$/i.test(file)) continue
17 if (file === 'example.js') continue
18 if (file === 'test.js') continue
19
20 fs.writeFileSync(path.join(__dirname, '..', subdir, file), tmp)
21 }
22}
23
24recurse(root)
25
26const pkg = require('sodium-javascript/package.json')
27const myPkg = require('../package.json')
28
29for (const key of Object.keys(pkg.dependencies)) {
30 myPkg.dependencies[key] = pkg.dependencies[key]
31}
32
33fs.writeFileSync(path.join(__dirname, '../package.json'), JSON.stringify(myPkg, null, 2) + '\n')
node_modules/noise-handshake/node_modules/sodium-universal/build-scripts/symbols.js +32 -0
……@@ -0,0 +1,32 @@
1var exec = require('child_process').execSync
2var path = require('path')
3
4var symbols = exec(`nm -gU "${path.join(require.resolve('sodium-native'), '../prebuilds/darwin-x64/libsodium.dylib')}"`).toString().trim().split('\n')
5var native = new Set(Object.keys(require('sodium-native')).sort())
6var js = new Set(Object.keys(require('sodium-javascript')).sort())
7
8symbols = symbols.map(l => l.split(' ').pop().replace(/^_/, '').replace(/_[^_]*bytes.*/, (s) => s.toUpperCase()))
9
10var missing = []
11
12console.log(`
13<!-- Generated by build-scripts/symbols.js with
14 sodium-native@${require('sodium-native/package.json').version}
15 sodium-javascript@${require('sodium-javascript/package.json').version} -->\
16`)
17
18const max = symbols.filter(s => native.has(s) || js.has(s)).map(s => s.length).reduce((a, b) => Math.max(a, b))
19const lines = ':-' + ''.padEnd(max, '--') + '-:'
20const center = s => s.padStart(Math.floor((max + s.length) / 2), ' ').padEnd(max, ' ')
21
22console.log(`| ${center('C Library Symbol')} | \`sodium-native\` | \`sodium-javascript\` |`)
23console.log(`|${lines}|:--------------------:|:--------------------:|`)
24
25for (var i = 0; i < symbols.length; i++) {
26 var s = symbols[i]
27 if (!(native.has(s) || js.has(s))) missing.push(s)
28 else console.log(`| \`${(s + '`').padEnd(max + 1, ' ')} | ${native.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} | ${js.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} |`)
29}
30
31console.log('\n### Missing altogether (Ctrl + F friendly)\n')
32console.log(missing.map(s => '`' + s + '`').join(', '))
node_modules/noise-handshake/node_modules/sodium-universal/build-scripts/transform.js +26 -0
……@@ -0,0 +1,26 @@
1const fs = require('fs')
2const path = require('path')
3const { Transform, PassThrough } = require('stream')
4
5module.exports = function (file, opts) {
6 const basedir = path.resolve(__dirname, '..')
7 const relname = path.relative(basedir, file)
8
9 if (opts._flags.browserField === false) {
10 return new PassThrough()
11 }
12
13 return new Transform({
14 transform (data, enc, cb) {
15 cb()
16 },
17 flush (cb) {
18 const filename = require.resolve('sodium-javascript/' + relname)
19 fs.readFile(filename, (err, buf) => {
20 if (err) return cb(err)
21 this.push(buf)
22 cb(null)
23 })
24 }
25 })
26}
node_modules/noise-handshake/node_modules/sodium-universal/crypto_aead.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_auth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_box.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_generichash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_hash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_hash_sha256.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_kdf.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_kx.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_onetimeauth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_scalarmult.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_secretbox.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_secretstream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_shorthash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_sign.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_stream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_stream_chacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/crypto_verify.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/helpers.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/index.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/internal/ed25519.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/internal/hchacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/internal/poly1305.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/memory.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/node_modules/sodium-universal/package.json +49 -0
……@@ -0,0 +1,49 @@
1{
2 "name": "sodium-universal",
3 "version": "5.0.1",
4 "description": "Universal wrapper for sodium-javascript and sodium-native working in Node.js and the Browser",
5 "main": "index.js",
6 "dependencies": {
7 "sodium-native": "^5.0.1"
8 },
9 "peerDependencies": {
10 "sodium-javascript": "~0.8.0"
11 },
12 "peerDependenciesMeta": {
13 "sodium-javascript": {
14 "optional": true
15 }
16 },
17 "scripts": {
18 "prepublish": "./build-scripts/generate.js"
19 },
20 "browser": {
21 "sodium-native": "sodium-javascript"
22 },
23 "browserify": {
24 "transform": [
25 "./build-scripts/transform.js"
26 ]
27 },
28 "repository": {
29 "type": "git",
30 "url": "git+https://github.com/holepunchto/sodium-universal.git"
31 },
32 "keywords": [
33 "libsodium",
34 "sodium",
35 "sodium-native",
36 "sodium-javascript",
37 "browserify"
38 ],
39 "contributors": [
40 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
41 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
42 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
43 ],
44 "license": "MIT",
45 "bugs": {
46 "url": "https://github.com/holepunchto/sodium-universal/issues"
47 },
48 "homepage": "https://github.com/holepunchto/sodium-universal#readme"
49}
node_modules/noise-handshake/node_modules/sodium-universal/randombytes.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/noise-handshake/noise.js +301 -0
……@@ -0,0 +1,301 @@
1const assert = require('nanoassert')
2const b4a = require('b4a')
3
4const SymmetricState = require('./symmetric-state')
5const { HASHLEN } = require('./hkdf')
6
7const PRESHARE_IS = Symbol('initiator static key preshared')
8const PRESHARE_RS = Symbol('responder static key preshared')
9
10const TOK_PSK = Symbol('psk')
11
12const TOK_S = Symbol('s')
13const TOK_E = Symbol('e')
14
15const TOK_ES = Symbol('es')
16const TOK_SE = Symbol('se')
17const TOK_EE = Symbol('ee')
18const TOK_SS = Symbol('ss')
19
20const HANDSHAKES = Object.freeze({
21 NN: [
22 [TOK_E],
23 [TOK_E, TOK_EE]
24 ],
25 NNpsk0: [
26 [TOK_PSK, TOK_E],
27 [TOK_E, TOK_EE]
28 ],
29 XX: [
30 [TOK_E],
31 [TOK_E, TOK_EE, TOK_S, TOK_ES],
32 [TOK_S, TOK_SE]
33 ],
34 XXpsk0: [
35 [TOK_PSK, TOK_E],
36 [TOK_E, TOK_EE, TOK_S, TOK_ES],
37 [TOK_S, TOK_SE]
38 ],
39 IK: [
40 PRESHARE_RS,
41 [TOK_E, TOK_ES, TOK_S, TOK_SS],
42 [TOK_E, TOK_EE, TOK_SE]
43 ],
44 XK: [
45 PRESHARE_RS,
46 [TOK_E, TOK_ES],
47 [TOK_E, TOK_EE],
48 [TOK_S, TOK_SE]
49 ]
50})
51
52class Writer {
53 constructor () {
54 this.size = 0
55 this.buffers = []
56 }
57
58 push (b) {
59 this.size += b.byteLength
60 this.buffers.push(b)
61 }
62
63 end () {
64 const all = b4a.alloc(this.size)
65 let offset = 0
66 for (const b of this.buffers) {
67 all.set(b, offset)
68 offset += b.byteLength
69 }
70 return all
71 }
72}
73
74class Reader {
75 constructor (buf) {
76 this.offset = 0
77 this.buffer = buf
78 }
79
80 shift (n) {
81 const start = this.offset
82 const end = this.offset += n
83 if (end > this.buffer.byteLength) throw new Error('Insufficient bytes')
84 return this.buffer.subarray(start, end)
85 }
86
87 end () {
88 return this.shift(this.buffer.byteLength - this.offset)
89 }
90}
91
92module.exports = class NoiseState extends SymmetricState {
93 constructor (pattern, initiator, staticKeypair, opts = {}) {
94 super(opts)
95
96 this.s = staticKeypair || this.curve.generateKeyPair()
97 this.e = null
98
99 this.psk = null
100 if (opts && opts.psk) this.psk = opts.psk
101
102 this.re = null
103 this.rs = null
104
105 this.pattern = pattern
106 this.handshake = HANDSHAKES[this.pattern].slice()
107
108 this.isPskHandshake = !!this.psk && hasPskToken(this.handshake)
109
110 this.protocol = b4a.from([
111 'Noise',
112 this.pattern,
113 this.DH_ALG,
114 this.CIPHER_ALG,
115 'BLAKE2b'
116 ].join('_'))
117
118 this.initiator = initiator
119 this.complete = false
120
121 this.rx = null
122 this.tx = null
123 this.hash = null
124 }
125
126 initialise (prologue, remoteStatic) {
127 if (this.protocol.byteLength <= HASHLEN) this.digest.set(this.protocol)
128 else this.mixHash(this.protocol)
129
130 this.chainingKey = b4a.from(this.digest)
131
132 this.mixHash(prologue)
133
134 while (!Array.isArray(this.handshake[0])) {
135 const message = this.handshake.shift()
136
137 // handshake steps should be as arrays, only
138 // preshare tokens are provided otherwise
139 assert(message === PRESHARE_RS || message === PRESHARE_IS,
140 'Unexpected pattern')
141
142 const takeRemoteKey = this.initiator
143 ? message === PRESHARE_RS
144 : message === PRESHARE_IS
145
146 if (takeRemoteKey) this.rs = remoteStatic
147
148 const key = takeRemoteKey ? this.rs : this.s.publicKey
149 assert(key != null, 'Remote pubkey required')
150
151 this.mixHash(key)
152 }
153 }
154
155 final () {
156 const [k1, k2] = this.split()
157
158 this.tx = this.initiator ? k1 : k2
159 this.rx = this.initiator ? k2 : k1
160
161 this.complete = true
162 this.hash = this.getHandshakeHash()
163
164 this._clear()
165 }
166
167 recv (buf) {
168 const r = new Reader(buf)
169
170 for (const pattern of this.handshake.shift()) {
171 switch (pattern) {
172 case TOK_PSK :
173 this.mixKeyAndHash(this.psk)
174 break
175
176 case TOK_E :
177 this.re = r.shift(this.curve.PKLEN)
178 this.mixHash(this.re)
179 if (this.isPskHandshake) this.mixKeyNormal(this.re)
180 break
181
182 case TOK_S : {
183 const klen = this.hasKey ? this.curve.PKLEN + 16 : this.curve.PKLEN
184 this.rs = this.decryptAndHash(r.shift(klen))
185 break
186 }
187
188 case TOK_EE :
189 case TOK_ES :
190 case TOK_SE :
191 case TOK_SS : {
192 const useStatic = keyPattern(pattern, this.initiator)
193
194 const localKey = useStatic.local ? this.s : this.e
195 const remoteKey = useStatic.remote ? this.rs : this.re
196
197 this.mixKey(remoteKey, localKey)
198 break
199 }
200
201 default :
202 throw new Error('Unexpected message')
203 }
204 }
205
206 const payload = this.decryptAndHash(r.end())
207
208 if (!this.handshake.length) this.final()
209 return payload
210 }
211
212 send (payload = b4a.alloc(0)) {
213 const w = new Writer()
214
215 for (const pattern of this.handshake.shift()) {
216 switch (pattern) {
217 case TOK_PSK :
218 this.mixKeyAndHash(this.psk)
219 break
220
221 case TOK_E :
222 if (this.e === null) this.e = this.curve.generateKeyPair()
223 this.mixHash(this.e.publicKey)
224 if (this.isPskHandshake) this.mixKeyNormal(this.e.publicKey)
225 w.push(this.e.publicKey)
226 break
227
228 case TOK_S :
229 w.push(this.encryptAndHash(this.s.publicKey))
230 break
231
232 case TOK_ES :
233 case TOK_SE :
234 case TOK_EE :
235 case TOK_SS : {
236 const useStatic = keyPattern(pattern, this.initiator)
237
238 const localKey = useStatic.local ? this.s : this.e
239 const remoteKey = useStatic.remote ? this.rs : this.re
240
241 this.mixKey(remoteKey, localKey)
242 break
243 }
244
245 default :
246 throw new Error('Unexpected message')
247 }
248 }
249
250 w.push(this.encryptAndHash(payload))
251 const response = w.end()
252
253 if (!this.handshake.length) this.final()
254 return response
255 }
256
257 _clear () {
258 super._clear()
259
260 this.e.secretKey.fill(0)
261 this.e.publicKey.fill(0)
262
263 this.re.fill(0)
264
265 this.e = null
266 this.re = null
267 }
268}
269
270function keyPattern (pattern, initiator) {
271 const ret = {
272 local: false,
273 remote: false
274 }
275
276 switch (pattern) {
277 case TOK_EE:
278 return ret
279
280 case TOK_ES:
281 ret.local ^= !initiator
282 ret.remote ^= initiator
283 return ret
284
285 case TOK_SE:
286 ret.local ^= initiator
287 ret.remote ^= !initiator
288 return ret
289
290 case TOK_SS:
291 ret.local ^= 1
292 ret.remote ^= 1
293 return ret
294 }
295}
296
297function hasPskToken (handshake) {
298 return handshake.some(x => {
299 return Array.isArray(x) && x.indexOf(TOK_PSK) !== -1
300 })
301}
node_modules/noise-handshake/package.json +28 -0
……@@ -0,0 +1,28 @@
1{
2 "name": "noise-handshake",
3 "version": "4.2.0",
4 "description": "Noise protocol handshake",
5 "main": "noise.js",
6 "files": [
7 "*.js"
8 ],
9 "scripts": {
10 "test": "standard && brittle test/*.js"
11 },
12 "author": "Holepunch",
13 "license": "Apache-2.0",
14 "repository": {
15 "type": "git",
16 "url": "git+https://github.com/holepunchto/noise-handshake.git"
17 },
18 "dependencies": {
19 "b4a": "^1.1.0",
20 "nanoassert": "^2.0.0",
21 "sodium-universal": "^5.0.0"
22 },
23 "devDependencies": {
24 "brittle": "^3.3.2",
25 "noise-protocol": "chm-diederichs/noise-protocol.git#xx-ephemeral-key",
26 "standard": "^16.0.3"
27 }
28}
node_modules/noise-handshake/symmetric-state.js +90 -0
……@@ -0,0 +1,90 @@
1const sodium = require('sodium-universal')
2const assert = require('nanoassert')
3const b4a = require('b4a')
4const CipherState = require('./cipher')
5const curve = require('./dh')
6const { HASHLEN, hkdf } = require('./hkdf')
7
8module.exports = class SymmetricState extends CipherState {
9 constructor (opts = {}) {
10 super()
11
12 this.curve = opts.curve || curve
13 this.digest = b4a.alloc(HASHLEN)
14 this.chainingKey = null
15 this.offset = 0
16
17 this.DH_ALG = this.curve.ALG
18 }
19
20 mixHash (data) {
21 accumulateDigest(this.digest, data)
22 }
23
24 mixKeyAndHash (key) {
25 const [ck, tempH, tempK] = hkdf(this.chainingKey, key, '', 3 * HASHLEN)
26 this.chainingKey = ck
27 this.mixHash(tempH)
28 this.initialiseKey(tempK.subarray(0, 32))
29 }
30
31 mixKeyNormal (key) {
32 const [ck, tempK] = hkdf(this.chainingKey, key)
33 this.chainingKey = ck
34 this.initialiseKey(tempK.subarray(0, 32))
35 }
36
37 mixKey (remoteKey, localKey) {
38 const dh = this.curve.dh(remoteKey, localKey)
39 const hkdfResult = hkdf(this.chainingKey, dh)
40 this.chainingKey = hkdfResult[0]
41 this.initialiseKey(hkdfResult[1].subarray(0, 32))
42 }
43
44 encryptAndHash (plaintext) {
45 const ciphertext = this.encrypt(plaintext, this.digest)
46 accumulateDigest(this.digest, ciphertext)
47 return ciphertext
48 }
49
50 decryptAndHash (ciphertext) {
51 const plaintext = this.decrypt(ciphertext, this.digest)
52 accumulateDigest(this.digest, ciphertext)
53 return plaintext
54 }
55
56 getHandshakeHash (out) {
57 if (!out) return this.getHandshakeHash(b4a.alloc(HASHLEN))
58 assert(out.byteLength === HASHLEN, `output must be ${HASHLEN} bytes`)
59
60 out.set(this.digest)
61 return out
62 }
63
64 split () {
65 const res = hkdf(this.chainingKey, b4a.alloc(0))
66 return res.map(k => k.subarray(0, 32))
67 }
68
69 _clear () {
70 super._clear()
71
72 sodium.sodium_memzero(this.digest)
73 sodium.sodium_memzero(this.chainingKey)
74
75 this.digest = null
76 this.chainingKey = null
77 this.offset = null
78
79 this.curve = null
80 }
81
82 static get alg () {
83 return CipherState.alg + '_BLAKE2b'
84 }
85}
86
87function accumulateDigest (digest, input) {
88 const toHash = b4a.concat([digest, input])
89 sodium.crypto_generichash(digest, toHash)
90}
node_modules/paparam/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/paparam/README.md +398 -0
……@@ -0,0 +1,398 @@
1# paparam
2
3Strict and fair parameter papa
4
5```
6npm install paparam
7```
8
9## Usage
10
11### Simple Command
12
13Use `paparam` to build a simple cli parser. Here is an example app invocation from the command line:
14
15```bash
16> app -i uuid-284h43j -b peer1 -b peer2 --storage /tmp/file/place link-32832uifsdjsfda
17```
18
19To handle this invocation, here is the `paparam` code
20
21```js
22import { header, summary, command, flag, arg } from 'paparam'
23const cmd = command(
24 'run',
25 header('A simple example app'),
26 summary('Example app that uses a roomLink to join a room and do work.'),
27 arg('<roomLink>', 'the room link key'),
28 flag('--uuid|-i [uuid]', 'The specific schema uuid to use'),
29 flag('--user|-u [user]', 'The user name associated with the entry'),
30 flag('--storage|-s [storage]', 'Path to storage directory'),
31 flag('--blind|-b [blind]', 'Blind peer keys (can be specified multiple times)').multiple()
32)
33const program = cmd.parse() // default args: process.argv.slice(2)
34if (program === null) throw new Error('missing arg')
35console.log('user', program.flags.user)
36console.log('storagePath', program.flags.storage || '/tmp')
37console.log('blindPeers', program.flags.blind || [])
38console.log('roomLink', program.args.roomLink)
39cmd.add(flag('--another', 'lazy added'))
40cmd.add({
41 '--more': 'via description object',
42 '--modifiers': ['are defined with array [desc, opts]', { multiple: true }]
43})
44cmd.parse(['-h'])
45```
46
47### Composed Commands
48
49Use `paparam` exports to compose commands together:
50
51```js
52const { header, footer, command, flag, arg, summary, description, rest } = require('paparam')
53const run = command(
54 'run',
55 summary('Run an app from a link'),
56 description(
57 'Run an app from a file link (or path) or from a pear link.\nOptionally supply store for custom store path'
58 ),
59 flag('--store|-s [path]', 'store path'),
60 arg('<link|channel>', 'link to run'),
61 rest('[...app-args]'),
62 () => console.log('ACTION ->', 'run', run.args.link, 'flags:', run.flags)
63)
64const cmd = command(
65 'pear',
66 summary('pear cli'),
67 {
68 // definition objects can also be used with form {[modifier <arg1>]: '<arg2>' | ['<arg2>', adjusters {...}]}:
69 'flag --log': 'log',
70 header: 'Welcome to the IoP'
71 },
72 header('Welcome to the IoP'),
73 footer('holepunch.to | pears.com | keet.io'),
74 run
75)
76cmd.parse(['--help']) // print pear help
77cmd.parse(['run', '-h']) // print run help
78cmd.parse(['run', '-s', '/path/to/store', 'pear://link']) // exec run command
79
80run.add(flag('--pre-io', 'Show stdout & stderr of pre scripts')) // update command
81
82cmd.parse(['run', '-s', '/path/to/store', '--pre-io', 'pear://link']) // exec run command
83```
84
85This should output:
86
87```
88Welcome to the IoP
89
90 pear [flags] [command]
91
92 pear cli
93
94 Flags:
95 --log log
96 --help|-h Show help
97
98 Commands:
99 run Run an app from a link
100
101holepunch.to | pears.com | keet.io
102
103Welcome to the IoP
104
105 pear run [flags] <link|channel> [...app-args]
106
107 Run an app from a link
108
109 Run an app from a file link (or path) or from a pear link.
110 Optionally supply store for custom store path
111
112 Arguments:
113 <link|channel> link to run
114 [...app-args]
115
116 Flags:
117 --store|-s [path] store path
118 --help|-h Show help
119
120holepunch.to | pears.com | keet.io
121
122ACTION -> run pear://link flags: { store: '/path/to/store', s: '/path/to/store', help: false, h: false }
123ACTION -> run pear://link flags: {
124 store: '/path/to/store',
125 s: '/path/to/store',
126 help: false,
127 h: false,
128 preIo: true
129}
130```
131
132## API
133
134### `command(name, ...args)`
135
136Defines a command with a specific behavior based on the supplied modifiers such as flags, arguments, and descriptions. This function is used to create the command object.
137
138- **Arguments**:
139 - `name` `<String>`: The name of the command.
140 - `...args` `<Modifier> | <Command> | <Object> | <Function>`: Supply modifiers and subcommands as arguments. Supply a [definition object](#definition-object) to declaratively define modifiers. Supply a single function argument as the command runner.
141
142- **Returns**:
143 - `cmd` `<Command>`: The command object capable of parsing CLI arguments and executing associated actions.
144
145#### `cmd.add(...args)`
146
147Update command with additional modifiers & subcommands. A runner function may also be added, but only one runner is supported so will in that case replace the prior command runner function.
148
149- **Arguments**:
150 - `...args` `<Modifier> | <Command> | <Function>`: Supply modifiers and subcommands as arguments. Supply a single function argument as the command runner.
151
152- **Returns**:
153 - `cmd` `<Command>`: The command object capable of parsing CLI arguments and executing associated actions.
154
155#### `cmd.parse(argv = process.argv.slice(2), opts)`
156
157Parses an array of command line arguments and executes the command based on the provided definition. Automatically handles '--help' or '-h' flags to display help information.
158
159- **Arguments**:
160 - `argv` `<String[]>`: An array of strings representing the command line arguments. Defaults to program arguments `process.argv.slice(2)` if unspecified. If the `-h` or `--help` flag is supplied help for the related command will be shown.
161 - `opts` `<Object>`: Parse options
162 - `sync` `<Boolean>`: Synchronous parse, only use this with synchronous function runners. Default `false`.
163 - `silent` `<Boolean>`: Suppress the help display, even if `-h` or `--help` is provided.
164 - `run` `<Boolean>`: If false, prevents the command runner from being executed.
165- **Returns**:
166 - `null` if the parsing leads to an error (with an error output) or the command object if the command executes without errors.
167
168#### `cmd.help(...subcommands)`
169
170Generates and returns help text for the command. Can take subcommand names as arguments to generate help for a specific subcommand path. When calling `cmd.parse(argv)`, if the `-h` or `--help` flag is supplied, this method is automatically called and output.
171
172#### `cmd.usage(...subcommands)`
173
174Returns help text without header or footer. Can take subcommand names as arguments to generate help for a specific subcommand path.
175
176#### `cmd.overview({ full = false })`
177
178Returns a string with a command overview. Set `full` to `true` to include detailed usage for each command.
179
180- **Arguments**:
181 - `full` `<Boolean>`: Whether to display a full overview that includes details of all defined sub-commands and flags.
182
183#### `cmd.running` `<Promise> | null`
184
185Either `null` if the command is not running or a promise that resolves when the command has completed running.
186
187#### `cmd.bailed` `<Object> | null`
188
189Either `null` if the command did not bail or an object descibing the bail. The object can be `{ bail <Object>, error <Error>?, output <String>? }`. If the object has an `error` property it failed to create the bail output (which could happen with a user defined bail function),
190otherwise the object has an `output` property which explains the reason for the bail. The `bail` property of the `bailed` object has the following shape: `{ reason <String>, flag <Flag>, arg <Arg>, err <Error>}`. When present, `err` property on the `bail` objects would have been thrown from the runner, whereas the `bailed.error` property holds errors that occur during bailing.
191
192#### `cmd.flags` `<Object>`
193
194After `cmd.parse` has been called, contains parsed flag values.
195
196#### `cmd.args` `<Object>`
197
198After `cmd.parse` has been called, contains parsed arguments.
199
200#### `cmd.positionals` `<Array>`
201
202After `cmd.parse` has been called, contains original arguments in isolation.
203
204#### `cmd.rest` `<Object>`
205
206After `cmd.parse` has been called, contains rest arguments, if any, on `cmd.rest.restName` where `restName` is defined
207by `rest(spec)` where `spec` is `[..rest-name]`.
208
209#### `cmd.parent` `<Command>`
210
211Command parent
212
213#### `cmd.name` `<String>`
214
215Command name
216
217#### `cmd.description` `<String>`
218
219Command description
220
221#### `cmd.summary` `<String>`
222
223Command summary
224
225#### `cmd.header` `<String>`
226
227Command header
228
229#### `cmd.footer` `<String> | <Object>`
230
231Command footer
232
233#### `cmd.indices.flags` `<Object>`
234
235After `cmd.parse` has been called, contains the index of each flag in the original array.
236
237#### `cmd.indices.args` `<Object>`
238
239After `cmd.parse` has been called, contains the index of each parsed argument in the original array.
240
241#### `cmd.indices.positionals` `<Array>`
242
243After `cmd.parse` has been called, contains the indexes of each positional argument in the original array.
244
245#### `cmd.indices.rest` `<Number>`
246
247After `cmd.parse` has been called, contains the index of the first rest argument in the positional array.
248
249### `flag(spec, description)`
250
251Defines a flag for a command. Flags can be simple boolean switches or can expect a value.
252
253- **Arguments**:
254 - `spec` `<String>`: `--long|-l (<value> | [value])?` , e.g., `--boolean-flag|-b`, `--string-flag [optional-value]`, `--string-flag <required-value>`
255 - `description` `<String>`: A description of what the flag does.
256
257- **Returns**:
258 - `flag` `<Flag>`: A modifier that configures the command to recognize and handle the specified flag.
259 - `flag.hide()` to hide the flag from help.
260 - `flag.multiple()` to make this flag into an array of all passed values instead of the latest one only.
261
262### `arg(spec, description)`
263
264Defines a positional argument for a command.
265
266- **Arguments**:
267 - `spec` `<String>`: `[arg] | <arg>` where arg is the placeholder name for the argument, e.g. `<name>`, (required) `[dir]` (optional)
268 - `description` `<String>`: A description of what the argument is for.
269
270- **Returns**:
271 - `<Arg>`: A modifier that configures the command to accept and process the specified argument.
272
273### `rest(spec, description)`
274
275Defines rest arguments that are captured after all flags and named arguments.
276
277- **Arguments**:
278 - `spec` `<String>`: `[...rest-name]`. The name to collect rest arguments under, e.g. `[...app-args]` array will be stored at `cmd.rest.appArgs`.
279 - `description` `<String>`: Description of what these rest arguments represent.
280
281- **Returns**:
282 - `<Rest>`: A modifier that configures the command to capture additional arguments not explicitly defined.
283
284### `validate(validator, description)`
285
286Defines a validation function for the command. This function is used to enforce custom validation logic on the command after parsing, such as checking the relationship of flags, arguments, rest arguments, etc.
287
288- **Arguments**:
289 - `validator` `<Function>`: A function that takes the parsed command object and returns a boolean indicating whether the validation passed. If the validation fails, the function should throw an error or return a string describing the validation error.
290 - **Parameters**:
291 - `args` `<Object>`: An object containing the parsed arguments.
292 - `flags` `<Object>`: An object containing the parsed flags.
293 - `positionals` `<Array>`: An array containing the positional arguments.
294 - `rest` `<Object>`: An object containing the rest arguments.
295 - `indices` `<Object>`: An object containing the indices of flags, arguments, positionals, and rest.
296 - `flags` `<Object>`: An object containing the indices of the flags.
297 - `args` `<Object>`: An object containing the indices of the arguments.
298 - `positionals` `<Array>`: An array containing the indices of the positional arguments.
299 - `rest` `<Number>`: The index of the rest arguments.
300 - `command` `<Command>`: The command object being validated.
301 - **Returns**:
302 - `<Boolean>`: The validator function should return true if the validation passes, indicating that the command is valid. If the validation fails, it should return false or throw an error. Returning false indicates that the command is invalid.
303
304- **Returns**:
305 - `<Validation>`: A modifier that configures the command to use the specified validation function.
306
307### `summary(text)`
308
309Defines a brief summary of the command's functionality.
310
311- **Arguments**:
312 - `text` `<String>`: Summary of the command's purpose.
313
314- **Returns**:
315 - `<Data>`: A modifier containing the summary information.
316
317### `` description(text) | description`text` ``
318
319Defines a detailed description of the command's functionality.
320When used as a tagged template function, `description` automatically dedents the text.
321
322- **Arguments**:
323 - `text` `<String>`: Detailed information about the command.
324
325- **Returns**:
326 - `<Data>`: A modifier containing the description information.
327
328### `header(text)`
329
330Define a header for the command's help output.
331
332- **Arguments**:
333 - `text` `<String>`: Text to display at the top of the output.
334
335- **Returns**:
336 - `<Data>`: A modifier that configures the header text.
337
338### `footer(text | { overview: text, help: text })`
339
340Define a footer for the command's help & overview output.
341
342- **Arguments**:
343 - `text` `<String> | { overview: text <String>, help: text <String> }`| : Text to display at the bottom of the help and/or overview output.
344
345- **Returns**:
346 - `<Data>`: A modifier that configures the footer text.
347
348### `bail(fn)`
349
350Set the bail handler to `fn`.
351
352### `sloppy(opts)`
353
354Configures the command to be non-strict when parsing unknown flags or arguments.
355
356### Definition Object
357
358The `command` function can also accept plain objects with the following form:
359
360```
361 {[modifier <arg1>]: '<arg2>' | ['<arg2>', adjusters {...}]}
362```
363
364`modifier`: names of exported functions designed to passed to `command` function such as `flag(...)`, `arg(...)`, `summary(...)` and so on.
365`<arg1>`: first arg passed, e.g. `flag('--some value') -> 'flag --some value'`, `rest('[...args]') -> 'rest [...args]'`
366`<arg2>`: second arg passed to modifier `flag('--some value', 'some flag') -> {'flag --some value': 'some flag'}`
367`['<arg2>', adjusters {...}]`: adjusters are methods on modifiers, such as `flag.multiple()`, `flag.choices(...)`, `flag.hide()` and `arg.hide()`. For adjusters with args the value should be the arg eg `{choices: ['a', 'b', 'c']}`, otherwise set to `true` to enable `{ multiple: true }`
368
369Example:
370
371```js
372import { command } from 'paparam'
373const cmd = command({
374 name: 'pear',
375 summary: 'summary text',
376 description: 'description text',
377 header: 'header text',
378 footer: 'footer text',
379 'flag --define flag': 'describe flag',
380 'flag --define multiflag': ['describe flag', { multiple: true }],
381 'flag --define hidden-flag': ['describe flag', { hide: true }],
382 'flag --define choices': ['describe flag', { choices: ['a', 'b', 'c'] }],
383 'arg <required>': 'required arg',
384 'hidden [arg]': ['hidden optional arg', { hide: true }],
385 rest: '[...args]',
386 command: {
387 name: 'run',
388 summary: 'a subcommand'
389 }
390})
391cmd.parse(['-h'])
392```
393
394This is a useful format for supporting JSON-based definitions of commands.
395
396## License
397
398Apache-2.0
node_modules/paparam/index.js +918 -0
……@@ -0,0 +1,918 @@
1'use strict'
2const EOL = '\n'
3const noop = () => {}
4module.exports = {
5 command,
6 hiddenCommand,
7 header,
8 footer,
9 argv,
10 flag,
11 hiddenFlag,
12 arg,
13 rest,
14 validate,
15 summary,
16 description,
17 sloppy,
18 bail
19}
20
21class Parser {
22 constructor(argv) {
23 this.argv = argv
24 this.i = 0
25 this.multi = null
26 }
27
28 rest() {
29 const rest = this.argv.slice(this.i)
30 this.lasti = this.i
31 this.i = this.argv.length
32 return rest
33 }
34
35 next() {
36 while (true) {
37 const r = {
38 flag: null,
39 rest: null,
40 arg: null
41 }
42
43 if (this.multi && this.multi.length) {
44 const name = this.multi.pop()
45 r.flag = { long: false, name, value: '' }
46 return r
47 }
48
49 this.multi = null
50
51 if (this.i >= this.argv.length) return null
52 this.lasti = this.i
53 const a = this.argv[this.i++]
54
55 if (a === '--') {
56 r.rest = this.rest()
57 return r
58 }
59
60 if (a.length > 2 && a[0] === '-' && a[1] === '-') {
61 let j = a.indexOf('=')
62 if (j === -1) j = a.length
63 const inverse = a.startsWith('--no-')
64 const name = inverse ? a.slice(5, j) : a.slice(2, j)
65 const value = a.slice(j + 1)
66 r.flag = { long: true, name, value, inverse }
67 return r
68 }
69
70 if (a.length > 1 && a[0] === '-') {
71 this.multi = []
72 for (let i = 1; i < a.length; i++) this.multi.push(a[i])
73 this.multi.reverse()
74 continue
75 }
76
77 r.arg = a
78 return r
79 }
80 }
81}
82
83class Command {
84 constructor(parent, name) {
85 this.parent = parent
86 this.name = name
87 this.hidden = false
88 this.description = ''
89 this.summary = ''
90 this.header = ''
91 this.footer = ''
92
93 this.flags = {}
94 this.args = {}
95 this.positionals = []
96 this.rest = null
97 this.bailed = null
98 this.indices = { flags: {}, args: {}, positionals: [], rest: undefined }
99
100 this.running = null
101 this.argv = null
102
103 this._validators = []
104 this._runner = null
105 this._onbail = null
106 this._indent = ''
107 this._strictFlags = true
108 this._strictArgs = true
109 this._labels = {
110 arguments: 'Arguments:',
111 flags: 'Flags:',
112 commands: 'Commands:'
113 }
114
115 this._definedCommands = new Map()
116 this._definedFlags = new Map()
117 this._definedArgs = []
118 this._definedRest = null
119 }
120
121 hide() {
122 this.hidden = true
123 return this
124 }
125
126 bail(bail) {
127 try {
128 this.bailed = { output: this._bail(bail), bail }
129 } catch (err) {
130 this.bailed = { error: err, bail }
131 throw err
132 }
133 return this.bailed
134 }
135
136 overview({ full = false } = {}) {
137 let s = ''
138 if (this.header) s += this.header + EOL + EOL
139
140 for (const [name, command] of this._definedCommands) {
141 if (command.hidden) continue
142 if (full) {
143 command._indent = this.header ? ' ' : ''
144 s += command._indent + command._oneliner(false) + EOL + command._aligned() + EOL
145 command._indent = ''
146 } else s += ' ' + this.name + ' ' + name + ' ~ ' + command.summary + EOL
147 }
148
149 if (this.footer) {
150 s += EOL + (Object.hasOwn(this.footer, 'overview') ? this.footer.overview : this.footer) + EOL
151 }
152
153 return s
154 }
155
156 help(...args) {
157 let s = ''
158
159 if (this.header) s += this.header + EOL + EOL
160 this._indent = this.header ? ' ' : ''
161 const output = this.usage(...args)
162 s += typeof output === 'string' ? output : ''
163 this._indent = ''
164
165 if (this.footer) {
166 s += EOL + (Object.hasOwn(this.footer, 'help') ? this.footer.help : this.footer) + EOL
167 }
168
169 return s
170 }
171
172 usage(subcommand, ...args) {
173 if (subcommand) {
174 const sub = this._definedCommands.get(subcommand)
175 if (!sub) return this.bail(createBail(this, 'UNKNOWN_ARG', null, { value: subcommand }))
176 sub.parent = this
177 const str = sub.usage(...args)
178 return str
179 }
180 let s = this._indent + this._oneliner(false) + EOL
181 s += this._aligned()
182
183 return s
184 }
185
186 parse(input = argv(), opts = { run: true }) {
187 const { sync = false, bails = true } = opts
188 const p = new Parser(input)
189
190 let c = this._reset()
191 let bail = null
192
193 const visited = [c]
194
195 while (bail === null) {
196 if (
197 c._definedRest !== null &&
198 c.positionals.length === c._definedArgs.length &&
199 c._definedArgs.length > 0
200 ) {
201 bail = c._onrest(p.rest(), p)
202 break
203 }
204
205 const n = p.next()
206 if (n === null) break
207
208 if (n.flag) {
209 bail = c._onflag(n.flag, p)
210 continue
211 }
212
213 if (n.arg && c._definedArgs.length > 0) {
214 bail = c._onarg(n.arg, p)
215 continue
216 }
217
218 if (c._definedCommands.size > 0) {
219 const cmd = c._getCommand(n.arg)
220
221 if (cmd !== null) {
222 c = cmd._reset()
223 visited.push(c)
224 continue
225 }
226 }
227
228 p.i--
229 bail = c._onrest(p.rest(), p)
230 }
231
232 if (c !== this && !c.parent) c.parent = this
233 if (c.parent) c.parent.current = c
234
235 if (!bail) {
236 const hasHelpFlag = 'help' in this.indices.flags
237 const missing = this._definedArgs.filter(
238 (arg) => !hasHelpFlag && !arg.optional && !(arg.name in c.args)
239 )
240
241 if (missing.length > 0) {
242 bail = createBail(this, 'MISSING_ARG', null, { value: missing[0].help })
243 }
244 }
245
246 if (!bail) {
247 if (c.flags.help) {
248 if (!opts.silent) console.log(c.help())
249 return null
250 }
251 for (const v of c._validators) {
252 bail = runValidation(v, c)
253 if (bail) {
254 if (bails) c.bail(bail)
255 return null
256 }
257 }
258 if (c._runner !== null && opts.run !== false) {
259 c.argv = input
260 if (sync) runSync(c)
261 else c.running = runAsync(c)
262 }
263 return c
264 }
265
266 if (bails) c.bail(bail)
267 return null
268 }
269
270 _oneliner(short, relative) {
271 const stack = [this]
272 if (!relative) {
273 while (stack[stack.length - 1].parent) stack.push(stack[stack.length - 1].parent)
274 }
275
276 const run = stack.reverse().map((c) => c.name || 'app')
277
278 if (!short) {
279 if (this._definedFlags.size > 0) run.push('[flags]')
280 for (const arg of this._definedArgs) run.push(arg.help)
281 if (this._definedCommands.size > 0) run.push('[command]')
282 if (this._definedRest !== null) run.push(this._definedRest.help)
283 }
284
285 return run.join(' ')
286 }
287
288 _aligned(padding = 0, color = false) {
289 const l = []
290 const visited = new Set()
291 const indent = this._indent
292 if (this.summary) {
293 l.push(['', ''])
294 l.push(...this.summary.split(EOL).map((line) => [this._indent + line, '']))
295 }
296 if (this.description) {
297 l.push(['', ''])
298 l.push(...this.description.split(EOL).map((line) => [this._indent + line, '']))
299 }
300
301 if (this._definedArgs.length > 0 || this._definedRest !== null) {
302 l.push(['', ''])
303 l.push([indent + this._labels.arguments, ''])
304 for (const arg of this._definedArgs) {
305 l.push([indent + ' ' + arg.help, arg.usage()])
306 }
307 }
308
309 if (this._definedRest) {
310 l.push([indent + ' ' + this._definedRest.help, this._definedRest.description])
311 }
312
313 if (this._definedFlags.size) {
314 l.push(['', ''])
315 l.push([indent + this._labels.flags, ''])
316 for (const flag of this._definedFlags.values()) {
317 if (visited.has(flag)) continue
318 visited.add(flag)
319 if (!flag.hidden) l.push([indent + ' ' + flag.help, flag.description])
320 }
321 }
322
323 if (this._definedCommands.size) {
324 l.push(['', ''])
325 l.push([indent + this._labels.commands, ''])
326 for (const c of this._definedCommands.values()) {
327 if (c.hidden) continue
328 l.push([indent + ' ' + c._oneliner(true, true), c.summary || c.description])
329 }
330 }
331
332 if (padding === 0) {
333 for (const [left, right] of l) {
334 if (!right) continue
335 if (left.length > padding) padding = left.length
336 }
337 }
338
339 if (color === false) {
340 return this._aligned(padding, true)
341 }
342
343 let s = ''
344 for (const [left, right] of l) {
345 s += (left.padEnd(padding, ' ') + ' ' + right).trimEnd() + EOL
346 }
347
348 s = s.trimEnd()
349
350 return s ? s + EOL : ''
351 }
352
353 add(...args) {
354 const c = this
355 for (const a of args) {
356 if (a instanceof Command) {
357 c._addCommand(a)
358 } else if (a instanceof Flag) {
359 c._addFlag(a)
360 } else if (a instanceof Arg) {
361 c._addArg(a)
362 } else if (a instanceof Rest) {
363 c._addRest(a)
364 } else if (a instanceof Data) {
365 c._addData(a)
366 } else if (a instanceof Validation) {
367 c._addValidation(a)
368 } else if (typeof a === 'function') {
369 c._addRunner(a)
370 } else if (a !== null && Array.isArray(a) === false && typeof a === 'object') {
371 c._addDefinition(a)
372 } else {
373 throw new Error('Unknown arg: ' + a)
374 }
375 }
376 c._addFlag(new Flag('--help|-h', 'Show help'))
377 if (!c._runner) c._addRunner(noop)
378 return c
379 }
380
381 _addDefinition(c) {
382 for (const [def, dsc] of Object.entries(c)) {
383 const [definer, ...definition] = def.split(' ')
384 const define = module.exports[definer]
385 if (typeof define === 'function') {
386 const [description, modifiers = {}] = Array.isArray(dsc) ? dsc : [dsc]
387 const mod =
388 definition.length === 0 ? define(description) : define(definition.join(' '), description)
389 for (const [modifier, value] of Object.entries(modifiers)) {
390 if (typeof mod[modifier] === 'function') {
391 if (value === true) mod[modifier]()
392 else if (value !== false) mod[modifier](value)
393 }
394 }
395 this.add(mod)
396 }
397 }
398 }
399
400 _addCommand(c) {
401 if (!c.header) c.header = this.header
402 if (!c.footer) c.footer = this.footer
403 if (!c.parent) c.parent = this
404 this._definedCommands.set(c.name, c)
405 }
406
407 _addFlag(f) {
408 this._definedFlags.set(f.name, f)
409 for (const alias of f.aliases) {
410 if (alias !== f.name) {
411 this._definedFlags.set(alias, f)
412 }
413 }
414 }
415
416 _addArg(a) {
417 this._definedArgs.push(a)
418 }
419
420 _addRest(a) {
421 this._definedRest = a
422 }
423
424 _addData(d) {
425 switch (d.type) {
426 case 'bail': {
427 if (this._onbail !== null) throw new Error('onbail already set')
428 this._onbail = d.value
429 break
430 }
431 case 'name': {
432 this.name = d.value
433 break
434 }
435 case 'summary': {
436 this.summary = d.value
437 break
438 }
439 case 'description': {
440 this.description = d.value
441 break
442 }
443 case 'header': {
444 this.header = unindent(d.value)
445 break
446 }
447 case 'footer': {
448 this.footer =
449 d.value !== null && typeof d.value === 'object'
450 ? { help: unindent(d.value.help || ''), overview: d.value.overview }
451 : unindent(d.value)
452 break
453 }
454 case 'sloppy': {
455 this._strictFlags = !d.value?.flags
456 this._strictArgs = !d.value?.args
457 break
458 }
459 }
460 }
461
462 _addValidation(_validator) {
463 this._validators.push(_validator)
464 }
465
466 _addRunner(_runner) {
467 this._runner = _runner
468 }
469
470 _reset() {
471 this.flags = {}
472 this.args = {}
473 this.positionals = []
474 this.rest = null
475 this.indices = { flags: {}, args: {}, positionals: [], rest: undefined }
476 this.running = null
477 this.argv = null
478 for (const [name, { value }] of this._definedFlags) {
479 if (name === snakeToCamel(name)) {
480 this.flags[name] = value
481 }
482 }
483 return this
484 }
485
486 _getFlag(name, flag) {
487 let f = this._definedFlags.get(name)
488 if (f && flag.long && f.aliases.indexOf(name) > 0) f = undefined
489 if (f === undefined && this._strictFlags === false) f = defaultFlag(name)
490 return f || null
491 }
492
493 _getCommand(name) {
494 return this._definedCommands.get(name) || null
495 }
496
497 _onflag(flag, parser) {
498 const def = this._getFlag(flag.name, flag)
499 if (def === null) return createBail(this, 'UNKNOWN_FLAG', flag, null)
500
501 if (def.boolean === true) {
502 if (flag.value) return createBail(this, 'INVALID_FLAG', flag, null)
503 this.flags[def.name] = !flag.inverse
504 if (def.aliases[1]) this.flags[def.aliases[1]] = this.flags[def.name]
505 def.aliases.forEach((e) => {
506 this.indices.flags[e] = parser.lasti
507 })
508 if (!def.aliases.includes(def.name)) this.indices.flags[def.name] = parser.lasti
509 return null
510 }
511
512 if (def.boolean === false) {
513 if (flag.value) {
514 if (def.valueChoices && !def.valueChoices.includes(flag.value)) {
515 return createBail(this, 'INVALID_FLAG', flag, null)
516 }
517
518 const value = def.multi ? (this.flags[def.name] || []).concat(flag.value) : flag.value
519 this.flags[def.name] = value
520 if (def.aliases[1]) this.flags[def.aliases[1]] = value
521 def.aliases.forEach((e) => {
522 this.indices.flags[e] = parser.lasti
523 })
524 if (!def.aliases.includes(def.name)) this.indices.flags[def.name] = parser.lasti
525 return null
526 }
527
528 const next = parser.next()
529 const argless = next === null || !next.arg
530 if (def.valueRequired && argless && !def.hasDefault) {
531 return createBail(this, 'INVALID_FLAG', flag, null)
532 }
533
534 const nextValue = !next?.arg && def.hasDefault ? def.value : next?.arg
535 if (def.valueChoices && !def.valueChoices.includes(nextValue)) {
536 return createBail(this, 'INVALID_FLAG', flag, null)
537 }
538 const value = def.multi ? (this.flags[def.name] || []).concat(nextValue) : nextValue
539 this.flags[def.name] = value
540 if (def.aliases[1]) this.flags[def.aliases[1]] = value
541 if (def.multi) {
542 def.aliases.forEach((e) => {
543 this.indices.flags[e] = (this.indices.flags[e] || []).concat(parser.lasti)
544 })
545 if (!def.aliases.includes(def.name)) {
546 this.indices.flags[def.name] = (this.indices.flags[def.name] || []).concat(parser.lasti)
547 }
548 } else {
549 def.aliases.forEach((e) => {
550 this.indices.flags[e] = parser.lasti
551 })
552 if (!def.aliases.includes(def.name)) this.indices.flags[def.name] = parser.lasti
553 }
554 }
555
556 return null
557 }
558
559 _onarg(arg, parser) {
560 const info = { index: this.positionals.length, value: arg }
561 if (this._definedArgs.length <= this.positionals.length) {
562 if (this._strictArgs === false) {
563 this.positionals.push(arg)
564 this.indices.positionals.push(parser.lasti)
565 return null
566 }
567
568 return createBail(this, 'UNKNOWN_ARG', null, info)
569 }
570
571 const def = this._definedArgs[this.positionals.length]
572 this.positionals.push(arg)
573 this.indices.positionals.push(parser.lasti)
574 this.args[def.name] = arg
575 this.indices.args[def.name] = parser.lasti
576
577 return null
578 }
579
580 _onrest(rest, parser) {
581 if (this._definedRest === null && this._strictArgs) {
582 return createBail(this, 'UNKNOWN_ARG', null, {
583 index: this.positionals.length,
584 value: rest.join(' ')
585 })
586 }
587
588 this.rest = rest
589 this.indices.rest = parser.lasti
590 return null
591 }
592
593 _bail(bail) {
594 if (typeof this._onbail === 'function') return this._onbail(bail)
595 if (this.parent) return this.parent._bail(bail)
596 if (bail.flag) throw new Bail(bail.reason + ': ' + bail.flag.name)
597 if (bail.arg) throw new Bail(bail.reason + ': ' + bail.arg.value)
598 throw new Bail(bail.reason)
599 }
600}
601
602class Flag {
603 constructor(spec, description = '') {
604 const { longName, shortName, aliases, boolean, help, value, valueRequired } = parseFlag(spec)
605 this.name = snakeToCamel(longName || shortName)
606 this.aliases = aliases
607 this.boolean = boolean
608 this.help = help
609 this.description = description
610 this.hidden = false
611 this.multi = false
612 this.valueChoices = undefined
613 this.hasDefault = false
614 this.value = value
615 this.valueRequired = valueRequired
616 }
617
618 default(val) {
619 this.hasDefault = true
620 this.value = val
621 this.description += ` (default: ${val})`
622 return this
623 }
624
625 multiple() {
626 this.multi = true
627 return this
628 }
629
630 choices(valueChoices) {
631 this.valueChoices = valueChoices
632 this.description += ` (choices: ${valueChoices.join(', ')})`
633 return this
634 }
635
636 hide() {
637 this.hidden = true
638 return this
639 }
640}
641
642class Arg {
643 constructor(help, description = '') {
644 this.optional = help.startsWith('[')
645 this.name = snakeToCamel(help)
646 this.help = help
647 this.description = description
648 this.hidden = false
649 }
650
651 hide() {
652 this.hidden = true
653 return this
654 }
655
656 usage() {
657 if (!this.optional) return this.description
658 const first = this.description.slice(0, 1)
659 return (
660 (this.description && first.toLowerCase() === first ? 'optional. ' : 'Optional. ') +
661 this.description
662 )
663 }
664}
665
666class Rest {
667 constructor(help, description = '') {
668 this.help = help
669 this.description = description
670 }
671}
672
673class Data {
674 constructor(type, value) {
675 this.type = type
676 this.value = value
677 }
678}
679
680class Validation {
681 constructor(validator, description = 'invalid command') {
682 if (typeof validator === 'string') [description, validator] = [validator, description]
683 this.validator = validator
684 this.description = description
685 }
686}
687
688function argv() {
689 return typeof process === 'undefined' ? global.Bare.argv.slice(2) : process.argv.slice(2)
690}
691
692function command(name, ...args) {
693 if (
694 name !== null &&
695 typeof name === 'object' &&
696 Object.getPrototypeOf(name) === Object.prototype
697 ) {
698 const arg = name
699 args.unshift(arg)
700 name = arg.name
701 }
702 const c = new Command(null, name)
703 c.add(...args)
704 return c
705}
706
707// deprecated, removed soon, use.hide()
708function hiddenCommand(name, ...args) {
709 return command(name, ...args).hide()
710}
711
712function bail(fn) {
713 return new Data('bail', fn)
714}
715
716function sloppy(opts) {
717 return new Data('sloppy', opts)
718}
719
720function summary(desc) {
721 return new Data('summary', desc)
722}
723
724function description(desc, ...values) {
725 if (Array.isArray(desc)) return description(dedent(desc, values))
726 return new Data('description', desc)
727}
728
729function header(desc) {
730 return new Data('header', desc)
731}
732
733function footer(desc) {
734 return new Data('footer', desc)
735}
736
737// deprecated, removed soon, use .hide()
738function hiddenFlag(help, description) {
739 return flag(help, description).hide()
740}
741
742function flag(help, description) {
743 return new Flag(help, description)
744}
745
746function rest(help, description) {
747 return new Rest(help, description)
748}
749
750function arg(help, description) {
751 return new Arg(help, description)
752}
753
754function validate(validator, description) {
755 return new Validation(validator, description)
756}
757
758function unindent(info) {
759 const lines = info.split('\n').filter(trimLine)
760 if (!lines.length) return ''
761 const indent = lines[0].match(/^(\s*)/)[1]
762
763 let s = ''
764 for (const line of lines) s += line.slice(indent.length).trimEnd() + '\n'
765 return s.trimEnd()
766}
767
768function trimLine(line) {
769 return line.trim()
770}
771
772function snakeToCamel(name) {
773 const parts = name.match(/([a-zA-Z0-9-]+)/)[1].split(/-+/)
774 for (let i = 1; i < parts.length; i++) {
775 parts[i] = parts[i].slice(0, 1).toUpperCase() + parts[i].slice(1)
776 }
777 return parts.join('')
778}
779
780function parseFlag(help) {
781 const parts = help.split(/[| ]/)
782 const result = {
783 longName: null,
784 shortName: null,
785 aliases: [],
786 boolean: true,
787 help,
788 value: null,
789 inverse: false,
790 valueRequired: false
791 }
792 for (const p of parts) {
793 result.inverse = p.startsWith('--no-')
794 if (p.startsWith('--')) {
795 const name = result.inverse ? trimFlag(p).slice(3) : trimFlag(p)
796 if (result.longName === null) result.longName = name
797 result.value = result.inverse
798 result.aliases.push(name)
799 continue
800 }
801
802 if (p.startsWith('-')) {
803 const name = trimFlag(p)
804 if (result.shortName === null) result.shortName = name
805 result.value = false
806 result.aliases.push(name)
807 continue
808 }
809
810 const valueRequired = p.startsWith('<')
811 const stringFlag = p.startsWith('[') || valueRequired
812 if (stringFlag) {
813 result.boolean = false
814 result.value = undefined
815 result.valueRequired = valueRequired
816 }
817 }
818
819 return result
820}
821
822function trimFlag(s) {
823 return s.replace(/(^[^0-9\w]+)|([^0-9\w]+$)/g, '')
824}
825
826function createBail(command, reason, flag, arg, err) {
827 return { command, reason, flag, arg, err }
828}
829
830function defaultFlag(name) {
831 return {
832 name,
833 aliases: [name],
834 boolean: false,
835 help: '',
836 description: '',
837 value: ''
838 }
839}
840
841function dedent(strings, values) {
842 const raw = String.raw(strings, ...values)
843 const lines = raw.split('\n')
844
845 let minIndent = Infinity
846 for (const line of lines) {
847 let i = 0
848 while (i < line.length && line[i] === ' ') i++
849 if (i < line.length) minIndent = Math.min(minIndent, i)
850 }
851
852 if (minIndent === Infinity) return raw.trim()
853
854 let result = ''
855 for (const line of lines) {
856 result += line.length >= minIndent ? line.slice(minIndent) + '\n' : '\n'
857 }
858
859 return result.trim()
860}
861
862function runValidation(v, c) {
863 try {
864 const isValid = v.validator({
865 args: c.args,
866 flags: c.flags,
867 positionals: c.positionals,
868 rest: c.rest,
869 indices: c.indices,
870 command: c
871 })
872 if (!isValid) {
873 const err = new Error(v.description)
874 err.code = 'ERR_INVALID'
875 err.bail = { reason: v.description }
876 throw err
877 }
878 return null
879 } catch (err) {
880 return createBail(c, err.bail?.reason ?? err.stack, err.bail?.flag, err.bail?.arg, err)
881 }
882}
883
884function runSync(c) {
885 try {
886 c._runner({
887 args: c.args,
888 flags: c.flags,
889 positionals: c.positionals,
890 rest: c.rest,
891 indices: c.indices,
892 argv: c.argv,
893 command: c
894 })
895 } catch (err) {
896 c.bail(createBail(c, err.stack, null, null, err))
897 }
898}
899
900async function runAsync(c) {
901 try {
902 await c._runner({
903 args: c.args,
904 flags: c.flags,
905 positionals: c.positionals,
906 rest: c.rest,
907 indices: c.indices,
908 argv: c.argv,
909 command: c
910 })
911 } catch (err) {
912 c.bail(createBail(c, err.stack, null, null, err))
913 }
914}
915
916class Bail extends Error {
917 name = 'Bail'
918}
node_modules/paparam/package.json +32 -0
……@@ -0,0 +1,32 @@
1{
2 "name": "paparam",
3 "version": "1.10.1",
4 "description": "Strict and fair parameter papa",
5 "main": "index.js",
6 "scripts": {
7 "format": "prettier --write .",
8 "lint": "prettier --check . && lunte",
9 "test": "npm run test:node && npm run test:bare",
10 "test:node": "brittle-node test.js",
11 "test:bare": "brittle-bare test.js"
12 },
13 "devDependencies": {
14 "brittle": "^3.5.0",
15 "lunte": "^1.0.0",
16 "prettier": "^3.6.2",
17 "prettier-config-holepunch": "^2.0.0"
18 },
19 "files": [
20 "index.js"
21 ],
22 "repository": {
23 "type": "git",
24 "url": "https://github.com/holepunchto/paparam.git"
25 },
26 "author": "Holepunch Inc.",
27 "license": "Apache-2.0",
28 "bugs": {
29 "url": "https://github.com/holepunchto/paparam/issues"
30 },
31 "homepage": "https://github.com/holepunchto/paparam"
32}
node_modules/protocol-buffers-encodings/.travis.yml +6 -0
……@@ -0,0 +1,6 @@
1language: node_js
2node_js:
3 - "9"
4 - "8"
5 - "6"
6 - "4"
node_modules/protocol-buffers-encodings/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2018 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/protocol-buffers-encodings/README.md +73 -0
……@@ -0,0 +1,73 @@
1# protocol-buffers-encodings
2
3Base encodings for [protocol-buffers](https://github.com/mafintosh/protocol-buffers).
4
5```
6npm install protocol-buffers-encodings
7```
8
9Note: use Node.js >= 16.15.0 to avoid a performance regression due to a slower `Buffer.subarray` function.
10
11[![build status](https://travis-ci.org/mafintosh/protocol-buffers-encodings.svg?branch=master)](https://travis-ci.org/mafintosh/protocol-buffers-encodings)
12
13Moved into its own module for lighter installs
14
15## Usage
16
17``` js
18var encodings = require('protocol-buffers-encodings')
19var buf = Buffer.alloc(4096)
20
21encodings.string('hi', buf, 0)
22console.log(encodings.string(buf, 0)) // prints 'hi'
23```
24
25## API
26
27In general all encoders follow this API
28
29#### `buffer = enc.encode(value, buffer, offset)`
30
31Encode a value. `buffer` should be a buffer big enough to fit the value, `offset` should be the byte offset in the buffer where you want to write it.
32The buffer is returned for convenience.
33
34After a value has been encoded `enc.encode.bytes` contains the amount of bytes used in the buffer.
35
36#### `value = enc.decode(buffer, offset)`
37
38Decode a value. `buffer` should be an encoded value and `offset` should be the byte offset where you want to start decoding.
39
40After a value has been decoded `enc.decode.bytes` contains the amount of bytes that was consumed from the buffer.
41
42#### `var len = enc.encodingLength(value)`
43
44Use this method to calculate how much space is needed to encode a value.
45
46#### `enc.type`
47
48A number indicating the protobuf wire type for the encoding
49
50## Encodings
51
52The following encodings are available
53
54* `encodings.bytes` - encode a buffer
55* `encodings.string` - encode a string
56* `encodings.bool` - encode a boolean
57* `encodings.uint64` - encode a uint64 to varint
58* `encodings.uint32` - encode a uint32 to varint
59* `encodings.sint64` - encode a signed int64 to a signed varint
60* `encodings.sint32` - encode a signed int32 to a signed varint
61* `encodings.int64` - encode a signed int64 to a varint
62* `encodings.int32` - encode a signed int32 to a varint
63* `encodings.fixed32` - encode a uint32 to a fixed 4 byte buffer
64* `encodings.sfixed32` - encode a signed int32 to a fixed 4 byte buffer
65* `encodings.fixed64` - encode a uint64 (represented as a buffer) to a fixed 8 byte buffer
66* `encodings.sfixed64` - encode a signed int64 (represented as a buffer) to a fixed 8 byte buffer
67* `encodings.double` - encode a double
68* `encodings.float` - encode a float
69* `encodings.enum` - encode a numeric enum as a varint
70
71## License
72
73MIT
node_modules/protocol-buffers-encodings/index.js +287 -0
……@@ -0,0 +1,287 @@
1var varint = require('varint')
2var svarint = require('signed-varint')
3var b4a = require('b4a')
4
5exports.make = encoder
6
7exports.name = function (enc) {
8 var keys = Object.keys(exports)
9 for (var i = 0; i < keys.length; i++) {
10 if (exports[keys[i]] === enc) return keys[i]
11 }
12 return null
13}
14
15exports.skip = function (type, buffer, offset) {
16 switch (type) {
17 case 0:
18 varint.decode(buffer, offset)
19 return offset + varint.decode.bytes
20
21 case 1:
22 return offset + 8
23
24 case 2:
25 var len = varint.decode(buffer, offset)
26 return offset + varint.decode.bytes + len
27
28 case 3:
29 case 4:
30 throw new Error('Groups are not supported')
31
32 case 5:
33 return offset + 4
34 }
35
36 throw new Error('Unknown wire type: ' + type)
37}
38
39exports.bytes = encoder(2,
40 function encode (val, buffer, offset) {
41 var oldOffset = offset
42 var len = bufferLength(val)
43
44 varint.encode(len, buffer, offset)
45 offset += varint.encode.bytes
46
47 if (b4a.isBuffer(val)) b4a.copy(val, buffer, offset)
48 else b4a.write(buffer, val, offset, len)
49 offset += len
50
51 encode.bytes = offset - oldOffset
52 return buffer
53 },
54 function decode (buffer, offset) {
55 var oldOffset = offset
56
57 var len = varint.decode(buffer, offset)
58 offset += varint.decode.bytes
59
60 var val = buffer.subarray(offset, offset + len)
61 offset += val.length
62
63 decode.bytes = offset - oldOffset
64 return val
65 },
66 function encodingLength (val) {
67 var len = bufferLength(val)
68 return varint.encodingLength(len) + len
69 }
70)
71
72exports.string = encoder(2,
73 function encode (val, buffer, offset) {
74 var oldOffset = offset
75 var len = b4a.byteLength(val)
76
77 varint.encode(len, buffer, offset, 'utf-8')
78 offset += varint.encode.bytes
79
80 b4a.write(buffer, val, offset, len)
81 offset += len
82
83 encode.bytes = offset - oldOffset
84 return buffer
85 },
86 function decode (buffer, offset) {
87 var oldOffset = offset
88
89 var len = varint.decode(buffer, offset)
90 offset += varint.decode.bytes
91
92 var val = b4a.toString(buffer, 'utf-8', offset, offset + len)
93 offset += len
94
95 decode.bytes = offset - oldOffset
96 return val
97 },
98 function encodingLength (val) {
99 var len = b4a.byteLength(val)
100 return varint.encodingLength(len) + len
101 }
102)
103
104exports.bool = encoder(0,
105 function encode (val, buffer, offset) {
106 buffer[offset] = val ? 1 : 0
107 encode.bytes = 1
108 return buffer
109 },
110 function decode (buffer, offset) {
111 var bool = buffer[offset] > 0
112 decode.bytes = 1
113 return bool
114 },
115 function encodingLength () {
116 return 1
117 }
118)
119
120exports.int32 = encoder(0,
121 function encode (val, buffer, offset) {
122 varint.encode(val < 0 ? val + 4294967296 : val, buffer, offset)
123 encode.bytes = varint.encode.bytes
124 return buffer
125 },
126 function decode (buffer, offset) {
127 var val = varint.decode(buffer, offset)
128 decode.bytes = varint.decode.bytes
129 return val > 2147483647 ? val - 4294967296 : val
130 },
131 function encodingLength (val) {
132 return varint.encodingLength(val < 0 ? val + 4294967296 : val)
133 }
134)
135
136exports.int64 = encoder(0,
137 function encode (val, buffer, offset) {
138 if (val < 0) {
139 var last = offset + 9
140 varint.encode(val * -1, buffer, offset)
141 offset += varint.encode.bytes - 1
142 buffer[offset] = buffer[offset] | 0x80
143 while (offset < last - 1) {
144 offset++
145 buffer[offset] = 0xff
146 }
147 buffer[last] = 0x01
148 encode.bytes = 10
149 } else {
150 varint.encode(val, buffer, offset)
151 encode.bytes = varint.encode.bytes
152 }
153 return buffer
154 },
155 function decode (buffer, offset) {
156 var val = varint.decode(buffer, offset)
157 if (val >= Math.pow(2, 63)) {
158 var limit = 9
159 while (buffer[offset + limit - 1] === 0xff) limit--
160 limit = limit || 9
161 var subset = b4a.allocUnsafe(limit)
162 b4a.copy(buffer, subset, 0, offset, offset + limit)
163 subset[limit - 1] = subset[limit - 1] & 0x7f
164 val = -1 * varint.decode(subset, 0)
165 decode.bytes = 10
166 } else {
167 decode.bytes = varint.decode.bytes
168 }
169 return val
170 },
171 function encodingLength (val) {
172 return val < 0 ? 10 : varint.encodingLength(val)
173 }
174)
175
176exports.sint32 =
177exports.sint64 = encoder(0,
178 svarint.encode,
179 svarint.decode,
180 svarint.encodingLength
181)
182
183exports.uint32 =
184exports.uint64 =
185exports.enum =
186exports.varint = encoder(0,
187 varint.encode,
188 varint.decode,
189 varint.encodingLength
190)
191
192// we cannot represent these in javascript so we just use buffers
193exports.fixed64 =
194exports.sfixed64 = encoder(1,
195 function encode (val, buffer, offset) {
196 b4a.copy(val, buffer, offset)
197 encode.bytes = 8
198 return buffer
199 },
200 function decode (buffer, offset) {
201 var val = buffer.subarray(offset, offset + 8)
202 decode.bytes = 8
203 return val
204 },
205 function encodingLength () {
206 return 8
207 }
208)
209
210exports.double = encoder(1,
211 function encode (val, buffer, offset) {
212 b4a.writeDoubleLE(buffer, val, offset)
213 encode.bytes = 8
214 return buffer
215 },
216 function decode (buffer, offset) {
217 var val = b4a.readDoubleLE(buffer, offset)
218 decode.bytes = 8
219 return val
220 },
221 function encodingLength () {
222 return 8
223 }
224)
225
226exports.fixed32 = encoder(5,
227 function encode (val, buffer, offset) {
228 b4a.writeUInt32LE(buffer, val, offset)
229 encode.bytes = 4
230 return buffer
231 },
232 function decode (buffer, offset) {
233 var val = b4a.readUInt32LE(buffer, offset)
234 decode.bytes = 4
235 return val
236 },
237 function encodingLength () {
238 return 4
239 }
240)
241
242exports.sfixed32 = encoder(5,
243 function encode (val, buffer, offset) {
244 b4a.writeInt32LE(buffer, val, offset)
245 encode.bytes = 4
246 return buffer
247 },
248 function decode (buffer, offset) {
249 var val = b4a.readInt32LE(buffer, offset)
250 decode.bytes = 4
251 return val
252 },
253 function encodingLength () {
254 return 4
255 }
256)
257
258exports.float = encoder(5,
259 function encode (val, buffer, offset) {
260 b4a.writeFloatLE(buffer, val, offset)
261 encode.bytes = 4
262 return buffer
263 },
264 function decode (buffer, offset) {
265 var val = b4a.readFloatLE(buffer, offset)
266 decode.bytes = 4
267 return val
268 },
269 function encodingLength () {
270 return 4
271 }
272)
273
274function encoder (type, encode, decode, encodingLength) {
275 encode.bytes = decode.bytes = 0
276
277 return {
278 type: type,
279 encode: encode,
280 decode: decode,
281 encodingLength: encodingLength
282 }
283}
284
285function bufferLength (val) {
286 return b4a.isBuffer(val) ? val.length : b4a.byteLength(val)
287}
node_modules/protocol-buffers-encodings/package.json +28 -0
……@@ -0,0 +1,28 @@
1{
2 "name": "protocol-buffers-encodings",
3 "version": "1.2.0",
4 "description": "Base encodings for protocol-buffers",
5 "main": "index.js",
6 "dependencies": {
7 "b4a": "^1.6.0",
8 "signed-varint": "^2.0.1",
9 "varint": "5.0.0"
10 },
11 "devDependencies": {
12 "standard": "^14.3.4",
13 "tape": "^5.0.1"
14 },
15 "scripts": {
16 "test": "standard && tape test.js"
17 },
18 "repository": {
19 "type": "git",
20 "url": "https://github.com/mafintosh/protocol-buffers-encodings.git"
21 },
22 "author": "Mathias Buus (@mafintosh)",
23 "license": "MIT",
24 "bugs": {
25 "url": "https://github.com/mafintosh/protocol-buffers-encodings/issues"
26 },
27 "homepage": "https://github.com/mafintosh/protocol-buffers-encodings"
28}
node_modules/protocol-buffers-encodings/test.js +151 -0
……@@ -0,0 +1,151 @@
1var tape = require('tape')
2var encodings = require('./')
3
4tape('name', function (t) {
5 t.same(encodings.name(encodings.varint), 'varint')
6 t.same(encodings.name(encodings.float), 'float')
7 t.end()
8})
9
10tape('varint', function (t) {
11 test(t, encodings.varint, [42, 10, 0, 999999])
12})
13
14tape('string', function (t) {
15 test(t, encodings.string, ['a', 'abefest', 'øøø'])
16})
17
18tape('bytes (node style)', function (t) {
19 test(
20 t,
21 encodings.bytes,
22 [Buffer.alloc(4096), Buffer.from('hi')],
23 [allocBuffer]
24 )
25})
26
27tape('bytes (browser style)', function (t) {
28 test(
29 t,
30 encodings.bytes,
31 [new Uint8Array(4096), new Uint8Array([104, 105])],
32 [allocUint8Array]
33 )
34})
35
36tape('bool', function (t) {
37 test(t, encodings.bool, [true, false])
38})
39
40tape('int32', function (t) {
41 test(t, encodings.int32, [-1, 0, 42, 4242424])
42})
43
44tape('int64', function (t) {
45 test(t, encodings.int64, [-1, 0, 1, 24242424244])
46})
47
48tape('sint64', function (t) {
49 test(t, encodings.sint64, [-14, 0, 144, 4203595524])
50})
51
52tape('uint64', function (t) {
53 test(t, encodings.uint64, [1, 0, 144, 424444, 4203595524])
54})
55
56tape('fixed64 (node style)', function (t) {
57 test(
58 t,
59 encodings.fixed64,
60 [Buffer.from([0, 0, 0, 0, 0, 0, 0, 1])],
61 [allocBuffer]
62 )
63})
64
65tape('fixed64 (browser style)', function (t) {
66 test(
67 t,
68 encodings.fixed64,
69 [new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1])],
70 [allocUint8Array]
71 )
72})
73
74tape('double', function (t) {
75 test(t, encodings.double, [0, 2, 0.5, 0.4])
76})
77
78tape('float', function (t) {
79 test(t, encodings.float, [0, 2, 0.5])
80})
81
82tape('fixed32', function (t) {
83 test(t, encodings.fixed32, [4, 0, 10000])
84})
85
86tape('sfixed32', function (t) {
87 test(t, encodings.sfixed32, [-100, 4, 0, 142425])
88})
89
90function test (t, enc, vals, allocFunctions = [allocBuffer, allocUint8Array]) {
91 if (!Array.isArray(vals)) vals = [vals]
92
93 for (const allocFunction of allocFunctions) {
94 for (const val of vals) {
95 let buf = allocFunction(enc.encodingLength(val))
96
97 enc.encode(val, buf, 0)
98
99 t.same(enc.encode.bytes, buf.length)
100 t.same(enc.encodingLength(val), buf.length)
101 t.same(enc.decode(buf, 0), val)
102 t.same(enc.decode.bytes, buf.length)
103
104 const anotherBuf = allocFunction(enc.encodingLength(val) + 1000)
105
106 buf = enc.encode(val, anotherBuf, 10)
107 t.same(buf, anotherBuf)
108 t.ok(enc.encode.bytes < anotherBuf.length)
109 t.same(enc.decode(buf, 10, 10 + enc.encodingLength(val)), val)
110 t.ok(enc.decode.bytes < anotherBuf.length)
111 }
112 }
113
114 t.end()
115}
116
117tape('test browser-style buffer', function (t) {
118 const enc = encodings.string
119 const val = 'value'
120 let buf = new Uint8Array(enc.encodingLength(val))
121 enc.encode(val, buf, 0)
122
123 // First elem is the length (5). Others are the encoded 'value'
124 const expectedEncodedVal = new Uint8Array([5, 118, 97, 108, 117, 101])
125 t.same(buf, expectedEncodedVal)
126
127 t.same(enc.encode.bytes, buf.length)
128 t.same(enc.encodingLength(val), buf.length)
129 t.same(enc.decode(buf, 0), val)
130 t.same(enc.decode.bytes, buf.length)
131
132 const anotherBuf = new Uint8Array(enc.encodingLength(val) + 1000)
133
134 buf = enc.encode(val, anotherBuf, 10)
135 t.same(buf, anotherBuf)
136 t.ok(enc.encode.bytes < anotherBuf.length)
137 t.same(enc.decode(buf, 10, 10 + enc.encodingLength(val)), val)
138 t.ok(enc.decode.bytes < anotherBuf.length)
139
140 t.end()
141})
142
143function allocBuffer (length) {
144 // Node style
145 return Buffer.alloc(length)
146}
147
148function allocUint8Array (length) {
149 // Browser style
150 return new Uint8Array(length)
151}
node_modules/protomux/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2021 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/protomux/README.md +183 -0
……@@ -0,0 +1,183 @@
1# protomux
2
3Multiplex multiple message oriented protocols over a stream
4
5```
6npm install protomux
7```
8
9## Usage
10
11``` js
12const Protomux = require('protomux')
13const c = require('compact-encoding')
14
15// By framed stream, it has be a stream that preserves the messages, ie something that length prefixes
16// like @hyperswarm/secret-stream
17
18const mux = new Protomux(aStreamThatFrames)
19
20// Now add some protocol channels
21
22const cool = mux.createChannel({
23 protocol: 'cool-protocol',
24 id: Buffer.from('optional binary id'),
25 onopen () {
26 console.log('the other side opened this protocol!')
27 },
28 onclose () {
29 console.log('either side closed the protocol')
30 }
31})
32
33// And add some messages
34
35const one = cool.addMessage({
36 encoding: c.string,
37 onmessage (m) {
38 console.log('recv message (1)', m)
39 }
40})
41
42const two = cool.addMessage({
43 encoding: c.bool,
44 onmessage (m) {
45 console.log('recv message (2)', m)
46 }
47})
48
49// open the channel
50
51cool.open()
52
53// And send some data
54
55one.send('a string')
56two.send(true)
57```
58
59## API
60
61#### `mux = new Protomux(stream, [options])`
62
63Make a new instance. `stream` should be a framed stream, preserving the messages written.
64
65Options include:
66
67``` js
68{
69 // Called when the muxer wants to allocate a message that is written, defaults to Buffer.allocUnsafe.
70 alloc (size) {}
71}
72```
73
74#### `mux = Protomux.from(stream | muxer, [options])`
75
76Helper to accept either an existing muxer instance or a stream (which creates a new one).
77
78#### `const channel = mux.createChannel(opts)`
79
80Add a new protocol channel.
81
82Options include:
83
84``` js
85{
86 // Used to match the protocol
87 protocol: 'name of the protocol',
88 // Optional additional binary id to identify this channel
89 id: buffer,
90 // Optional encoding for a handshake
91 handshake: encoding,
92 // Optional array of messages types you want to send/receive.
93 messages: [],
94 // Called when the remote side adds this protocol.
95 // Errors here are caught and forwared to stream.destroy
96 async onopen (handshake) {},
97 // Called when the channel closes - ie the remote side closes or rejects this protocol or we closed it.
98 // Errors here are caught and forwared to stream.destroy
99 async onclose () {},
100 // Called after onclose when all pending promises has resolved.
101 async ondestroy () {}
102}
103```
104
105Sessions are paired based on a queue, so the first remote channel with the same `protocol` and `id`.
106
107__NOTE__: `mux.createChannel` returns `null` if the channel should not be opened, ie it's a duplicate channel or the remote has already closed this one.
108
109If you want multiple sessions with the same `protocol` and `id`, set `unique: false` as an option.
110
111#### `const opened = mux.opened({ protocol, id })`
112
113Boolean that indicates if the channel is opened.
114
115#### `mux.pair({ protocol, id }, callback)`
116
117Register a callback to be called everytime a new channel is requested.
118
119#### `mux.unpair({ protocol, id })`
120
121Unregisters the pair callback.
122
123#### `channel.open([handshake])`
124
125Open the channel.
126
127#### `const m = channel.addMessage(opts)`
128
129Add/register a message type for a certain encoding. Options include:
130
131``` js
132{
133 // compact-encoding specifying how to encode/decode this message
134 encoding: c.binary,
135 // Called when the remote side sends a message.
136 // Errors here are caught and forwared to stream.destroy
137 async onmessage (message) { }
138}
139```
140
141#### `m.send(data)`
142
143Send a message.
144
145#### `m.onmessage`
146
147Function that is called when a message arrives.
148
149#### `m.encoding`
150
151The encoding for this message.
152
153#### `channel.close()`
154
155Closes the protocol channel.
156
157#### `channel.cork()`
158
159Corking the protocol channel, makes it buffer messages and send them all in a batch when it uncorks.
160
161#### `channel.uncork()`
162
163Uncork and send the batch.
164
165#### `mux.cork()`
166
167Same as `channel.cork` but on the muxer instance.
168
169#### `mux.uncork()`
170
171Same as `channel.uncork` but on the muxer instance.
172
173#### `for (const channel of muxer) { ... }`
174
175The muxer instance is iterable, so you can iterate over all the channels.
176
177#### `mux.isIdle()`
178
179Convenience method that returns true if the number of channels is currently 0.
180
181## License
182
183MIT
node_modules/protomux/index.js +767 -0
……@@ -0,0 +1,767 @@
1const b4a = require('b4a')
2const c = require('compact-encoding')
3const queueTick = require('queue-tick')
4const safetyCatch = require('safety-catch')
5const unslab = require('unslab')
6
7const MAX_BUFFERED = 32768
8const MAX_BACKLOG = Infinity // TODO: impl "open" backpressure
9const MAX_BATCH = 8 * 1024 * 1024
10
11class Channel {
12 constructor (mux, info, userData, protocol, aliases, id, handshake, messages, onopen, onclose, ondestroy, ondrain) {
13 this.userData = userData
14 this.protocol = protocol
15 this.aliases = aliases
16 this.id = id
17 this.handshake = null
18 this.messages = []
19
20 this.opened = false
21 this.closed = false
22 this.destroyed = false
23
24 this.onopen = onopen
25 this.onclose = onclose
26 this.ondestroy = ondestroy
27 this.ondrain = ondrain
28
29 this._handshake = handshake
30 this._mux = mux
31 this._info = info
32 this._localId = 0
33 this._remoteId = 0
34 this._active = 0
35 this._extensions = null
36
37 this._decBound = this._dec.bind(this)
38 this._decAndDestroyBound = this._decAndDestroy.bind(this)
39
40 this._openedPromise = null
41 this._openedResolve = null
42
43 this._destroyedPromise = null
44 this._destroyedResolve = null
45
46 for (const m of messages) this.addMessage(m)
47 }
48
49 get drained () {
50 return this._mux.drained
51 }
52
53 fullyOpened () {
54 if (this.opened) return Promise.resolve(true)
55 if (this.closed) return Promise.resolve(false)
56 if (this._openedPromise) return this._openedPromise
57
58 this._openedPromise = new Promise((resolve) => { this._openedResolve = resolve })
59 return this._openedPromise
60 }
61
62 fullyClosed () {
63 if (this.destroyed) return Promise.resolve()
64 if (this._destroyedPromise) return this._destroyedPromise
65
66 this._destroyedPromise = new Promise((resolve) => { this._destroyedResolve = resolve })
67 return this._destroyedPromise
68 }
69
70 open (handshake) {
71 const id = this._mux._free.length > 0
72 ? this._mux._free.pop()
73 : this._mux._local.push(null) - 1
74
75 this._info.opened++
76 this._info.lastChannel = this
77 this._localId = id + 1
78 this._mux._local[id] = this
79
80 if (this._remoteId === 0) {
81 this._info.outgoing.push(this._localId)
82 }
83
84 const state = { buffer: null, start: 2, end: 2 }
85
86 c.uint.preencode(state, this._localId)
87 c.string.preencode(state, this.protocol)
88 c.buffer.preencode(state, this.id)
89 if (this._handshake) this._handshake.preencode(state, handshake)
90
91 state.buffer = this._mux._alloc(state.end)
92
93 state.buffer[0] = 0
94 state.buffer[1] = 1
95 c.uint.encode(state, this._localId)
96 c.string.encode(state, this.protocol)
97 c.buffer.encode(state, this.id)
98 if (this._handshake) this._handshake.encode(state, handshake)
99
100 this._mux._write0(state.buffer)
101 }
102
103 _dec () {
104 if (--this._active === 0 && this.closed === true) this._destroy()
105 }
106
107 _decAndDestroy (err) {
108 this._dec()
109 this._mux._safeDestroy(err)
110 }
111
112 _fullyOpenSoon () {
113 this._mux._remote[this._remoteId - 1].session = this
114 queueTick(this._fullyOpen.bind(this))
115 }
116
117 _fullyOpen () {
118 if (this.opened === true || this.closed === true) return
119
120 const remote = this._mux._remote[this._remoteId - 1]
121
122 this.opened = true
123 this.handshake = this._handshake ? this._handshake.decode(remote.state) : null
124 this._track(this.onopen(this.handshake, this))
125
126 remote.session = this
127 remote.state = null
128 if (remote.pending !== null) this._drain(remote)
129
130 this._resolveOpen(true)
131 }
132
133 _resolveOpen (opened) {
134 if (this._openedResolve !== null) {
135 this._openedResolve(opened)
136 this._openedResolve = this._openedPromise = null
137 }
138 }
139
140 _resolveDestroyed () {
141 if (this._destroyedResolve !== null) {
142 this._destroyedResolve()
143 this._destroyedResolve = this._destroyedPromise = null
144 }
145 }
146
147 _drain (remote) {
148 for (let i = 0; i < remote.pending.length; i++) {
149 const p = remote.pending[i]
150 this._mux._buffered -= byteSize(p.state)
151 this._recv(p.type, p.state)
152 }
153
154 remote.pending = null
155 this._mux._resumeMaybe()
156 }
157
158 _track (p) {
159 if (isPromise(p) === true) {
160 this._active++
161 return p.then(this._decBound, this._decAndDestroyBound)
162 }
163
164 return null
165 }
166
167 _close (isRemote) {
168 if (this.closed === true) return
169 this.closed = true
170
171 this._info.opened--
172 if (this._info.lastChannel === this) this._info.lastChannel = null
173
174 if (this._remoteId > 0) {
175 this._mux._remote[this._remoteId - 1] = null
176 this._remoteId = 0
177 // If remote has acked, we can reuse the local id now
178 // otherwise, we need to wait for the "ack" to arrive
179 this._mux._free.push(this._localId - 1)
180 }
181
182 this._mux._local[this._localId - 1] = null
183 this._localId = 0
184
185 this._mux._gc(this._info)
186 this._track(this.onclose(isRemote, this))
187
188 if (this._active === 0) this._destroy()
189
190 this._resolveOpen(false)
191 }
192
193 _destroy () {
194 if (this.destroyed === true) return
195 this.destroyed = true
196 this._track(this.ondestroy(this))
197 this._resolveDestroyed()
198 }
199
200 _recv (type, state) {
201 if (type < this.messages.length) {
202 const m = this.messages[type]
203 const p = m.recv(state, this)
204 if (m.autoBatch === true) return p
205 }
206 return null
207 }
208
209 cork () {
210 this._mux.cork()
211 }
212
213 uncork () {
214 this._mux.uncork()
215 }
216
217 close () {
218 if (this.closed === true) return
219
220 const state = { buffer: null, start: 2, end: 2 }
221
222 c.uint.preencode(state, this._localId)
223
224 state.buffer = this._mux._alloc(state.end)
225
226 state.buffer[0] = 0
227 state.buffer[1] = 3
228 c.uint.encode(state, this._localId)
229
230 this._close(false)
231 this._mux._write0(state.buffer)
232 }
233
234 addMessage (opts) {
235 if (!opts) return this._skipMessage()
236
237 const type = this.messages.length
238 const autoBatch = opts.autoBatch !== false
239 const encoding = opts.encoding || c.raw
240 const onmessage = opts.onmessage || noop
241
242 const s = this
243 const typeLen = encodingLength(c.uint, type)
244
245 const m = {
246 type,
247 autoBatch,
248 encoding,
249 onmessage,
250 recv (state, session) {
251 return session._track(m.onmessage(encoding.decode(state), session))
252 },
253 send (m, session = s) {
254 if (session.closed === true) return false
255
256 const mux = session._mux
257 const state = { buffer: null, start: 0, end: typeLen }
258
259 if (mux._batch !== null) {
260 encoding.preencode(state, m)
261 state.buffer = mux._alloc(state.end)
262
263 c.uint.encode(state, type)
264 encoding.encode(state, m)
265
266 mux._pushBatch(session._localId, state.buffer)
267 return true
268 }
269
270 c.uint.preencode(state, session._localId)
271 encoding.preencode(state, m)
272
273 state.buffer = mux._alloc(state.end)
274
275 c.uint.encode(state, session._localId)
276 c.uint.encode(state, type)
277 encoding.encode(state, m)
278
279 mux.drained = mux.stream.write(state.buffer)
280
281 return mux.drained
282 }
283 }
284
285 this.messages.push(m)
286
287 return m
288 }
289
290 _skipMessage () {
291 const type = this.messages.length
292 const m = {
293 type,
294 encoding: c.raw,
295 onmessage: noop,
296 recv (state, session) {},
297 send (m, session) {}
298 }
299
300 this.messages.push(m)
301 return m
302 }
303}
304
305module.exports = class Protomux {
306 constructor (stream, { alloc } = {}) {
307 if (stream.userData === null) stream.userData = this
308
309 this.isProtomux = true
310 this.stream = stream
311 this.corked = 0
312 this.drained = true
313
314 this._alloc = alloc || (typeof stream.alloc === 'function' ? stream.alloc.bind(stream) : b4a.allocUnsafe)
315 this._safeDestroyBound = this._safeDestroy.bind(this)
316 this._uncorkBound = this.uncork.bind(this)
317
318 this._remoteBacklog = 0
319 this._buffered = 0
320 this._paused = false
321 this._remote = []
322 this._local = []
323 this._free = []
324 this._batch = null
325 this._batchState = null
326
327 this._infos = new Map()
328 this._notify = new Map()
329
330 this.stream.on('data', this._ondata.bind(this))
331 this.stream.on('drain', this._ondrain.bind(this))
332 this.stream.on('end', this._onend.bind(this))
333 this.stream.on('error', noop) // we handle this in "close"
334 this.stream.on('close', this._shutdown.bind(this))
335 }
336
337 static from (stream, opts) {
338 if (stream.userData && stream.userData.isProtomux) return stream.userData
339 if (stream.isProtomux) return stream
340 return new this(stream, opts)
341 }
342
343 static isProtomux (mux) {
344 return typeof mux === 'object' && mux.isProtomux === true
345 }
346
347 * [Symbol.iterator] () {
348 for (const session of this._local) {
349 if (session !== null) yield session
350 }
351 }
352
353 isIdle () {
354 return this._local.length === this._free.length
355 }
356
357 cork () {
358 if (++this.corked === 1) {
359 this._batch = []
360 this._batchState = { buffer: null, start: 0, end: 1 }
361 }
362 }
363
364 uncork () {
365 if (--this.corked === 0) {
366 this._sendBatch(this._batch, this._batchState)
367 this._batch = null
368 this._batchState = null
369 }
370 }
371
372 getLastChannel ({ protocol, id = null }) {
373 const key = toKey(protocol, id)
374 const info = this._infos.get(key)
375 if (info) return info.lastChannel
376 return null
377 }
378
379 pair ({ protocol, id = null }, notify) {
380 this._notify.set(toKey(protocol, id), notify)
381 }
382
383 unpair ({ protocol, id = null }) {
384 this._notify.delete(toKey(protocol, id))
385 }
386
387 opened ({ protocol, id = null }) {
388 const key = toKey(protocol, id)
389 const info = this._infos.get(key)
390 return info ? info.opened > 0 : false
391 }
392
393 createChannel ({ userData = null, protocol, aliases = [], id = null, unique = true, handshake = null, messages = [], onopen = noop, onclose = noop, ondestroy = noop, ondrain = noop }) {
394 if (this.stream.destroyed) return null
395
396 const info = this._get(protocol, id, aliases)
397 if (unique && info.opened > 0) return null
398
399 if (info.incoming.length === 0) {
400 return new Channel(this, info, userData, protocol, aliases, id, handshake, messages, onopen, onclose, ondestroy, ondrain)
401 }
402
403 this._remoteBacklog--
404
405 const remoteId = info.incoming.shift()
406 const r = this._remote[remoteId - 1]
407 if (r === null) return null
408
409 const session = new Channel(this, info, userData, protocol, aliases, id, handshake, messages, onopen, onclose, ondestroy, ondrain)
410
411 session._remoteId = remoteId
412 session._fullyOpenSoon()
413
414 return session
415 }
416
417 _pushBatch (localId, buffer) {
418 if (this._batchState.end >= MAX_BATCH) {
419 this._sendBatch(this._batch, this._batchState)
420 this._batch = []
421 this._batchState = { buffer: null, start: 0, end: 1 }
422 }
423
424 if (this._batch.length === 0 || this._batch[this._batch.length - 1].localId !== localId) {
425 this._batchState.end++
426 c.uint.preencode(this._batchState, localId)
427 }
428 c.buffer.preencode(this._batchState, buffer)
429 this._batch.push({ localId, buffer })
430 }
431
432 _sendBatch (batch, state) {
433 if (batch.length === 0) return
434
435 let prev = batch[0].localId
436
437 state.buffer = this._alloc(state.end)
438 state.buffer[state.start++] = 0
439 state.buffer[state.start++] = 0
440
441 c.uint.encode(state, prev)
442
443 for (let i = 0; i < batch.length; i++) {
444 const b = batch[i]
445 if (prev !== b.localId) {
446 state.buffer[state.start++] = 0
447 c.uint.encode(state, (prev = b.localId))
448 }
449 c.buffer.encode(state, b.buffer)
450 }
451
452 this.drained = this.stream.write(state.buffer)
453 }
454
455 _get (protocol, id, aliases = []) {
456 const key = toKey(protocol, id)
457
458 let info = this._infos.get(key)
459 if (info) return info
460
461 info = { key, protocol, aliases: [], id, pairing: 0, opened: 0, incoming: [], outgoing: [], lastChannel: null }
462 this._infos.set(key, info)
463
464 for (const alias of aliases) {
465 const key = toKey(alias, id)
466 info.aliases.push(key)
467
468 this._infos.set(key, info)
469 }
470
471 return info
472 }
473
474 _gc (info) {
475 if (info.opened === 0 && info.outgoing.length === 0 && info.incoming.length === 0) {
476 this._infos.delete(info.key)
477
478 for (const alias of info.aliases) this._infos.delete(alias)
479 }
480 }
481
482 _ondata (buffer) {
483 if (buffer.byteLength === 0) return // ignore empty frames...
484 try {
485 const state = { buffer, start: 0, end: buffer.byteLength }
486 this._decode(c.uint.decode(state), state)
487 } catch (err) {
488 this._safeDestroy(err)
489 }
490 }
491
492 _ondrain () {
493 this.drained = true
494
495 for (const s of this._local) {
496 if (s !== null) s._track(s.ondrain(s))
497 }
498 }
499
500 _onend () { // TODO: support half open mode for the users who wants that here
501 this.stream.end()
502 }
503
504 _decode (remoteId, state) {
505 const type = c.uint.decode(state)
506
507 if (remoteId === 0) {
508 return this._oncontrolsession(type, state)
509 }
510
511 const r = remoteId <= this._remote.length ? this._remote[remoteId - 1] : null
512
513 // if the channel is closed ignore - could just be a pipeline message...
514 if (r === null) return null
515
516 if (r.pending !== null) {
517 this._bufferMessage(r, type, state)
518 return null
519 }
520
521 return r.session._recv(type, state)
522 }
523
524 _oncontrolsession (type, state) {
525 switch (type) {
526 case 0:
527 this._onbatch(state)
528 break
529
530 case 1:
531 // return the promise back up as this has sideeffects so we can batch reply
532 return this._onopensession(state)
533
534 case 2:
535 this._onrejectsession(state)
536 break
537
538 case 3:
539 this._onclosesession(state)
540 break
541 }
542
543 return null
544 }
545
546 _bufferMessage (r, type, { buffer, start, end }) {
547 const state = { buffer, start, end } // copy
548 r.pending.push({ type, state })
549 this._buffered += byteSize(state)
550 this._pauseMaybe()
551 }
552
553 _pauseMaybe () {
554 if (this._paused === true || this._buffered <= MAX_BUFFERED) return
555 this._paused = true
556 this.stream.pause()
557 }
558
559 _resumeMaybe () {
560 if (this._paused === false || this._buffered > MAX_BUFFERED) return
561 this._paused = false
562 this.stream.resume()
563 }
564
565 _onbatch (state) {
566 const end = state.end
567 let remoteId = c.uint.decode(state)
568
569 let waiting = null
570
571 while (state.end > state.start) {
572 const len = c.uint.decode(state)
573 if (len === 0) {
574 remoteId = c.uint.decode(state)
575 continue
576 }
577 state.end = state.start + len
578 // if batch contains more than one message, cork it so we reply back with a batch
579 if (end !== state.end && waiting === null) {
580 waiting = []
581 this.cork()
582 }
583 const p = this._decode(remoteId, state)
584 if (waiting !== null && p !== null) waiting.push(p)
585 state.start = state.end
586 state.end = end
587 }
588
589 if (waiting !== null) {
590 // the waiting promises are not allowed to throw but we destroy the stream in case we are wrong
591 Promise.all(waiting).then(this._uncorkBound, this._safeDestroyBound)
592 }
593 }
594
595 _onopensession (state) {
596 const remoteId = c.uint.decode(state)
597 const protocol = c.string.decode(state)
598 const id = unslab(c.buffer.decode(state))
599
600 // remote tried to open the control session - auto reject for now
601 // as we can use as an explicit control protocol declaration if we need to
602 if (remoteId === 0) {
603 this._rejectSession(0)
604 return null
605 }
606
607 const rid = remoteId - 1
608 const info = this._get(protocol, id)
609
610 // allow the remote to grow the ids by one
611 if (this._remote.length === rid) {
612 this._remote.push(null)
613 }
614
615 if (rid >= this._remote.length || this._remote[rid] !== null) {
616 throw new Error('Invalid open message')
617 }
618
619 if (info.outgoing.length > 0) {
620 const localId = info.outgoing.shift()
621 const session = this._local[localId - 1]
622
623 if (session === null) { // we already closed the channel - ignore
624 this._free.push(localId - 1)
625 return null
626 }
627
628 this._remote[rid] = { state, pending: null, session: null }
629
630 session._remoteId = remoteId
631 session._fullyOpen()
632 return null
633 }
634
635 const copyState = { buffer: state.buffer, start: state.start, end: state.end }
636 this._remote[rid] = { state: copyState, pending: [], session: null }
637
638 if (++this._remoteBacklog > MAX_BACKLOG) {
639 throw new Error('Remote exceeded backlog')
640 }
641
642 info.pairing++
643 info.incoming.push(remoteId)
644
645 return this._requestSession(protocol, id, info).catch(this._safeDestroyBound)
646 }
647
648 _onrejectsession (state) {
649 const localId = c.uint.decode(state)
650
651 // TODO: can be done smarter...
652 for (const info of this._infos.values()) {
653 const i = info.outgoing.indexOf(localId)
654 if (i === -1) continue
655
656 info.outgoing.splice(i, 1)
657
658 const session = this._local[localId - 1]
659
660 this._free.push(localId - 1)
661 if (session !== null) session._close(true)
662
663 this._gc(info)
664 return
665 }
666
667 throw new Error('Invalid reject message')
668 }
669
670 _onclosesession (state) {
671 const remoteId = c.uint.decode(state)
672
673 if (remoteId === 0) return // ignore
674
675 const rid = remoteId - 1
676 const r = rid < this._remote.length ? this._remote[rid] : null
677
678 if (r === null) return
679
680 if (r.session !== null) r.session._close(true)
681 }
682
683 async _requestSession (protocol, id, info) {
684 const notify = this._notify.get(toKey(protocol, id)) || this._notify.get(toKey(protocol, null))
685
686 if (notify) await notify(id)
687
688 if (--info.pairing > 0) return
689
690 while (info.incoming.length > 0) {
691 this._rejectSession(info, info.incoming.shift())
692 }
693
694 this._gc(info)
695 }
696
697 _rejectSession (info, remoteId) {
698 if (remoteId > 0) {
699 const r = this._remote[remoteId - 1]
700
701 if (r.pending !== null) {
702 for (let i = 0; i < r.pending.length; i++) {
703 this._buffered -= byteSize(r.pending[i].state)
704 }
705 }
706
707 this._remote[remoteId - 1] = null
708 this._resumeMaybe()
709 }
710
711 const state = { buffer: null, start: 2, end: 2 }
712
713 c.uint.preencode(state, remoteId)
714
715 state.buffer = this._alloc(state.end)
716
717 state.buffer[0] = 0
718 state.buffer[1] = 2
719 c.uint.encode(state, remoteId)
720
721 this._write0(state.buffer)
722 }
723
724 _write0 (buffer) {
725 if (this._batch !== null) {
726 this._pushBatch(0, buffer.subarray(1))
727 return
728 }
729
730 this.drained = this.stream.write(buffer)
731 }
732
733 destroy (err) {
734 this.stream.destroy(err)
735 }
736
737 _safeDestroy (err) {
738 safetyCatch(err)
739 this.stream.destroy(err)
740 }
741
742 _shutdown () {
743 for (const s of this._local) {
744 if (s !== null) s._close(true)
745 }
746 }
747}
748
749function noop () {}
750
751function toKey (protocol, id) {
752 return protocol + '##' + (id ? b4a.toString(id, 'hex') : '')
753}
754
755function byteSize (state) {
756 return 512 + (state.end - state.start)
757}
758
759function isPromise (p) {
760 return !!(p && typeof p.then === 'function')
761}
762
763function encodingLength (enc, val) {
764 const state = { buffer: null, start: 0, end: 0 }
765 enc.preencode(state, val)
766 return state.end
767}
node_modules/protomux/package.json +34 -0
……@@ -0,0 +1,34 @@
1{
2 "name": "protomux",
3 "version": "3.10.1",
4 "description": "Multiplex multiple message oriented protocols over a stream",
5 "main": "index.js",
6 "files": [
7 "index.js"
8 ],
9 "dependencies": {
10 "b4a": "^1.3.1",
11 "compact-encoding": "^2.5.1",
12 "queue-tick": "^1.0.0",
13 "safety-catch": "^1.0.1",
14 "unslab": "^1.3.0"
15 },
16 "devDependencies": {
17 "@hyperswarm/secret-stream": "^6.0.0",
18 "brittle": "^3.0.0",
19 "standard": "^16.0.4"
20 },
21 "scripts": {
22 "test": "standard && brittle test.js"
23 },
24 "repository": {
25 "type": "git",
26 "url": "https://github.com/mafintosh/protomux.git"
27 },
28 "author": "Mathias Buus (@mafintosh)",
29 "license": "MIT",
30 "bugs": {
31 "url": "https://github.com/mafintosh/protomux/issues"
32 },
33 "homepage": "https://github.com/mafintosh/protomux"
34}
node_modules/queue-tick/.github/workflows/test-node.yml +24 -0
……@@ -0,0 +1,24 @@
1name: Build Status
2
3on:
4 push:
5 branches:
6 - master
7 pull_request:
8 branches:
9 - master
10jobs:
11 build:
12 strategy:
13 matrix:
14 node-version: [14.x]
15 os: [ubuntu-16.04, macos-latest, windows-latest]
16 runs-on: ${{ matrix.os }}
17 steps:
18 - uses: actions/checkout@v2
19 - name: Use Node.js ${{ matrix.node-version }}
20 uses: actions/setup-node@v1
21 with:
22 node-version: ${{ matrix.node-version }}
23 - run: npm install
24 - run: npm test
node_modules/queue-tick/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2021 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/queue-tick/README.md +20 -0
……@@ -0,0 +1,20 @@
1# queue-tick
2
3Next tick shim that prefers process.nextTick over queueMicrotask for compat
4
5```
6npm install queue-tick
7```
8
9## Usage
10
11``` js
12const queueTick = require('queue-tick')
13
14// in Node it uses process.nextTick, in browsers it uses queueMicrotask
15queueTick(() => console.log('laters'))
16```
17
18## License
19
20MIT
node_modules/queue-tick/package.json +25 -0
……@@ -0,0 +1,25 @@
1{
2 "name": "queue-tick",
3 "version": "1.0.1",
4 "description": "Next tick shim that prefers process.nextTick over queueMicrotask for compat",
5 "main": "./process-next-tick.js",
6 "browser": "./queue-microtask.js",
7 "dependencies": {},
8 "devDependencies": {
9 "standard": "^16.0.3",
10 "tape": "^5.3.1"
11 },
12 "scripts": {
13 "test": "standard && tape test.js"
14 },
15 "repository": {
16 "type": "git",
17 "url": "https://github.com/mafintosh/queue-tick.git"
18 },
19 "author": "Mathias Buus (@mafintosh)",
20 "license": "MIT",
21 "bugs": {
22 "url": "https://github.com/mafintosh/queue-tick/issues"
23 },
24 "homepage": "https://github.com/mafintosh/queue-tick"
25}
node_modules/queue-tick/process-next-tick.js +3 -0
……@@ -0,0 +1,3 @@
1module.exports = (typeof process !== 'undefined' && typeof process.nextTick === 'function')
2 ? process.nextTick.bind(process)
3 : require('./queue-microtask')
node_modules/queue-tick/queue-microtask.js +1 -0
……@@ -0,0 +1 @@
1module.exports = typeof queueMicrotask === 'function' ? queueMicrotask : (fn) => Promise.resolve().then(fn)
node_modules/queue-tick/test.js +10 -0
……@@ -0,0 +1,10 @@
1const tape = require('tape')
2const queueTick = require('./')
3const js = require('./queue-microtask')
4
5tape('basic', function (t) {
6 t.plan(2)
7
8 queueTick(() => t.pass('tick'))
9 js(() => t.pass('tock'))
10})
node_modules/quickbit-native/CMakeLists.txt +70 -0
……@@ -0,0 +1,70 @@
1cmake_minimum_required(VERSION 3.31)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6
7project(quickbit_native C CXX)
8
9bare_target(target)
10
11if(target MATCHES "win32")
12 add_compile_options(/MT$<$<CONFIG:Debug>:d>)
13endif()
14
15fetch_package("github:holepunchto/libquickbit#5ecf908")
16fetch_package("github:holepunchto/libjstl#d08e05c")
17
18add_bare_module(quickbit_native_bare)
19
20target_sources(
21 ${quickbit_native_bare}
22 PRIVATE
23 binding.cc
24)
25
26target_link_libraries(
27 ${quickbit_native_bare}
28 PRIVATE
29 $<TARGET_OBJECTS:quickbit>
30 $<TARGET_OBJECTS:simdle>
31 PUBLIC
32 quickbit
33 simdle
34 PRIVATE
35 jstl
36)
37
38add_napi_module(quickbit_native_node)
39
40target_sources(
41 ${quickbit_native_node}
42 PRIVATE
43 binding.cc
44)
45
46target_compile_definitions(
47 ${quickbit_native_node}
48 PRIVATE
49 NAPI_VERSION=9
50)
51
52target_link_libraries(
53 ${quickbit_native_node}
54 PRIVATE
55 $<TARGET_OBJECTS:quickbit>
56 $<TARGET_OBJECTS:simdle>
57 PUBLIC
58 quickbit
59 simdle
60 PRIVATE
61 jstl
62)
63
64resolve_node_module(bare-compat-napi compat)
65
66target_include_directories(
67 ${quickbit_native_node}
68 PRIVATE
69 "${compat}/include"
70)
node_modules/quickbit-native/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/quickbit-native/README.md +72 -0
……@@ -0,0 +1,72 @@
1# quickbit-native
2
3https://github.com/holepunchto/libquickbit JavaScript bindings for Node.js.
4
5```sh
6npm install quickbit-native
7```
8
9## Usage
10
11```js
12const { get, set, findFirst } = require('quickbit-native')
13
14const field = Buffer.alloc(256) // 2048 bits
15
16const changed = set(field, 1000)
17// true
18
19get(field, 1000)
20// true
21
22findFirst(field, true)
23// 1000
24```
25
26## API
27
28#### `const b = get(field, bit)`
29
30Get the given bit, which will either be `true` (set) or `false` (unset).
31
32#### `const changed = set(field, bit[, value])`
33
34Set the given bit to `value`, which defaults to `true`. Returns `true` if the bit changed, otherwise `false`.
35
36#### `field = fill(field, value[, start[, end]])`
37
38Fill the given bit range with `value`. `start` defaults to `0` and `end` defaults to the bit length of the field. Returns the modified field.
39
40#### `clear(field, chunk)`
41
42Clear the bits from `field` that are set in the `{ field, offset }` chunk.
43
44#### `const i = findFirst(field, value[, position])`
45
46Return the index of the first occurrence of `value`, or `-1` if not found. If `position` is given, return the first index that is greater than or equal to `position`.
47
48#### `const i = findLast(field, value[, position])`
49
50Return the index of the last occurrence of `value`, or `-1` if not found. If `position` is given, return the last index that is less than or equal to `position`.
51
52### Indexing
53
54#### `const index = Index.from(fieldOrChunks)`
55
56Construct an index of the bits in a bit field or an array of sparse `{ field, offset }` chunks.
57
58#### `const changed = index.update(bit)`
59
60Update the given bit in the index.
61
62#### `const position = index.skipFirst(value[, position])`
63
64Skip the first parts of the index that contain nothing but `value`. If the index contains _only_ `value`, the last index of the field is returned.
65
66#### `const position = index.skipLast(value[, position])`
67
68Skip the last parts of the index that contain nothing but `value`. If the index contains _only_ `value`, the first index of the field is returned.
69
70## License
71
72Apache-2.0
node_modules/quickbit-native/binding.cc +221 -0
……@@ -0,0 +1,221 @@
1#include <bare.h>
2#include <js.h>
3#include <jstl.h>
4#include <quickbit.h>
5
6template <>
7struct js_type_info_t<quickbit_chunk_t> {
8 using type = js_value_t *;
9
10 static constexpr auto signature = js_object;
11
12 template <js_type_options_t options>
13 static auto
14 unmarshall(js_env_t *env, js_value_t *value, quickbit_chunk_t &chunk) {
15 int err;
16
17 js_typedarray_span_t<uint8_t> field;
18 err = js_get_property(env, value, "field", field);
19 if (err < 0) return err;
20
21 uint32_t offset;
22 err = js_get_property(env, value, "offset", offset);
23 if (err < 0) return err;
24
25 chunk = {
26 .field = field.data(),
27 .len = field.size(),
28 .offset = offset,
29 };
30
31 return 0;
32 }
33};
34
35static inline uint32_t
36quickbit_napi_get(
37 js_env_t *env,
38 js_receiver_t,
39 js_typedarray_span_t<uint8_t> field,
40 int32_t bit
41) {
42 return quickbit_get(field.data(), field.size(), bit);
43}
44
45static inline uint32_t
46quickbit_napi_set(
47 js_env_t *env,
48 js_receiver_t,
49 js_typedarray_span_t<uint8_t> field,
50 int32_t bit,
51 uint32_t value
52) {
53 return quickbit_set(field.data(), field.size(), bit, value);
54}
55
56static inline void
57quickbit_napi_fill(
58 js_env_t *env,
59 js_receiver_t,
60 js_typedarray_span_t<uint8_t> field,
61 uint32_t value,
62 int32_t start,
63 int32_t end
64) {
65 quickbit_fill(field.data(), field.size(), value, start, end);
66}
67
68static inline void
69quickbit_napi_clear(
70 js_env_t *env,
71 js_receiver_t,
72 js_typedarray_span_t<uint8_t> field,
73 std::vector<quickbit_chunk_t> chunks
74) {
75 for (auto &chunk : chunks) {
76 quickbit_clear(field.data(), field.size(), &chunk);
77 }
78}
79
80static inline int32_t
81quickbit_napi_find_first(
82 js_env_t *env,
83 js_receiver_t,
84 js_typedarray_span_t<uint8_t> field,
85 uint32_t value,
86 int32_t position
87) {
88 return quickbit_find_first(field.data(), field.size(), value, position);
89}
90
91static inline int32_t
92quickbit_napi_find_last(
93 js_env_t *env,
94 js_receiver_t,
95 js_typedarray_span_t<uint8_t> field,
96 uint32_t value,
97 int32_t position
98) {
99 return quickbit_find_last(field.data(), field.size(), value, position);
100}
101
102static inline void
103quickbit_napi_index_init(
104 js_env_t *env,
105 js_receiver_t,
106 js_typedarray_span_t<uint8_t> index,
107 js_typedarray_span_t<uint8_t> field
108) {
109 quickbit_index_init(index.data(), field.data(), field.size());
110}
111
112static inline void
113quickbit_napi_index_init_sparse(
114 js_env_t *env,
115 js_receiver_t,
116 js_typedarray_span_t<uint8_t> index,
117 std::vector<quickbit_chunk_t> chunks
118) {
119 quickbit_index_init_sparse(index.data(), chunks.data(), chunks.size());
120}
121
122static inline uint32_t
123quickbit_napi_index_update(
124 js_env_t *env,
125 js_receiver_t,
126 js_typedarray_span_t<uint8_t> index,
127 js_typedarray_span_t<uint8_t> field,
128 int32_t bit
129) {
130 return quickbit_index_update(index.data(), field.data(), field.size(), bit);
131}
132
133static inline uint32_t
134quickbit_napi_index_update_sparse(
135 js_env_t *env,
136 js_receiver_t,
137 js_typedarray_span_t<uint8_t> index,
138 js_typedarray_span_t<uint8_t> field,
139 uint32_t offset,
140 int32_t bit
141) {
142 quickbit_chunk_t chunk = {
143 .field = field.data(),
144 .len = field.size(),
145 .offset = offset,
146 };
147
148 return quickbit_index_update_sparse(index.data(), &chunk, 1, bit);
149}
150
151static inline uint32_t
152quickbit_napi_skip_first(
153 js_env_t *env,
154 js_receiver_t,
155 js_typedarray_span_t<uint8_t> index,
156 uint32_t len,
157 uint32_t value,
158 int32_t position
159) {
160 return quickbit_skip_first(index.data(), len, value, position);
161}
162
163static inline uint32_t
164quickbit_napi_skip_last(
165 js_env_t *env,
166 js_receiver_t,
167 js_typedarray_span_t<uint8_t> index,
168 uint32_t len,
169 uint32_t value,
170 int32_t position
171) {
172 return quickbit_skip_last(index.data(), len, value, position);
173}
174
175static js_value_t *
176quickbit_napi_exports(js_env_t *env, js_value_t *exports) {
177 int err;
178
179 err = js_set_property(env, exports, "sizeof_quickbit_index_t", uint32_t(sizeof(quickbit_index_t)));
180 assert(err == 0);
181
182 err = js_set_property<quickbit_napi_get>(env, exports, "quickbit_napi_get");
183 assert(err == 0);
184
185 err = js_set_property<quickbit_napi_set>(env, exports, "quickbit_napi_set");
186 assert(err == 0);
187
188 err = js_set_property<quickbit_napi_fill>(env, exports, "quickbit_napi_fill");
189 assert(err == 0);
190
191 err = js_set_property<quickbit_napi_clear>(env, exports, "quickbit_napi_clear");
192 assert(err == 0);
193
194 err = js_set_property<quickbit_napi_find_first>(env, exports, "quickbit_napi_find_first");
195 assert(err == 0);
196
197 err = js_set_property<quickbit_napi_find_last>(env, exports, "quickbit_napi_find_last");
198 assert(err == 0);
199
200 err = js_set_property<quickbit_napi_index_init>(env, exports, "quickbit_napi_index_init");
201 assert(err == 0);
202
203 err = js_set_property<quickbit_napi_index_init_sparse>(env, exports, "quickbit_napi_index_init_sparse");
204 assert(err == 0);
205
206 err = js_set_property<quickbit_napi_index_update>(env, exports, "quickbit_napi_index_update");
207 assert(err == 0);
208
209 err = js_set_property<quickbit_napi_index_update_sparse>(env, exports, "quickbit_napi_index_update_sparse");
210 assert(err == 0);
211
212 err = js_set_property<quickbit_napi_skip_first>(env, exports, "quickbit_napi_skip_first");
213 assert(err == 0);
214
215 err = js_set_property<quickbit_napi_skip_last>(env, exports, "quickbit_napi_skip_last");
216 assert(err == 0);
217
218 return exports;
219}
220
221BARE_MODULE(quickbit_napi, quickbit_napi_exports)
node_modules/quickbit-native/binding.js +3 -0
……@@ -0,0 +1,3 @@
1require.addon = require('require-addon')
2
3module.exports = require.addon('.', __filename)
node_modules/quickbit-native/index.js +217 -0
……@@ -0,0 +1,217 @@
1const binding = require('./binding')
2
3exports.get = function get(field, bit) {
4 const n = field.byteLength * 8
5
6 if (bit < 0) bit += n
7 if (bit < 0 || bit >= n) return false
8
9 return binding.quickbit_napi_get(toBuffer(field), bit) !== 0
10}
11
12exports.set = function set(field, bit, value = true) {
13 const n = field.byteLength * 8
14
15 if (bit < 0) bit += n
16 if (bit < 0 || bit >= n) return false
17
18 return binding.quickbit_napi_set(toBuffer(field), bit, value ? 1 : 0) !== 0
19}
20
21exports.fill = function fill(
22 field,
23 value,
24 start = 0,
25 end = field.byteLength * 8
26) {
27 const n = field.byteLength * 8
28
29 if (start < 0) start += n
30 if (end < 0) end += n
31 if (start < 0 || start >= field.byteLength * 8 || start >= end) return field
32
33 binding.quickbit_napi_fill(toBuffer(field), value ? 1 : 0, start, end)
34 return field
35}
36
37exports.clear = function clear(field, ...chunks) {
38 binding.quickbit_napi_clear(toBuffer(field), chunks.map(toBufferChunk))
39}
40
41exports.findFirst = function findFirst(field, value, position = 0) {
42 const n = field.byteLength * 8
43
44 if (position < 0) position += n
45 if (position < 0) position = 0
46 if (position >= n) return -1
47
48 return binding.quickbit_napi_find_first(
49 toBuffer(field),
50 value ? 1 : 0,
51 position
52 )
53}
54
55exports.findLast = function findLast(
56 field,
57 value,
58 position = field.byteLength * 8 - 1
59) {
60 const n = field.byteLength * 8
61
62 if (position < 0) position += n
63 if (position < 0) return -1
64 if (position >= n) position = n - 1
65
66 return binding.quickbit_napi_find_last(
67 toBuffer(field),
68 value ? 1 : 0,
69 position
70 )
71}
72
73function toBuffer(field) {
74 if (field.BYTES_PER_ELEMENT === 1) return field
75 return new Uint8Array(field.buffer, field.byteOffset, field.byteLength)
76}
77
78function toBufferChunk(chunk) {
79 return { field: toBuffer(chunk.field), offset: chunk.offset }
80}
81
82class Index {
83 static from(fieldOrChunks, byteLength = -1) {
84 if (Array.isArray(fieldOrChunks)) {
85 return new SparseIndex(fieldOrChunks, byteLength)
86 } else {
87 return new DenseIndex(fieldOrChunks, byteLength)
88 }
89 }
90
91 constructor(byteLength) {
92 this._byteLength = byteLength
93 this.handle = Buffer.allocUnsafe(binding.sizeof_quickbit_index_t)
94 }
95
96 get byteLength() {
97 return this._byteLength
98 }
99
100 skipFirst(value, position = 0) {
101 const n = this.byteLength * 8
102
103 if (position < 0) position += n
104 if (position < 0) position = 0
105 if (position >= n) return n - 1
106
107 return binding.quickbit_napi_skip_first(
108 this.handle,
109 this.byteLength,
110 value ? 1 : 0,
111 position
112 )
113 }
114
115 skipLast(value, position = this.byteLength * 8 - 1) {
116 const n = this.byteLength * 8
117
118 if (position < 0) position += n
119 if (position < 0) return 0
120 if (position >= n) position = n - 1
121
122 return binding.quickbit_napi_skip_last(
123 this.handle,
124 this.byteLength,
125 value ? 1 : 0,
126 position
127 )
128 }
129}
130
131exports.Index = Index
132
133class DenseIndex extends Index {
134 constructor(field, byteLength) {
135 super(byteLength)
136 this.field = field
137
138 binding.quickbit_napi_index_init(this.handle, toBuffer(this.field))
139 }
140
141 get byteLength() {
142 if (this._byteLength !== -1) return this._byteLength
143 return this.field.byteLength
144 }
145
146 update(bit) {
147 const n = this.byteLength * 8
148
149 if (bit < 0) bit += n
150 if (bit < 0 || bit >= n) return false
151
152 return (
153 binding.quickbit_napi_index_update(
154 this.handle,
155 toBuffer(this.field),
156 bit
157 ) !== 0
158 )
159 }
160}
161
162function selectChunk(chunks, offset) {
163 for (let i = 0; i < chunks.length; i++) {
164 const next = chunks[i]
165
166 const start = next.offset
167 const end = next.offset + next.field.byteLength
168
169 if (offset >= start && offset + 16 <= end) {
170 return next
171 }
172 }
173
174 return null
175}
176
177class SparseIndex extends Index {
178 constructor(chunks, byteLength) {
179 super(byteLength)
180 this.chunks = chunks
181
182 binding.quickbit_napi_index_init_sparse(
183 this.handle,
184 this.chunks.map(toBufferChunk)
185 )
186 }
187
188 get byteLength() {
189 if (this._byteLength !== -1) return this._byteLength
190 const last = this.chunks[this.chunks.length - 1]
191 return last ? last.offset + last.field.byteLength : 0
192 }
193
194 update(bit) {
195 const n = this.byteLength * 8
196
197 if (bit < 0) bit += n
198 if (bit < 0 || bit >= n) return false
199
200 const j = Math.floor(bit / 128)
201
202 const offset = j * 16
203
204 const chunk = selectChunk(this.chunks, offset)
205
206 if (chunk === null) return false
207
208 return (
209 binding.quickbit_napi_index_update_sparse(
210 this.handle,
211 toBuffer(chunk.field),
212 chunk.offset,
213 bit
214 ) !== 0
215 )
216 }
217}
node_modules/quickbit-native/package.json +44 -0
……@@ -0,0 +1,44 @@
1{
2 "name": "quickbit-native",
3 "version": "2.4.8",
4 "description": "libquickbit JavaScript bindings for Node.js",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "macros.h",
9 "binding.cc",
10 "binding.js",
11 "CMakeLists.txt",
12 "prebuilds"
13 ],
14 "addon": true,
15 "scripts": {
16 "test": "npm run lint && npm run test:bare && npm run test:node",
17 "test:bare": "bare test.mjs",
18 "test:node": "node test.mjs",
19 "lint": "prettier . --check"
20 },
21 "repository": {
22 "type": "git",
23 "url": "git+https://github.com/holepunchto/quickbit-native.git"
24 },
25 "author": "Holepunch",
26 "license": "Apache-2.0",
27 "bugs": {
28 "url": "https://github.com/holepunchto/quickbit-native/issues"
29 },
30 "homepage": "https://github.com/holepunchto/quickbit-native#readme",
31 "dependencies": {
32 "require-addon": "^1.1.0"
33 },
34 "devDependencies": {
35 "b4a": "^1.6.7",
36 "bare-compat-napi": "^1.3.2",
37 "brittle": "^3.1.0",
38 "cmake-bare": "^1.1.7",
39 "cmake-fetch": "^1.1.0",
40 "cmake-napi": "^1.0.2",
41 "prettier": "^3.5.3",
42 "prettier-config-standard": "^7.0.0"
43 }
44}
node_modules/quickbit-native/prebuilds/android-arm/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/android-arm/quickbit-native.node +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/android-arm64/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/android-arm64/quickbit-native.node +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/android-ia32/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/android-ia32/quickbit-native.node +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/android-x64/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/android-x64/quickbit-native.node +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/darwin-arm64/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/darwin-arm64/quickbit-native.node +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/darwin-x64/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/darwin-x64/quickbit-native.node +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/ios-arm64-simulator/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/ios-arm64/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/ios-x64-simulator/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/linux-arm64/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/linux-arm64/quickbit-native.node +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/linux-x64/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/linux-x64/quickbit-native.node +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/win32-arm64/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/win32-arm64/quickbit-native.node +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/win32-x64/quickbit-native.bare +0 -0
(no content changes — binary or rename)
node_modules/quickbit-native/prebuilds/win32-x64/quickbit-native.node +0 -0
(no content changes — binary or rename)
node_modules/quickbit-universal/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/quickbit-universal/README.md +72 -0
……@@ -0,0 +1,72 @@
1# quickbit-universal
2
3Universal wrapper for https://github.com/holepunchto/libquickbit with a JavaScript fallback.
4
5```sh
6npm install quickbit-universal
7```
8
9## Usage
10
11```js
12const { get, set, findFirst } = require('quickbit-native')
13
14const field = Buffer.alloc(256) // 2048 bits
15
16const changed = set(field, 1000)
17// true
18
19get(field, 1000)
20// true
21
22findFirst(field, true)
23// 1000
24```
25
26## API
27
28#### `const b = get(field, bit)`
29
30Get the given bit, which will either be `true` (set) or `false` (unset).
31
32#### `const changed = set(field, bit[, value])`
33
34Set the given bit to `value`, which defaults to `true`. Returns `true` if the bit changed, otherwise `false`.
35
36#### `field = fill(field, value[, start[, end]])`
37
38Fill the given bit range with `value`. `start` defaults to `0` and `end` defaults to the bit length of the field. Returns the modified field.
39
40#### `clear(field, chunk)`
41
42Clear the bits from `field` that are set in the `{ field, offset }` chunk.
43
44#### `const i = findFirst(field, value[, position])`
45
46Return the index of the first occurrence of `value`, or `-1` if not found. If `position` is given, return the first index that is greater than or equal to `position`.
47
48#### `const i = findLast(field, value[, position])`
49
50Return the index of the last occurrence of `value`, or `-1` if not found. If `position` is given, return the last index that is less than or equal to `position`.
51
52### Indexing
53
54#### `const index = Index.from(fieldOrChunks)`
55
56Construct an index of the bits in a bit field or an array of sparse `{ field, offset }` chunks.
57
58#### `const changed = index.update(bit)`
59
60Update the given bit in the index.
61
62#### `const position = index.skipFirst(value[, position])`
63
64Skip the first parts of the index that contain nothing but `value`. If the index contains *only* `value`, the last index of the field is returned.
65
66#### `const position = index.skipLast(value[, position])`
67
68Skip the last parts of the index that contain nothing but `value`. If the index contains *only* `value`, the first index of the field is returned.
69
70## License
71
72Apache 2.0
node_modules/quickbit-universal/fallback.js +442 -0
……@@ -0,0 +1,442 @@
1const simdle = require('simdle-universal')
2
3const INDEX_LEN = (16 /* root */ + 128 * 16 /* children */) * 2
4
5const get = exports.get = function get (field, bit) {
6 const n = field.byteLength * 8
7
8 if (bit < 0) bit += n
9 if (bit < 0 || bit >= n) return false
10
11 const m = field.BYTES_PER_ELEMENT * 8
12
13 const offset = bit & (m - 1)
14 const i = (bit - offset) / m
15
16 return (field[i] & (1 << offset)) !== 0
17}
18
19const set = exports.set = function set (field, bit, value = true) {
20 const n = field.byteLength * 8
21
22 if (bit < 0) bit += n
23 if (bit < 0 || bit >= n) return false
24
25 const m = field.BYTES_PER_ELEMENT * 8
26
27 const offset = bit & (m - 1)
28 const i = (bit - offset) / m
29 const mask = 1 << offset
30
31 if (value) {
32 if ((field[i] & mask) !== 0) return false
33 } else {
34 if ((field[i] & mask) === 0) return false
35 }
36
37 field[i] ^= mask
38
39 return true
40}
41
42exports.fill = function fill (field, value, start = 0, end = field.byteLength * 8) {
43 const n = field.byteLength * 8
44
45 if (start < 0) start += n
46 if (end < 0) end += n
47 if (start < 0 || start >= field.byteLength * 8 || start >= end) return field
48
49 const m = field.BYTES_PER_ELEMENT * 8
50
51 let i, j
52
53 {
54 const offset = start & (m - 1)
55 i = (start - offset) / m
56
57 if (offset !== 0) {
58 let shift = m - offset
59 if (end - start < shift) shift = end - start
60
61 const mask = ((1 << shift) - 1) << offset
62
63 if (value) field[i] |= mask
64 else field[i] &= ~mask
65
66 i++
67 }
68 }
69
70 {
71 const offset = end & (m - 1)
72 j = (end - offset) / m
73
74 if (offset !== 0 && j >= i) {
75 const mask = (1 << offset) - 1
76
77 if (value) field[j] |= mask
78 else field[j] &= ~mask
79 }
80 }
81
82 if (i < j) field.fill(value ? (2 ** m) - 1 : 0, i, j)
83
84 return field
85}
86
87exports.clear = function clear (field, ...chunks) {
88 const n = field.byteLength
89
90 for (const chunk of chunks) {
91 if (chunk.offset >= n) continue
92
93 const m = chunk.field.byteLength
94
95 let i = chunk.offset
96 let j = 0
97
98 while (((i & 15) !== 0 || (j & 15) !== 0) && i < n && j < m) {
99 field[i] = field[i] & ~chunk.field[j]
100 i++
101 j++
102 }
103
104 if (i + 15 < n && j + 15 < m) {
105 const len = Math.min(n - (n & 15) - i, m - (m & 15) - j)
106
107 simdle.clear(field.subarray(i, i + len), chunk.field.subarray(j, j + len), field.subarray(i, i + len))
108 }
109
110 while (i < n && j < m) {
111 field[i] = field[i] & ~chunk.field[j]
112 i++
113 j++
114 }
115 }
116}
117
118function bitOffset (bit, offset) {
119 return !bit ? offset : (INDEX_LEN * 8 / 2) + offset
120}
121
122function byteOffset (bit, offset) {
123 return !bit ? offset : (INDEX_LEN / 2) + offset
124}
125
126exports.findFirst = function findFirst (field, value, position = 0) {
127 const n = field.byteLength * 8
128
129 if (position < 0) position += n
130 if (position < 0) position = 0
131 if (position >= n) return -1
132
133 value = !!value
134
135 for (let i = position; i < n; i++) {
136 if (get(field, i) === value) return i
137 }
138
139 return -1
140}
141
142exports.findLast = function findLast (field, value, position = field.byteLength * 8 - 1) {
143 const n = field.byteLength * 8
144
145 if (position < 0) position += n
146 if (position < 0) return -1
147 if (position >= n) position = n - 1
148
149 value = !!value
150
151 for (let i = position; i >= 0; i--) {
152 if (get(field, i) === value) return i
153 }
154
155 return -1
156}
157
158const Index = exports.Index = class Index {
159 static from (fieldOrChunks, byteLength = -1) {
160 if (Array.isArray(fieldOrChunks)) {
161 return new SparseIndex(fieldOrChunks, byteLength)
162 } else {
163 return new DenseIndex(fieldOrChunks, byteLength)
164 }
165 }
166
167 constructor (byteLength) {
168 this._byteLength = byteLength
169 this.handle = new Uint32Array(INDEX_LEN / 4)
170 }
171
172 get byteLength () {
173 return this._byteLength
174 }
175
176 skipFirst (value, position = 0) {
177 const n = this.byteLength * 8
178
179 if (position < 0) position += n
180 if (position < 0) position = 0
181 if (position >= n) return n - 1
182
183 let i = Math.floor(position / 16384)
184
185 if (i > 127) return position
186
187 while (i <= 127 && get(this.handle, bitOffset(value, i))) {
188 i++
189 }
190
191 if (i === 128) return n - 1
192
193 let k = i * 16384
194 let j = 0
195
196 if (position > k) j = Math.floor((position - k) / 128)
197
198 while (j <= 127 && get(this.handle, bitOffset(value, i * 128 + j + 128))) {
199 j++
200 k += 128
201 }
202
203 if (j === 128 && i !== 127) return this.skipFirst(value, (i + 1) * 16384)
204
205 if (k > position) position = k
206
207 return position < n ? position : n - 1
208 }
209
210 skipLast (value, position = this.byteLength * 8 - 1) {
211 const n = this.byteLength * 8
212
213 if (position < 0) position += n
214 if (position < 0) return 0
215 if (position >= n) position = n - 1
216
217 let i = Math.floor(position / 16384)
218
219 if (i > 127) return position
220
221 while (i >= 0 && get(this.handle, bitOffset(value, i))) {
222 i--
223 }
224
225 if (i === -1) return 0
226
227 let k = ((i + 1) * 16384) - 1
228 let j = 127
229
230 if (position < k) j = 128 - Math.ceil((k - position) / 128)
231
232 while (j >= 0 && get(this.handle, bitOffset(value, i * 128 + j + 128))) {
233 j--
234 k -= 128
235 }
236
237 if (j === -1 && i !== 0) return this.skipLast(value, i * 16384 - 1)
238
239 if (k < position) position = k
240
241 return position
242 }
243}
244
245class DenseIndex extends Index {
246 constructor (field, byteLength) {
247 super(byteLength)
248 this.field = field
249
250 const m = field.BYTES_PER_ELEMENT
251
252 for (let i = 0; i < 128; i++) {
253 for (let j = 0; j < 128; j++) {
254 const offset = (i * 128 + j) * 16
255 let allz = true
256 let allo = false
257
258 if (offset + 16 <= this.field.byteLength) {
259 const vec = this.field.subarray(offset / m, (offset + 16) / m)
260
261 allz = simdle.allz(vec)
262 allo = simdle.allo(vec)
263 }
264
265 const k = i * 128 + 128 + j
266
267 set(this.handle, bitOffset(false, k), allz)
268 set(this.handle, bitOffset(true, k), allo)
269 }
270
271 {
272 const offset = byteOffset(false, i * 16 + 16) / 4
273 const allo = simdle.allo(this.handle.subarray(offset, offset + 4))
274
275 set(this.handle, bitOffset(false, i), allo)
276 }
277
278 {
279 const offset = byteOffset(true, i * 16 + 16) / 4
280 const allo = simdle.allo(this.handle.subarray(offset, offset + 4))
281
282 set(this.handle, bitOffset(true, i), allo)
283 }
284 }
285 }
286
287 get byteLength () {
288 if (this._byteLength !== -1) return this._byteLength
289 return this.field.byteLength
290 }
291
292 update (bit) {
293 const n = this.byteLength * 8
294
295 if (bit < 0) bit += n
296 if (bit < 0 || bit >= n) return false
297
298 const m = this.field.BYTES_PER_ELEMENT
299
300 const i = Math.floor(bit / 16384)
301 const j = Math.floor(bit / 128)
302
303 const offset = (j * 16) / m
304 const vec = this.field.subarray(offset, offset + (16 / m))
305
306 const allz = simdle.allz(vec)
307 const allo = simdle.allo(vec)
308
309 let changed = false
310
311 if (set(this.handle, bitOffset(false, 128 + j), allz)) {
312 changed = true
313
314 const offset = byteOffset(false, i * 16 + 16) / 4
315 const allo = simdle.allo(this.handle.subarray(offset, offset + 4))
316
317 set(this.handle, bitOffset(false, i), allo)
318 }
319
320 if (set(this.handle, bitOffset(true, 128 + j), allo)) {
321 changed = true
322
323 const offset = byteOffset(true, i * 16 + 16) / 4
324 const allo = simdle.allo(this.handle.subarray(offset, offset + 4))
325
326 set(this.handle, bitOffset(true, i), allo)
327 }
328
329 return changed
330 }
331}
332
333function selectChunk (chunks, offset) {
334 for (let i = 0; i < chunks.length; i++) {
335 const next = chunks[i]
336
337 const start = next.offset
338 const end = next.offset + next.field.byteLength
339
340 if (offset >= start && offset + 16 <= end) {
341 return next
342 }
343 }
344
345 return null
346}
347
348class SparseIndex extends Index {
349 constructor (chunks, byteLength) {
350 super(byteLength)
351 this.chunks = chunks
352
353 for (let i = 0; i < 128; i++) {
354 for (let j = 0; j < 128; j++) {
355 const offset = (i * 128 + j) * 16
356 let allz = true
357 let allo = false
358
359 const chunk = selectChunk(this.chunks, offset)
360
361 if (chunk !== null) {
362 const m = chunk.field.BYTES_PER_ELEMENT
363
364 const vec = chunk.field.subarray((offset - chunk.offset) / m, (offset - chunk.offset + 16) / m)
365
366 allz = simdle.allz(vec)
367 allo = simdle.allo(vec)
368 }
369
370 const k = i * 128 + 128 + j
371
372 set(this.handle, bitOffset(false, k), allz)
373 set(this.handle, bitOffset(true, k), allo)
374 }
375
376 {
377 const offset = byteOffset(false, i * 16 + 16) / 4
378 const allo = simdle.allo(this.handle.subarray(offset, offset + 4))
379
380 set(this.handle, bitOffset(false, i), allo)
381 }
382
383 {
384 const offset = byteOffset(true, i * 16 + 16) / 4
385 const allo = simdle.allo(this.handle.subarray(offset, offset + 4))
386
387 set(this.handle, bitOffset(true, i), allo)
388 }
389 }
390 }
391
392 get byteLength () {
393 if (this._byteLength !== -1) return this._byteLength
394 const last = this.chunks[this.chunks.length - 1]
395 return last ? last.offset + last.field.byteLength : 0
396 }
397
398 update (bit) {
399 const n = this.byteLength * 8
400
401 if (bit < 0) bit += n
402 if (bit < 0 || bit >= n) return false
403
404 const i = Math.floor(bit / 16384)
405 const j = Math.floor(bit / 128)
406
407 const offset = j * 16
408
409 const chunk = selectChunk(this.chunks, offset)
410
411 if (chunk === null) return false
412
413 const m = chunk.field.BYTES_PER_ELEMENT
414
415 const vec = chunk.field.subarray((offset - chunk.offset) / m, (offset - chunk.offset + 16) / m)
416
417 const allz = simdle.allz(vec)
418 const allo = simdle.allo(vec)
419
420 let changed = false
421
422 if (set(this.handle, bitOffset(false, 128 + j), allz)) {
423 changed = true
424
425 const offset = byteOffset(false, i * 16 + 16) / 4
426 const allo = simdle.allo(this.handle.subarray(offset, offset + 4))
427
428 set(this.handle, bitOffset(false, i), allo)
429 }
430
431 if (set(this.handle, bitOffset(true, 128 + j), allo)) {
432 changed = true
433
434 const offset = byteOffset(true, i * 16 + 16) / 4
435 const allo = simdle.allo(this.handle.subarray(offset, offset + 4))
436
437 set(this.handle, bitOffset(true, i), allo)
438 }
439
440 return changed
441 }
442}
node_modules/quickbit-universal/index.js +18 -0
……@@ -0,0 +1,18 @@
1const fallback = require('./fallback')
2
3try {
4 const native = require('quickbit-native')
5
6 // These functions are faster in JavaScript
7 exports.get = fallback.get
8 exports.set = fallback.set
9 exports.fill = fallback.fill
10
11 // These functions are faster in C
12 exports.clear = native.clear
13 exports.findFirst = native.findFirst
14 exports.findLast = native.findLast
15 exports.Index = native.Index
16} catch {
17 module.exports = fallback
18}
node_modules/quickbit-universal/package.json +37 -0
……@@ -0,0 +1,37 @@
1{
2 "name": "quickbit-universal",
3 "version": "2.2.0",
4 "description": "Universal wrapper for libquickbit with a JavaScript fallback",
5 "main": "index.js",
6 "files": [
7 "fallback.js",
8 "index.js"
9 ],
10 "browser": {
11 "./index.js": "./fallback.js"
12 },
13 "scripts": {
14 "test": "standard && brittle test.mjs"
15 },
16 "repository": {
17 "type": "git",
18 "url": "git+https://github.com/holepunchto/quickbit-universal.git"
19 },
20 "author": "Kasper Isager Dalsgarð <kasper@funktionel.co>",
21 "license": "ISC",
22 "bugs": {
23 "url": "https://github.com/holepunchto/quickbit-universal/issues"
24 },
25 "homepage": "https://github.com/holepunchto/quickbit-universal#readme",
26 "dependencies": {
27 "b4a": "^1.6.0",
28 "simdle-universal": "^1.1.0"
29 },
30 "optionalDependencies": {
31 "quickbit-native": "^2.2.0"
32 },
33 "devDependencies": {
34 "brittle": "^3.1.0",
35 "standard": "^17.0.0"
36 }
37}
node_modules/rabin-native/CMakeLists.txt +57 -0
……@@ -0,0 +1,57 @@
1cmake_minimum_required(VERSION 4.0)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6
7project(rabin_native C)
8
9bare_target(target)
10
11fetch_package("github:holepunchto/librabin#2e4f70b")
12
13add_bare_module(rabin_native_bare)
14
15target_sources(
16 ${rabin_native_bare}
17 PRIVATE
18 binding.c
19)
20
21target_link_libraries(
22 ${rabin_native_bare}
23 PRIVATE
24 $<TARGET_OBJECTS:rabin>
25 PUBLIC
26 rabin
27)
28
29add_napi_module(rabin_native_node)
30
31target_sources(
32 ${rabin_native_node}
33 PRIVATE
34 binding.c
35)
36
37target_link_libraries(
38 ${rabin_native_node}
39 PRIVATE
40 $<TARGET_OBJECTS:rabin>
41 PUBLIC
42 rabin
43)
44
45target_compile_definitions(
46 ${rabin_native_node}
47 PRIVATE
48 NAPI_VERSION=9
49)
50
51resolve_node_module(bare-compat-napi compat)
52
53target_include_directories(
54 ${rabin_native_node}
55 PRIVATE
56 "${compat}/include"
57)
node_modules/rabin-native/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/rabin-native/README.md +62 -0
……@@ -0,0 +1,62 @@
1# rabin-native
2
3<https://github.com/holepunchto/librabin> bindings for JavaScript.
4
5```
6npm i rabin-native
7```
8
9## Usage
10
11```js
12const rabin = require('rabin-native')
13
14const chunker = new rabin.Chunker()
15const chunks = []
16
17for (const chunk of chunker.push(shakespeare)) {
18 chunks.push(chunk)
19}
20
21const chunk = chunker.end()
22
23if (chunk) chunks.push(chunk)
24```
25
26## API
27
28#### `const chunker = new Chunker([options])`
29
30Construct a new chunker.
31
32Options include:
33
34```js
35options = {
36 minSize: 512 * 1024, // 512 KiB
37 maxSize: 8 * 1024 * 1024 // 8 MiB
38}
39```
40
41#### `const iterator = chunker.push(data)`
42
43Push data to the chunker, returning an iterator over the identified chunks.
44
45Each chunk has the following shape:
46
47```js
48chunk = {
49 // Size of the chunk in bytes
50 length,
51 // Offset of the chunk within the stream
52 offset
53}
54```
55
56#### `const chunk = chunker.end()`
57
58Finish the chunker, returning the trailing chunk or `null`.
59
60## License
61
62Apache-2.0
node_modules/rabin-native/binding.c +165 -0
……@@ -0,0 +1,165 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4#include <rabin.h>
5#include <uv.h>
6
7typedef struct {
8 rabin_t context;
9} rabin_native_t;
10
11static js_value_t *
12rabin_native_init(js_env_t *env, js_callback_info_t *info) {
13 int err;
14
15 size_t argc = 2;
16 js_value_t *argv[2];
17
18 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
19 assert(err == 0);
20
21 assert(argc == 2);
22
23 uint32_t min_size;
24 err = js_get_value_uint32(env, argv[0], &min_size);
25 assert(err == 0);
26
27 uint32_t max_size;
28 err = js_get_value_uint32(env, argv[1], &max_size);
29 assert(err == 0);
30
31 js_value_t *handle;
32
33 rabin_native_t *chunker;
34 err = js_create_arraybuffer(env, sizeof(rabin_native_t), (void **) &chunker, &handle);
35 assert(err == 0);
36
37 rabin_init(&chunker->context);
38
39 chunker->context.chunk_min = min_size;
40 chunker->context.chunk_max = max_size;
41
42 return handle;
43}
44
45static js_value_t *
46rabin_native_push(js_env_t *env, js_callback_info_t *info) {
47 int err;
48
49 size_t argc = 4;
50 js_value_t *argv[4];
51
52 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
53 assert(err == 0);
54
55 assert(argc == 4);
56
57 rabin_native_t *chunker;
58 err = js_get_arraybuffer_info(env, argv[0], (void **) &chunker, NULL);
59 assert(err == 0);
60
61 void *data;
62 err = js_get_arraybuffer_info(env, argv[1], &data, NULL);
63 assert(err == 0);
64
65 int64_t offset;
66 err = js_get_value_int64(env, argv[2], &offset);
67 assert(err == 0);
68
69 int64_t len;
70 err = js_get_value_int64(env, argv[3], &len);
71 assert(err == 0);
72
73 len = rabin_push(&chunker->context, &data[offset], len);
74
75 js_value_t *result;
76 err = js_create_int64(env, len, &result);
77 assert(err == 0);
78
79 return result;
80}
81
82static js_value_t *
83rabin_native_end(js_env_t *env, js_callback_info_t *info) {
84 int err;
85
86 size_t argc = 1;
87 js_value_t *argv[1];
88
89 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
90 assert(err == 0);
91
92 assert(argc == 1);
93
94 rabin_native_t *chunker;
95 err = js_get_arraybuffer_info(env, argv[0], (void **) &chunker, NULL);
96 assert(err == 0);
97
98 int64_t len = rabin_end(&chunker->context);
99
100 js_value_t *result;
101 err = js_create_int64(env, len, &result);
102 assert(err == 0);
103
104 return result;
105}
106
107static js_value_t *
108rabin_native_last_chunk(js_env_t *env, js_callback_info_t *info) {
109 int err;
110
111 size_t argc = 1;
112 js_value_t *argv[1];
113
114 err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
115 assert(err == 0);
116
117 assert(argc == 1);
118
119 rabin_native_t *chunker;
120 err = js_get_arraybuffer_info(env, argv[0], (void **) &chunker, NULL);
121 assert(err == 0);
122
123 js_value_t *result;
124 err = js_create_object(env, &result);
125 assert(err == 0);
126
127#define V(name, property) \
128 { \
129 js_value_t *val; \
130 err = js_create_int64(env, chunker->context.last_chunk.property, &val); \
131 assert(err == 0); \
132 err = js_set_named_property(env, result, name, val); \
133 assert(err == 0); \
134 }
135
136 V("length", length)
137 V("offset", offset)
138#undef V
139
140 return result;
141}
142
143static js_value_t *
144rabin_native_exports(js_env_t *env, js_value_t *exports) {
145 int err;
146
147#define V(name, fn) \
148 { \
149 js_value_t *val; \
150 err = js_create_function(env, name, -1, fn, NULL, &val); \
151 assert(err == 0); \
152 err = js_set_named_property(env, exports, name, val); \
153 assert(err == 0); \
154 }
155
156 V("init", rabin_native_init)
157 V("push", rabin_native_push)
158 V("end", rabin_native_end)
159 V("lastChunk", rabin_native_last_chunk)
160#undef V
161
162 return exports;
163}
164
165BARE_MODULE(rabin_native, rabin_native_exports)
node_modules/rabin-native/binding.js +3 -0
……@@ -0,0 +1,3 @@
1require.addon = require('require-addon')
2
3module.exports = require.addon('.', __filename)
node_modules/rabin-native/index.js +34 -0
……@@ -0,0 +1,34 @@
1const binding = require('./binding')
2
3class RabinChunker {
4 constructor(opts = {}) {
5 const {
6 minSize = 512 * 1024, // 512 KiB
7 maxSize = 8 * 1024 * 1024 // 8 MiB
8 } = opts
9
10 this._handle = binding.init(minSize, maxSize)
11 }
12
13 *push(data) {
14 while (true) {
15 const length = binding.push(this._handle, data.buffer, data.byteOffset, data.byteLength)
16
17 if (length === 0) return
18
19 data = data.subarray(length)
20
21 yield binding.lastChunk(this._handle)
22 }
23 }
24
25 end() {
26 const length = binding.end(this._handle)
27
28 if (length === 0) return null
29
30 return binding.lastChunk(this._handle)
31 }
32}
33
34exports.Chunker = RabinChunker
node_modules/rabin-native/package.json +60 -0
……@@ -0,0 +1,60 @@
1{
2 "name": "rabin-native",
3 "version": "2.0.0",
4 "description": "librabin bindings for JavaScript",
5 "exports": {
6 "./package": "./package.json",
7 ".": "./index.js"
8 },
9 "imports": {
10 "fs": {
11 "bare": "bare-fs",
12 "default": "fs"
13 },
14 "path": {
15 "bare": "bare-path",
16 "default": "path"
17 }
18 },
19 "files": [
20 "index.js",
21 "binding.c",
22 "binding.js",
23 "CMakeLists.txt",
24 "prebuilds"
25 ],
26 "addon": true,
27 "scripts": {
28 "format": "prettier --write .",
29 "lint": "prettier --check . && lunte",
30 "test": "npm run test:node && npm run test:bare",
31 "test:bare": "brittle-bare --coverage test.js",
32 "test:node": "brittle-node --coverage test.js"
33 },
34 "repository": {
35 "type": "git",
36 "url": "git+https://github.com/holepunchto/rabin-native.git"
37 },
38 "author": "Holepunch",
39 "license": "Apache-2.0",
40 "bugs": {
41 "url": "https://github.com/holepunchto/rabin-native/issues"
42 },
43 "homepage": "https://github.com/holepunchto/rabin-native#readme",
44 "dependencies": {
45 "require-addon": "^1.1.0"
46 },
47 "devDependencies": {
48 "bare-compat-napi": "^1.3.9",
49 "bare-fs": "^4.5.3",
50 "bare-path": "^3.0.0",
51 "brittle": "^3.1.0",
52 "cmake-bare": "^1.1.7",
53 "cmake-fetch": "^1.1.0",
54 "cmake-napi": "^1.0.2",
55 "cmake-npm": "^1.1.0",
56 "lunte": "^1.3.0",
57 "prettier": "^3.6.2",
58 "prettier-config-holepunch": "^2.0.0"
59 }
60}
node_modules/rabin-native/prebuilds/android-arm/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/android-arm/rabin-native.node +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/android-arm64/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/android-arm64/rabin-native.node +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/android-ia32/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/android-ia32/rabin-native.node +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/android-x64/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/android-x64/rabin-native.node +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/darwin-arm64/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/darwin-arm64/rabin-native.node +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/darwin-x64/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/darwin-x64/rabin-native.node +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/ios-arm64-simulator/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/ios-arm64/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/ios-x64-simulator/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/linux-arm64/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/linux-arm64/rabin-native.node +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/linux-x64/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/linux-x64/rabin-native.node +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/win32-arm64/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/win32-arm64/rabin-native.node +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/win32-x64/rabin-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rabin-native/prebuilds/win32-x64/rabin-native.node +0 -0
(no content changes — binary or rename)
node_modules/rabin-stream/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/rabin-stream/README.md +31 -0
……@@ -0,0 +1,31 @@
1# rabin-stream
2
3Streaming Rabin chunker.
4
5```
6npm i rabin-stream
7```
8
9## Usage
10
11```js
12const RabinStream = require('rabin-stream')
13
14const r = new RabinStream()
15
16r.on('data', function (data) {
17 console.log('Chunk', data)
18})
19
20someStream.pipe(r)
21```
22
23## API
24
25#### `const stream = new RabinStream([options])`
26
27Construct a new chunker stream. Options supported by <https://github.com/holepunchto/rabin-native> may be specified.
28
29## License
30
31Apache-2.0
node_modules/rabin-stream/index.js +49 -0
……@@ -0,0 +1,49 @@
1const { Transform } = require('streamx')
2const rabin = require('rabin-native')
3
4module.exports = class RabinStream extends Transform {
5 constructor(opts = {}) {
6 super()
7
8 this._rabin = new rabin.Chunker(opts)
9 this._buffer = []
10 }
11
12 _transform(data, cb) {
13 if (typeof data === 'string') data = Buffer.from(data)
14
15 this._buffer.push(data)
16
17 const chunks = this._rabin.push(data)
18
19 for (const chunk of chunks) {
20 let data = this._buffer[0]
21
22 if (data.byteLength < chunk.length) {
23 data = Buffer.concat(this._buffer)
24
25 this._buffer = []
26 } else {
27 this._buffer.pop()
28 }
29
30 this.push(data.subarray(0, chunk.length))
31
32 data = data.subarray(chunk.length)
33
34 if (data.byteLength) this._buffer.unshift(data)
35 }
36
37 cb(null)
38 }
39
40 _flush(cb) {
41 if (this._buffer.length) {
42 this.push(Buffer.concat(this._buffer))
43 }
44
45 this._buffer = []
46
47 cb(null)
48 }
49}
node_modules/rabin-stream/package.json +51 -0
……@@ -0,0 +1,51 @@
1{
2 "name": "rabin-stream",
3 "version": "2.0.0",
4 "description": "Streaming Rabin chunker",
5 "exports": {
6 "./package": "./package.json",
7 ".": "./index.js"
8 },
9 "imports": {
10 "fs": {
11 "bare": "bare-fs",
12 "default": "fs"
13 },
14 "path": {
15 "bare": "bare-path",
16 "default": "path"
17 }
18 },
19 "files": [
20 "index.js"
21 ],
22 "scripts": {
23 "format": "prettier --write .",
24 "lint": "prettier --check . && lunte",
25 "test": "npm run test:node && npm run test:bare",
26 "test:bare": "brittle-bare --coverage test.js",
27 "test:node": "brittle-node --coverage test.js"
28 },
29 "repository": {
30 "type": "git",
31 "url": "git+https://github.com/holepunchto/rabin-stream.git"
32 },
33 "author": "Holepunch",
34 "license": "Apache-2.0",
35 "bugs": {
36 "url": "https://github.com/holepunchto/rabin-stream/issues"
37 },
38 "homepage": "https://github.com/holepunchto/rabin-stream#readme",
39 "dependencies": {
40 "rabin-native": "^2.0.0",
41 "streamx": "^2.23.0"
42 },
43 "devDependencies": {
44 "bare-fs": "^4.5.4",
45 "bare-path": "^3.0.0",
46 "brittle": "^3.1.0",
47 "lunte": "^1.3.0",
48 "prettier": "^3.6.2",
49 "prettier-config-holepunch": "^2.0.0"
50 }
51}
node_modules/rache/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/rache/README.md +105 -0
……@@ -0,0 +1,105 @@
1# Rache
2
3A random-eviction cache which imposes a global cache-size limit on all the caches derived from it.
4
5Useful when you have many caches and want to limit their memory usage as a whole, instead of per cache.
6
7The `get` and `set` operations as well as `delete` (and cache eviction) take constant time.
8
9## Install
10
11```
12npm i rache
13```
14
15## Usage
16
17```
18const Rache = require('rache')
19
20const cache = new Rache({ maxSize: 3 })
21const cache2 = cache.sub()
22const cache3 = cache.sub()
23
24cache.set('key', 'value')
25cache2.set('key', 'otherValue')
26cache3.set('some', 'thing')
27
28// cache 1 is a separate cache from cache2 and cache3
29console.log('cached:', cache.get('key')) // 'value'
30
31// But they share the same global size
32console.log(cache.globalSize, 'of', cache.maxSize) // 3 of 3
33
34cache.set('key2', 'another value')
35// The cache was full, so one of the existing 3 entries got evicted
36
37console.log(cache.globalSize, 'of', cache.maxSize) // 3 of 3
38```
39
40## API
41
42#### `const cache = new Rache({ maxSize=65536 })`
43
44Create a new cache.
45
46`maxSize` is the maximum amount of entries globally, across this cache and all derived caches (derived with `cache.sub()` or `Rache.from(cache)`).
47
48#### `const subCache = cache.sub()`
49
50Create a new cache which shares the global memory limit with the original cache.
51
52#### `const aCache = Rache.from(cache?)`
53
54Create a new rache instance.
55
56If an existing cache is passed in, it will create a sub-cache (equivalent to `aCache = cache.sub()`).
57
58Otherwise (if no `cache` or a falsy value is passed in), it will create a new cache (equivalent to `aCache = new Rache()`).
59
60
61#### `cache.globalSize`
62
63The current amount of entries across all caches.
64
65#### `cache.maxSize`
66
67The maximum amount of entries across all caches.
68
69#### `cache.size`
70
71The amount of entries in this specific cache.
72
73#### `cache.set(key, value)`
74
75Set the key to the given value.
76
77If the global cache size was at the limit, a random old entry is evicted from the cache.
78
79#### `cache.delete(key)`
80
81Delete the entry corresponding to `key`, if any.
82
83Returns `true` if an entry was deleted, `false` otherwise.
84
85#### `cache.get(key)`
86
87Returns the value corresponding to the given key, or `undefined` if there is none.
88
89#### `cache.keys()`
90
91Returns an iterator over the keys of this particular cache.
92
93#### `cache.values()`
94
95Returns an iterator over the values of this particular cache.
96
97#### `cache.clear()`
98
99Clear all entries from this particular cache.
100
101After clearing, new entries can again be added to the cache.
102
103#### `cache.destroy()`
104
105Destroys the cache. The cache should no longer be used after it has been destroyed.
node_modules/rache/index.js +119 -0
……@@ -0,0 +1,119 @@
1class CacheEntry {
2 constructor (key, index, map) {
3 this.key = key
4 this.index = index
5 this.map = map
6 }
7}
8
9class CacheValue {
10 constructor (entry, value) {
11 this.entry = entry
12 this.value = value
13 }
14}
15
16class Rache {
17 constructor ({ maxSize = 65536, parent = null } = {}) {
18 this.maxSize = parent?.maxSize || maxSize
19
20 this._array = parent?._array || []
21 this._map = new Map()
22 }
23
24 static from (cache) {
25 return cache ? new this({ parent: cache }) : new this()
26 }
27
28 get globalSize () {
29 return this._array.length
30 }
31
32 get size () {
33 return this._map.size
34 }
35
36 sub () {
37 return new Rache({ parent: this })
38 }
39
40 set (key, value) { // ~constant time
41 const existing = this._map.get(key)
42 if (existing !== undefined) {
43 existing.value = value
44 return
45 }
46
47 if (this._array.length >= this.maxSize) this._gc()
48
49 const entry = new CacheEntry(key, this._array.length, this._map)
50 this._array.push(entry)
51 const cacheValue = new CacheValue(entry, value)
52 this._map.set(key, cacheValue)
53 }
54
55 delete (key) {
56 const existing = this._map.get(key)
57 if (existing === undefined) return false
58
59 this._delete(existing.entry.index)
60 return true
61 }
62
63 get (key) {
64 const existing = this._map.get(key)
65 return existing === undefined ? undefined : existing.value
66 }
67
68 * [Symbol.iterator] () {
69 for (const [key, { value }] of this._map) {
70 yield [key, value]
71 }
72 }
73
74 keys () {
75 return this._map.keys()
76 }
77
78 * values () {
79 for (const { value } of this._map.values()) {
80 yield value
81 }
82 }
83
84 clear () {
85 // The entries in map linger on in _array,
86 // so on top of clearing the map, we also kill the ref,
87 // so that any gc running later on the old map won't interfere
88 // (in case a new entry was added with the same key as a cleared entry)
89
90 this._map.clear()
91 this._map = new Map()
92 }
93
94 destroy () {
95 this._map = null
96 this._array = null
97 }
98
99 _gc () {
100 this._delete(Math.floor(Math.random() * this._array.length))
101 }
102
103 _delete (index) { // ~constant time
104 if (index >= this._array.length) throw new Error('Cannot delete unused index (logic bug?)')
105
106 const head = this._array.pop()
107 let removed = head
108
109 if (index < this._array.length) {
110 removed = this._array[index]
111 head.index = index
112 this._array[index] = head
113 }
114
115 removed.map.delete(removed.key)
116 }
117}
118
119module.exports = Rache
node_modules/rache/package.json +27 -0
……@@ -0,0 +1,27 @@
1{
2 "name": "rache",
3 "version": "1.0.0",
4 "description": "Random-eviction cache",
5 "main": "index.js",
6 "scripts": {
7 "test": "standard && brittle test.js --coverage"
8 },
9 "repository": {
10 "type": "git",
11 "url": "git+https://github.com/holepunchto/rache.git"
12 },
13 "author": "Holepunch",
14 "license": "Apache-2.0",
15 "bugs": {
16 "url": "https://github.com/holepunchto/rache/issues"
17 },
18 "homepage": "https://github.com/holepunchto/rache#readme",
19 "files": [
20 "index.js"
21 ],
22 "dependencies": {},
23 "devDependencies": {
24 "brittle": "^3.5.2",
25 "standard": "^17.1.0"
26 }
27}
node_modules/random-access-file/README.md +97 -0
……@@ -0,0 +1,97 @@
1# random-access-file
2
3Continuous reading or writing to a file using random offsets and lengths
4
5```
6npm install random-access-file
7```
8
9## Why?
10
11If you are receiving a file in multiple pieces in a distributed system it can be useful to write these pieces to disk one by one in various places throughout the file without having to open and close a file descriptor all the time.
12
13random-access-file allows you to do just this.
14
15## Usage
16
17``` js
18const RandomAccessFile = require('random-access-file')
19
20const file = new RandomAccessFile('my-file.txt')
21
22file.write(10, Buffer.from('hello'), function(err) {
23 // write a buffer to offset 10
24 file.read(10, 5, function(err, buffer) {
25 console.log(buffer) // read 5 bytes from offset 10
26 file.close(function() {
27 console.log('file is closed')
28 })
29 })
30})
31```
32
33file will use an open file descriptor. When you are done with the file you should call `file.close()`.
34
35## API
36
37#### `const file = new RandomAccessFile(filename, [options])`
38
39Create a new file. Options include:
40
41``` js
42{
43 truncate: false, // truncate the file before reading / writing
44 size: someSize, // truncate the file to this size first
45 readable: true, // should the file be opened as readable?
46 writable: true, // should the file be opened as writable?
47 lock: false, // lock the file
48 sparse: false // mark the file as sparse
49}
50```
51
52#### `file.write(offset, buffer, [callback])`
53
54Write a buffer at a specific offset.
55
56#### `file.read(offset, length, callback)`
57
58Read a buffer at a specific offset. Callback is called with the buffer read.
59
60#### `file.del(offset, length, callback)`
61
62Delete a portion of the file. Any partial file blocks in the deleted portion are zeroed and, if the file is sparse, the remaining file blocks unlinked in-place.
63
64#### `file.truncate(offset, callback)`
65
66Truncate the file length to this offset.
67
68#### `file.stat(callback)`
69
70Stat the storage. Should return an object with useful information about the underlying storage, including:
71
72```js
73{
74 size: number // how many bytes of data is stored?
75}
76```
77
78#### `file.close([callback])`
79
80Close the underlying file descriptor.
81
82#### `file.unlink([callback])`
83
84Unlink the underlying file.
85
86#### `file.on('open')`
87
88Emitted when the file descriptor has been opened. You can access the fd using `file.fd`.
89You do not need to wait for this event before doing any reads/writes.
90
91#### `file.on('close')`
92
93Emitted when the file has been closed.
94
95## License
96
97MIT
node_modules/random-access-file/browser.js +3 -0
……@@ -0,0 +1,3 @@
1module.exports = function () {
2 throw new Error('random-access-file is not supported in the browser')
3}
node_modules/random-access-file/index.js +255 -0
……@@ -0,0 +1,255 @@
1const RandomAccessStorage = require('random-access-storage')
2const fs = require('fs')
3const path = require('path')
4const constants = fs.constants
5
6let fsext = null
7try {
8 fsext = require('fs-native-extensions')
9} catch {}
10
11const RDWR = constants.O_RDWR
12const RDONLY = constants.O_RDONLY
13const WRONLY = constants.O_WRONLY
14const CREAT = constants.O_CREAT
15
16class Pool {
17 constructor (maxSize) {
18 this.maxSize = maxSize
19 this.active = []
20 }
21
22 _onactive (file) {
23 // suspend a random one when the pool
24 if (this.active.length >= this.maxSize) {
25 const r = Math.floor(Math.random() * this.active.length)
26 this.active[r].suspend()
27 }
28
29 file._pi = this.active.push(file) - 1
30 }
31
32 _oninactive (file) {
33 const head = this.active.pop()
34 if (head !== file) {
35 head._pi = file._pi
36 this.active[head._pi] = head
37 }
38 }
39}
40
41module.exports = class RandomAccessFile extends RandomAccessStorage {
42 constructor (filename, opts = {}) {
43 const size = opts.size || (opts.truncate ? 0 : -1)
44
45 super()
46
47 if (opts.directory) filename = path.join(opts.directory, path.resolve('/', filename).replace(/^\w+:\\/, ''))
48
49 this.directory = opts.directory || null
50 this.filename = filename
51 this.fd = 0
52
53 const {
54 readable = true,
55 writable = true
56 } = opts
57
58 this.mode = readable && writable ? RDWR : (readable ? RDONLY : WRONLY)
59
60 this._pi = 0 // pool index
61 this._pool = opts.pool || null
62 this._size = size
63 this._rmdir = !!opts.rmdir
64 this._lock = opts.lock === true
65 this._sparse = opts.sparse === true
66 this._alloc = opts.alloc || Buffer.allocUnsafe
67 this._alwaysCreate = size >= 0
68 }
69
70 static createPool (maxSize) {
71 return new Pool(maxSize)
72 }
73
74 _open (req) {
75 const create = this._alwaysCreate || this.writing // .writing comes from RAS
76 const self = this
77 const mode = this.mode | (create ? CREAT : 0)
78
79 if (create) fs.mkdir(path.dirname(this.filename), { recursive: true }, ondir)
80 else ondir(null)
81
82 function ondir (err) {
83 if (err) return req.callback(err)
84 fs.open(self.filename, mode, onopen)
85 }
86
87 function onopen (err, fd) {
88 if (err) return onerror(err)
89
90 self.fd = fd
91
92 if (!self._lock || !fsext) return onlock(null)
93
94 // Should we aquire a read lock?
95 const shared = self.mode === RDONLY
96
97 if (fsext.tryLock(self.fd, { shared })) onlock(null)
98 else onlock(createLockError(self.filename))
99 }
100
101 function onlock (err) {
102 if (err) return onerrorafteropen(err)
103
104 if (!self._sparse || !fsext || self.mode === RDONLY) return onsparse(null)
105
106 fsext.sparse(self.fd).then(onsparse, onsparse)
107 }
108
109 function onsparse (err) {
110 if (err) return onerrorafteropen(err)
111
112 if (self._size < 0) return ontruncate(null)
113
114 fs.ftruncate(self.fd, self._size, ontruncate)
115 }
116
117 function ontruncate (err) {
118 if (err) return onerrorafteropen(err)
119 if (self._pool !== null) self._pool._onactive(self)
120 req.callback(null)
121 }
122
123 function onerror (err) {
124 req.callback(err)
125 }
126
127 function onerrorafteropen (err) {
128 fs.close(self.fd, function () {
129 self.fd = 0
130 onerror(err)
131 })
132 }
133 }
134
135 _write (req) {
136 const data = req.data
137 const fd = this.fd
138
139 fs.write(fd, data, 0, req.size, req.offset, onwrite)
140
141 function onwrite (err, wrote) {
142 if (err) return req.callback(err)
143
144 req.size -= wrote
145 req.offset += wrote
146
147 if (!req.size) return req.callback(null)
148 fs.write(fd, data, data.length - req.size, req.size, req.offset, onwrite)
149 }
150 }
151
152 _read (req) {
153 const self = this
154 const data = req.data || this._alloc(req.size)
155 const fd = this.fd
156
157 if (!req.size) return process.nextTick(readEmpty, req)
158 fs.read(fd, data, 0, req.size, req.offset, onread)
159
160 function onread (err, read) {
161 if (err) return req.callback(err)
162 if (!read) return req.callback(createReadError(self.filename, req.offset, req.size))
163
164 req.size -= read
165 req.offset += read
166
167 if (!req.size) return req.callback(null, data)
168 fs.read(fd, data, data.length - req.size, req.size, req.offset, onread)
169 }
170 }
171
172 _del (req) {
173 if (req.size === Infinity) return this._truncate(req) // TODO: remove this when all callsites use truncate
174
175 if (!fsext) return req.callback(null)
176
177 fsext.trim(this.fd, req.offset, req.size).then(ontrim, ontrim)
178
179 function ontrim (err) {
180 req.callback(err)
181 }
182 }
183
184 _truncate (req) {
185 fs.ftruncate(this.fd, req.offset, ontruncate)
186
187 function ontruncate (err) {
188 req.callback(err)
189 }
190 }
191
192 _stat (req) {
193 fs.fstat(this.fd, onstat)
194
195 function onstat (err, st) {
196 req.callback(err, st)
197 }
198 }
199
200 _close (req) {
201 const self = this
202
203 fs.close(this.fd, onclose)
204
205 function onclose (err) {
206 if (err) return req.callback(err)
207 if (self._pool !== null) self._pool._oninactive(self)
208 self.fd = 0
209 req.callback(null)
210 }
211 }
212
213 _unlink (req) {
214 const self = this
215
216 const root = this.directory && path.resolve(path.join(this.directory, '.'))
217 let dir = path.resolve(path.dirname(this.filename))
218
219 fs.unlink(this.filename, onunlink)
220
221 function onunlink (err) {
222 // if the file isn't there, its already unlinked, ignore
223 if (err && err.code === 'ENOENT') err = null
224
225 if (err || !self._rmdir || !root || dir === root) return req.callback(err)
226 fs.rmdir(dir, onrmdir)
227 }
228
229 function onrmdir (err) {
230 dir = path.join(dir, '..')
231 if (err || dir === root) return req.callback(null)
232 fs.rmdir(dir, onrmdir)
233 }
234 }
235}
236
237function readEmpty (req) {
238 req.callback(null, Buffer.alloc(0))
239}
240
241function createLockError (path) {
242 const err = new Error('ELOCKED: File is locked')
243 err.code = 'ELOCKED'
244 err.path = path
245 return err
246}
247
248function createReadError (path, offset, size) {
249 const err = new Error('EPARTIALREAD: Could not satisfy length')
250 err.code = 'EPARTIALREAD'
251 err.path = path
252 err.offset = offset
253 err.size = size
254 return err
255}
node_modules/random-access-file/package.json +46 -0
……@@ -0,0 +1,46 @@
1{
2 "name": "random-access-file",
3 "version": "4.1.2",
4 "description": "Continuous reading or writing to a file using random offsets and lengths",
5 "main": "index.js",
6 "scripts": {
7 "test": "standard && brittle test/*.js"
8 },
9 "browser": "./browser.js",
10 "files": [
11 "index.js",
12 "browser.js"
13 ],
14 "imports": {
15 "fs": {
16 "bare": "bare-fs",
17 "default": "fs"
18 },
19 "path": {
20 "bare": "bare-path",
21 "default": "path"
22 }
23 },
24 "dependencies": {
25 "bare-fs": "^4.0.1",
26 "bare-path": "^3.0.0",
27 "random-access-storage": "^3.0.0"
28 },
29 "optionalDependencies": {
30 "fs-native-extensions": "^1.3.1"
31 },
32 "devDependencies": {
33 "brittle": "^3.3.0",
34 "standard": "^17.0.0"
35 },
36 "repository": {
37 "type": "git",
38 "url": "https://github.com/random-access-storage/random-access-file.git"
39 },
40 "author": "Mathias Buus (@mafintosh)",
41 "license": "MIT",
42 "bugs": {
43 "url": "https://github.com/random-access-storage/random-access-file/issues"
44 },
45 "homepage": "https://github.com/random-access-storage/random-access-file"
46}
node_modules/random-access-storage/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2018 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/random-access-storage/README.md +266 -0
……@@ -0,0 +1,266 @@
1# random-access-storage
2
3Easily make random-access-storage instances
4
5```
6npm install random-access-storage
7```
8
9A random-access-storage instance is a common interface for a storage abstraction, that provides the following core api.
10
11* `read(offset, size)` - Read a buffer at a custom offset.
12* `write(offset, data)` - Write a buffer to a custom offset.
13* `del(offset, size)` - Delete data at a custom offset.
14
15This module exposes a base class that implements most of the plumbing and flow you'd usually want to implement when making one.
16
17## Usage
18
19``` js
20const RandomAccessStorage = require('random-access-storage')
21const fs = require('fs')
22
23const file = fileReader('index.js')
24
25file.read(0, 10, (err, buf) => console.log('0-10: ' + buf.toString()))
26file.read(40, 15, (err, buf) => console.log('40-55: ' + buf.toString()))
27file.close()
28
29function fileReader (name) {
30 let fd = 0
31 return new RandomAccessStorage({
32 open: function (req) {
33 // called once automatically before the first read call
34 fs.open(name, 'r', function (err, res) {
35 if (err) return req.callback(err)
36 fd = res
37 req.callback(null)
38 })
39 },
40 read: function (req) {
41 const buf = Buffer.allocUnsafe(req.size)
42 fs.read(fd, buf, 0, buf.length, req.offset, function (err, read) {
43 if (err) return req.callback(err)
44 if (read < buf.length) return req.callback(new Error('Could not read'))
45 req.callback(null, buf)
46 })
47 },
48 close: function (req) {
49 if (!fd) return req.callback(null)
50 fs.close(fd, err => req.callback(err))
51 }
52 })
53}
54```
55
56## API
57
58#### `const storage = new RandomAccessStorage([options])`
59
60Make a new instance. Options include:
61
62``` js
63{
64 createAlways: false, // always create storage on first open
65 open: fn, // sets ._open
66 read: fn, // sets ._read
67 write: fn, // sets ._write
68 del: fn, // sets ._del
69 truncate: fn, // sets ._truncate
70 stat: fn, // sets ._stat
71 suspend: fn, // sets ._suspend
72 close: fn, // sets ._close
73 unlink: fn // sets ._unlink
74}
75```
76
77#### `storage.readable`
78
79True if the storage implements `._read`.
80
81#### `storage.writable`
82
83True if the storage implements `._write`.
84
85#### `storage.deletable`
86
87True if the storage implements `._del`.
88
89#### `storage.truncatable`
90
91True if the storage implements `._truncate`.
92
93#### `storage.statable`
94
95True if the storage implements `._stat`.
96
97#### `storage.opened`
98
99True if the storage has been fully opened.
100
101#### `storage.closed`
102
103True if the storage has been fully closed.
104
105#### `storage.unlinked`
106
107True if the storage has been fully unlinked.
108
109#### `storage.writing`
110
111True if the storage is currently being written to.
112
113#### `storage.on('open')`
114
115Emitted when the storage is fully open.
116
117#### `storage.on('close')`
118
119Emitted when the storage is fully closed.
120
121#### `storage.on('unlink')`
122
123Emitted when the storage is fully unlinked.
124
125#### `storage.on('suspend')`
126
127Emitted when the storage is fully suspended
128
129#### `storage.on('unsuspend')`
130
131Emitted when the storage comes out of suspension.
132
133#### `storage.open(cb)`
134
135Explicitly open the storage. If you do not call this yourself,
136it will automatically called before any read/write/del/stat operation.
137
138It is safe to call this more than once.
139
140Triggers *one* call to `_open` if you implement that.
141
142#### `storage._open(req)`
143
144Implement storage open.
145
146* `req.create` is `true` if the storage should be created.
147
148Call `req.callback` when it is fully opened.
149
150#### `storage.read(offset, size, callback)`
151
152Read the specified bytes from the storage at the specified byte offset.
153Calls the callback with a `(err, buffer)`.
154
155#### `storage._read(req)`
156
157Implement storage read.
158
159* `req.offset` contains the byte offset you should read at.
160* `req.size` contains the amount of bytes you should read.
161
162Call `req.callback(err, buffer)` when the read is completed.
163
164Note that this is guaranteed to run after the storage has been opened and not after it has been closed.
165
166#### `storage.write(offset, buffer, [callback])`
167
168Write the specified buffer to the specified byte offset. Optionally pass a callback that is called with `(err)` when the write has completed.
169
170#### `storage._write(req)`
171
172Implement storage write.
173
174* `req.offset` contains the byte offset you should write at.
175* `req.data` contains the buffer you should write.
176
177Call `req.callback(err)` when the write is completed.
178
179Note that this is guaranteed to run after the storage has been opened and not after it has been closed.
180
181#### `storage.del(offset, size, [callback])`
182
183Delete the specified amount of bytes at the specified offset. Optionally pass a callback that is called with `(err)` when the delete has completed.
184
185#### `storage._del(req)`
186
187Implement storage delete.
188
189* `req.offset` contains the byte offset to delete at.
190* `req.size` contains the amount of bytes to delete.
191
192Call `req.callback(err)` when the delete has completed.
193
194Note that this is guaranteed to run after the storage has been opened and not after it has been closed.
195
196#### `storage.truncate(offset, [callback])`
197
198Truncate the storage at the specified offset. Optionally pass a callback that is called with `(err)` when the truncate has completed.
199
200#### `storage._truncate(req)`
201
202Implement storage truncate. Defaults to `storage._del(req)`.
203
204* `req.offset` contains the byte offset to truncate at.
205
206Call `req.callback(err)` when the truncate has completed.
207
208Note that this is guaranteed to run after the storage has been opened and not after it has been closed.
209
210#### `storage.stat(callback)`
211
212Stat the storage. Should return an object with useful information about the underlying storage, including:
213
214```
215{
216 size: number // how many bytes of data is stored?
217}
218```
219
220#### `storage._stat(req)`
221
222Implement storage stat.
223
224Call `req.callback(err, statObject)` when the stat has completed.
225
226Note that this is guaranteed to run after the storage has been opened and not after it has been closed.
227
228#### `storage.suspend([callback])`
229
230Suspend (temporarily close) the storage instance.
231
232#### `storage._suspend(req)`
233
234Implement storage suspend. Defaults to calling `_close`.
235
236Optionally implement this to add a way for your storage instance to temporarily free resources.
237
238Call `req.callback(err)` when the storage has been fully suspended.
239
240#### `storage.close([callback])`
241
242Close the storage instance.
243
244#### `storage._close(req)`
245
246Implement storage close.
247
248Call `req.callback(err)` when the storage is fully closed.
249
250Note this is guaranteed to run after all pending read/write/stat/del operations has finished and no methods will run after.
251
252#### `storage.unlink([callback])`
253
254Unlink the storage instance, removing all underlying data.
255
256#### `storage._unlink(req)`
257
258Implement storage unlink.
259
260Call `req.callback(err)` when the storage has been fully unlinked.
261
262Note this is guaranteed to run after `.close()` has been called and no methods will be run after.
263
264## License
265
266MIT
node_modules/random-access-storage/index.js +333 -0
……@@ -0,0 +1,333 @@
1const EventEmitter = require('events')
2const queueTick = require('queue-tick')
3
4const NOT_READABLE = defaultImpl(new Error('Not readable'))
5const NOT_WRITABLE = defaultImpl(new Error('Not writable'))
6const NOT_DELETABLE = defaultImpl(new Error('Not deletable'))
7const NOT_STATABLE = defaultImpl(new Error('Not statable'))
8
9const DEFAULT_OPEN = defaultImpl(null)
10const DEFAULT_CLOSE = defaultImpl(null)
11const DEFAULT_UNLINK = defaultImpl(null)
12
13// NON_BLOCKING_OPS
14const READ_OP = 0
15const WRITE_OP = 1
16const DEL_OP = 2
17const TRUNCATE_OP = 3
18const STAT_OP = 4
19
20// BLOCKING_OPS
21const OPEN_OP = 5
22const SUSPEND_OP = 6
23const CLOSE_OP = 7
24const UNLINK_OP = 8
25
26module.exports = class RandomAccessStorage extends EventEmitter {
27 constructor (opts) {
28 super()
29
30 this._queued = []
31 this._pending = 0
32 this._needsOpen = true
33
34 this.opened = false
35 this.suspended = false
36 this.closed = false
37 this.unlinked = false
38 this.writing = false
39
40 if (opts) {
41 if (opts.open) this._open = opts.open
42 if (opts.read) this._read = opts.read
43 if (opts.write) this._write = opts.write
44 if (opts.del) this._del = opts.del
45 if (opts.truncate) this._truncate = opts.truncate
46 if (opts.stat) this._stat = opts.stat
47 if (opts.suspend) this._suspend = opts.suspend
48 if (opts.close) this._close = opts.close
49 if (opts.unlink) this._unlink = opts.unlink
50 }
51
52 this.readable = this._read !== RandomAccessStorage.prototype._read
53 this.writable = this._write !== RandomAccessStorage.prototype._write
54 this.deletable = this._del !== RandomAccessStorage.prototype._del
55 this.truncatable = this._truncate !== RandomAccessStorage.prototype._truncate || this.deletable
56 this.statable = this._stat !== RandomAccessStorage.prototype._stat
57 }
58
59 read (offset, size, cb) {
60 this.run(new Request(this, READ_OP, offset, size, null, cb), false)
61 }
62
63 _read (req) {
64 return NOT_READABLE(req)
65 }
66
67 write (offset, data, cb) {
68 if (!cb) cb = noop
69 this.run(new Request(this, WRITE_OP, offset, data.length, data, cb), true)
70 }
71
72 _write (req) {
73 return NOT_WRITABLE(req)
74 }
75
76 del (offset, size, cb) {
77 if (!cb) cb = noop
78 this.run(new Request(this, DEL_OP, offset, size, null, cb), true)
79 }
80
81 _del (req) {
82 return NOT_DELETABLE(req)
83 }
84
85 truncate (offset, cb) {
86 if (!cb) cb = noop
87 this.run(new Request(this, TRUNCATE_OP, offset, 0, null, cb), true)
88 }
89
90 _truncate (req) {
91 req.size = Infinity
92 this._del(req)
93 }
94
95 stat (cb) {
96 this.run(new Request(this, STAT_OP, 0, 0, null, cb), false)
97 }
98
99 _stat (req) {
100 return NOT_STATABLE(req)
101 }
102
103 open (cb) {
104 if (!cb) cb = noop
105 if (this.opened && !this._needsOpen) return nextTickCallback(cb)
106 this._needsOpen = false
107 queueAndRun(this, new Request(this, OPEN_OP, 0, 0, null, cb))
108 }
109
110 _open (req) {
111 return DEFAULT_OPEN(req)
112 }
113
114 suspend (cb) {
115 if (!cb) cb = noop
116 if (this.closed || this.suspended) return nextTickCallback(cb)
117 this._needsOpen = true
118 queueAndRun(this, new Request(this, SUSPEND_OP, 0, 0, null, cb))
119 }
120
121 _suspend (req) {
122 this._close(req)
123 }
124
125 close (cb) {
126 if (!cb) cb = noop
127 if (this.closed) return nextTickCallback(cb)
128 queueAndRun(this, new Request(this, CLOSE_OP, 0, 0, null, cb))
129 }
130
131 _close (req) {
132 return DEFAULT_CLOSE(req)
133 }
134
135 unlink (cb) {
136 if (!cb) cb = noop
137 if (!this.closed) this.close(noop)
138 queueAndRun(this, new Request(this, UNLINK_OP, 0, 0, null, cb))
139 }
140
141 _unlink (req) {
142 return DEFAULT_UNLINK(req)
143 }
144
145 run (req, writing) {
146 if (writing && !this.writing) {
147 this.writing = true
148 this._needsOpen = true
149 }
150
151 if (this._needsOpen) this.open(noop)
152 if (this._queued.length) this._queued.push(req)
153 else req._run()
154 }
155}
156
157class Request {
158 constructor (self, type, offset, size, data, cb) {
159 this.type = type
160 this.offset = offset
161 this.size = size
162 this.data = data
163 this.storage = self
164
165 this._sync = false
166 this._callback = cb
167 this._openError = null
168 }
169
170 _maybeOpenError (err) {
171 if (this.type !== OPEN_OP) return
172 const queued = this.storage._queued
173 for (let i = 1; i < queued.length; i++) {
174 const q = queued[i]
175 if (q.type === OPEN_OP) break
176 q._openError = err
177 }
178 }
179
180 _unqueue (err) {
181 const ra = this.storage
182 const queued = ra._queued
183
184 if (err) {
185 this._maybeOpenError(err)
186 } else if (this.type > 4) {
187 switch (this.type) {
188 case OPEN_OP:
189 if (ra.suspended) {
190 ra.suspended = false
191 ra.emit('unsuspend')
192 }
193 if (!ra.opened) {
194 ra.opened = true
195 ra.emit('open')
196 }
197 break
198
199 case SUSPEND_OP:
200 if (!ra.suspended) {
201 ra.suspended = true
202 ra.emit('suspend')
203 }
204 break
205
206 case CLOSE_OP:
207 if (!ra.closed) {
208 ra.closed = true
209 ra.emit('close')
210 }
211 break
212
213 case UNLINK_OP:
214 if (!ra.unlinked) {
215 ra.unlinked = true
216 ra.emit('unlink')
217 }
218 break
219 }
220 }
221
222 if (queued.length && queued[0] === this) queued.shift()
223
224 if (!--ra._pending) drainQueue(ra)
225 }
226
227 callback (err, val) {
228 if (this._sync) return nextTick(this, err, val)
229 this._unqueue(err)
230 this._callback(err, val)
231 }
232
233 _openAndNotClosed () {
234 const ra = this.storage
235 if (ra.opened && !ra.closed && !ra.suspended) return true
236 if (!ra.opened || ra.suspended) nextTick(this, this._openError || new Error('Not opened'))
237 else if (ra.closed) nextTick(this, new Error('Closed'))
238 return false
239 }
240
241 _open () {
242 const ra = this.storage
243
244 if (ra.opened && !ra.suspended) return nextTick(this, null)
245 if (ra.closed) return nextTick(this, new Error('Closed'))
246
247 ra._open(this)
248 }
249
250 _run () {
251 const ra = this.storage
252 ra._pending++
253
254 this._sync = true
255
256 switch (this.type) {
257 case READ_OP:
258 if (this._openAndNotClosed()) ra._read(this)
259 break
260
261 case WRITE_OP:
262 if (this._openAndNotClosed()) ra._write(this)
263 break
264
265 case DEL_OP:
266 if (this._openAndNotClosed()) ra._del(this)
267 break
268
269 case TRUNCATE_OP:
270 if (this._openAndNotClosed()) ra._truncate(this)
271 break
272
273 case STAT_OP:
274 if (this._openAndNotClosed()) ra._stat(this)
275 break
276
277 case OPEN_OP:
278 this._open()
279 break
280
281 case SUSPEND_OP:
282 if (ra.closed || !ra.opened || ra.suspended) nextTick(this, null)
283 else ra._suspend(this)
284 break
285
286 case CLOSE_OP:
287 if (ra.closed || !ra.opened || ra.suspended) nextTick(this, null)
288 else ra._close(this)
289 break
290
291 case UNLINK_OP:
292 if (ra.unlinked) nextTick(this, null)
293 else ra._unlink(this)
294 break
295 }
296
297 this._sync = false
298 }
299}
300
301function queueAndRun (self, req) {
302 self._queued.push(req)
303 if (!self._pending) req._run()
304}
305
306function drainQueue (self) {
307 const queued = self._queued
308
309 while (queued.length > 0) {
310 const blocking = queued[0].type > 4
311 if (!blocking || !self._pending) queued[0]._run()
312 if (blocking) return
313 queued.shift()
314 }
315}
316
317function defaultImpl (err) {
318 return overridable
319
320 function overridable (req) {
321 nextTick(req, err)
322 }
323}
324
325function nextTick (req, err, val) {
326 queueTick(() => req.callback(err, val))
327}
328
329function nextTickCallback (cb) {
330 queueTick(() => cb(null))
331}
332
333function noop () {}
node_modules/random-access-storage/package.json +36 -0
……@@ -0,0 +1,36 @@
1{
2 "name": "random-access-storage",
3 "version": "3.0.2",
4 "description": "Easily make random-access-storage instances",
5 "main": "index.js",
6 "imports": {
7 "events": {
8 "bare": "bare-events",
9 "default": "events"
10 }
11 },
12 "dependencies": {
13 "bare-events": "^2.2.0",
14 "queue-tick": "^1.0.0"
15 },
16 "devDependencies": {
17 "brittle": "^3.0.0",
18 "standard": "^17.0.0"
19 },
20 "files": [
21 "index.js"
22 ],
23 "scripts": {
24 "test": "standard && brittle test.js"
25 },
26 "repository": {
27 "type": "git",
28 "url": "https://github.com/random-access-storage/random-access-storage.git"
29 },
30 "author": "Mathias Buus (@mafintosh)",
31 "license": "MIT",
32 "bugs": {
33 "url": "https://github.com/random-access-storage/random-access-storage/issues"
34 },
35 "homepage": "https://github.com/random-access-storage/random-access-storage"
36}
node_modules/random-array-iterator/.github/workflows/test.yml +24 -0
……@@ -0,0 +1,24 @@
1name: Build Status
2
3on:
4 push:
5 branches:
6 - master
7 pull_request:
8 branches:
9 - master
10jobs:
11 build:
12 strategy:
13 matrix:
14 node-version: [10.x, 12.x, 14.x]
15 os: [ubuntu-16.04, macos-latest, windows-latest]
16 runs-on: ${{ matrix.os }}
17 steps:
18 - uses: actions/checkout@v2
19 - name: Use Node.js ${{ matrix.node-version }}
20 uses: actions/setup-node@v1
21 with:
22 node-version: ${{ matrix.node-version }}
23 - run: npm install
24 - run: npm test
node_modules/random-array-iterator/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2020 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/random-array-iterator/README.md +48 -0
……@@ -0,0 +1,48 @@
1# random-array-iterator
2
3An iterator to iterate an array in random order with controls to requeue or dequeue
4elements during the iteration.
5
6```
7npm install random-array-iterator
8```
9
10## Usage
11
12``` js
13const RandomArrayIterator = require('random-array-iterator')
14
15const ite = new RandomArrayIterator([1, 2, 3, 4, 5])
16
17for (const val of ite) {
18 console.log(val) // random value
19
20 // call requeue if you want to revisit this value is the same iteration
21 if (someCondition) ite.requeue()
22
23 // call dequeue if you want to remove the value from the iteration and array entirely
24 if (someOtherCondition) ite.dequeue()
25}
26```
27
28## API
29
30#### `ite = new RandomArrayIterator(array)`
31
32Make a new iterator. Implements the JavaScript iterator interface.
33
34#### `ite.requeue()`
35
36Requeue the current value. Only valid to call during an iteration.
37
38#### `ite.dequeue()`
39
40Remove the current value from the array and iteration. Only valid to vall during an iteration.
41
42#### `ite.restart()`
43
44Restarts the iterator.
45
46## License
47
48MIT
node_modules/random-array-iterator/index.js +46 -0
……@@ -0,0 +1,46 @@
1module.exports = class RandomArrayIterator {
2 constructor (values) {
3 this.values = values
4 this.start = 0
5 this.length = this.values.length
6 }
7
8 next () {
9 if (this.length === 0) {
10 if (this.start === 0) return { done: true, value: undefined }
11 this.length = this.start
12 this.start = 0
13 }
14
15 const i = this.start + ((Math.random() * this.length) | 0)
16 const j = this.start + --this.length
17 const value = this.values[i]
18
19 this.values[i] = this.values[j]
20 this.values[j] = value
21
22 return { done: false, value }
23 }
24
25 dequeue () {
26 this.values[this.start + this.length] = this.values[this.values.length - 1]
27 this.values.pop()
28 }
29
30 requeue () {
31 const i = this.start + this.length
32 const value = this.values[i]
33 this.values[i] = this.values[this.start]
34 this.values[this.start++] = value
35 }
36
37 restart () {
38 this.start = 0
39 this.length = this.values.length
40 return this
41 }
42
43 [Symbol.iterator] () {
44 return this
45 }
46}
node_modules/random-array-iterator/package.json +24 -0
……@@ -0,0 +1,24 @@
1{
2 "name": "random-array-iterator",
3 "version": "1.0.0",
4 "description": "An iterator to iterate an array in random order with controls to requeue or dequeue elements during the iteration",
5 "main": "index.js",
6 "dependencies": {},
7 "devDependencies": {
8 "standard": "^16.0.3",
9 "tape": "^5.0.1"
10 },
11 "scripts": {
12 "test": "standard && tape test.js"
13 },
14 "repository": {
15 "type": "git",
16 "url": "https://github.com/mafintosh/random-array-iterator.git"
17 },
18 "author": "Mathias Buus (@mafintosh)",
19 "license": "MIT",
20 "bugs": {
21 "url": "https://github.com/mafintosh/random-array-iterator/issues"
22 },
23 "homepage": "https://github.com/mafintosh/random-array-iterator"
24}
node_modules/random-array-iterator/test.js +96 -0
……@@ -0,0 +1,96 @@
1const tape = require('tape')
2const Iterator = require('./')
3
4tape('basic', function (t) {
5 let diff = 0
6
7 for (let n = 0; n < 5; n++) {
8 const values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
9 const old = values.join(',')
10
11 const cnts = {}
12 for (const i of new Iterator(values)) {
13 cnts[i] = (cnts[i] || 0) + 1
14 t.same(cnts[i], 1)
15 }
16
17 if (values.join(',') !== old) diff++
18 t.same(Object.keys(cnts).length, values.length)
19 }
20
21 t.ok(diff > 1)
22 t.end()
23})
24
25tape('requeue', function (t) {
26 const values = [1, 2, 3, 4, 5]
27
28 let requeues = 2
29
30 const cnts = {}
31 const ite = new Iterator(values)
32 for (const i of ite) {
33 if ((i === 1 || i === 3) && requeues-- > 0) {
34 ite.requeue()
35 }
36 cnts[i] = (cnts[i] || 0) + 1
37 }
38
39 t.same(cnts, {
40 1: 2,
41 2: 1,
42 3: 2,
43 4: 1,
44 5: 1
45 })
46
47 t.end()
48})
49
50tape('dequeue', function (t) {
51 const values = [1, 2, 3, 4, 5]
52
53 const ite = new Iterator(values)
54 for (const i of ite) {
55 if (i === 2 || i === 5) ite.dequeue()
56 }
57
58 t.same(values.sort(), [1, 3, 4])
59 t.end()
60})
61
62tape('dequeue all', function (t) {
63 const values = [1, 2, 3, 4, 5]
64
65 const trace = []
66 const ite = new Iterator(values)
67 for (const i of ite) {
68 ite.dequeue()
69 trace.push(i)
70 }
71
72 t.same(trace.sort(), [1, 2, 3, 4, 5])
73 t.same(values, [])
74 t.end()
75})
76
77tape('dequeue and requeue', function (t) {
78 const values = [1, 2, 3, 4, 5]
79
80 const ite = new Iterator(values)
81 const trace = []
82 let requeue = true
83
84 for (const i of ite) {
85 if (i === 2 || i === 5) ite.dequeue()
86 if (requeue && i === 3) {
87 requeue = false
88 ite.requeue()
89 }
90 trace.push(i)
91 }
92
93 t.same(values.sort(), [1, 3, 4])
94 t.same(trace.sort(), [1, 2, 3, 3, 4, 5])
95 t.end()
96})
node_modules/read-write-mutexify/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - master
6 pull_request:
7 branches:
8 - master
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v2
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v2
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/read-write-mutexify/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2023 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/read-write-mutexify/README.md +35 -0
……@@ -0,0 +1,35 @@
1# read-write-mutexify
2
3Like [mutexify](https://github.com/mafintosh/mutexify) but with read/write locks
4
5```
6npm install read-write-mutexify
7```
8
9## Usage
10
11``` js
12const RW = require('read-write-mutexify')
13
14const rw = new RW()
15
16// read locks waits for writer locks to be released
17await rw.read.lock()
18await rw.read.lock() // make as many as you want
19
20// unlock with unlock
21rw.read.unlock()
22rw.read.unlock()
23
24// only one writer can have the write lock and it waits
25// for any read lock to be released
26
27await rw.write.lock()
28
29// unlock with unlock
30rw.write.unlock()
31```
32
33## License
34
35MIT
node_modules/read-write-mutexify/index.js +134 -0
……@@ -0,0 +1,134 @@
1class WriteLock {
2 constructor (parent) {
3 this.writing = false
4
5 this._waiting = []
6 this._parent = parent
7 this._wait = pushToQueue.bind(this, this._waiting)
8 }
9
10 get locked () {
11 return this.writing || this._parent.read.readers > 0
12 }
13
14 get waiting () {
15 return this._waiting.length
16 }
17
18 lock () {
19 if (this._parent._destroying) {
20 return Promise.reject(this._parent._destroyError)
21 }
22
23 if (this.writing === false && this._parent.read.readers === 0) {
24 this.writing = true
25 return Promise.resolve()
26 }
27
28 return new Promise(this._wait)
29 }
30
31 unlock () {
32 this.writing = false
33 this._parent._bump()
34 }
35
36 async flush () {
37 if (this.writing === false) return
38 try {
39 await this.lock()
40 } catch {
41 return
42 }
43 this.unlock()
44 }
45}
46
47class ReadLock {
48 constructor (parent) {
49 this.readers = 0
50
51 this._waiting = []
52 this._parent = parent
53 this._wait = pushToQueue.bind(this, this._waiting)
54 }
55
56 get locked () {
57 return this._parent.writing
58 }
59
60 get waiting () {
61 return this._waiting.length
62 }
63
64 lock () {
65 if (this._parent._destroying) {
66 return Promise.reject(this._parent._destroyError)
67 }
68
69 if (this._parent.write.writing === false) {
70 this.readers++
71 return Promise.resolve()
72 }
73
74 return new Promise(this._wait)
75 }
76
77 unlock () {
78 this.readers--
79 this._parent._bump()
80 }
81
82 async flush () {
83 if (this.writing === false) return
84 try {
85 await this.lock()
86 } catch {
87 return
88 }
89 this.unlock()
90 }
91}
92
93module.exports = class ReadWriteLock {
94 constructor () {
95 this.read = new ReadLock(this)
96 this.write = new WriteLock(this)
97
98 this._destroyError = null
99 this._destroying = null
100 }
101
102 get destroyed () {
103 return !!this._destroying
104 }
105
106 destroy (err) {
107 if (this._destroying) return this._destroying
108
109 this._destroying = Promise.all([this.read.flush(), this.write.flush()])
110 this._destroyError = err || new Error('Mutex has been destroyed')
111
112 if (err) {
113 while (this.read._waiting) this._waiting.shift()[1](err)
114 while (this.write._waiting) this._waiting.shift()[1](err)
115 }
116
117 return this._destroying
118 }
119
120 _bump () {
121 if (this.write.writing === false && this.read.readers === 0 && this.write._waiting.length > 0) {
122 this.write.writing = true
123 this.write._waiting.shift()[0]()
124 }
125 while (this.write.writing === false && this.read._waiting.length > 0) {
126 this.read.readers++
127 this.read._waiting.shift()[0]()
128 }
129 }
130}
131
132function pushToQueue (queue, resolve, reject) {
133 queue.push([resolve, reject])
134}
node_modules/read-write-mutexify/package.json +23 -0
……@@ -0,0 +1,23 @@
1{
2 "name": "read-write-mutexify",
3 "version": "2.1.0",
4 "description": "Like mutexify but with read/write locks",
5 "main": "index.js",
6 "scripts": {
7 "test": "standard && brittle test.js"
8 },
9 "devDependencies": {
10 "brittle": "^3.3.0",
11 "standard": "^17.1.0"
12 },
13 "repository": {
14 "type": "git",
15 "url": "https://github.com/mafintosh/read-write-mutexify.git"
16 },
17 "author": "Mathias Buus (@mafintosh)",
18 "license": "MIT",
19 "bugs": {
20 "url": "https://github.com/mafintosh/read-write-mutexify/issues"
21 },
22 "homepage": "https://github.com/mafintosh/read-write-mutexify"
23}
node_modules/read-write-mutexify/test.js +73 -0
……@@ -0,0 +1,73 @@
1const test = require('brittle')
2const RW = require('./')
3
4test('as many reads as you want', async function (t) {
5 const rw = new RW()
6
7 await rw.read.lock()
8 await rw.read.lock()
9
10 t.pass('didnt dead lock')
11
12 rw.read.unlock()
13 rw.read.unlock()
14})
15
16test('only one read at the time', async function (t) {
17 t.plan(1)
18
19 const rw = new RW()
20
21 let released = false
22 await rw.write.lock()
23
24 rw.write.lock().then(() => {
25 t.ok(released, 'only one writer active')
26 })
27
28 await new Promise(resolve => setImmediate(resolve))
29
30 rw.write.unlock()
31 released = true
32})
33
34test('reads waits for writer', async function (t) {
35 t.plan(1)
36
37 const rw = new RW()
38
39 let released = false
40 await rw.write.lock()
41
42 rw.read.lock().then(() => {
43 t.ok(released, 'read waited for writer')
44 })
45
46 await new Promise(resolve => setImmediate(resolve))
47
48 rw.write.unlock()
49 released = true
50})
51
52test('writer waits for all reads', async function (t) {
53 t.plan(1)
54
55 const rw = new RW()
56
57 let released = false
58 await rw.read.lock()
59 await rw.read.lock()
60
61 rw.write.lock().then(() => {
62 t.ok(released, 'write waited for all readers')
63 })
64
65 await new Promise(resolve => setImmediate(resolve))
66
67 rw.read.unlock()
68
69 await new Promise(resolve => setImmediate(resolve))
70
71 rw.read.unlock()
72 released = true
73})
node_modules/ready-resource/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2022 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/ready-resource/README.md +39 -0
……@@ -0,0 +1,39 @@
1# ready-resource
2
3Modern single resource management
4
5```
6npm install ready-resource
7```
8
9## Usage
10
11``` js
12const ReadyResource = require('ready-resource')
13
14class Thing extends ReadyResource {
15 constructor () {
16 super()
17 }
18
19 async _open () {
20 // open the resource
21 }
22
23 async _close () {
24 // close the resource
25 }
26}
27
28const r = new Thing()
29
30await r.ready() // calls _open once
31await r.ready() // noop
32
33await r.close() // calls _close after _open has finished
34await r.close() // noop
35```
36
37## License
38
39MIT
node_modules/ready-resource/index.d.ts +53 -0
……@@ -0,0 +1,53 @@
1declare module 'ready-resource' {
2 import { EventEmitter } from 'events';
3
4 /**
5 * Runtime export is CommonJS:
6 * module.exports = class ReadyResource extends EventEmitter {}
7 * This declaration mirrors that shape.
8 */
9 class ReadyResource extends EventEmitter {
10 constructor();
11
12 /** Set when a call to ready() has started; resolves when _open completes */
13 opening: Promise<void> | null;
14
15 /** Set when a call to close() has started; resolves when _close completes */
16 closing: Promise<void> | null;
17
18 /** True after successful _open */
19 opened: boolean;
20
21 /** True after successful _close (or attempted close after failed open) */
22 closed: boolean;
23
24 /** Ensure the resource is opened; returns the in-flight promise if any */
25 ready(): Promise<void>;
26
27 /** Ensure the resource is closed; returns the in-flight promise if any */
28 close(): Promise<void>;
29
30 /** Override these in subclasses */
31 protected _open(): Promise<void>;
32 protected _close(): Promise<void>;
33
34 // Typed events emitted by the implementation
35 on(event: 'ready', listener: () => void): this;
36 on(event: 'close', listener: () => void): this;
37 once(event: 'ready', listener: () => void): this;
38 once(event: 'close', listener: () => void): this;
39 off(event: 'ready', listener: () => void): this;
40 off(event: 'close', listener: () => void): this;
41 emit(event: 'ready'): boolean;
42 emit(event: 'close'): boolean;
43
44 // Fallback EventEmitter overloads
45 on(event: string | symbol, listener: (...args: any[]) => void): this;
46 once(event: string | symbol, listener: (...args: any[]) => void): this;
47 off(event: string | symbol, listener: (...args: any[]) => void): this;
48 emit(event: string | symbol, ...args: any[]): boolean;
49 }
50
51 // Match CommonJS runtime export
52 export = ReadyResource;
53}
node_modules/ready-resource/index.js +59 -0
……@@ -0,0 +1,59 @@
1const EventEmitter = require('events')
2
3module.exports = class ReadyResource extends EventEmitter {
4 constructor () {
5 super()
6
7 this.opening = null
8 this.closing = null
9
10 this.opened = false
11 this.closed = false
12 }
13
14 ready () {
15 if (this.opening !== null) return this.opening
16 this.opening = open(this)
17 return this.opening
18 }
19
20 close () {
21 if (this.closing !== null) return this.closing
22 this.closing = close(this)
23 return this.closing
24 }
25
26 async _open () {
27 // add impl here
28 }
29
30 async _close () {
31 // add impl here
32 }
33}
34
35async function open (self) {
36 // open after close
37 if (self.closing !== null) return
38
39 try {
40 await self._open()
41 } catch (err) {
42 self.close() // safe to run in bg
43 throw err
44 }
45
46 self.opened = true
47 self.emit('ready')
48}
49
50async function close (self) {
51 try {
52 if (self.opened === false && self.opening !== null) await self.opening
53 } catch {
54 // ignore errors on closing
55 }
56 if (self.opened === true || self.opening === null) await self._close()
57 self.closed = true
58 self.emit('close')
59}
node_modules/ready-resource/package.json +37 -0
……@@ -0,0 +1,37 @@
1{
2 "name": "ready-resource",
3 "version": "1.2.0",
4 "description": "Modern single resource management",
5 "main": "index.js",
6 "imports": {
7 "events": {
8 "bare": "bare-events",
9 "default": "events"
10 }
11 },
12 "types": "index.d.ts",
13 "files": [
14 "index.js",
15 "index.d.ts"
16 ],
17 "scripts": {
18 "test": "standard && brittle test.js"
19 },
20 "devDependencies": {
21 "brittle": "^3.1.0",
22 "standard": "^17.0.0"
23 },
24 "repository": {
25 "type": "git",
26 "url": "git+https://github.com/holepunchto/ready-resource.git"
27 },
28 "author": "Mathias Buus (@mafintosh)",
29 "license": "MIT",
30 "bugs": {
31 "url": "https://github.com/holepunchto/ready-resource/issues"
32 },
33 "homepage": "https://github.com/holepunchto/ready-resource",
34 "dependencies": {
35 "bare-events": "^2.2.0"
36 }
37}
node_modules/refcounter/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/refcounter/NOTICE +13 -0
……@@ -0,0 +1,13 @@
1Copyright 2023 Holepunch Inc
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
node_modules/refcounter/README.md +25 -0
……@@ -0,0 +1,25 @@
1# refcounter
2
3Simple refcounter
4
5```
6npm install refcounter
7```
8
9## Usage
10
11``` js
12const RefCounter = require('refcounter')
13
14const refs = new RefCounter()
15
16refs.inc()
17refs.dec()
18
19refs.isIdle() // true is no refs
20await refs.idle() // wait for no refs
21```
22
23## License
24
25Apache-2.0
node_modules/refcounter/index.js +38 -0
……@@ -0,0 +1,38 @@
1module.exports = class RefCounter {
2 constructor() {
3 this.count = 0
4
5 this._onidle = null
6 this._idle = null
7 }
8
9 isIdle() {
10 return this.count === 0
11 }
12
13 idle() {
14 if (this.count === 0) return Promise.resolve()
15 if (this._idle !== null) return this._idle
16
17 this._idle = new Promise((resolve) => {
18 this._onidle = resolve
19 })
20
21 return this._idle
22 }
23
24 inc() {
25 this.count++
26 }
27
28 dec() {
29 if (--this.count > 0) return
30
31 if (this._onidle !== null) {
32 const resolve = this._onidle
33 this._idle = null
34 this._onidle = null
35 resolve()
36 }
37 }
38}
node_modules/refcounter/package.json +18 -0
……@@ -0,0 +1,18 @@
1{
2 "name": "refcounter",
3 "version": "1.0.0",
4 "description": "Simple refcounter",
5 "main": "index.js",
6 "dependencies": {},
7 "devDependencies": {},
8 "repository": {
9 "type": "git",
10 "url": "https://github.com/holepunchto/refcounter.git"
11 },
12 "author": "Holepunch Inc",
13 "license": "Apache-2.0",
14 "bugs": {
15 "url": "https://github.com/holepunchto/refcounter/issues"
16 },
17 "homepage": "https://github.com/holepunchto/refcounter"
18}
node_modules/require-addon/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/require-addon/README.md +19 -0
……@@ -0,0 +1,19 @@
1# require-addon
2
3Import native addons across JavaScript runtimes.
4
5```
6npm i require-addon
7```
8
9## Usage
10
11```js
12require.addon = require('require-addon')
13
14const bindings = require.addon('.', __filename)
15```
16
17## License
18
19Apache-2.0
node_modules/require-addon/lib/bare.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require.addon.bind(require)
node_modules/require-addon/lib/default.js +7 -0
……@@ -0,0 +1,7 @@
1if (typeof require.addon === 'function') {
2 module.exports = require.addon.bind(require)
3} else {
4 module.exports = function addon(specifier, parentURL) {
5 throw new Error(`Cannot find addon '${specifier}' imported from '${parentURL}'`)
6 }
7}
node_modules/require-addon/lib/node.js +71 -0
……@@ -0,0 +1,71 @@
1if (typeof require.addon === 'function') {
2 module.exports = require.addon.bind(require)
3} else {
4 const url = require('url')
5 const fs = require('fs')
6 const resolve = require('bare-addon-resolve')
7
8 let host = process.platform + '-' + process.arch
9 const conditions = ['addon', 'node', process.platform, process.arch]
10 const extensions = ['.node']
11
12 if (isAlpine()) {
13 host += '-musl'
14 conditions.push('musl')
15 }
16
17 module.exports = function addon(specifier, parentURL) {
18 if (typeof parentURL === 'string') parentURL = url.pathToFileURL(parentURL)
19
20 const candidates = []
21
22 let cause
23
24 for (const resolution of resolve(
25 specifier,
26 parentURL,
27 { host, conditions, extensions },
28 readPackage
29 )) {
30 candidates.push(resolution)
31
32 switch (resolution.protocol) {
33 case 'file:':
34 try {
35 return require(url.fileURLToPath(resolution))
36 } catch (err) {
37 cause = err
38 continue
39 }
40 }
41 }
42
43 let message = `Cannot find addon '${specifier}' imported from '${parentURL.href}'`
44
45 if (candidates.length > 0) {
46 message += '\nCandidates:'
47 message += '\n' + candidates.map((url) => '- ' + url.href).join('\n')
48 }
49
50 const err = new Error(message, cause ? { cause } : {})
51
52 err.code = 'ADDON_NOT_FOUND'
53 err.specifier = specifier
54 err.referrer = parentURL
55 err.candidates = candidates
56
57 throw err
58 }
59
60 function readPackage(packageURL) {
61 try {
62 return require(url.fileURLToPath(packageURL))
63 } catch (err) {
64 return null
65 }
66 }
67
68 function isAlpine() {
69 return process.platform === 'linux' && fs.existsSync('/etc/alpine-release')
70 }
71}
node_modules/require-addon/package.json +63 -0
……@@ -0,0 +1,63 @@
1{
2 "name": "require-addon",
3 "version": "1.2.0",
4 "description": "Import native addons across JavaScript runtimes",
5 "exports": {
6 "./package": "./package.json",
7 ".": {
8 "bare": "./lib/bare.js",
9 "node": "./lib/node.js",
10 "default": "./lib/default.js"
11 }
12 },
13 "imports": {
14 "fs": {
15 "bare": "bare-fs",
16 "default": "fs"
17 },
18 "path": {
19 "bare": "bare-path",
20 "default": "path"
21 },
22 "url": {
23 "bare": "bare-url",
24 "default": "url"
25 }
26 },
27 "files": [
28 "lib"
29 ],
30 "scripts": {
31 "test": "npm run lint && npm run test:bare && npm run test:node",
32 "test:bare": "bare test.js",
33 "test:node": "node test.js",
34 "lint": "prettier --check .",
35 "format": "prettier --write ."
36 },
37 "repository": {
38 "type": "git",
39 "url": "git+https://github.com/holepunchto/require-addon.git"
40 },
41 "author": "Holepunch",
42 "license": "Apache-2.0",
43 "bugs": {
44 "url": "https://github.com/holepunchto/require-addon/issues"
45 },
46 "homepage": "https://github.com/holepunchto/require-addon#readme",
47 "engines": {
48 "bare": ">=1.10.0"
49 },
50 "dependencies": {
51 "bare-addon-resolve": "^1.3.0"
52 },
53 "devDependencies": {
54 "bare-bundle": "^1.8.1",
55 "bare-bundle-evaluate": "^1.1.0",
56 "bare-fs": "^4.0.0",
57 "bare-path": "^3.0.0",
58 "bare-url": "^2.1.0",
59 "brittle": "^3.7.0",
60 "prettier": "^3.6.2",
61 "prettier-config-holepunch": "^2.0.0"
62 }
63}
node_modules/resolve-reject-promise/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - main
6 pull_request:
7 branches:
8 - main
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v3
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v3
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/resolve-reject-promise/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2024 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/resolve-reject-promise/README.md +19 -0
……@@ -0,0 +1,19 @@
1# resolve-reject-promise
2
3Create an inverted promise with no function allocs
4
5```
6npm install resolve-reject-promise
7```
8
9## Usage
10
11``` js
12const rrp = require('resolve-reject-promise')
13
14const { resolve, reject, promise } = rrp()
15```
16
17## License
18
19MIT
node_modules/resolve-reject-promise/index.js +18 -0
……@@ -0,0 +1,18 @@
1let tmpResolve = null
2let tmpReject = null
3
4if (Promise.withResolvers) {
5 module.exports = Promise.withResolvers.bind(Promise)
6} else {
7 module.exports = function resolveRejectPromise () {
8 const promise = new Promise(setTmp)
9 const result = { promise, resolve: tmpResolve, reject: tmpReject }
10 tmpResolve = tmpReject = null
11 return result
12 }
13}
14
15function setTmp (resolve, reject) {
16 tmpResolve = resolve
17 tmpReject = reject
18}
node_modules/resolve-reject-promise/package.json +22 -0
……@@ -0,0 +1,22 @@
1{
2 "name": "resolve-reject-promise",
3 "version": "1.1.0",
4 "description": "Create an inverted promise with no function allocs",
5 "main": "index.js",
6 "scripts": {
7 "test": "standard"
8 },
9 "devDependencies": {
10 "standard": "^17.1.2"
11 },
12 "repository": {
13 "type": "git",
14 "url": "https://github.com/mafintosh/resolve-reject-promise.git"
15 },
16 "author": "Mathias Buus (@mafintosh)",
17 "license": "MIT",
18 "bugs": {
19 "url": "https://github.com/mafintosh/resolve-reject-promise/issues"
20 },
21 "homepage": "https://github.com/mafintosh/resolve-reject-promise"
22}
node_modules/rocksdb-native/CMakeLists.txt +63 -0
……@@ -0,0 +1,63 @@
1cmake_minimum_required(VERSION 4.0)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6find_package(cmake-npm REQUIRED PATHS node_modules/cmake-npm)
7
8project(rocksdb_native C CXX)
9
10bare_target(target)
11
12fetch_package("github:holepunchto/librocksdb#efb0607")
13fetch_package("github:holepunchto/libjstl#387f6d0")
14
15add_bare_module(rocksdb_native_bare)
16
17target_sources(
18 ${rocksdb_native_bare}
19 PRIVATE
20 binding.cc
21)
22
23target_link_libraries(
24 ${rocksdb_native_bare}
25 PRIVATE
26 $<TARGET_OBJECTS:rocksdb>
27 jstl
28 PUBLIC
29 rocksdb
30 rocksdb_facebook
31)
32
33add_napi_module(rocksdb_native_napi)
34
35target_sources(
36 ${rocksdb_native_napi}
37 PRIVATE
38 binding.cc
39)
40
41target_compile_definitions(
42 ${rocksdb_native_napi}
43 PRIVATE
44 NAPI_VERSION=9
45)
46
47target_link_libraries(
48 ${rocksdb_native_napi}
49 PRIVATE
50 $<TARGET_OBJECTS:rocksdb>
51 jstl
52 PUBLIC
53 rocksdb
54 rocksdb_facebook
55)
56
57resolve_node_module(bare-compat-napi compat)
58
59target_include_directories(
60 ${rocksdb_native_napi}
61 PRIVATE
62 "${compat}/include"
63)
node_modules/rocksdb-native/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/rocksdb-native/README.md +32 -0
……@@ -0,0 +1,32 @@
1# rocksdb-native
2
3<https://github.com/holepunchto/librocksdb> bindings for JavaScript.
4
5```
6npm i rocksdb-native
7```
8
9> [!IMPORTANT]
10> On Linux `libatomic` must be installed as well.
11
12## Usage
13
14```js
15const RocksDB = require('rocksdb-native')
16
17const db = new RocksDB('./example.db')
18
19const w = db.write()
20w.put('hello', 'world')
21await w.flush()
22
23const r = db.read()
24const p = r.get('hello')
25r.flush()
26
27console.log(await p)
28```
29
30## License
31
32Apache-2.0
node_modules/rocksdb-native/binding.cc +1869 -0
……@@ -0,0 +1,1869 @@
1#include <set>
2
3#include <assert.h>
4#include <bare.h>
5#include <js.h>
6#include <jstl.h>
7#include <rocksdb.h>
8#include <stdlib.h>
9#include <string.h>
10#include <utf.h>
11#include <uv.h>
12
13using rocksdb_native_on_open_t = js_function_t<void, js_receiver_t, std::optional<js_object_t>>;
14using rocksdb_native_on_close_t = js_function_t<void, js_receiver_t>;
15using rocksdb_native_on_suspend_t = js_function_t<void, js_receiver_t, std::optional<js_object_t>>;
16using rocksdb_native_on_resume_t = js_function_t<void, js_receiver_t, std::optional<js_object_t>>;
17using rocksdb_native_on_flush_t = js_function_t<void, js_receiver_t, std::optional<js_object_t>>;
18using rocksdb_native_on_write_t = js_function_t<void, js_receiver_t, std::optional<js_object_t>>;
19using rocksdb_native_on_read_t = js_function_t<void, js_receiver_t, js_array_t, js_array_t>;
20using rocksdb_native_on_iterator_open_t = js_function_t<void, js_receiver_t, std::optional<js_object_t>>;
21using rocksdb_native_on_iterator_close_t = js_function_t<void, js_receiver_t, std::optional<js_object_t>>;
22using rocksdb_native_on_iterator_read_t = js_function_t<void, js_receiver_t, std::optional<js_object_t>, js_array_t, js_array_t>;
23using rocksdb_native_on_compact_range_t = js_function_t<void, js_receiver_t, std::optional<js_object_t>>;
24using rocksdb_native_on_approximate_size_t = js_function_t<void, js_receiver_t, std::optional<js_object_t>, uint64_t>;
25
26struct rocksdb_native_t;
27
28struct rocksdb_native_column_family_t {
29 rocksdb_column_family_t *handle;
30 rocksdb_column_family_descriptor_t descriptor;
31
32 rocksdb_native_t *db;
33
34 js_persistent_t<js_arraybuffer_t> ctx;
35};
36
37struct rocksdb_native_snapshot_t {
38 rocksdb_snapshot_t handle;
39
40 rocksdb_native_t *db;
41
42 js_persistent_t<js_arraybuffer_t> ctx;
43};
44
45struct rocksdb_native_t {
46 rocksdb_t handle;
47 rocksdb_options_t options;
48
49 js_env_t *env;
50 js_persistent_t<js_receiver_t> ctx;
51
52 bool closing;
53 bool exiting;
54
55 std::set<rocksdb_native_column_family_t *> column_families;
56 std::set<rocksdb_native_snapshot_t *> snapshots;
57
58 js_deferred_teardown_t *teardown;
59};
60
61struct rocksdb_native_open_t {
62 rocksdb_open_t handle;
63
64 js_env_t *env;
65 js_persistent_t<js_receiver_t> ctx;
66 js_persistent_t<rocksdb_native_on_open_t> on_open;
67
68 js_persistent_t<js_array_t> column_families;
69};
70
71struct rocksdb_native_close_t {
72 rocksdb_close_t handle;
73
74 js_env_t *env;
75 js_persistent_t<js_receiver_t> ctx;
76 js_persistent_t<rocksdb_native_on_close_t> on_close;
77};
78
79struct rocksdb_native_suspend_t {
80 rocksdb_suspend_t handle;
81
82 js_env_t *env;
83 js_persistent_t<js_receiver_t> ctx;
84 js_persistent_t<rocksdb_native_on_suspend_t> on_suspend;
85};
86
87struct rocksdb_native_resume_t {
88 rocksdb_resume_t handle;
89
90 js_env_t *env;
91 js_persistent_t<js_receiver_t> ctx;
92 js_persistent_t<rocksdb_native_on_resume_t> on_resume;
93};
94
95struct rocksdb_native_iterator_t {
96 rocksdb_iterator_t handle;
97
98 rocksdb_slice_t *keys;
99 rocksdb_slice_t *values;
100
101 js_env_t *env;
102 js_persistent_t<js_receiver_t> ctx;
103 js_persistent_t<rocksdb_native_on_iterator_open_t> on_open;
104 js_persistent_t<rocksdb_native_on_iterator_close_t> on_close;
105 js_persistent_t<rocksdb_native_on_iterator_read_t> on_read;
106
107 bool closing;
108 bool exiting;
109
110 js_deferred_teardown_t *teardown;
111};
112
113struct rocksdb_native_read_batch_t {
114 rocksdb_read_batch_t handle;
115
116 rocksdb_read_t *reads;
117
118 size_t capacity;
119
120 js_env_t *env;
121 js_persistent_t<js_receiver_t> ctx;
122 js_persistent_t<rocksdb_native_on_read_t> on_read;
123};
124
125struct rocksdb_native_write_batch_t {
126 rocksdb_write_batch_t handle;
127
128 rocksdb_write_t *writes;
129
130 size_t capacity;
131
132 js_env_t *env;
133 js_persistent_t<js_receiver_t> ctx;
134 js_persistent_t<rocksdb_native_on_write_t> on_write;
135};
136
137struct rocksdb_native_flush_t {
138 rocksdb_flush_t handle;
139
140 js_env_t *env;
141 js_persistent_t<js_receiver_t> ctx;
142 js_persistent_t<rocksdb_native_on_flush_t> on_flush;
143
144 js_persistent_t<rocksdb_native_column_family_t> column_family;
145};
146
147struct rocksdb_native_compact_range_t {
148 rocksdb_compact_range_t handle;
149
150 js_env_t *env;
151 js_persistent_t<js_receiver_t> ctx;
152 js_persistent_t<rocksdb_native_on_compact_range_t> on_compact_range;
153};
154
155struct rocksdb_native_approximate_size_t {
156 rocksdb_approximate_size_t handle;
157
158 js_env_t *env;
159 js_persistent_t<js_receiver_t> ctx;
160 js_persistent_t<rocksdb_native_on_approximate_size_t> on_approximate_size;
161};
162
163static void
164rocksdb_native__on_free(js_env_t *env, char *data) {
165 free(data);
166}
167
168static int
169rocksdb_native__try_create_external_arraybuffer(js_env_t *env, char *data, size_t len, js_arraybuffer_t &result) {
170 int err;
171
172 err = js_create_external_arraybuffer<rocksdb_native__on_free>(env, data, len, result);
173 if (err == 0) return 0;
174
175 err = js_create_arraybuffer(env, data, len, result);
176 assert(err == 0);
177
178 free(data);
179
180 return 0;
181}
182
183static void
184rocksdb_native__on_open(rocksdb_open_t *handle, int status) {
185 int err;
186
187 assert(status == 0);
188
189 auto req = reinterpret_cast<rocksdb_native_open_t *>(handle->data);
190
191 auto db = reinterpret_cast<rocksdb_native_t *>(req->handle.req.db);
192
193 auto env = req->env;
194
195 auto descriptors = handle->column_families;
196 auto handles = handle->handles;
197
198 js_handle_scope_t *scope;
199 err = js_open_handle_scope(env, &scope);
200 assert(err == 0);
201
202 js_receiver_t ctx;
203 err = js_get_reference_value(env, req->ctx, ctx);
204 assert(err == 0);
205
206 rocksdb_native_on_open_t cb;
207 err = js_get_reference_value(env, req->on_open, cb);
208 assert(err == 0);
209
210 js_array_t column_families;
211 err = js_get_reference_value(env, req->column_families, column_families);
212 assert(err == 0);
213
214 req->on_open.reset();
215 req->column_families.reset();
216 req->ctx.reset();
217
218 std::optional<js_object_t> error;
219
220 if (req->handle.error) {
221 err = js_create_error(env, uv_err_name(req->handle.status), req->handle.error, error.emplace());
222 assert(err == 0);
223 } else {
224 std::vector<js_arraybuffer_t> elements;
225 err = js_get_array_elements(env, column_families, elements);
226 assert(err == 0);
227
228 const auto len = elements.size();
229
230 for (uint32_t i = 0; i < len; i++) {
231 if (db->exiting) rocksdb_column_family_destroy(&db->handle, handles[i]);
232 else {
233 js_arraybuffer_t handle = elements[i];
234
235 rocksdb_native_column_family_t *column_family;
236 err = js_get_arraybuffer_info(env, handle, column_family);
237 assert(err == 0);
238
239 column_family->handle = handles[i];
240
241 err = js_create_reference(env, handle, column_family->ctx);
242 assert(err == 0);
243
244 db->column_families.insert(column_family);
245 }
246 }
247 }
248
249 if (!db->exiting) {
250 err = js_call_function_with_checkpoint(env, cb, ctx, error);
251 (void) err;
252 }
253
254 err = js_close_handle_scope(env, scope);
255 assert(err == 0);
256
257 delete[] descriptors;
258 delete[] handles;
259}
260
261static void
262rocksdb_native__on_idle(rocksdb_t *handle) {
263 int err;
264
265 auto db = reinterpret_cast<rocksdb_native_t *>(handle);
266
267 for (auto &column_family : db->column_families) {
268 err = rocksdb_column_family_destroy(&column_family->db->handle, column_family->handle);
269 assert(err == 0);
270
271 column_family->handle = nullptr;
272
273 column_family->ctx.reset();
274 }
275
276 for (auto &snapshot : db->snapshots) {
277 rocksdb_snapshot_destroy(&snapshot->handle);
278
279 snapshot->ctx.reset();
280 }
281
282 db->column_families.~set();
283 db->snapshots.~set();
284}
285
286static void
287rocksdb_native__on_close(rocksdb_close_t *handle, int status) {
288 int err;
289
290 assert(status == 0);
291
292 auto req = reinterpret_cast<rocksdb_native_close_t *>(handle->data);
293
294 auto db = reinterpret_cast<rocksdb_native_t *>(req->handle.req.db);
295
296 auto env = req->env;
297
298 auto teardown = db->teardown;
299
300 if (db->closing) {
301 js_handle_scope_t *scope;
302 err = js_open_handle_scope(env, &scope);
303 assert(err == 0);
304
305 js_receiver_t ctx;
306 err = js_get_reference_value(env, req->ctx, ctx);
307 assert(err == 0);
308
309 rocksdb_native_on_close_t cb;
310 err = js_get_reference_value(env, req->on_close, cb);
311 assert(err == 0);
312
313 req->on_close.reset();
314 req->ctx.reset();
315
316 if (!db->exiting) {
317 err = js_call_function_with_checkpoint(env, cb, ctx);
318 (void) err;
319 }
320
321 err = js_close_handle_scope(env, scope);
322 assert(err == 0);
323 } else {
324 delete req;
325 }
326
327 db->ctx.reset();
328
329 err = js_finish_deferred_teardown_callback(teardown);
330 assert(err == 0);
331}
332
333static void
334rocksdb_native__on_teardown(js_deferred_teardown_t *teardown, void *data) {
335 int err;
336
337 auto db = reinterpret_cast<rocksdb_native_t *>(data);
338
339 db->exiting = true;
340
341 if (db->closing) return;
342
343 auto env = db->env;
344
345 auto req = new rocksdb_native_close_t();
346
347 req->env = env;
348 req->handle.data = req;
349
350 err = rocksdb_close(&db->handle, &req->handle, rocksdb_native__on_idle, rocksdb_native__on_close);
351 assert(err == 0);
352}
353
354static js_arraybuffer_t
355rocksdb_native_init(
356 js_env_t *env,
357 bool read_only,
358 bool create_if_missing,
359 bool create_missing_column_families,
360 int32_t max_background_jobs,
361 uint64_t bytes_per_sync,
362 int32_t max_open_files,
363 bool use_direct_reads,
364 bool avoid_unnecessary_blocking_io,
365 bool skip_stats_update_on_db_open,
366 bool use_direct_io_for_flush_and_compaction,
367 int32_t max_file_opening_threads,
368 uint32_t wal_recovery_mode,
369 bool best_efforts_recovery
370) {
371 int err;
372
373 js_arraybuffer_t handle;
374
375 rocksdb_native_t *db;
376 err = js_create_arraybuffer(env, db, handle);
377 assert(err == 0);
378
379 db->env = env;
380 db->closing = false;
381 db->exiting = false;
382
383 new (&db->column_families) std::set<rocksdb_native_column_family_t *>();
384 new (&db->snapshots) std::set<rocksdb_native_snapshot_t *>();
385
386 db->options = (rocksdb_options_t) {
387 5,
388 read_only,
389 create_if_missing,
390 create_missing_column_families,
391 max_background_jobs,
392 bytes_per_sync,
393 max_open_files,
394 use_direct_reads,
395 avoid_unnecessary_blocking_io,
396 skip_stats_update_on_db_open,
397 use_direct_io_for_flush_and_compaction,
398 max_file_opening_threads,
399 -1,
400 rocksdb_wal_recovery_mode_t(wal_recovery_mode),
401 best_efforts_recovery,
402 };
403
404 return handle;
405}
406
407static js_arraybuffer_t
408rocksdb_native_open(
409 js_env_t *env,
410 js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
411 js_receiver_t self,
412 char *path,
413 js_array_t column_families_array,
414 int lock,
415 js_receiver_t ctx,
416 rocksdb_native_on_open_t on_open
417) {
418 int err;
419
420 std::vector<js_arraybuffer_t> elements;
421 err = js_get_array_elements(env, column_families_array, elements);
422 assert(err == 0);
423
424 const auto len = elements.size();
425
426 auto column_families = new rocksdb_column_family_descriptor_t[len];
427
428 for (uint32_t i = 0; i < len; i++) {
429 js_arraybuffer_t handle = elements[i];
430
431 rocksdb_native_column_family_t *column_family;
432 err = js_get_arraybuffer_info(env, handle, column_family);
433 assert(err == 0);
434
435 memcpy(&column_families[i], &column_family->descriptor, sizeof(rocksdb_column_family_descriptor_t));
436
437 column_family->db = db;
438 }
439
440 auto handles = new rocksdb_column_family_t *[len];
441
442 uv_loop_t *loop;
443 err = js_get_env_loop(env, &loop);
444 assert(err == 0);
445
446 js_arraybuffer_t handle;
447
448 rocksdb_native_open_t *req;
449 err = js_create_arraybuffer(env, req, handle);
450 assert(err == 0);
451
452 req->env = env;
453 req->handle.data = req;
454
455 db->options.lock = lock;
456
457 err = rocksdb_open(loop, &db->handle, &req->handle, path, &db->options, column_families, handles, len, nullptr, rocksdb_native__on_open);
458
459 if (err < 0) {
460 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
461 assert(err == 0);
462
463 if (lock >= 0) {
464 uv_fs_t fs;
465 err = uv_fs_close(NULL, &fs, lock, NULL);
466 assert(err == 0);
467 }
468
469 throw js_pending_exception;
470 }
471
472 err = js_create_reference(env, self, db->ctx);
473 assert(err == 0);
474
475 err = js_create_reference(env, ctx, req->ctx);
476 assert(err == 0);
477
478 err = js_create_reference(env, on_open, req->on_open);
479 assert(err == 0);
480
481 err = js_create_reference(env, column_families_array, req->column_families);
482 assert(err == 0);
483
484 err = js_add_deferred_teardown_callback(env, rocksdb_native__on_teardown, db, &db->teardown);
485 assert(err == 0);
486
487 return handle;
488}
489
490static js_arraybuffer_t
491rocksdb_native_close(
492 js_env_t *env,
493 js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
494 js_receiver_t ctx,
495 rocksdb_native_on_close_t on_close
496) {
497 int err;
498
499 js_arraybuffer_t handle;
500
501 rocksdb_native_close_t *req;
502 err = js_create_arraybuffer(env, req, handle);
503 assert(err == 0);
504
505 req->env = env;
506 req->handle.data = req;
507
508 err = rocksdb_close(&db->handle, &req->handle, rocksdb_native__on_idle, rocksdb_native__on_close);
509
510 if (err < 0) {
511 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
512 assert(err == 0);
513
514 throw js_pending_exception;
515 }
516
517 err = js_create_reference(env, ctx, req->ctx);
518 assert(err == 0);
519
520 err = js_create_reference(env, on_close, req->on_close);
521 assert(err == 0);
522
523 db->closing = true;
524
525 return handle;
526}
527
528static void
529rocksdb_native__on_suspend(rocksdb_suspend_t *handle, int status) {
530 int err;
531
532 assert(status == 0);
533
534 auto req = reinterpret_cast<rocksdb_native_suspend_t *>(handle->data);
535
536 auto db = reinterpret_cast<rocksdb_native_t *>(req->handle.req.db);
537
538 auto env = req->env;
539
540 js_handle_scope_t *scope;
541 err = js_open_handle_scope(env, &scope);
542 assert(err == 0);
543
544 js_receiver_t ctx;
545 err = js_get_reference_value(env, req->ctx, ctx);
546 assert(err == 0);
547
548 rocksdb_native_on_suspend_t cb;
549 err = js_get_reference_value(env, req->on_suspend, cb);
550 assert(err == 0);
551
552 req->on_suspend.reset();
553 req->ctx.reset();
554
555 std::optional<js_object_t> error;
556
557 if (req->handle.error) {
558 err = js_create_error(env, uv_err_name(req->handle.status), req->handle.error, error.emplace());
559 assert(err == 0);
560 }
561
562 if (!db->exiting) {
563 err = js_call_function_with_checkpoint(env, cb, ctx, error);
564 (void) err;
565 }
566
567 err = js_close_handle_scope(env, scope);
568 assert(err == 0);
569}
570
571static js_arraybuffer_t
572rocksdb_native_suspend(
573 js_env_t *env,
574 js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
575 js_receiver_t ctx,
576 rocksdb_native_on_suspend_t on_suspend
577) {
578 int err;
579
580 js_arraybuffer_t handle;
581
582 rocksdb_native_suspend_t *req;
583 err = js_create_arraybuffer(env, req, handle);
584 assert(err == 0);
585
586 req->env = env;
587 req->handle.data = req;
588
589 err = rocksdb_suspend(&db->handle, &req->handle, rocksdb_native__on_suspend);
590
591 if (err < 0) {
592 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
593 assert(err == 0);
594
595 throw js_pending_exception;
596 }
597
598 err = js_create_reference(env, ctx, req->ctx);
599 assert(err == 0);
600
601 err = js_create_reference(env, on_suspend, req->on_suspend);
602 assert(err == 0);
603
604 return handle;
605}
606
607static void
608rocksdb_native__on_resume(rocksdb_resume_t *handle, int status) {
609 int err;
610
611 assert(status == 0);
612
613 auto req = reinterpret_cast<rocksdb_native_resume_t *>(handle->data);
614
615 auto db = reinterpret_cast<rocksdb_native_t *>(req->handle.req.db);
616
617 auto env = req->env;
618
619 js_handle_scope_t *scope;
620 err = js_open_handle_scope(env, &scope);
621 assert(err == 0);
622
623 js_receiver_t ctx;
624 err = js_get_reference_value(env, req->ctx, ctx);
625 assert(err == 0);
626
627 rocksdb_native_on_resume_t cb;
628 err = js_get_reference_value(env, req->on_resume, cb);
629 assert(err == 0);
630
631 req->on_resume.reset();
632 req->ctx.reset();
633
634 std::optional<js_object_t> error;
635
636 if (req->handle.error) {
637 err = js_create_error(env, uv_err_name(req->handle.status), req->handle.error, error.emplace());
638 assert(err == 0);
639 }
640
641 if (!db->exiting) {
642 err = js_call_function_with_checkpoint(env, cb, ctx, error);
643 (void) err;
644 }
645
646 err = js_close_handle_scope(env, scope);
647 assert(err == 0);
648}
649
650static js_arraybuffer_t
651rocksdb_native_resume(
652 js_env_t *env,
653 js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
654 js_receiver_t ctx,
655 rocksdb_native_on_resume_t on_resume
656) {
657 int err;
658
659 js_arraybuffer_t handle;
660
661 rocksdb_native_resume_t *req;
662 err = js_create_arraybuffer(env, req, handle);
663 assert(err == 0);
664
665 req->env = env;
666 req->handle.data = req;
667
668 err = rocksdb_resume(&db->handle, &req->handle, rocksdb_native__on_resume);
669
670 if (err < 0) {
671 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
672 assert(err == 0);
673
674 throw js_pending_exception;
675 }
676
677 err = js_create_reference(env, ctx, req->ctx);
678 assert(err == 0);
679
680 err = js_create_reference(env, on_resume, req->on_resume);
681 assert(err == 0);
682
683 return handle;
684}
685
686static js_arraybuffer_t
687rocksdb_native_column_family_init(
688 js_env_t *env,
689 char *name,
690 bool enable_blob_files,
691 uint64_t min_blob_size,
692 uint64_t blob_file_size,
693 bool enable_blob_garbage_collection,
694 uint64_t block_size,
695 bool cache_index_and_filter_blocks,
696 uint32_t format_version,
697 bool optimize_filters_for_memory,
698 bool no_block_cache,
699 uint32_t filter_policy_type,
700 double bits_per_key,
701 int32_t bloom_before_level,
702 uint32_t top_level_index_pinning_tier,
703 uint32_t partition_pinning_tier,
704 uint32_t unpartitioned_pinning_tier,
705 bool optimize_filters_for_hits,
706 int32_t num_levels,
707 int32_t max_write_buffer_number,
708 double blob_garbage_collection_age_cutoff,
709 double blob_garbage_collection_force_threshold
710) {
711 int err;
712
713 rocksdb_filter_policy_t filter_policy = {rocksdb_filter_policy_type_t(filter_policy_type)};
714
715 switch (filter_policy_type) {
716 case rocksdb_bloom_filter_policy:
717 filter_policy.bloom = (rocksdb_bloom_filter_options_t) {
718 0,
719 bits_per_key
720 };
721 break;
722
723 case rocksdb_ribbon_filter_policy:
724 filter_policy.ribbon = (rocksdb_ribbon_filter_options_t) {
725 0,
726 bits_per_key,
727 bloom_before_level,
728 };
729 break;
730 }
731
732 uv_loop_t *loop;
733 err = js_get_env_loop(env, &loop);
734 assert(err == 0);
735
736 js_arraybuffer_t handle;
737
738 rocksdb_native_column_family_t *column_family;
739 err = js_create_arraybuffer(env, column_family, handle);
740 assert(err == 0);
741
742 column_family->db = nullptr;
743 column_family->handle = nullptr;
744
745 column_family->descriptor = (rocksdb_column_family_descriptor_t) {
746 name,
747 {
748 5,
749 rocksdb_level_compaction,
750 enable_blob_files,
751 min_blob_size,
752 blob_file_size,
753 enable_blob_garbage_collection,
754 block_size,
755 cache_index_and_filter_blocks,
756 format_version,
757 optimize_filters_for_memory,
758 no_block_cache,
759 filter_policy,
760 rocksdb_pinning_tier_t(top_level_index_pinning_tier),
761 rocksdb_pinning_tier_t(partition_pinning_tier),
762 rocksdb_pinning_tier_t(unpartitioned_pinning_tier),
763 optimize_filters_for_hits,
764 num_levels,
765 max_write_buffer_number,
766 blob_garbage_collection_age_cutoff,
767 blob_garbage_collection_force_threshold,
768 }
769 };
770
771 return handle;
772}
773
774static void
775rocksdb_native_column_family_destroy(
776 js_env_t *env,
777 js_arraybuffer_span_of_t<rocksdb_native_column_family_t, 1> column_family
778) {
779 int err;
780
781 if (column_family->handle == nullptr) return;
782
783 err = rocksdb_column_family_destroy(&column_family->db->handle, column_family->handle);
784 assert(err == 0);
785
786 column_family->handle = nullptr;
787
788 column_family->db->column_families.erase(column_family);
789
790 column_family->ctx.reset();
791}
792
793static js_arraybuffer_t
794rocksdb_native_iterator_init(js_env_t *env) {
795 int err;
796
797 js_arraybuffer_t handle;
798
799 rocksdb_native_iterator_t *req;
800 err = js_create_arraybuffer(env, req, handle);
801 assert(err == 0);
802
803 req->env = env;
804 req->closing = false;
805 req->exiting = false;
806 req->handle.data = req;
807
808 return handle;
809}
810
811static js_arraybuffer_t
812rocksdb_native_iterator_buffer(
813 js_env_t *env,
814 js_arraybuffer_span_of_t<rocksdb_native_iterator_t, 1> req,
815 uint32_t capacity
816) {
817 int err;
818
819 js_arraybuffer_t handle;
820
821 uint8_t *data;
822 err = js_create_arraybuffer(env, 2 * capacity * sizeof(rocksdb_slice_t), data, handle);
823 assert(err == 0);
824
825 size_t offset = 0;
826
827 req->keys = reinterpret_cast<rocksdb_slice_t *>(&data[offset]);
828
829 offset += capacity * sizeof(rocksdb_slice_t);
830
831 req->values = reinterpret_cast<rocksdb_slice_t *>(&data[offset]);
832
833 return handle;
834}
835
836static void
837rocksdb_native__on_iterator_close(rocksdb_iterator_t *handle, int status) {
838 int err;
839
840 assert(status == 0);
841
842 auto req = reinterpret_cast<rocksdb_native_iterator_t *>(handle->data);
843
844 auto env = req->env;
845
846 auto teardown = req->teardown;
847
848 js_handle_scope_t *scope;
849 err = js_open_handle_scope(env, &scope);
850 assert(err == 0);
851
852 js_receiver_t ctx;
853 err = js_get_reference_value(env, req->ctx, ctx);
854 assert(err == 0);
855
856 rocksdb_native_on_iterator_close_t cb;
857 err = js_get_reference_value(env, req->on_close, cb);
858 assert(err == 0);
859
860 req->on_open.reset();
861 req->on_close.reset();
862 req->on_read.reset();
863 req->ctx.reset();
864
865 std::optional<js_object_t> error;
866
867 if (req->handle.error) {
868 err = js_create_error(env, uv_err_name(req->handle.status), req->handle.error, error.emplace());
869 assert(err == 0);
870 }
871
872 if (!req->exiting) {
873 err = js_call_function_with_checkpoint(env, cb, ctx, error);
874 (void) err;
875 }
876
877 err = js_close_handle_scope(env, scope);
878 assert(err == 0);
879
880 err = js_finish_deferred_teardown_callback(teardown);
881 assert(err == 0);
882}
883
884static void
885rocksdb_native__on_iterator_open(rocksdb_iterator_t *handle, int status) {
886 int err;
887
888 assert(status == 0);
889
890 auto req = reinterpret_cast<rocksdb_native_iterator_t *>(handle->data);
891
892 auto env = req->env;
893
894 js_handle_scope_t *scope;
895 err = js_open_handle_scope(env, &scope);
896 assert(err == 0);
897
898 js_receiver_t ctx;
899 err = js_get_reference_value(env, req->ctx, ctx);
900 assert(err == 0);
901
902 rocksdb_native_on_iterator_open_t cb;
903 err = js_get_reference_value(env, req->on_open, cb);
904 assert(err == 0);
905
906 std::optional<js_object_t> error;
907
908 if (req->handle.error) {
909 err = js_create_error(env, uv_err_name(req->handle.status), req->handle.error, error.emplace());
910 assert(err == 0);
911 }
912
913 if (!req->exiting) {
914 err = js_call_function_with_checkpoint(env, cb, ctx, error);
915 (void) err;
916 }
917
918 err = js_close_handle_scope(env, scope);
919 assert(err == 0);
920}
921
922static void
923rocksdb_native__on_iterator_teardown(js_deferred_teardown_t *teardown, void *data) {
924 int err;
925
926 auto req = reinterpret_cast<rocksdb_native_iterator_t *>(data);
927
928 req->exiting = true;
929
930 if (req->closing) return;
931
932 err = rocksdb_iterator_close(&req->handle, rocksdb_native__on_iterator_close);
933 assert(err == 0);
934}
935
936static void
937rocksdb_native_iterator_open(
938 js_env_t *env,
939 js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
940 js_arraybuffer_span_of_t<rocksdb_native_iterator_t, 1> req,
941 js_arraybuffer_span_of_t<rocksdb_native_column_family_t, 1> column_family,
942 js_typedarray_t<> gt,
943 js_typedarray_t<> gte,
944 js_typedarray_t<> lt,
945 js_typedarray_t<> lte,
946 bool reverse,
947 bool keys_only,
948 std::optional<js_arraybuffer_span_of_t<rocksdb_native_snapshot_t, 1>> snapshot,
949 js_receiver_t ctx,
950 rocksdb_native_on_iterator_open_t on_open,
951 rocksdb_native_on_iterator_close_t on_close,
952 rocksdb_native_on_iterator_read_t on_read
953) {
954 int err;
955
956 rocksdb_range_t range;
957
958 err = js_get_typedarray_info(env, gt, range.gt.data, range.gt.len);
959 assert(err == 0);
960
961 err = js_get_typedarray_info(env, gte, range.gte.data, range.gte.len);
962 assert(err == 0);
963
964 err = js_get_typedarray_info(env, lt, range.lt.data, range.lt.len);
965 assert(err == 0);
966
967 err = js_get_typedarray_info(env, lte, range.lte.data, range.lte.len);
968 assert(err == 0);
969
970 rocksdb_iterator_options_t options = {
971 .version = 0,
972 .reverse = reverse,
973 .keys_only = keys_only
974 };
975
976 if (snapshot) options.snapshot = &snapshot.value()->handle;
977
978 err = rocksdb_iterator_open(&db->handle, &req->handle, column_family->handle, range, &options, rocksdb_native__on_iterator_open);
979
980 if (err < 0) {
981 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
982 assert(err == 0);
983
984 throw js_pending_exception;
985 }
986
987 err = js_create_reference(env, ctx, req->ctx);
988 assert(err == 0);
989
990 err = js_create_reference(env, on_open, req->on_open);
991 assert(err == 0);
992
993 err = js_create_reference(env, on_close, req->on_close);
994 assert(err == 0);
995
996 err = js_create_reference(env, on_read, req->on_read);
997 assert(err == 0);
998
999 err = js_add_deferred_teardown_callback(env, rocksdb_native__on_iterator_teardown, req, &req->teardown);
1000 assert(err == 0);
1001}
1002
1003static void
1004rocksdb_native_iterator_close(js_env_t *env, js_arraybuffer_span_of_t<rocksdb_native_iterator_t, 1> req) {
1005 int err;
1006
1007 err = rocksdb_iterator_close(&req->handle, rocksdb_native__on_iterator_close);
1008
1009 if (err < 0) {
1010 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1011 assert(err == 0);
1012
1013 throw js_pending_exception;
1014 }
1015
1016 req->closing = true;
1017}
1018
1019static void
1020rocksdb_native__on_iterator_read(rocksdb_iterator_t *handle, int status) {
1021 int err;
1022
1023 assert(status == 0);
1024
1025 auto req = reinterpret_cast<rocksdb_native_iterator_t *>(handle->data);
1026
1027 auto db = reinterpret_cast<rocksdb_native_t *>(req->handle.req.db);
1028
1029 auto len = req->handle.len;
1030
1031 auto env = req->env;
1032
1033 js_handle_scope_t *scope;
1034 err = js_open_handle_scope(env, &scope);
1035 assert(err == 0);
1036
1037 js_receiver_t ctx;
1038 err = js_get_reference_value(env, req->ctx, ctx);
1039 assert(err == 0);
1040
1041 rocksdb_native_on_iterator_read_t cb;
1042 err = js_get_reference_value(env, req->on_read, cb);
1043 assert(err == 0);
1044
1045 std::optional<js_object_t> error;
1046
1047 js_array_t keys;
1048 err = js_create_array(env, len, keys);
1049 assert(err == 0);
1050
1051 js_array_t values;
1052 err = js_create_array(env, len, values);
1053 assert(err == 0);
1054
1055 if (req->handle.error) {
1056 err = js_create_error(env, uv_err_name(req->handle.status), req->handle.error, error.emplace());
1057 assert(err == 0);
1058 } else {
1059 for (size_t i = 0; i < len; i++) {
1060 rocksdb_slice_t *key = &req->keys[i];
1061 rocksdb_slice_t *value = &req->values[i];
1062
1063 if (req->exiting) {
1064 rocksdb_slice_destroy(key);
1065 rocksdb_slice_destroy(value);
1066 } else {
1067 js_arraybuffer_t result;
1068
1069 err = rocksdb_native__try_create_external_arraybuffer(env, const_cast<char *>(key->data), key->len, result);
1070 assert(err == 0);
1071
1072 err = js_set_element(env, keys, i, result);
1073 assert(err == 0);
1074
1075 err = rocksdb_native__try_create_external_arraybuffer(env, const_cast<char *>(value->data), value->len, result);
1076 assert(err == 0);
1077
1078 err = js_set_element(env, values, i, result);
1079 assert(err == 0);
1080 }
1081 }
1082 }
1083
1084 if (!req->exiting) {
1085 err = js_call_function_with_checkpoint(env, cb, ctx, error, keys, values);
1086 (void) err;
1087 }
1088
1089 err = js_close_handle_scope(env, scope);
1090 assert(err == 0);
1091}
1092
1093static void
1094rocksdb_native_iterator_read(
1095 js_env_t *env,
1096 js_arraybuffer_span_of_t<rocksdb_native_iterator_t, 1> req,
1097 uint32_t capacity
1098) {
1099 int err;
1100
1101 err = rocksdb_iterator_read(&req->handle, req->keys, req->values, capacity, rocksdb_native__on_iterator_read);
1102
1103 if (err < 0) {
1104 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1105 assert(err == 0);
1106
1107 throw js_pending_exception;
1108 }
1109}
1110
1111static js_arraybuffer_t
1112rocksdb_native_read_init(js_env_t *env) {
1113 int err;
1114
1115 js_arraybuffer_t handle;
1116
1117 rocksdb_native_read_batch_t *req;
1118 err = js_create_arraybuffer(env, req, handle);
1119 assert(err == 0);
1120
1121 req->env = env;
1122 req->handle.data = req;
1123
1124 return handle;
1125}
1126
1127static js_arraybuffer_t
1128rocksdb_native_read_buffer(
1129 js_env_t *env,
1130 js_arraybuffer_span_of_t<rocksdb_native_read_batch_t, 1> req,
1131 uint32_t capacity
1132) {
1133 int err;
1134
1135 js_arraybuffer_t handle;
1136
1137 rocksdb_read_t *reads;
1138 err = js_create_arraybuffer(env, capacity, reads, handle);
1139 assert(err == 0);
1140
1141 req->capacity = capacity;
1142 req->reads = reads;
1143
1144 return handle;
1145}
1146
1147static void
1148rocksdb_native__on_read(rocksdb_read_batch_t *handle, int status) {
1149 int err;
1150
1151 assert(status == 0);
1152
1153 auto req = reinterpret_cast<rocksdb_native_read_batch_t *>(handle->data);
1154
1155 auto db = reinterpret_cast<rocksdb_native_t *>(req->handle.req.db);
1156
1157 auto len = req->handle.len;
1158
1159 auto env = req->env;
1160
1161 js_handle_scope_t *scope;
1162 err = js_open_handle_scope(env, &scope);
1163 assert(err == 0);
1164
1165 js_receiver_t ctx;
1166 err = js_get_reference_value(env, req->ctx, ctx);
1167 assert(err == 0);
1168
1169 rocksdb_native_on_read_t cb;
1170 err = js_get_reference_value(env, req->on_read, cb);
1171 assert(err == 0);
1172
1173 req->on_read.reset();
1174 req->ctx.reset();
1175
1176 js_array_t errors;
1177 err = js_create_array(env, len, errors);
1178 assert(err == 0);
1179
1180 js_array_t values;
1181 err = js_create_array(env, len, values);
1182 assert(err == 0);
1183
1184 for (size_t i = 0; i < len; i++) {
1185 char *error = req->handle.errors[i];
1186 int status = req->handle.statuses[i];
1187
1188 if (error) {
1189 js_object_t result;
1190
1191 err = js_create_error(env, uv_err_name(status), error, result);
1192 assert(err == 0);
1193
1194 err = js_set_element(env, errors, i, result);
1195 assert(err == 0);
1196 } else {
1197 rocksdb_slice_t *value = &req->reads[i].value;
1198
1199 if (db->exiting) rocksdb_slice_destroy(value);
1200 else {
1201 js_arraybuffer_t result;
1202
1203 if (value->data == nullptr && value->len == size_t(-1)) {
1204 err = js_get_null(env, static_cast<js_value_t **>(result));
1205 assert(err == 0);
1206 } else {
1207 err = rocksdb_native__try_create_external_arraybuffer(env, const_cast<char *>(value->data), value->len, result);
1208 assert(err == 0);
1209 }
1210
1211 err = js_set_element(env, values, i, result);
1212 assert(err == 0);
1213 }
1214 }
1215 }
1216
1217 if (!db->exiting) {
1218 err = js_call_function_with_checkpoint(env, cb, ctx, errors, values);
1219 (void) err;
1220 }
1221
1222 err = js_close_handle_scope(env, scope);
1223 assert(err == 0);
1224}
1225
1226static void
1227rocksdb_native_read(
1228 js_env_t *env,
1229 js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
1230 js_arraybuffer_span_of_t<rocksdb_native_read_batch_t, 1> req,
1231 js_array_t operations,
1232 std::optional<js_arraybuffer_span_of_t<rocksdb_native_snapshot_t, 1>> snapshot,
1233 bool async_io,
1234 bool fill_cache,
1235 js_receiver_t ctx,
1236 rocksdb_native_on_read_t on_read
1237) {
1238 int err;
1239
1240 std::vector<js_object_t> elements;
1241 err = js_get_array_elements(env, operations, elements);
1242 assert(err == 0);
1243
1244 const auto len = elements.size();
1245
1246 for (uint32_t i = 0; i < len; i++) {
1247 js_object_t read = elements[i];
1248
1249 rocksdb_read_type_t type;
1250 err = js_get_property(env, read, "type", reinterpret_cast<uint32_t &>(type));
1251 assert(err == 0);
1252
1253 req->reads[i].type = type;
1254
1255 js_arraybuffer_t column_family_property;
1256 err = js_get_property(env, read, "columnFamily", column_family_property);
1257 assert(err == 0);
1258
1259 rocksdb_native_column_family_t *column_family;
1260 err = js_get_arraybuffer_info(env, column_family_property, column_family);
1261 assert(err == 0);
1262
1263 req->reads[i].column_family = column_family->handle;
1264
1265 switch (type) {
1266 case rocksdb_get: {
1267 js_typedarray_t property;
1268
1269 rocksdb_slice_t *key = &req->reads[i].key;
1270
1271 err = js_get_property(env, read, "key", property);
1272 assert(err == 0);
1273
1274 err = js_get_typedarray_info(env, property, key->data, key->len);
1275 assert(err == 0);
1276 break;
1277 }
1278 }
1279 }
1280
1281 rocksdb_read_options_t options = {
1282 .version = 1,
1283 .async_io = async_io,
1284 .fill_cache = fill_cache
1285 };
1286
1287 if (snapshot) options.snapshot = &snapshot.value()->handle;
1288
1289 err = rocksdb_read(&db->handle, &req->handle, req->reads, len, &options, rocksdb_native__on_read);
1290
1291 if (err < 0) {
1292 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1293 assert(err == 0);
1294
1295 throw js_pending_exception;
1296 }
1297
1298 err = js_create_reference(env, ctx, req->ctx);
1299 assert(err == 0);
1300
1301 err = js_create_reference(env, on_read, req->on_read);
1302 assert(err == 0);
1303}
1304
1305static js_arraybuffer_t
1306rocksdb_native_write_init(js_env_t *env) {
1307 int err;
1308
1309 js_arraybuffer_t handle;
1310
1311 rocksdb_native_write_batch_t *req;
1312 err = js_create_arraybuffer(env, req, handle);
1313 assert(err == 0);
1314
1315 req->env = env;
1316 req->handle.data = req;
1317
1318 return handle;
1319}
1320
1321static js_arraybuffer_t
1322rocksdb_native_write_buffer(
1323 js_env_t *env,
1324 js_arraybuffer_span_of_t<rocksdb_native_write_batch_t, 1> req,
1325 uint32_t capacity
1326) {
1327 int err;
1328
1329 js_arraybuffer_t handle;
1330
1331 rocksdb_write_t *writes;
1332 err = js_create_arraybuffer(env, capacity, writes, handle);
1333 assert(err == 0);
1334
1335 req->capacity = capacity;
1336 req->writes = writes;
1337
1338 return handle;
1339}
1340
1341static void
1342rocksdb_native__on_write(rocksdb_write_batch_t *handle, int status) {
1343 int err;
1344
1345 assert(status == 0);
1346
1347 auto req = reinterpret_cast<rocksdb_native_write_batch_t *>(handle->data);
1348
1349 auto db = reinterpret_cast<rocksdb_native_t *>(req->handle.req.db);
1350
1351 auto env = req->env;
1352
1353 js_handle_scope_t *scope;
1354 err = js_open_handle_scope(env, &scope);
1355 assert(err == 0);
1356
1357 js_receiver_t ctx;
1358 err = js_get_reference_value(env, req->ctx, ctx);
1359 assert(err == 0);
1360
1361 rocksdb_native_on_write_t cb;
1362 err = js_get_reference_value(env, req->on_write, cb);
1363 assert(err == 0);
1364
1365 req->on_write.reset();
1366 req->ctx.reset();
1367
1368 std::optional<js_object_t> error;
1369
1370 if (req->handle.error) {
1371 err = js_create_error(env, uv_err_name(req->handle.status), req->handle.error, error.emplace());
1372 assert(err == 0);
1373 }
1374
1375 if (!db->exiting) {
1376 err = js_call_function_with_checkpoint(env, cb, ctx, error);
1377 (void) err;
1378 }
1379
1380 err = js_close_handle_scope(env, scope);
1381 assert(err == 0);
1382}
1383
1384static void
1385rocksdb_native_write(
1386 js_env_t *env,
1387 js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
1388 js_arraybuffer_span_of_t<rocksdb_native_write_batch_t, 1> req,
1389 js_array_t operations,
1390 js_receiver_t ctx,
1391 rocksdb_native_on_write_t on_write
1392) {
1393 int err;
1394
1395 std::vector<js_object_t> elements;
1396 err = js_get_array_elements(env, operations, elements);
1397 assert(err == 0);
1398
1399 const auto len = elements.size();
1400
1401 for (uint32_t i = 0; i < len; i++) {
1402 js_object_t write = elements[i];
1403
1404 rocksdb_write_type_t type;
1405 err = js_get_property(env, write, "type", reinterpret_cast<uint32_t &>(type));
1406 assert(err == 0);
1407
1408 req->writes[i].type = type;
1409
1410 js_arraybuffer_t column_family_property;
1411 err = js_get_property(env, write, "columnFamily", column_family_property);
1412 assert(err == 0);
1413
1414 rocksdb_native_column_family_t *column_family;
1415 err = js_get_arraybuffer_info(env, column_family_property, column_family);
1416 assert(err == 0);
1417
1418 req->writes[i].column_family = column_family->handle;
1419
1420 js_typedarray_t property;
1421
1422 switch (type) {
1423 case rocksdb_put: {
1424 rocksdb_slice_t *key = &req->writes[i].key;
1425
1426 err = js_get_property(env, write, "key", property);
1427 assert(err == 0);
1428
1429 err = js_get_typedarray_info(env, property, key->data, key->len);
1430 assert(err == 0);
1431
1432 rocksdb_slice_t *value = &req->writes[i].value;
1433
1434 err = js_get_property(env, write, "value", property);
1435 assert(err == 0);
1436
1437 err = js_get_typedarray_info(env, property, value->data, value->len);
1438 assert(err == 0);
1439 break;
1440 }
1441
1442 case rocksdb_delete: {
1443 rocksdb_slice_t *key = &req->writes[i].key;
1444
1445 err = js_get_property(env, write, "key", property);
1446 assert(err == 0);
1447
1448 err = js_get_typedarray_info(env, property, key->data, key->len);
1449 assert(err == 0);
1450 break;
1451 }
1452
1453 case rocksdb_delete_range: {
1454 rocksdb_slice_t *start = &req->writes[i].start;
1455
1456 err = js_get_property(env, write, "start", property);
1457 assert(err == 0);
1458
1459 err = js_get_typedarray_info(env, property, start->data, start->len);
1460 assert(err == 0);
1461
1462 rocksdb_slice_t *end = &req->writes[i].end;
1463
1464 err = js_get_property(env, write, "end", property);
1465 assert(err == 0);
1466
1467 err = js_get_typedarray_info(env, property, end->data, end->len);
1468 assert(err == 0);
1469 break;
1470 }
1471 }
1472 }
1473
1474 err = rocksdb_write(&db->handle, &req->handle, req->writes, len, nullptr, rocksdb_native__on_write);
1475
1476 if (err < 0) {
1477 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1478 assert(err == 0);
1479
1480 throw js_pending_exception;
1481 }
1482
1483 err = js_create_reference(env, ctx, req->ctx);
1484 assert(err == 0);
1485
1486 err = js_create_reference(env, on_write, req->on_write);
1487 assert(err == 0);
1488}
1489
1490static void
1491rocksdb_native__on_flush(rocksdb_flush_t *handle, int status) {
1492 int err;
1493
1494 assert(status == 0);
1495
1496 auto req = reinterpret_cast<rocksdb_native_flush_t *>(handle->data);
1497
1498 auto db = reinterpret_cast<rocksdb_native_t *>(req->handle.req.db);
1499
1500 auto env = req->env;
1501
1502 js_handle_scope_t *scope;
1503 err = js_open_handle_scope(env, &scope);
1504 assert(err == 0);
1505
1506 js_receiver_t ctx;
1507 err = js_get_reference_value(env, req->ctx, ctx);
1508 assert(err == 0);
1509
1510 rocksdb_native_on_flush_t cb;
1511 err = js_get_reference_value(env, req->on_flush, cb);
1512 assert(err == 0);
1513
1514 req->on_flush.reset();
1515 req->ctx.reset();
1516
1517 std::optional<js_object_t> error;
1518
1519 if (req->handle.error) {
1520 err = js_create_error(env, uv_err_name(req->handle.status), req->handle.error, error.emplace());
1521 assert(err == 0);
1522 }
1523
1524 if (!db->exiting) {
1525 err = js_call_function_with_checkpoint(env, cb, ctx, error);
1526 (void) err;
1527 }
1528
1529 err = js_close_handle_scope(env, scope);
1530 assert(err == 0);
1531}
1532
1533static js_arraybuffer_t
1534rocksdb_native_flush(
1535 js_env_t *env,
1536 js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
1537 js_arraybuffer_span_of_t<rocksdb_native_column_family_t, 1> column_family,
1538 js_receiver_t ctx,
1539 rocksdb_native_on_flush_t on_flush
1540) {
1541 int err;
1542
1543 js_arraybuffer_t handle;
1544
1545 rocksdb_native_flush_t *req;
1546 err = js_create_arraybuffer(env, req, handle);
1547 assert(err == 0);
1548
1549 req->env = env;
1550 req->handle.data = req;
1551
1552 err = rocksdb_flush(&db->handle, &req->handle, column_family->handle, nullptr, rocksdb_native__on_flush);
1553
1554 if (err < 0) {
1555 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1556 assert(err == 0);
1557
1558 throw js_pending_exception;
1559 }
1560
1561 err = js_create_reference(env, ctx, req->ctx);
1562 assert(err == 0);
1563
1564 err = js_create_reference(env, on_flush, req->on_flush);
1565 assert(err == 0);
1566
1567 return handle;
1568}
1569
1570static void
1571rocksdb_native__on_compact_range(rocksdb_compact_range_t *handle, int status) {
1572 int err;
1573
1574 assert(status == 0);
1575
1576 auto req = reinterpret_cast<rocksdb_native_compact_range_t *>(handle->data);
1577
1578 auto db = reinterpret_cast<rocksdb_native_t *>(req->handle.req.db);
1579
1580 auto env = req->env;
1581
1582 js_handle_scope_t *scope;
1583 err = js_open_handle_scope(env, &scope);
1584 assert(err == 0);
1585
1586 js_receiver_t ctx;
1587 err = js_get_reference_value(env, req->ctx, ctx);
1588 assert(err == 0);
1589
1590 rocksdb_native_on_compact_range_t cb;
1591 err = js_get_reference_value(env, req->on_compact_range, cb);
1592 assert(err == 0);
1593
1594 req->on_compact_range.reset();
1595 req->ctx.reset();
1596
1597 std::optional<js_object_t> error;
1598
1599 if (req->handle.error) {
1600 err = js_create_error(env, uv_err_name(req->handle.status), req->handle.error, error.emplace());
1601 assert(err == 0);
1602 }
1603
1604 if (!db->exiting) {
1605 err = js_call_function_with_checkpoint(env, cb, ctx, error);
1606 (void) err;
1607 }
1608
1609 err = js_close_handle_scope(env, scope);
1610 assert(err == 0);
1611}
1612
1613static js_arraybuffer_t
1614rocksdb_native_compact_range(
1615 js_env_t *env,
1616 js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
1617 js_arraybuffer_span_of_t<rocksdb_native_column_family_t, 1> column_family,
1618 js_typedarray_t<> start,
1619 js_typedarray_t<> end,
1620 bool exclusive,
1621 uint32_t blob_garbage_collection_policy,
1622 double blob_garbage_collection_age_cutoff,
1623 uint32_t bottommost_level_compaction,
1624 js_receiver_t ctx,
1625 rocksdb_native_on_compact_range_t on_compact_range
1626) {
1627 int err;
1628
1629 rocksdb_slice_t start_slice;
1630 err = js_get_typedarray_info(env, start, start_slice.data, start_slice.len);
1631 assert(err == 0);
1632
1633 rocksdb_slice_t end_slice;
1634 err = js_get_typedarray_info(env, end, end_slice.data, end_slice.len);
1635 assert(err == 0);
1636
1637 js_arraybuffer_t handle;
1638
1639 rocksdb_native_compact_range_t *req;
1640 err = js_create_arraybuffer(env, req, handle);
1641 assert(err == 0);
1642
1643 req->env = env;
1644 req->handle.data = req;
1645
1646 rocksdb_compact_range_options_t options = {
1647 .version = 1,
1648 .exclusive_manual_compaction = exclusive,
1649 .blob_garbage_collection_policy = rocksdb_blob_garbage_collection_policy_t(blob_garbage_collection_policy),
1650 .blob_garbage_collection_age_cutoff = blob_garbage_collection_age_cutoff,
1651 .bottommost_level_compaction = rocksdb_bottommost_level_compaction_t(bottommost_level_compaction),
1652 };
1653
1654 err = rocksdb_compact_range(&db->handle, &req->handle, column_family->handle, start_slice, end_slice, &options, rocksdb_native__on_compact_range);
1655
1656 if (err < 0) {
1657 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1658 assert(err == 0);
1659
1660 throw js_pending_exception;
1661 }
1662
1663 err = js_create_reference(env, ctx, req->ctx);
1664 assert(err == 0);
1665
1666 err = js_create_reference(env, on_compact_range, req->on_compact_range);
1667 assert(err == 0);
1668
1669 return handle;
1670}
1671
1672static void
1673rocksdb_native__on_approximate_size(rocksdb_approximate_size_t *handle, int status) {
1674 int err;
1675
1676 assert(status == 0);
1677
1678 auto req = reinterpret_cast<rocksdb_native_approximate_size_t *>(handle->data);
1679
1680 auto db = reinterpret_cast<rocksdb_native_t *>(req->handle.req.db);
1681
1682 auto env = req->env;
1683
1684 js_handle_scope_t *scope;
1685 err = js_open_handle_scope(env, &scope);
1686 assert(err == 0);
1687
1688 js_receiver_t ctx;
1689 err = js_get_reference_value(env, req->ctx, ctx);
1690 assert(err == 0);
1691
1692 rocksdb_native_on_approximate_size_t cb;
1693 err = js_get_reference_value(env, req->on_approximate_size, cb);
1694 assert(err == 0);
1695
1696 req->on_approximate_size.reset();
1697 req->ctx.reset();
1698
1699 std::optional<js_object_t> error;
1700
1701 if (req->handle.error) {
1702 err = js_create_error(env, uv_err_name(req->handle.status), req->handle.error, error.emplace());
1703 assert(err == 0);
1704 }
1705
1706 if (!db->exiting) {
1707 err = js_call_function_with_checkpoint(env, cb, ctx, error, req->handle.result);
1708 (void) err;
1709 }
1710
1711 err = js_close_handle_scope(env, scope);
1712 assert(err == 0);
1713}
1714
1715static js_arraybuffer_t
1716rocksdb_native_approximate_size(
1717 js_env_t *env,
1718 js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
1719 js_arraybuffer_span_of_t<rocksdb_native_column_family_t, 1> column_family,
1720 js_typedarray_t<> start,
1721 js_typedarray_t<> end,
1722 bool include_memtables,
1723 bool include_files,
1724 double error_margin,
1725 js_receiver_t ctx,
1726 rocksdb_native_on_approximate_size_t on_approximate_size
1727) {
1728 int err;
1729
1730 rocksdb_slice_t start_slice;
1731 err = js_get_typedarray_info(env, start, start_slice.data, start_slice.len);
1732 assert(err == 0);
1733
1734 rocksdb_slice_t end_slice;
1735 err = js_get_typedarray_info(env, end, end_slice.data, end_slice.len);
1736 assert(err == 0);
1737
1738 js_arraybuffer_t handle;
1739
1740 rocksdb_native_approximate_size_t *req;
1741 err = js_create_arraybuffer(env, req, handle);
1742 assert(err == 0);
1743
1744 req->env = env;
1745 req->handle.data = req;
1746
1747 rocksdb_approximate_size_options_t options = {
1748 .version = 0,
1749 .include_memtables = include_memtables,
1750 .include_files = include_files,
1751 .files_size_error_margin = error_margin,
1752 };
1753
1754 err = rocksdb_approximate_size(&db->handle, &req->handle, column_family->handle, start_slice, end_slice, &options, rocksdb_native__on_approximate_size);
1755
1756 if (err < 0) {
1757 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1758 assert(err == 0);
1759
1760 throw js_pending_exception;
1761 }
1762
1763 err = js_create_reference(env, ctx, req->ctx);
1764 assert(err == 0);
1765
1766 err = js_create_reference(env, on_approximate_size, req->on_approximate_size);
1767 assert(err == 0);
1768
1769 return handle;
1770}
1771
1772static js_arraybuffer_t
1773rocksdb_native_snapshot_create(js_env_t *env, js_arraybuffer_span_of_t<rocksdb_native_t, 1> db) {
1774 int err;
1775
1776 js_arraybuffer_t handle;
1777
1778 rocksdb_native_snapshot_t *snapshot;
1779 err = js_create_arraybuffer(env, snapshot, handle);
1780 assert(err == 0);
1781
1782 snapshot->db = db;
1783
1784 err = rocksdb_snapshot_create(&db->handle, &snapshot->handle);
1785
1786 if (err < 0) {
1787 err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
1788 assert(err == 0);
1789
1790 throw js_pending_exception;
1791 }
1792
1793 err = js_create_reference(env, handle, snapshot->ctx);
1794 assert(err == 0);
1795
1796 db->snapshots.insert(snapshot);
1797
1798 return handle;
1799}
1800
1801static void
1802rocksdb_native_snapshot_destroy(js_env_t *env, js_arraybuffer_span_of_t<rocksdb_native_snapshot_t, 1> snapshot) {
1803 int err;
1804
1805 rocksdb_snapshot_destroy(&snapshot->handle);
1806
1807 snapshot->db->snapshots.erase(snapshot);
1808
1809 snapshot->ctx.reset();
1810}
1811
1812static js_value_t *
1813rocksdb_native_exports(js_env_t *env, js_value_t *exports) {
1814 int err;
1815
1816#define V(name, fn) \
1817 err = js_set_property<fn>(env, exports, name); \
1818 assert(err == 0);
1819
1820 V("init", rocksdb_native_init)
1821 V("open", rocksdb_native_open)
1822 V("close", rocksdb_native_close)
1823 V("suspend", rocksdb_native_suspend)
1824 V("resume", rocksdb_native_resume)
1825
1826 V("columnFamilyInit", rocksdb_native_column_family_init)
1827 V("columnFamilyDestroy", rocksdb_native_column_family_destroy)
1828
1829 V("readInit", rocksdb_native_read_init)
1830 V("readBuffer", rocksdb_native_read_buffer)
1831 V("read", rocksdb_native_read)
1832
1833 V("writeInit", rocksdb_native_write_init)
1834 V("writeBuffer", rocksdb_native_write_buffer)
1835 V("write", rocksdb_native_write)
1836
1837 V("iteratorInit", rocksdb_native_iterator_init)
1838 V("iteratorBuffer", rocksdb_native_iterator_buffer)
1839 V("iteratorOpen", rocksdb_native_iterator_open)
1840 V("iteratorClose", rocksdb_native_iterator_close)
1841 V("iteratorRead", rocksdb_native_iterator_read)
1842
1843 V("flush", rocksdb_native_flush)
1844 V("compactRange", rocksdb_native_compact_range)
1845 V("approximateSize", rocksdb_native_approximate_size)
1846
1847 V("snapshotCreate", rocksdb_native_snapshot_create)
1848 V("snapshotDestroy", rocksdb_native_snapshot_destroy)
1849#undef V
1850
1851#define V(name, n) \
1852 { \
1853 js_value_t *val; \
1854 err = js_create_uint32(env, n, &val); \
1855 assert(err == 0); \
1856 err = js_set_named_property(env, exports, name, val); \
1857 assert(err == 0); \
1858 }
1859
1860 V("GET", rocksdb_get)
1861 V("PUT", rocksdb_put)
1862 V("DELETE", rocksdb_delete)
1863 V("DELETE_RANGE", rocksdb_delete_range)
1864#undef V
1865
1866 return exports;
1867}
1868
1869BARE_MODULE(rocksdb_native, rocksdb_native_exports)
node_modules/rocksdb-native/binding.js +3 -0
……@@ -0,0 +1,3 @@
1require.addon = require('require-addon')
2
3module.exports = require.addon('.', __filename)
node_modules/rocksdb-native/index.js +223 -0
……@@ -0,0 +1,223 @@
1const ColumnFamily = require('./lib/column-family')
2const Iterator = require('./lib/iterator')
3const Snapshot = require('./lib/snapshot')
4const State = require('./lib/state')
5const { BloomFilterPolicy, RibbonFilterPolicy } = require('./lib/filter-policy')
6const constants = require('./lib/constants')
7
8class RocksDB {
9 constructor(path, opts = {}) {
10 const {
11 columnFamily,
12 state = new State(this, path, opts),
13 snapshot = null,
14 keyEncoding = null,
15 valueEncoding = null
16 } = opts
17
18 this._state = state
19 this._snapshot = snapshot
20 this._columnFamily = state.getColumnFamily(columnFamily)
21 this._keyEncoding = keyEncoding
22 this._valueEncoding = valueEncoding
23 this._index = -1
24
25 this._state.addSession(this)
26 }
27
28 get opened() {
29 return this._state.opened
30 }
31
32 get closed() {
33 return this.isRoot() ? this._state.closed : this._index === -1
34 }
35
36 get path() {
37 return this._state.path
38 }
39
40 get stats() {
41 return this._state.stats
42 }
43
44 get snapshotted() {
45 return this._snapshot !== null
46 }
47
48 get defaultColumnFamily() {
49 return this._columnFamily
50 }
51
52 session({
53 columnFamily = this._columnFamily,
54 snapshot = this._snapshot !== null,
55 keyEncoding = this._keyEncoding,
56 valueEncoding = this._valueEncoding
57 } = {}) {
58 maybeClosed(this)
59
60 return new RocksDB(null, {
61 state: this._state,
62 columnFamily,
63 snapshot: snapshot ? this._snapshot || new Snapshot(this._state) : null,
64 keyEncoding,
65 valueEncoding
66 })
67 }
68
69 columnFamily(name, opts) {
70 return this.session({ ...opts, columnFamily: name })
71 }
72
73 snapshot() {
74 return this.session({ snapshot: true })
75 }
76
77 isRoot() {
78 return this === this._state.db
79 }
80
81 ready() {
82 return this._state.ready()
83 }
84
85 async close({ force } = {}) {
86 if (!this._state.opened) await this._state.ready()
87
88 if (this._index !== -1) this._state.removeSession(this)
89
90 if (force) {
91 while (this._state.sessions.length > 0) {
92 await this._state.sessions[this._state.sessions.length - 1].close()
93 }
94 }
95
96 return this.isRoot() ? this._state.close() : Promise.resolve()
97 }
98
99 suspend() {
100 maybeClosed(this)
101
102 return this._state.suspend()
103 }
104
105 resume() {
106 maybeClosed(this)
107
108 return this._state.resume()
109 }
110
111 isIdle() {
112 return this._state.handles.isIdle()
113 }
114
115 idle() {
116 return this._state.handles.idle()
117 }
118
119 iterator(range, opts) {
120 maybeClosed(this)
121
122 return new Iterator(this, { ...range, ...opts })
123 }
124
125 async *keys(range, opts) {
126 for await (const { key } of this.iterator(range, {
127 ...opts,
128 values: false
129 })) {
130 yield key
131 }
132 }
133
134 async peek(range, opts) {
135 for await (const value of this.iterator({ ...range, ...opts, limit: 1 })) {
136 return value
137 }
138
139 return null
140 }
141
142 read(opts) {
143 maybeClosed(this)
144
145 return this._state.createReadBatch(this, opts)
146 }
147
148 write(opts) {
149 maybeClosed(this)
150
151 return this._state.createWriteBatch(this, opts)
152 }
153
154 flush(opts) {
155 maybeClosed(this)
156
157 return this._state.flush(this, opts)
158 }
159
160 async get(key, opts) {
161 const batch = this.read({ ...opts, capacity: 1, autoDestroy: true })
162 const value = batch.get(key)
163 batch.tryFlush()
164 return value
165 }
166
167 async put(key, value, opts) {
168 const batch = this.write({ ...opts, capacity: 1, autoDestroy: true })
169 batch.tryPut(key, value)
170 await batch.flush()
171 }
172
173 async delete(key, opts) {
174 const batch = this.write({ ...opts, capacity: 1, autoDestroy: true })
175 batch.tryDelete(key)
176 await batch.flush()
177 }
178
179 async deleteRange(start, end, opts) {
180 const batch = this.write({ ...opts, capacity: 1, autoDestroy: true })
181 batch.tryDeleteRange(start, end)
182 await batch.flush()
183 }
184
185 async compactRange(start = null, end = null, opts = {}) {
186 if (typeof end === 'object' && end !== null) {
187 opts = end
188 end = null
189 } else if (typeof start === 'object' && start !== null) {
190 opts = start
191 start = null
192 end = null
193 }
194
195 await this._state.compactRange(this, start, end, opts)
196 }
197
198 async approximateSize(start, end, opts = {}) {
199 return this._state.approximateSize(this, start, end, opts)
200 }
201
202 _ref() {
203 if (this._snapshot) this._snapshot.ref()
204 this._state.handles.inc()
205 }
206
207 _unref() {
208 if (this._snapshot) this._snapshot.unref()
209 this._state.handles.dec()
210 }
211}
212
213module.exports = exports = RocksDB
214
215exports.constants = constants
216
217exports.ColumnFamily = ColumnFamily
218exports.BloomFilterPolicy = BloomFilterPolicy
219exports.RibbonFilterPolicy = RibbonFilterPolicy
220
221function maybeClosed(db) {
222 if (db._state.closing || db._index === -1) throw new Error('RocksDB session is closed')
223}
node_modules/rocksdb-native/lib/batch.js +438 -0
……@@ -0,0 +1,438 @@
1const c = require('compact-encoding')
2const binding = require('../binding')
3
4const empty = Buffer.alloc(0)
5const resolved = Promise.resolve()
6
7class RocksDBBatch {
8 constructor(db, opts = {}) {
9 const { capacity = 8, autoDestroy = false } = opts
10
11 db._ref()
12
13 this._db = db
14 this._destroyed = false
15 this._capacity = capacity
16 this._operations = []
17 this._promises = []
18
19 this._enqueuePromise = this._enqueuePromise.bind(this)
20
21 this._request = null
22 this._resolve = null
23 this._reject = null
24
25 this._handle = null
26 this._buffer = null
27 this._autoDestroy = autoDestroy
28 this._stats = null
29
30 this._resetStats()
31
32 if (db._state.opened === true) this.ready()
33 }
34
35 _reuse(db, opts = {}) {
36 const { autoDestroy = false } = opts
37
38 db._ref()
39
40 this._db = db
41 this._destroyed = false
42 this._autoDestroy = autoDestroy
43 }
44
45 _onfinished(err) {
46 const resolve = this._resolve
47 const reject = this._reject
48
49 if (this._request) this._db._state.io.dec()
50
51 this._operations = []
52 this._promises = []
53 this._request = null
54 this._resolve = null
55 this._reject = null
56
57 this._resetStats()
58
59 if (this._autoDestroy === true) this.destroy()
60
61 if (reject !== null && err) reject(err)
62 else if (resolve !== null) resolve()
63 }
64
65 _resize() {
66 if (this._operations.length <= this._capacity) return false
67
68 while (this._operations.length > this._capacity) {
69 this._capacity *= 2
70 }
71
72 return true
73 }
74
75 async ready() {
76 if (this._handle !== null) return
77
78 if (this._db._state.opened === false) await this._db._state.ready()
79
80 this._init()
81 }
82
83 destroy() {
84 if (this._request) throw new Error('Request in progress')
85 if (this._destroyed) return
86
87 this._destroyed = true
88
89 if (this._promises.length) this._abort()
90
91 this._db._unref()
92 this._onfree()
93 }
94
95 _onfree() {
96 this._resetStats()
97 this._db._state.freeBatch(this, false)
98 this._db = null
99 }
100
101 _abort() {
102 for (let i = 0; i < this._promises.length; i++) {
103 const promise = this._promises[i]
104 if (promise !== null) promise.reject(new Error('Batch is destroyed'))
105 }
106
107 this._onfinished(new Error('Batch is destroyed'))
108 }
109
110 _resetStats() {}
111
112 async flush() {
113 if (this._request) throw new Error('Request in progress')
114 if (this._destroyed) throw new Error('Batch is destroyed')
115
116 this._request = new Promise((resolve, reject) => {
117 this._resolve = resolve
118 this._reject = reject
119 })
120
121 this._flush()
122
123 return this._request
124 }
125
126 tryFlush() {
127 if (this._request) throw new Error('Request in progress')
128 if (this._destroyed) throw new Error('Batch is destroyed')
129
130 this._request = resolved
131
132 this._flush()
133 }
134
135 async _flush() {
136 if (this._handle === null) await this.ready()
137
138 this._db._state.io.inc()
139
140 if (this._db._state.resumed !== null) {
141 const resumed = await this._db._state.resumed.promise
142
143 if (!resumed) {
144 if (this._destroyed) {
145 this._db._state.io.dec()
146 } else {
147 this._destroyed = true
148 this._abort()
149 this._db._unref()
150 }
151 }
152 }
153 }
154
155 _enqueuePromise(resolve, reject) {
156 this._promises.push({ resolve, reject })
157 }
158
159 _encodeKey(k) {
160 if (this._db._keyEncoding) return c.encode(this._db._keyEncoding, k)
161 if (typeof k === 'string') return Buffer.from(k)
162 return k
163 }
164
165 _encodeValue(v) {
166 if (this._db._valueEncoding) return c.encode(this._db._valueEncoding, v)
167 if (v === null) return empty
168 if (typeof v === 'string') return Buffer.from(v)
169 return v
170 }
171
172 _decodeValue(b) {
173 if (this._db._valueEncoding) return c.decode(this._db._valueEncoding, b)
174 return b
175 }
176}
177
178exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
179 constructor(db, opts = {}) {
180 super(db, opts)
181
182 const { asyncIO = false, fillCache = true } = opts
183
184 this._asyncIO = asyncIO
185 this._fillCache = fillCache
186 }
187
188 _init() {
189 this._handle = binding.readInit()
190 this._buffer = binding.readBuffer(this._handle, this._capacity)
191 }
192
193 _resize() {
194 if (super._resize() && this._handle !== null) {
195 this._buffer = binding.readBuffer(this._handle, this._capacity)
196 }
197 }
198
199 async _flush() {
200 await super._flush()
201
202 if (this._destroyed) return
203
204 try {
205 binding.read(
206 this._db._state._handle,
207 this._handle,
208 this._operations,
209 this._db._snapshot ? this._db._snapshot._handle : undefined,
210 this._asyncIO,
211 this._fillCache,
212 this,
213 this._onread
214 )
215 } catch (err) {
216 this._db._state.io.dec()
217 throw err
218 }
219
220 this._db._state.stats.gets += this._stats.gets
221 this._db._state.stats.readBatches++
222 }
223
224 _onread(errs, values) {
225 let applied = true
226
227 for (let i = 0, n = this._promises.length; i < n; i++) {
228 const err = errs[i]
229 if (err) applied = false
230
231 const promise = this._promises[i]
232 if (promise === null) continue
233
234 if (err) promise.reject(err)
235 else promise.resolve(values[i] ? this._decodeValue(Buffer.from(values[i])) : null)
236 }
237
238 this._onfinished(applied ? null : new AggregateError(errs, 'Batch was not applied'))
239 }
240
241 _resetStats() {
242 this._stats = { gets: 0 }
243 }
244
245 get(key) {
246 if (this._request) throw new Error('Request already in progress')
247 this._stats.gets++
248
249 const promise = new Promise(this._enqueuePromise)
250
251 this._operations.push(new RocksDBGet(this._encodeKey(key), this._db._columnFamily))
252
253 this._resize()
254
255 return promise
256 }
257}
258
259exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
260 _init() {
261 this._handle = binding.writeInit()
262 this._buffer = binding.writeBuffer(this._handle, this._capacity)
263 }
264
265 _resize() {
266 if (super._resize() && this._handle !== null) {
267 this._buffer = binding.writeBuffer(this._handle, this._capacity)
268 }
269 }
270
271 _onfree() {
272 this._resetStats()
273 this._db._state.freeBatch(this, true)
274 this._db = null
275 }
276
277 async _flush() {
278 await super._flush()
279
280 if (this._destroyed) return
281
282 try {
283 binding.write(this._db._state._handle, this._handle, this._operations, this, this._onwrite)
284 } catch (err) {
285 this._db._state.io.dec()
286 throw err
287 }
288
289 this._db._state.stats.puts += this._stats.puts
290 this._db._state.stats.deletes += this._stats.deletes
291 this._db._state.stats.rangeDeletes += this._stats.rangeDeletes
292 this._db._state.stats.writeBatches++
293 }
294
295 _onwrite(err) {
296 const applied = !err
297
298 for (let i = 0, n = this._promises.length; i < n; i++) {
299 const promise = this._promises[i]
300 if (promise === null) continue
301
302 if (err) promise.reject(err)
303 else promise.resolve()
304 }
305
306 this._onfinished(applied ? null : new Error('Batch was not applied', { cause: err }))
307 }
308
309 _resetStats() {
310 this._stats = { puts: 0, deletes: 0, rangeDeletes: 0 }
311 }
312
313 put(key, value) {
314 if (this._request) throw new Error('Request already in progress')
315 this._stats.puts++
316
317 const promise = new Promise(this._enqueuePromise)
318
319 this._operations.push(
320 new RocksDBPut(this._encodeKey(key), this._encodeValue(value), this._db._columnFamily)
321 )
322
323 this._resize()
324
325 return promise
326 }
327
328 tryPut(key, value) {
329 if (this._request) throw new Error('Request already in progress')
330 this._stats.puts++
331
332 this._operations.push(
333 new RocksDBPut(this._encodeKey(key), this._encodeValue(value), this._db._columnFamily)
334 )
335
336 this._promises.push(null)
337
338 this._resize()
339 }
340
341 delete(key) {
342 if (this._request) throw new Error('Request already in progress')
343 this._stats.deletes++
344
345 const promise = new Promise(this._enqueuePromise)
346
347 this._operations.push(new RocksDBDelete(this._encodeKey(key), this._db._columnFamily))
348
349 this._resize()
350
351 return promise
352 }
353
354 tryDelete(key) {
355 if (this._request) throw new Error('Request already in progress')
356 this._stats.deletes++
357
358 this._operations.push(new RocksDBDelete(this._encodeKey(key), this._db._columnFamily))
359
360 this._promises.push(null)
361
362 this._resize()
363 }
364
365 deleteRange(start, end) {
366 if (this._request) throw new Error('Request already in progress')
367 this._stats.rangeDeletes++
368
369 const promise = new Promise(this._enqueuePromise)
370
371 this._operations.push(
372 new RocksDBDeleteRange(this._encodeKey(start), this._encodeKey(end), this._db._columnFamily)
373 )
374
375 this._resize()
376
377 return promise
378 }
379
380 tryDeleteRange(start, end) {
381 if (this._request) throw new Error('Request already in progress')
382 this._stats.rangeDeletes++
383
384 this._operations.push(
385 new RocksDBDeleteRange(this._encodeKey(start), this._encodeKey(end), this._db._columnFamily)
386 )
387
388 this._promises.push(null)
389
390 this._resize()
391 }
392}
393
394class RocksDBGet {
395 constructor(key, columnFamily) {
396 this.key = key
397 this.columnFamily = columnFamily._handle
398 }
399
400 get type() {
401 return binding.GET
402 }
403}
404
405class RocksDBPut {
406 constructor(key, value, columnFamily) {
407 this.key = key
408 this.value = value
409 this.columnFamily = columnFamily._handle
410 }
411
412 get type() {
413 return binding.PUT
414 }
415}
416
417class RocksDBDelete {
418 constructor(key, columnFamily) {
419 this.key = key
420 this.columnFamily = columnFamily._handle
421 }
422
423 get type() {
424 return binding.DELETE
425 }
426}
427
428class RocksDBDeleteRange {
429 constructor(start, end, columnFamily) {
430 this.start = start
431 this.end = end
432 this.columnFamily = columnFamily._handle
433 }
434
435 get type() {
436 return binding.DELETE_RANGE
437 }
438}
node_modules/rocksdb-native/lib/column-family.js +108 -0
……@@ -0,0 +1,108 @@
1const binding = require('../binding')
2const constants = require('./constants')
3const { BloomFilterPolicy } = require('./filter-policy')
4
5class RocksDBColumnFamily {
6 constructor(name, opts = {}) {
7 const {
8 // Blob options
9 enableBlobFiles = false,
10 minBlobSize = 0,
11 blobFileSize = 0,
12 enableBlobGarbageCollection = true,
13 // Block table options
14 tableBlockSize = 8192,
15 tableCacheIndexAndFilterBlocks = true,
16 tableFormatVersion = 6,
17 optimizeFiltersForMemory = false,
18 blockCache = true,
19 filterPolicy = new BloomFilterPolicy(10),
20 topLevelIndexPinningTier = constants.pinningTier.ALL,
21 partitionPinningTier = constants.pinningTier.ALL,
22 unpartitionedPinningTier = constants.pinningTier.ALL,
23 optimizeFiltersForHits = false,
24 numLevels = 7,
25 maxWriteBufferNumber = 2,
26 blobGarbageCollectionAgeCutOff = 0.25,
27 blobGarbageCollectionForceThreshold = 1.0
28 } = opts
29
30 this._name = name
31 this._flushing = null
32 this._options = {
33 enableBlobFiles,
34 minBlobSize,
35 blobFileSize,
36 enableBlobGarbageCollection,
37 tableBlockSize,
38 tableCacheIndexAndFilterBlocks,
39 tableFormatVersion,
40 optimizeFiltersForMemory,
41 blockCache,
42 filterPolicy,
43 topLevelIndexPinningTier,
44 partitionPinningTier,
45 unpartitionedPinningTier,
46 optimizeFiltersForHits,
47 numLevels,
48 maxWriteBufferNumber
49 }
50
51 const filterPolicyArguments = [0, 0, 0]
52
53 if (filterPolicy !== null) {
54 filterPolicyArguments[0] = filterPolicy.type
55
56 switch (filterPolicy.type) {
57 case 1: // Bloom filter policy
58 filterPolicyArguments[1] = filterPolicy.bitsPerKey
59 break
60 case 2: // Ribbon filter policy
61 filterPolicyArguments[1] = filterPolicy.bloomEquivalentBitsPerKey
62 filterPolicyArguments[2] = filterPolicy.bloomBeforeLevel
63
64 break
65 }
66 }
67
68 this._handle = binding.columnFamilyInit(
69 name,
70 enableBlobFiles,
71 minBlobSize,
72 blobFileSize,
73 enableBlobGarbageCollection,
74 tableBlockSize,
75 tableCacheIndexAndFilterBlocks,
76 tableFormatVersion,
77 optimizeFiltersForMemory,
78 blockCache === false,
79 ...filterPolicyArguments,
80 topLevelIndexPinningTier,
81 partitionPinningTier,
82 unpartitionedPinningTier,
83 optimizeFiltersForHits,
84 numLevels,
85 maxWriteBufferNumber,
86 blobGarbageCollectionAgeCutOff,
87 blobGarbageCollectionForceThreshold
88 )
89 }
90
91 cloneSettings(name) {
92 return new RocksDBColumnFamily(name, this._options)
93 }
94
95 get name() {
96 return this._name
97 }
98
99 destroy() {
100 if (this._handle === null) return
101
102 binding.columnFamilyDestroy(this._handle)
103
104 this._handle = null
105 }
106}
107
108module.exports = RocksDBColumnFamily
node_modules/rocksdb-native/lib/constants.js +23 -0
……@@ -0,0 +1,23 @@
1module.exports = {
2 pinningTier: {
3 NONE: 0,
4 FLUSHED_AND_SIMILAR: 1,
5 ALL: 2
6 },
7 garbageCollectionPolicy: {
8 DEFAULT: 0,
9 FORCE: 1,
10 DISABLE: 2
11 },
12 bottommostLevelCompaction: {
13 NONE: 0,
14 SKIP: 1,
15 FORCE: 2
16 },
17 walRecoveryMode: {
18 TOLERATE_CORRUPTED_TAIL_RECORDS: 0,
19 ABSOLUTE_CONSISTENCY: 1,
20 POINT_IN_TIME: 2,
21 SKIP_ANY_CORRUPTED_RECORDS: 3
22 }
23}
node_modules/rocksdb-native/lib/filter-policy.js +20 -0
……@@ -0,0 +1,20 @@
1exports.BloomFilterPolicy = class RocksDBBloomFilterPolicy {
2 get type() {
3 return 1
4 }
5
6 constructor(bitsPerKey) {
7 this.bitsPerKey = bitsPerKey
8 }
9}
10
11exports.RibbonFilterPolicy = class RocksDBRibbonFilterPolicy {
12 get type() {
13 return 2
14 }
15
16 constructor(bloomEquivalentBitsPerKey, bloomBeforeLevel = 0) {
17 this.bloomEquivalentBitsPerKey = bloomEquivalentBitsPerKey
18 this.bloomBeforeLevel = bloomBeforeLevel
19 }
20}
node_modules/rocksdb-native/lib/iterator.js +208 -0
……@@ -0,0 +1,208 @@
1const { Readable } = require('streamx')
2const c = require('compact-encoding')
3const binding = require('../binding')
4
5const empty = Buffer.alloc(0)
6
7module.exports = class RocksDBIterator extends Readable {
8 constructor(db, opts = {}) {
9 const {
10 gt = null,
11 gte = null,
12 lt = null,
13 lte = null,
14 reverse = false,
15 values = true,
16 limit = Infinity,
17 capacity = 8
18 } = opts
19
20 super()
21
22 db._ref()
23
24 this._db = db
25
26 this._gt = gt ? this._encodeKey(gt) : empty
27 this._gte = gte ? this._encodeKey(gte) : empty
28 this._lt = lt ? this._encodeKey(lt) : empty
29 this._lte = lte ? this._encodeKey(lte) : empty
30
31 this._reverse = reverse
32 this._values = values
33 this._limit = limit < 0 ? Infinity : limit
34 this._capacity = capacity
35 this._opened = false
36
37 this._pendingOpen = null
38 this._pendingRead = null
39 this._pendingDestroy = null
40
41 this._buffer = null
42 this._handle = null
43
44 if (this._db._state.opened === true) this.ready()
45 }
46
47 _onopen(err) {
48 const cb = this._pendingOpen
49 this._pendingOpen = null
50 this._opened = true
51 this._db._state.io.dec()
52 cb(err)
53 }
54
55 _onread(err, keys, values) {
56 const cb = this._pendingRead
57 this._pendingRead = null
58 this._db._state.io.dec()
59 if (err) return cb(err)
60
61 const n = keys.length
62
63 this._limit -= n
64
65 for (let i = 0; i < n; i++) {
66 this.push({
67 key: this._decodeKey(Buffer.from(keys[i])),
68 value: this._values ? this._decodeValue(Buffer.from(values[i])) : null
69 })
70 }
71
72 if (n < this._capacity) this.push(null)
73
74 cb(null)
75 }
76
77 _onclose(err) {
78 const cb = this._pendingDestroy
79 this._pendingDestroy = null
80 this._db._state.io.dec()
81 this._db._unref()
82 cb(err)
83 }
84
85 _resize() {
86 if (this._handle !== null) {
87 this._buffer = binding.iteratorBuffer(this._handle, this._capacity)
88 }
89 }
90
91 async ready() {
92 if (this._handle !== null) return
93
94 if (this._db._state.opened === false) await this._db._state.ready()
95
96 this._init()
97 }
98
99 _init() {
100 this._handle = binding.iteratorInit()
101 this._buffer = binding.iteratorBuffer(this._handle, this._capacity)
102 }
103
104 async _open(cb) {
105 await this.ready()
106
107 this._db._state.io.inc()
108
109 if (this._db._state.resumed !== null) {
110 const resumed = await this._db._state.resumed.promise
111
112 if (!resumed) {
113 this._db._state.io.dec()
114
115 return cb(new Error('RocksDB session is closed'))
116 }
117 }
118
119 this._pendingOpen = cb
120
121 try {
122 binding.iteratorOpen(
123 this._db._state._handle,
124 this._handle,
125 this._db._columnFamily._handle,
126 this._gt,
127 this._gte,
128 this._lt,
129 this._lte,
130 this._reverse,
131 !this._values, // Keys only
132 this._db._snapshot ? this._db._snapshot._handle : undefined,
133 this,
134 this._onopen,
135 this._onclose,
136 this._onread
137 )
138 } catch (err) {
139 this._db._state.io.dec()
140
141 cb(err)
142 }
143 }
144
145 async _read(cb) {
146 this._db._state.io.inc()
147
148 if (this._db._state.resumed !== null) {
149 const resumed = await this._db._state.resumed.promise
150
151 if (!resumed) {
152 this._db._state.io.dec()
153
154 return cb(new Error('RocksDB session is closed'))
155 }
156 }
157
158 this._pendingRead = cb
159
160 try {
161 binding.iteratorRead(this._handle, Math.min(this._capacity, this._limit))
162 } catch (err) {
163 this._db._state.io.dec()
164
165 cb(err)
166 }
167 }
168
169 async _destroy(cb) {
170 await this.ready()
171
172 this._db._state.io.inc()
173
174 if (this._opened === false) {
175 this._db._state.io.dec()
176 this._db._unref()
177
178 return cb(null)
179 }
180
181 this._pendingDestroy = cb
182
183 try {
184 binding.iteratorClose(this._handle)
185 } catch (err) {
186 this._db._state.io.dec()
187 this._db._unref()
188
189 cb(err)
190 }
191 }
192
193 _encodeKey(k) {
194 if (this._db._keyEncoding !== null) return c.encode(this._db._keyEncoding, k)
195 if (typeof k === 'string') return Buffer.from(k)
196 return k
197 }
198
199 _decodeKey(b) {
200 if (this._db._keyEncoding !== null) return c.decode(this._db._keyEncoding, b)
201 return b
202 }
203
204 _decodeValue(b) {
205 if (this._db._valueEncoding !== null) return c.decode(this._db._valueEncoding, b)
206 return b
207 }
208}
node_modules/rocksdb-native/lib/snapshot.js +30 -0
……@@ -0,0 +1,30 @@
1const binding = require('../binding')
2
3module.exports = class RocksDBSnapshot {
4 constructor(state) {
5 this._state = state
6
7 this._handle = null
8 this._refs = 0
9
10 if (state.deferSnapshotInit === false) this._init()
11 }
12
13 _init() {
14 this._handle = binding.snapshotCreate(this._state._handle)
15 }
16
17 ref() {
18 this._refs++
19 }
20
21 unref() {
22 if (--this._refs > 0) return
23
24 if (this._handle === null) return
25
26 binding.snapshotDestroy(this._handle)
27
28 this._handle = null
29 }
30}
node_modules/rocksdb-native/lib/state.js +435 -0
……@@ -0,0 +1,435 @@
1const ReadyResource = require('ready-resource')
2const RefCounter = require('refcounter')
3const rrp = require('resolve-reject-promise')
4const SignalPromise = require('signal-promise')
5const c = require('compact-encoding')
6const { ReadBatch, WriteBatch } = require('./batch')
7const ColumnFamily = require('./column-family')
8const binding = require('../binding')
9const constants = require('./constants')
10
11const MAX_BATCH_REUSE = 64
12const empty = Buffer.alloc(0)
13
14module.exports = class RocksDBState extends ReadyResource {
15 constructor(db, path, opts) {
16 super()
17
18 const {
19 columnFamily = new ColumnFamily('default', opts),
20 columnFamilies = [],
21 readOnly = false,
22 createIfMissing = true,
23 createMissingColumnFamilies = true,
24 maxBackgroundJobs = 6,
25 bytesPerSync = 1048576,
26 maxOpenFiles = -1,
27 useDirectReads = false,
28 avoidUnnecessaryBlockingIO = false,
29 skipStatsUpdateOnOpen = false,
30 useDirectIOForFlushAndCompaction = false,
31 maxFileOpeningThreads = 16,
32 lock = null,
33 walRecoveryMode = constants.walRecoveryMode.POINT_IN_TIME,
34 bestEffortsRecovery = false
35 } = opts
36
37 this.path = path
38 this.db = db
39 this.handles = new RefCounter()
40 this.io = new RefCounter()
41 this.sessions = []
42 this.columnFamilies = [columnFamily]
43 this.deferSnapshotInit = true
44 this.resumed = null
45 this.stats = {
46 gets: 0,
47 puts: 0,
48 deletes: 0,
49 rangeDeletes: 0,
50 readBatches: 0,
51 writeBatches: 0
52 }
53
54 this._suspended = false
55 this._suspending = false
56 this._updating = false
57 this._updatingSignal = new SignalPromise()
58 this._columnsFlushed = false
59 this._lock = lock
60 this._readBatches = []
61 this._writeBatches = []
62
63 for (const columnFamily of columnFamilies) {
64 this.columnFamilies.push(
65 typeof columnFamily === 'string' ? new ColumnFamily(columnFamily, opts) : columnFamily
66 )
67 }
68
69 this._handle = binding.init(
70 readOnly,
71 createIfMissing,
72 createMissingColumnFamilies,
73 maxBackgroundJobs,
74 bytesPerSync,
75 maxOpenFiles,
76 useDirectReads,
77 avoidUnnecessaryBlockingIO,
78 skipStatsUpdateOnOpen,
79 useDirectIOForFlushAndCompaction,
80 maxFileOpeningThreads,
81 walRecoveryMode,
82 bestEffortsRecovery
83 )
84 }
85
86 createReadBatch(db, opts) {
87 if (this._readBatches.length === 0) return new ReadBatch(db, opts)
88 const batch = this._readBatches.pop()
89 batch._reuse(db, opts)
90 return batch
91 }
92
93 createWriteBatch(db, opts) {
94 if (this._writeBatches.length === 0) return new WriteBatch(db, opts)
95 const batch = this._writeBatches.pop()
96 batch._reuse(db, opts)
97 return batch
98 }
99
100 freeBatch(batch, writable) {
101 if (batch._capacity > 16) return
102 const queue = writable ? this._writeBatches : this._readBatches
103 if (queue.length >= MAX_BATCH_REUSE) return
104 queue.push(batch)
105 }
106
107 addSession(db) {
108 db._index = this.sessions.push(db) - 1
109 if (db._snapshot) db._snapshot.ref()
110 }
111
112 removeSession(db) {
113 const head = this.sessions.pop()
114 if (head !== db) this.sessions[(head._index = db._index)] = head
115 db._index = -1
116 if (db._snapshot) db._snapshot.unref()
117 }
118
119 upsertColumnFamily(c) {
120 if (typeof c === 'string') {
121 let col = this.getColumnFamilyByName(c)
122 if (col) return col
123 col = this.columnFamilies[0].cloneSettings(c)
124 this.columnFamilies.push(col)
125 return col
126 }
127
128 if (this.columnFamilies.includes(c)) return c
129 this.columnFamilies.push(c)
130 return c
131 }
132
133 getColumnFamily(c) {
134 if (!c) return this.columnFamilies[0]
135 if (!this._columnsFlushed) return this.upsertColumnFamily(c)
136
137 if (typeof c !== 'string') return c
138
139 const col = this.getColumnFamilyByName(c)
140 if (col === null) throw new Error('Unknown column family')
141 return col
142 }
143
144 getColumnFamilyByName(name) {
145 for (const col of this.columnFamilies) {
146 if (col.name === name) return col
147 }
148 return null
149 }
150
151 async _open() {
152 await Promise.resolve() // Allow column families to populate if on-demand
153
154 if (this._lock) await this._lock.ready()
155
156 const req = { resolve: null, reject: null, handle: null }
157
158 const promise = new Promise((resolve, reject) => {
159 req.resolve = resolve
160 req.reject = reject
161 })
162
163 this._columnsFlushed = true
164
165 const lock = this._lock === null ? -1 : this._lock.transfer()
166
167 req.handle = binding.open(
168 this._handle,
169 this,
170 this.path,
171 this.columnFamilies.map((c) => c._handle),
172 lock,
173 req,
174 onopen
175 )
176
177 await promise
178
179 this.deferSnapshotInit = false
180
181 for (const session of this.sessions) {
182 if (session._snapshot) session._snapshot._init()
183 }
184
185 function onopen(err) {
186 if (err) req.reject(err)
187 else req.resolve()
188 }
189 }
190
191 async _close() {
192 while (this._updating) await this._updatingSignal.wait()
193 if (this.resumed) this.resumed.resolve(false)
194
195 while (!this.io.isIdle()) await this.io.idle()
196 while (!this.handles.isIdle()) await this.handles.idle()
197
198 while (this.sessions.length > 0) {
199 await this.sessions[this.sessions.length - 1].close()
200 }
201
202 for (const columnFamily of this.columnFamilies) columnFamily.destroy()
203
204 const req = { resolve: null, reject: null, handle: null }
205
206 const promise = new Promise((resolve, reject) => {
207 req.resolve = resolve
208 req.reject = reject
209 })
210
211 req.handle = binding.close(this._handle, req, onclose)
212
213 try {
214 await promise
215 } finally {
216 if (this._lock) await this._lock.close()
217 }
218
219 function onclose(err) {
220 if (err) req.reject(err)
221 else req.resolve()
222 }
223 }
224
225 async flush(db, opts) {
226 if (this.opened === false) await this.ready()
227
228 this.io.inc()
229
230 if (this.resumed !== null) {
231 const resumed = await this.resumed.promise
232
233 if (!resumed) {
234 this.io.dec()
235
236 throw new Error('RocksDB session is closed')
237 }
238 }
239
240 const req = { resolve: null, reject: null, handle: null }
241
242 const promise = new Promise((resolve, reject) => {
243 req.resolve = resolve
244 req.reject = reject
245 })
246
247 try {
248 req.handle = binding.flush(this._handle, db._columnFamily._handle, req, onflush)
249
250 await promise
251 } finally {
252 this.io.dec()
253 }
254
255 function onflush(err) {
256 if (err) req.reject(err)
257 else req.resolve()
258 }
259 }
260
261 suspend() {
262 this._suspending = true
263 return this.update()
264 }
265
266 resume() {
267 this._suspending = false
268 return this.update()
269 }
270
271 async update() {
272 while (this._updating) await this._updatingSignal.wait()
273 if (this._suspending === this._suspended || this.closing) return
274 this._updating = true
275 try {
276 if (this._suspending) await this._suspend()
277 else await this._resume()
278 } finally {
279 this._updating = false
280 this._updatingSignal.notify()
281 }
282 }
283
284 async _suspend() {
285 if (this._suspended === true) return
286
287 while (!this.io.isIdle()) await this.io.idle()
288
289 this.io.inc()
290 this.resumed = rrp()
291
292 const req = { resolve: null, reject: null, handle: null }
293
294 const promise = new Promise((resolve, reject) => {
295 req.resolve = resolve
296 req.reject = reject
297 })
298
299 try {
300 req.handle = binding.suspend(this._handle, req, onsuspend)
301
302 await promise
303
304 this._suspended = true
305 } finally {
306 this.io.dec()
307 }
308
309 function onsuspend(err) {
310 if (err) req.reject(err)
311 else req.resolve()
312 }
313 }
314
315 async _resume() {
316 if (this._suspended === false) return
317
318 const req = { resolve: null, reject: null, handle: null }
319
320 const promise = new Promise((resolve, reject) => {
321 req.resolve = resolve
322 req.reject = reject
323 })
324
325 req.handle = binding.resume(this._handle, req, onresume)
326
327 await promise
328
329 this._suspended = false
330
331 const resumed = this.resumed
332 this.resumed = null
333 resumed.resolve(true)
334
335 function onresume(err) {
336 if (err) req.reject(err)
337 else req.resolve()
338 }
339 }
340
341 async compactRange(db, start, end, opts) {
342 if (this.opened === false) await this.ready()
343
344 this.io.inc()
345
346 const {
347 exclusive = false,
348 blobGarbageCollectionPolicy = constants.garbageCollectionPolicy.DEFAULT,
349 blobGarbageCollectionAgeCutoff = 0.25,
350 bottommostLevelCompaction = constants.bottommostLevelCompaction.NONE
351 } = opts
352
353 start = this._encodeKey(start)
354 end = this._encodeKey(end)
355
356 const req = { resolve: null, reject: null, handle: null, start, end }
357
358 const promise = new Promise((resolve, reject) => {
359 req.resolve = resolve
360 req.reject = reject
361 })
362
363 try {
364 req.handle = binding.compactRange(
365 this._handle,
366 db._columnFamily._handle,
367 start,
368 end,
369 exclusive,
370 blobGarbageCollectionPolicy,
371 blobGarbageCollectionAgeCutoff,
372 bottommostLevelCompaction,
373 req,
374 oncompactrange
375 )
376
377 await promise
378 } finally {
379 this.io.dec()
380 }
381
382 function oncompactrange(err) {
383 if (err) req.reject(err)
384 else req.resolve()
385 }
386 }
387
388 async approximateSize(db, start, end, opts) {
389 if (this.opened === false) await this.ready()
390
391 this.io.inc()
392
393 const { includeMemtables = false, includeFiles = true, filesSizeErrorMargin = -1 } = opts
394
395 start = this._encodeKey(start)
396 end = this._encodeKey(end)
397
398 const req = { resolve: null, reject: null, handle: null, start, end }
399
400 const promise = new Promise((resolve, reject) => {
401 req.resolve = resolve
402 req.reject = reject
403 })
404
405 try {
406 req.handle = binding.approximateSize(
407 this._handle,
408 db._columnFamily._handle,
409 start,
410 end,
411 includeMemtables,
412 includeFiles,
413 filesSizeErrorMargin,
414 req,
415 onapproximatesize
416 )
417
418 return await promise
419 } finally {
420 this.io.dec()
421 }
422
423 function onapproximatesize(err, result) {
424 if (err) req.reject(err)
425 else req.resolve(result)
426 }
427 }
428
429 _encodeKey(k) {
430 if (this.db._keyEncoding) return c.encode(this.db._keyEncoding, k)
431 if (typeof k === 'string') return Buffer.from(k)
432 if (k === null) return empty
433 return k
434 }
435}
node_modules/rocksdb-native/package.json +77 -0
……@@ -0,0 +1,77 @@
1{
2 "name": "rocksdb-native",
3 "version": "3.15.0",
4 "description": "librocksdb bindings for JavaScript",
5 "exports": {
6 ".": "./index.js",
7 "./package": "./package.json"
8 },
9 "imports": {
10 "crypto": {
11 "bare": "bare-crypto",
12 "default": "crypto"
13 },
14 "fs": {
15 "bare": "bare-fs",
16 "default": "fs"
17 },
18 "path": {
19 "bare": "bare-path",
20 "default": "path"
21 }
22 },
23 "files": [
24 "index.js",
25 "binding.cc",
26 "binding.js",
27 "CMakeLists.txt",
28 "lib",
29 "prebuilds",
30 "!prebuilds/android-*/**/*.node"
31 ],
32 "addon": true,
33 "scripts": {
34 "format": "prettier --write .",
35 "lint": "prettier --check . && lunte",
36 "test": "npm run test:node && npm run test:bare",
37 "test:bare": "brittle-bare test.js",
38 "test:node": "brittle-node test.js"
39 },
40 "repository": {
41 "type": "git",
42 "url": "git+https://github.com/holepunchto/rocksdb-native.git"
43 },
44 "author": "Holepunch Inc",
45 "license": "Apache-2.0",
46 "bugs": {
47 "url": "https://github.com/holepunchto/rocksdb-native/issues"
48 },
49 "homepage": "https://github.com/holepunchto/rocksdb-native",
50 "engines": {
51 "bare": ">=1.16.0"
52 },
53 "dependencies": {
54 "compact-encoding": "^2.15.0",
55 "ready-resource": "^1.0.0",
56 "refcounter": "^1.0.0",
57 "require-addon": "^1.0.2",
58 "resolve-reject-promise": "^1.1.0",
59 "signal-promise": "^1.0.3",
60 "streamx": "^2.16.1"
61 },
62 "devDependencies": {
63 "bare-compat-napi": "^1.3.0",
64 "bare-crypto": "^1.12.0",
65 "bare-fs": "^4.5.0",
66 "bare-path": "^3.0.0",
67 "brittle": "^3.5.0",
68 "cmake-bare": "^1.1.14",
69 "cmake-fetch": "^1.0.1",
70 "cmake-napi": "^1.0.6",
71 "fd-lock": "^2.0.0",
72 "lunte": "^1.3.0",
73 "paparam": "^1.9.0",
74 "prettier": "^3.6.2",
75 "prettier-config-holepunch": "^2.0.0"
76 }
77}
node_modules/rocksdb-native/prebuilds/android-arm/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/android-arm64/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/android-ia32/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/android-x64/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/darwin-arm64/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/darwin-arm64/rocksdb-native.node +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/darwin-x64/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/darwin-x64/rocksdb-native.node +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/ios-arm64-simulator/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/ios-arm64/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/ios-x64-simulator/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/linux-arm64/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/linux-arm64/rocksdb-native.node +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/linux-x64/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/linux-x64/rocksdb-native.node +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/win32-arm64/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/win32-arm64/rocksdb-native.node +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/win32-x64/rocksdb-native.bare +0 -0
(no content changes — binary or rename)
node_modules/rocksdb-native/prebuilds/win32-x64/rocksdb-native.node +0 -0
(no content changes — binary or rename)
node_modules/safety-catch/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2021 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/safety-catch/README.md +29 -0
……@@ -0,0 +1,29 @@
1# safety-catch
2
3Small module that makes sure your catch, caught an actual error and not a programming mistake or assertion.
4
5```
6npm install safety-catch
7```
8
9Triggers an unhandled error in the next tick, when you pass it an SyntaxError, TypeError, AssertionError and other builtins.
10
11## Usage
12
13``` js
14const safetyCatch = require('safety-catch')
15
16try {
17 foo.bar()
18} catch (err) {
19 // Was this a programming mistake and should you crash your program?
20 // Ask the safety catch
21 safetyCatch(err)
22
23 console.log('Actual error')
24}
25```
26
27## License
28
29MIT
node_modules/safety-catch/example.js +7 -0
……@@ -0,0 +1,7 @@
1const safetyCatch = require('./')
2
3try {
4 foo.bar()
5} catch (err) {
6 safetyCatch(err)
7}
node_modules/safety-catch/index.js +24 -0
……@@ -0,0 +1,24 @@
1module.exports = safetyCatch
2
3function isActuallyUncaught (err) {
4 if (!err) return false
5 return err instanceof TypeError ||
6 err instanceof SyntaxError ||
7 err instanceof ReferenceError ||
8 err instanceof EvalError ||
9 err instanceof RangeError ||
10 err instanceof URIError ||
11 err.code === 'ERR_ASSERTION' ||
12 err.name === 'AssertionError'
13}
14
15function throwErrorNT (err) {
16 queueMicrotask(() => { throw err })
17}
18
19function safetyCatch (err) {
20 if (isActuallyUncaught(err)) {
21 throwErrorNT(err)
22 throw err
23 }
24}
node_modules/safety-catch/package.json +18 -0
……@@ -0,0 +1,18 @@
1{
2 "name": "safety-catch",
3 "version": "1.0.3",
4 "description": "Small module that makes sure your catch, caught an actual error and not a programming mistake or assertion",
5 "main": "index.js",
6 "dependencies": {},
7 "devDependencies": {},
8 "repository": {
9 "type": "git",
10 "url": "https://github.com/mafintosh/safety-catch.git"
11 },
12 "author": "Mathias Buus (@mafintosh)",
13 "license": "MIT",
14 "bugs": {
15 "url": "https://github.com/mafintosh/safety-catch/issues"
16 },
17 "homepage": "https://github.com/mafintosh/safety-catch"
18}
node_modules/same-data/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - master
6 pull_request:
7 branches:
8 - master
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v2
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v2
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/same-data/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2022 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/same-data/README.md +26 -0
……@@ -0,0 +1,26 @@
1# same-data
2
3Deep equal with no deps and only for "data" objects, ie basic objects, arrays, primitives and typed arrays
4
5```
6npm install same-data
7```
8
9Designed to be simple and for data. Does NOT do anything magic for functions, symbols, recursive objects
10
11## Usage
12
13``` js
14const sameData = require('same-data')
15
16console.log(sameData(1, 1)) // true
17console.log(sameData(1, 2)) // false
18console.log(sameData({ foo: 1 }, { foo: 1 })) // true
19console.log(sameData({ foo: 1 }, { foo: 1, bar: true })) // false
20console.log(sameData({ foo: 1, nested: { a: 1 } }, { foo: 1, nested: { a: 1 } })) // true
21console.log(sameData([{ a: 1 }, { b: 1 }], [{ a: 1 }, { b: 1 }])) // true
22```
23
24## License
25
26MIT
node_modules/same-data/index.js +58 -0
……@@ -0,0 +1,58 @@
1module.exports = sameData
2
3function type (o) {
4 const t = typeof o
5
6 return t === 'object'
7 ? Array.isArray(o)
8 ? 'array'
9 : isTypedArray(o)
10 ? (typeof o.equals === 'function') ? 'buffer' : 'array'
11 : (o === null ? 'null' : 'object')
12 : t
13}
14
15function isTypedArray (a) {
16 return !!a && typeof a.length === 'number' && ArrayBuffer.isView(a.array)
17}
18
19function sameData (a, b) {
20 if (a === b) return true
21
22 const ta = type(a)
23 const tb = type(b)
24
25 if (ta !== tb) return false
26
27 if (ta === 'buffer') return a.equals(b)
28
29 if (ta === 'array') {
30 if (a.length !== b.length) return false
31
32 for (let i = 0; i < a.length; i++) {
33 if (!sameData(a[i], b[i])) return false
34 }
35
36 return true
37 }
38
39 if (ta !== 'object') return false
40
41 const ea = Object.entries(a)
42 const eb = Object.entries(b)
43
44 if (ea.length !== eb.length) return false
45
46 ea.sort(cmp)
47 eb.sort(cmp)
48
49 for (let i = 0; i < ea.length; i++) {
50 if (ea[i][0] !== eb[i][0] || !sameData(ea[i][1], eb[i][1])) return false
51 }
52
53 return true
54}
55
56function cmp (a, b) {
57 return a[0] === b[0] ? 0 : a[0] < b[0] ? -1 : 1
58}
node_modules/same-data/package.json +23 -0
……@@ -0,0 +1,23 @@
1{
2 "name": "same-data",
3 "version": "1.0.0",
4 "description": "Deep equal with no deps and only for 'data' objects, ie basic objects, arrays, primitives and typed arrays",
5 "main": "index.js",
6 "scripts": {
7 "test": "standard && brittle test.js"
8 },
9 "devDependencies": {
10 "brittle": "^3.1.1",
11 "standard": "^17.0.0"
12 },
13 "repository": {
14 "type": "git",
15 "url": "https://github.com/mafintosh/same-data.git"
16 },
17 "author": "Mathias Buus (@mafintosh)",
18 "license": "MIT",
19 "bugs": {
20 "url": "https://github.com/mafintosh/same-data/issues"
21 },
22 "homepage": "https://github.com/mafintosh/same-data"
23}
node_modules/same-data/test.js +28 -0
……@@ -0,0 +1,28 @@
1const test = require('brittle')
2const sameData = require('./')
3
4test('basic', function (t) {
5 t.is(sameData(1, 1), true)
6 t.is(sameData(1, 2), false)
7 t.is(sameData(), true) // undef undef
8 t.is(sameData(true, true), true)
9 t.is(sameData('true', true), false)
10 t.is(sameData('true', 'true'), true)
11})
12
13test('objects', function (t) {
14 t.is(sameData({ foo: 1 }, { foo: 1 }), true)
15 t.is(sameData({ foo: 1 }, { foo: 1, bar: true }), false)
16 t.is(sameData({ foo: 1, nested: { a: 1 } }, { foo: 1, nested: { a: 1 } }), true)
17 t.is(sameData([{ a: 1 }, { b: 1 }], [{ a: 1 }, { b: 1 }]), true)
18})
19
20test('typed arrays', function (t) {
21 t.is(sameData(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3])), true)
22 t.is(sameData(new Uint8Array([1, 2, 1]), new Uint8Array([1, 2, 3])), false)
23})
24
25test('buffers', function (t) {
26 t.is(sameData(Buffer.from([1, 2, 3]), Buffer.from([1, 2, 3])), true)
27 t.is(sameData(Buffer.from([1, 2, 1]), Buffer.from([1, 2, 3])), false)
28})
node_modules/signal-promise/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2020 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/signal-promise/README.md +45 -0
……@@ -0,0 +1,45 @@
1# signal-promise
2
3Simple wait/notify promise with optional max wait time
4
5```
6npm install signal-promise
7```
8
9## Usage
10
11``` js
12const Signal = require('signal-promise')
13
14const input = new Signal()
15
16while (await input.wait()) {
17 console.log('someone typed!')
18}
19
20process.stdin.on('stdin', function () {
21 input.notify()
22})
23```
24
25## API
26
27#### `s = new Signal()`
28
29Make a new signal
30
31#### `await s.wait([maxWaitTime])`
32
33Wait for someone to call notify. If you specify `maxWaitTime`
34the promise will resolve after `maxWaitTime` ms if no notify call has happened.
35
36As a convenience the promise resolves to `true` so it's easy to use it as a condition.
37
38#### `s.notify([error])`
39
40Notify everyone waiting. If you pass an error the wait promise
41will reject with that error.
42
43## License
44
45MIT
node_modules/signal-promise/example.js +16 -0
……@@ -0,0 +1,16 @@
1const Signal = require('./')
2
3const s = new Signal()
4
5main().catch(console.error)
6
7async function main () {
8 while (await s.wait(2000)) {
9 console.log('nu!')
10 }
11 console.log('efter')
12}
13
14process.stdin.on('data', function () {
15 s.notify()
16})
node_modules/signal-promise/index.js +57 -0
……@@ -0,0 +1,57 @@
1module.exports = class Signal {
2 constructor () {
3 this._resolve = null
4 this._reject = null
5 this._promise = null
6 this._bind = bind.bind(this)
7 this._onerror = clear.bind(this)
8 this._onsuccess = clear.bind(this, null)
9 this._timers = new Set()
10 }
11
12 wait (max) {
13 if (!this._promise) {
14 this._promise = new Promise(this._bind)
15 this._promise.then(this._onsuccess).catch(this._onerror)
16 }
17 if (max) return this._sleep(max)
18 return this._promise
19 }
20
21 _sleep (max) {
22 const s = new Promise((resolve, reject) => {
23 const done = () => {
24 this._timers.delete(state)
25 resolve(true)
26 }
27 const id = setTimeout(done, max)
28 const state = { id, resolve, reject }
29 this._timers.add(state)
30 })
31
32 return s
33 }
34
35 notify (err) {
36 if (!this._promise) return
37 const resolve = this._resolve
38 const reject = this._reject
39 this._promise = null
40 if (err) reject(err)
41 else resolve(true)
42 }
43}
44
45function clear (err) {
46 for (const { id, resolve, reject } of this._timers) {
47 clearTimeout(id)
48 if (err) reject(err)
49 else resolve(true)
50 }
51 this._timers.clear()
52}
53
54function bind (resolve, reject) {
55 this._resolve = resolve
56 this._reject = reject
57}
node_modules/signal-promise/package.json +18 -0
……@@ -0,0 +1,18 @@
1{
2 "name": "signal-promise",
3 "version": "1.0.3",
4 "description": "Simple wait/notify promise with optional max wait time",
5 "main": "index.js",
6 "dependencies": {},
7 "devDependencies": {},
8 "repository": {
9 "type": "git",
10 "url": "https://github.com/mafintosh/signal-promise.git"
11 },
12 "author": "Mathias Buus (@mafintosh)",
13 "license": "MIT",
14 "bugs": {
15 "url": "https://github.com/mafintosh/signal-promise/issues"
16 },
17 "homepage": "https://github.com/mafintosh/signal-promise"
18}
node_modules/signed-varint/LICENSE +22 -0
……@@ -0,0 +1,22 @@
1Copyright (c) 2014 Dominic Tarr
2
3Permission is hereby granted, free of charge,
4to any person obtaining a copy of this software and
5associated documentation files (the "Software"), to
6deal in the Software without restriction, including
7without limitation the rights to use, copy, modify,
8merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom
10the Software is furnished to do so,
11subject to the following conditions:
12
13The above copyright notice and this permission notice
14shall be included in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
20ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
node_modules/signed-varint/README.md +28 -0
……@@ -0,0 +1,28 @@
1# signed-varint
2
3store signed integers efficiently, as per protocol-buffers.
4
5For unsigned integers use
6[varint](https://github.com/chrisdickinson/varint).
7
8Integers are mapped to positive integers, so that positive integers
9become positive even numbers (n*2)
10and negative integers become positive odd numbers. (n*-2 - 1)
11
12This is the same as moving the sign bit from the most significant
13possition to the least significant. Otherwise, varint will encode
14negative numbers as large integers.
15
16``` js
17var varint = require('varint')
18var svarint = require('signed-varint')
19
20console.log('unsigned', varint.encode(-1))
21console.log('signed', svarint.encode(-1))
22
23//=> unsigned [255,255,255, 15]
24// signed [1]
25```
26## License
27
28MIT
node_modules/signed-varint/index.js +16 -0
……@@ -0,0 +1,16 @@
1var varint = require('varint')
2exports.encode = function encode (v, b, o) {
3 v = v >= 0 ? v*2 : v*-2 - 1
4 var r = varint.encode(v, b, o)
5 encode.bytes = varint.encode.bytes
6 return r
7}
8exports.decode = function decode (b, o) {
9 var v = varint.decode(b, o)
10 decode.bytes = varint.decode.bytes
11 return v & 1 ? (v+1) / -2 : v / 2
12}
13
14exports.encodingLength = function (v) {
15 return varint.encodingLength(v >= 0 ? v*2 : v*-2 - 1)
16}
node_modules/signed-varint/package.json +21 -0
……@@ -0,0 +1,21 @@
1{
2 "name": "signed-varint",
3 "description": "efficiently store signed integers in varint",
4 "version": "2.0.1",
5 "homepage": "https://github.com/dominictarr/signed-varint",
6 "repository": {
7 "type": "git",
8 "url": "git://github.com/dominictarr/signed-varint.git"
9 },
10 "dependencies": {
11 "varint": "~5.0.0"
12 },
13 "devDependencies": {
14 "tape": "~2.12.3"
15 },
16 "scripts": {
17 "test": "node test.js"
18 },
19 "author": "Dominic Tarr <dominic.tarr@gmail.com> (http://dominictarr.com)",
20 "license": "MIT"
21}
node_modules/signed-varint/test.js +49 -0
……@@ -0,0 +1,49 @@
1var tape = require('tape')
2
3var svi = require('./')
4
5function encodeDecode (t, v, bytes) {
6 var b = svi.encode(v)
7 t.equal(b.length, bytes)
8 t.equal(svi.decode(b), v)
9 t.equal(svi.encode.bytes, bytes)
10 t.equal(svi.decode.bytes, bytes)
11}
12
13tape('single byte', function (t) {
14 encodeDecode(t, 1, 1)
15 encodeDecode(t, -1, 1)
16 encodeDecode(t, 63, 1)
17 encodeDecode(t, -64, 1)
18 t.end()
19})
20tape('double byte', function (t) {
21 encodeDecode(t, 64, 2)
22 encodeDecode(t, -65, 2)
23 encodeDecode(t, 127, 2)
24 encodeDecode(t, -128, 2)
25 encodeDecode(t, 128, 2)
26 encodeDecode(t, -129, 2)
27 encodeDecode(t, 255, 2)
28 encodeDecode(t, -256, 2)
29 t.end()
30})
31tape('tripple', function (t) {
32 encodeDecode(t, 0x4000, 3)
33 encodeDecode(t, -0x4001, 3)
34 encodeDecode(t, 1048574, 3)
35 encodeDecode(t, -1048575, 3)
36 t.end()
37})
38
39tape('quad', function (t) {
40 encodeDecode(t, 134217726, 4)
41 encodeDecode(t, -134217727, 4)
42 t.end()
43})
44
45tape('large int', function (t) {
46 encodeDecode(t, 0x80000000000, 7)
47 encodeDecode(t, -0x80000000000, 7)
48 t.end()
49})
node_modules/simdle-native/CMakeLists.txt +64 -0
……@@ -0,0 +1,64 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6
7project(simdle_native C CXX)
8
9bare_target(target)
10
11if(target MATCHES "win32")
12 add_compile_options(/MT$<$<CONFIG:Debug>:d>)
13endif()
14
15fetch_package("github:holepunchto/libsimdle#014ad4e")
16fetch_package("github:holepunchto/libjstl#098664c")
17
18add_bare_module(simdle_native_bare)
19
20target_sources(
21 ${simdle_native_bare}
22 PRIVATE
23 binding.cc
24)
25
26target_link_libraries(
27 ${simdle_native_bare}
28 PRIVATE
29 $<TARGET_OBJECTS:simdle>
30 jstl
31 PUBLIC
32 simdle
33)
34
35add_napi_module(simdle_native_node)
36
37target_sources(
38 ${simdle_native_node}
39 PRIVATE
40 binding.cc
41)
42
43target_link_libraries(
44 ${simdle_native_node}
45 PRIVATE
46 $<TARGET_OBJECTS:simdle>
47 jstl
48 PUBLIC
49 simdle
50)
51
52target_compile_definitions(
53 ${simdle_native_node}
54 PRIVATE
55 NAPI_VERSION=9
56)
57
58resolve_node_module(bare-compat-napi compat)
59
60target_include_directories(
61 ${simdle_native_node}
62 PRIVATE
63 "${compat}/include"
64)
node_modules/simdle-native/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/simdle-native/README.md +76 -0
……@@ -0,0 +1,76 @@
1# simdle-native
2
3https://github.com/holepunchto/libsimdle JavaScript bindings for Node.js.
4
5```sh
6npm install simdle-native
7```
8
9## Usage
10
11```js
12const { cnt } = require('simdle-native')
13
14cnt(Buffer.alloc(16, 0xff))
15// <Buffer 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08>
16```
17
18## API
19
20The lane width of all APIs is determined by the input buffer. That is, if providing a `Uint8Array` the lane width will be 8 bits, if providing a `Uint16Array` the lane width will be 16 bits and so on.
21
22#### `const result = allo(buffer)`
23
24Check if the buffer contains only ones.
25
26#### `const result = allz(buffer)`
27
28Check if the buffer contains only zeros.
29
30#### `const result = and(a, b[, result])`
31
32Compute the bitwise AND of `a` and `b`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
33
34#### `const result = clear(a, b[, result])`
35
36Clear the bits in `b` from `a`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
37
38#### `const result = clo(buffer[, result])`
39
40Count the number of leading ones in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
41
42#### `const result = clz(buffer[, result])`
43
44Count the number of leading zeroes in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
45
46#### `const result = cnt(buffer[, result])`
47
48Compute the population count in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
49
50#### `const result = cto(buffer[, result])`
51
52Count the number of trailing ones in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
53
54#### `const result = ctz(buffer[, result])`
55
56Count the number of trailing zeroes in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
57
58#### `const result = not(buffer[, result])`
59
60Compute the bitwise NOT in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
61
62#### `const result = or(a, b[, result])`
63
64Compute the bitwise OR of `a` and `b`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
65
66#### `const result = sum(buffer)`
67
68Compute the sum of `buffer` as a `bigint`.
69
70#### `const result = xor(a, b[, result])`
71
72Compute the bitwise XOR of `a` and `b`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
73
74## License
75
76Apache-2.0
node_modules/simdle-native/binding.cc +219 -0
……@@ -0,0 +1,219 @@
1#include <bare.h>
2#include <js.h>
3#include <jstl.h>
4#include <simdle.h>
5#include <stdint.h>
6
7template <auto fn, typename T>
8struct simdle_native_op_t {
9 static bool
10 predicate(
11 js_env_t *env,
12 js_receiver_t,
13 js_typedarray_t<T> buf
14 ) {
15 int err;
16
17 simdle_v128_t *buf_data;
18 size_t buf_len;
19 err = js_get_typedarray_info(env, buf, reinterpret_cast<T *&>(buf_data), buf_len);
20 assert(err == 0);
21
22 for (size_t i = 0, n = buf_len * sizeof(T) / 16; i < n; i++) {
23 if (!fn(buf_data[i])) return false;
24 }
25
26 return true;
27 }
28
29 static void
30 unary(
31 js_env_t *env,
32 js_receiver_t,
33 js_typedarray_t<T> buf,
34 js_typedarray_t<T> result
35 ) {
36 int err;
37
38 simdle_v128_t *buf_data;
39 size_t buf_len;
40 err = js_get_typedarray_info(env, buf, reinterpret_cast<T *&>(buf_data), buf_len);
41 assert(err == 0);
42
43 simdle_v128_t *result_data;
44 size_t result_len;
45 err = js_get_typedarray_info(env, result, reinterpret_cast<T *&>(result_data), result_len);
46 assert(err == 0);
47
48 for (size_t i = 0, n = buf_len * sizeof(T) / 16; i < n; i++) {
49 result_data[i] = fn(buf_data[i]);
50 }
51 }
52
53 static void
54 binary(
55 js_env_t *env,
56 js_receiver_t,
57 js_typedarray_t<T> a_buf,
58 js_typedarray_t<T> b_buf,
59 js_typedarray_t<T> result_buf
60 ) {
61 int err;
62
63 size_t len;
64
65 simdle_v128_t *a;
66 err = js_get_typedarray_info(env, a_buf, reinterpret_cast<T *&>(a), len);
67 assert(err == 0);
68
69 simdle_v128_t *b;
70 err = js_get_typedarray_info(env, b_buf, reinterpret_cast<T *&>(b), len);
71 assert(err == 0);
72
73 simdle_v128_t *result;
74 err = js_get_typedarray_info(env, result_buf, reinterpret_cast<T *&>(result), len);
75 assert(err == 0);
76
77 for (size_t i = 0, n = len * sizeof(T) / 16; i < n; i++) {
78 result[i] = fn(a[i], b[i]);
79 }
80 }
81
82 static int64_t
83 reduce(
84 js_env_t *env,
85 js_receiver_t,
86 js_typedarray_t<T> buf
87 ) {
88 simdle_v128_t *buf_data;
89 size_t buf_len;
90 int err = js_get_typedarray_info(env, buf, reinterpret_cast<T *&>(buf_data), buf_len);
91 assert(err == 0);
92
93 uint64_t result = 0;
94
95 for (size_t i = 0, n = buf_len * sizeof(T) / 16; i < n; i++) {
96 result += fn(buf_data[i]);
97 }
98
99 return result;
100 }
101};
102
103constexpr auto simdle_native_allo_v128_u8 = simdle_native_op_t<simdle_allo_v128, uint8_t>::predicate;
104constexpr auto simdle_native_allo_v128_u16 = simdle_native_op_t<simdle_allo_v128, uint16_t>::predicate;
105constexpr auto simdle_native_allo_v128_u32 = simdle_native_op_t<simdle_allo_v128, uint32_t>::predicate;
106
107constexpr auto simdle_native_allz_v128_u8 = simdle_native_op_t<simdle_allz_v128, uint8_t>::predicate;
108constexpr auto simdle_native_allz_v128_u16 = simdle_native_op_t<simdle_allz_v128, uint16_t>::predicate;
109constexpr auto simdle_native_allz_v128_u32 = simdle_native_op_t<simdle_allz_v128, uint32_t>::predicate;
110
111constexpr auto simdle_native_cnt_v128_u8 = simdle_native_op_t<simdle_cnt_v128_u8, uint8_t>::unary;
112constexpr auto simdle_native_cnt_v128_u16 = simdle_native_op_t<simdle_cnt_v128_u16, uint16_t>::unary;
113constexpr auto simdle_native_cnt_v128_u32 = simdle_native_op_t<simdle_cnt_v128_u32, uint32_t>::unary;
114
115constexpr auto simdle_native_clo_v128_u8 = simdle_native_op_t<simdle_clo_v128_u8, uint8_t>::unary;
116constexpr auto simdle_native_clo_v128_u16 = simdle_native_op_t<simdle_clo_v128_u16, uint16_t>::unary;
117constexpr auto simdle_native_clo_v128_u32 = simdle_native_op_t<simdle_clo_v128_u32, uint32_t>::unary;
118
119constexpr auto simdle_native_clz_v128_u8 = simdle_native_op_t<simdle_clz_v128_u8, uint8_t>::unary;
120constexpr auto simdle_native_clz_v128_u16 = simdle_native_op_t<simdle_clz_v128_u16, uint16_t>::unary;
121constexpr auto simdle_native_clz_v128_u32 = simdle_native_op_t<simdle_clz_v128_u32, uint32_t>::unary;
122
123constexpr auto simdle_native_cto_v128_u8 = simdle_native_op_t<simdle_cto_v128_u8, uint8_t>::unary;
124constexpr auto simdle_native_cto_v128_u16 = simdle_native_op_t<simdle_cto_v128_u16, uint16_t>::unary;
125constexpr auto simdle_native_cto_v128_u32 = simdle_native_op_t<simdle_cto_v128_u32, uint32_t>::unary;
126
127constexpr auto simdle_native_ctz_v128_u8 = simdle_native_op_t<simdle_ctz_v128_u8, uint8_t>::unary;
128constexpr auto simdle_native_ctz_v128_u16 = simdle_native_op_t<simdle_ctz_v128_u16, uint16_t>::unary;
129constexpr auto simdle_native_ctz_v128_u32 = simdle_native_op_t<simdle_ctz_v128_u32, uint32_t>::unary;
130
131constexpr auto simdle_native_not_v128_u8 = simdle_native_op_t<simdle_not_v128_u8, uint8_t>::unary;
132constexpr auto simdle_native_not_v128_u16 = simdle_native_op_t<simdle_not_v128_u16, uint16_t>::unary;
133constexpr auto simdle_native_not_v128_u32 = simdle_native_op_t<simdle_not_v128_u32, uint32_t>::unary;
134
135constexpr auto simdle_native_and_v128_u8 = simdle_native_op_t<simdle_and_v128_u8, uint8_t>::binary;
136constexpr auto simdle_native_and_v128_u16 = simdle_native_op_t<simdle_and_v128_u16, uint16_t>::binary;
137constexpr auto simdle_native_and_v128_u32 = simdle_native_op_t<simdle_and_v128_u32, uint32_t>::binary;
138
139constexpr auto simdle_native_clear_v128_u8 = simdle_native_op_t<simdle_clear_v128_u8, uint8_t>::binary;
140constexpr auto simdle_native_clear_v128_u16 = simdle_native_op_t<simdle_clear_v128_u16, uint16_t>::binary;
141constexpr auto simdle_native_clear_v128_u32 = simdle_native_op_t<simdle_clear_v128_u32, uint32_t>::binary;
142
143constexpr auto simdle_native_or_v128_u8 = simdle_native_op_t<simdle_or_v128_u8, uint8_t>::binary;
144constexpr auto simdle_native_or_v128_u16 = simdle_native_op_t<simdle_or_v128_u16, uint16_t>::binary;
145constexpr auto simdle_native_or_v128_u32 = simdle_native_op_t<simdle_or_v128_u32, uint32_t>::binary;
146
147constexpr auto simdle_native_xor_v128_u8 = simdle_native_op_t<simdle_xor_v128_u8, uint8_t>::binary;
148constexpr auto simdle_native_xor_v128_u16 = simdle_native_op_t<simdle_xor_v128_u16, uint16_t>::binary;
149constexpr auto simdle_native_xor_v128_u32 = simdle_native_op_t<simdle_xor_v128_u32, uint32_t>::binary;
150
151constexpr auto simdle_native_sum_v128_u8 = simdle_native_op_t<simdle_sum_v128_u8, uint8_t>::reduce;
152constexpr auto simdle_native_sum_v128_u16 = simdle_native_op_t<simdle_sum_v128_u16, uint16_t>::reduce;
153constexpr auto simdle_native_sum_v128_u32 = simdle_native_op_t<simdle_sum_v128_u32, uint32_t>::reduce;
154
155static js_value_t *
156simdle_native_exports(js_env_t *env, js_value_t *exports) {
157 int err;
158
159#define V(fn) \
160 err = js_set_property<fn>(env, exports, #fn); \
161 assert(err == 0);
162
163 V(simdle_native_allo_v128_u8);
164 V(simdle_native_allo_v128_u16);
165 V(simdle_native_allo_v128_u32);
166
167 V(simdle_native_allz_v128_u8);
168 V(simdle_native_allz_v128_u16);
169 V(simdle_native_allz_v128_u32);
170
171 V(simdle_native_cnt_v128_u8);
172 V(simdle_native_cnt_v128_u16);
173 V(simdle_native_cnt_v128_u32);
174
175 V(simdle_native_clz_v128_u8);
176 V(simdle_native_clz_v128_u16);
177 V(simdle_native_clz_v128_u32);
178
179 V(simdle_native_and_v128_u8);
180 V(simdle_native_and_v128_u16);
181 V(simdle_native_and_v128_u32);
182
183 V(simdle_native_clear_v128_u8);
184 V(simdle_native_clear_v128_u16);
185 V(simdle_native_clear_v128_u32);
186
187 V(simdle_native_clo_v128_u8);
188 V(simdle_native_clo_v128_u16);
189 V(simdle_native_clo_v128_u32);
190
191 V(simdle_native_cto_v128_u8);
192 V(simdle_native_cto_v128_u16);
193 V(simdle_native_cto_v128_u32);
194
195 V(simdle_native_ctz_v128_u8);
196 V(simdle_native_ctz_v128_u16);
197 V(simdle_native_ctz_v128_u32);
198
199 V(simdle_native_not_v128_u8);
200 V(simdle_native_not_v128_u16);
201 V(simdle_native_not_v128_u32);
202
203 V(simdle_native_or_v128_u8);
204 V(simdle_native_or_v128_u16);
205 V(simdle_native_or_v128_u32);
206
207 V(simdle_native_sum_v128_u8);
208 V(simdle_native_sum_v128_u16);
209 V(simdle_native_sum_v128_u32);
210
211 V(simdle_native_xor_v128_u8);
212 V(simdle_native_xor_v128_u16);
213 V(simdle_native_xor_v128_u32);
214#undef V
215
216 return exports;
217}
218
219BARE_MODULE(simdle_native, simdle_native_exports)
node_modules/simdle-native/binding.js +3 -0
……@@ -0,0 +1,3 @@
1require.addon = require('require-addon')
2
3module.exports = require.addon('.', __filename)
node_modules/simdle-native/index.js +148 -0
……@@ -0,0 +1,148 @@
1const binding = require('./binding')
2const b4a = require('b4a')
3
4function predicate(u8, u16, u32) {
5 return function predicate(buf) {
6 if (buf.byteLength % 16 !== 0) {
7 throw new Error('Buffer length must be a multiple of 16')
8 }
9
10 const n = buf.BYTES_PER_ELEMENT
11
12 if (n === 1) return u8(buf)
13 if (n === 2) return u16(buf)
14 return u32(buf)
15 }
16}
17
18function unary(u8, u16, u32) {
19 return function unary(buf, result = b4a.allocUnsafe(buf.byteLength)) {
20 if (buf.byteLength % 16 !== 0) {
21 throw new Error('Buffer length must be a multiple of 16')
22 }
23
24 if (buf.byteLength !== result.byteLength) {
25 throw new Error('Length of result buffer is insufficient')
26 }
27
28 const n = buf.BYTES_PER_ELEMENT
29
30 if (n === 1) u8(buf, result)
31 else if (n === 2) u16(buf, result)
32 else u32(buf, result)
33
34 return result
35 }
36}
37
38function binary(u8, u16, u32) {
39 return function binary(a, b, result = b4a.allocUnsafe(a.byteLength)) {
40 if (a.byteLength % 16 !== 0) {
41 throw new Error('Buffer length must be a multiple of 16')
42 }
43
44 if (a.byteLength !== b.byteLength || a.byteLength !== result.byteLength) {
45 throw new Error('Buffers must be the same length')
46 }
47
48 const n = a.BYTES_PER_ELEMENT
49
50 if (n === 1) u8(a, b, result)
51 else if (n === 2) u16(a, b, result)
52 else u32(a, b, result)
53
54 return result
55 }
56}
57
58function reduce(u8, u16, u32) {
59 return function reduce(buf) {
60 if (buf.byteLength % 16 !== 0) {
61 throw new Error('Buffer length must be a multiple of 16')
62 }
63
64 const n = buf.BYTES_PER_ELEMENT
65
66 if (n === 1) return u8(buf)
67 if (n === 2) return u16(buf)
68 return u32(buf)
69 }
70}
71
72exports.allo = predicate(
73 binding.simdle_native_allo_v128_u8,
74 binding.simdle_native_allo_v128_u16,
75 binding.simdle_native_allo_v128_u32
76)
77
78exports.allz = predicate(
79 binding.simdle_native_allz_v128_u8,
80 binding.simdle_native_allz_v128_u16,
81 binding.simdle_native_allz_v128_u32
82)
83
84exports.and = binary(
85 binding.simdle_native_and_v128_u8,
86 binding.simdle_native_and_v128_u16,
87 binding.simdle_native_and_v128_u32
88)
89
90exports.clear = binary(
91 binding.simdle_native_clear_v128_u8,
92 binding.simdle_native_clear_v128_u16,
93 binding.simdle_native_clear_v128_u32
94)
95
96exports.clo = unary(
97 binding.simdle_native_clo_v128_u8,
98 binding.simdle_native_clo_v128_u16,
99 binding.simdle_native_clo_v128_u32
100)
101
102exports.clz = unary(
103 binding.simdle_native_clz_v128_u8,
104 binding.simdle_native_clz_v128_u16,
105 binding.simdle_native_clz_v128_u32
106)
107
108exports.cnt = unary(
109 binding.simdle_native_cnt_v128_u8,
110 binding.simdle_native_cnt_v128_u16,
111 binding.simdle_native_cnt_v128_u32
112)
113
114exports.cto = unary(
115 binding.simdle_native_cto_v128_u8,
116 binding.simdle_native_cto_v128_u16,
117 binding.simdle_native_cto_v128_u32
118)
119
120exports.ctz = unary(
121 binding.simdle_native_ctz_v128_u8,
122 binding.simdle_native_ctz_v128_u16,
123 binding.simdle_native_ctz_v128_u32
124)
125
126exports.not = unary(
127 binding.simdle_native_not_v128_u8,
128 binding.simdle_native_not_v128_u16,
129 binding.simdle_native_not_v128_u32
130)
131
132exports.or = binary(
133 binding.simdle_native_or_v128_u8,
134 binding.simdle_native_or_v128_u16,
135 binding.simdle_native_or_v128_u32
136)
137
138exports.sum = reduce(
139 binding.simdle_native_sum_v128_u8,
140 binding.simdle_native_sum_v128_u16,
141 binding.simdle_native_sum_v128_u32
142)
143
144exports.xor = binary(
145 binding.simdle_native_xor_v128_u8,
146 binding.simdle_native_xor_v128_u16,
147 binding.simdle_native_xor_v128_u32
148)
node_modules/simdle-native/package.json +44 -0
……@@ -0,0 +1,44 @@
1{
2 "name": "simdle-native",
3 "version": "1.3.9",
4 "description": "libsimdle JavaScript bindings for Node.js",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "binding.cc",
9 "binding.js",
10 "CMakeLists.txt",
11 "prebuilds"
12 ],
13 "addon": true,
14 "scripts": {
15 "format": "prettier --write .",
16 "lint": "prettier --check .",
17 "test": "npm run lint && npm run test:bare && npm run test:node",
18 "test:bare": "bare test.mjs",
19 "test:node": "node test.mjs"
20 },
21 "repository": {
22 "type": "git",
23 "url": "git+https://github.com/holepunchto/simdle-native.git"
24 },
25 "author": "Holepunch",
26 "license": "Apache-2.0",
27 "bugs": {
28 "url": "https://github.com/holepunchto/simdle-native/issues"
29 },
30 "homepage": "https://github.com/holepunchto/simdle-native#readme",
31 "dependencies": {
32 "b4a": "^1.6.0",
33 "require-addon": "^1.1.0"
34 },
35 "devDependencies": {
36 "bare-compat-napi": "^1.3.2",
37 "brittle": "^3.1.0",
38 "cmake-bare": "^1.1.7",
39 "cmake-fetch": "^1.1.0",
40 "cmake-napi": "^1.0.2",
41 "prettier": "^3.6.2",
42 "prettier-config-holepunch": "^1.0.0"
43 }
44}
node_modules/simdle-native/prebuilds/android-arm/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/android-arm/simdle-native.node +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/android-arm64/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/android-arm64/simdle-native.node +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/android-ia32/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/android-ia32/simdle-native.node +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/android-x64/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/android-x64/simdle-native.node +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/darwin-arm64/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/darwin-arm64/simdle-native.node +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/darwin-x64/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/darwin-x64/simdle-native.node +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/ios-arm64-simulator/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/ios-arm64/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/ios-x64-simulator/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/linux-arm64/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/linux-arm64/simdle-native.node +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/linux-x64/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/linux-x64/simdle-native.node +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/win32-arm64/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/win32-arm64/simdle-native.node +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/win32-x64/simdle-native.bare +0 -0
(no content changes — binary or rename)
node_modules/simdle-native/prebuilds/win32-x64/simdle-native.node +0 -0
(no content changes — binary or rename)
node_modules/simdle-universal/LICENSE +15 -0
……@@ -0,0 +1,15 @@
1ISC License
2
3Copyright (c) 2022 Contributors
4
5Permission to use, copy, modify, and/or distribute this software for any
6purpose with or without fee is hereby granted, provided that the above
7copyright notice and this permission notice appear in all copies.
8
9THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15PERFORMANCE OF THIS SOFTWARE.
node_modules/simdle-universal/README.md +76 -0
……@@ -0,0 +1,76 @@
1# simdle-universal
2
3Universal wrapper for https://github.com/holepunchto/libsimdle with a JavaScript fallback.
4
5```sh
6npm install simdle-universal
7```
8
9## Usage
10
11```js
12const { cnt } = require('simdle-universal')
13
14cnt(Buffer.alloc(16, 0xff))
15// <Buffer 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08>
16```
17
18## API
19
20The lane width of all APIs is determined by the input buffer. That is, if providing a `Uint8Array` the lane width will be 8 bits, if providing a `Uint16Array` the lane width will be 16 bits and so on.
21
22#### `const result = allo(buffer)`
23
24Check if the buffer contains only ones.
25
26#### `const result = allz(buffer)`
27
28Check if the buffer contains only zeros.
29
30#### `const result = and(a, b[, result])`
31
32Compute the bitwise AND of `a` and `b`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
33
34#### `const result = clear(a, b[, result])`
35
36Clear the bits in `b` from `a`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
37
38#### `const result = clo(buffer[, result])`
39
40Count the number of leading ones in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
41
42#### `const result = clz(buffer[, result])`
43
44Count the number of leading zeroes in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
45
46#### `const result = cnt(buffer[, result])`
47
48Compute the population count in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
49
50#### `const result = cto(buffer[, result])`
51
52Count the number of trailing ones in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
53
54#### `const result = ctz(buffer[, result])`
55
56Count the number of trailing zeroes in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
57
58#### `const result = not(buffer[, result])`
59
60Compute the bitwise NOT in `buffer`, storing the result in `result`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
61
62#### `const result = or(a, b[, result])`
63
64Compute the bitwise OR of `a` and `b`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
65
66#### `const result = sum(buffer)`
67
68Compute the sum of `buffer` as a `bigint`.
69
70#### `const result = xor(a, b[, result])`
71
72Compute the bitwise XOR of `a` and `b`. If `result` is not provided, a fresh buffer is allocated. The `result` buffer is returned to the caller.
73
74## License
75
76ISC
node_modules/simdle-universal/fallback.js +236 -0
……@@ -0,0 +1,236 @@
1const b4a = require('b4a')
2const scalar = require('./scalar')
3
4function view (buf, n) {
5 if (n === buf.BYTES_PER_ELEMENT) return buf
6
7 let TypedArray
8
9 if (n === 1) TypedArray = Uint8Array
10 else if (n === 2) TypedArray = Uint16Array
11 else TypedArray = Uint32Array
12
13 return new TypedArray(buf.buffer, buf.byteOffset, buf.byteLength / n)
14}
15
16function unary (u8, u16 = u8, u32 = u16) {
17 return function unary (buf, result = b4a.allocUnsafe(buf.byteLength)) {
18 if (buf.byteLength % 16 !== 0) {
19 throw new Error('Buffer length must be a multiple of 16')
20 }
21
22 if (buf.byteLength !== result.byteLength) {
23 throw new Error('Length of result buffer is insufficient')
24 }
25
26 const n = buf.BYTES_PER_ELEMENT
27
28 if (n === 1) u8(buf, view(result, n))
29 else if (n === 2) u16(buf, view(result, n))
30 else u32(buf, view(result, n))
31
32 return result
33 }
34}
35
36function binary (u8, u16 = u8, u32 = u16) {
37 return function binary (a, b, result = b4a.allocUnsafe(a.byteLength)) {
38 if (a.byteLength % 16 !== 0) {
39 throw new Error('Buffer length must be a multiple of 16')
40 }
41
42 if (a.byteLength !== b.byteLength || a.byteLength !== result.byteLength) {
43 throw new Error('Buffers must be the same length')
44 }
45
46 const n = a.BYTES_PER_ELEMENT
47
48 if (n === 1) u8(a, b, view(result, n))
49 else if (n === 2) u16(a, b, view(result, n))
50 else u32(a, b, view(result, n))
51
52 return result
53 }
54}
55
56function reduce (u8, u16 = u8, u32 = u16) {
57 return function reduce (buf) {
58 if (buf.byteLength % 16 !== 0) {
59 throw new Error('Buffer length must be a multiple of 16')
60 }
61
62 const n = buf.BYTES_PER_ELEMENT
63
64 if (n === 1) return u8(buf)
65 if (n === 2) return u16(buf)
66 return u32(buf)
67 }
68}
69
70exports.allo = function allo (buf) {
71 if (buf.byteLength % 16 !== 0) {
72 throw new Error('Buffer length must be a multiple of 16')
73 }
74
75 const m = 2 ** (buf.BYTES_PER_ELEMENT * 8) - 1
76
77 for (let i = 0, n = buf.length; i < n; i++) {
78 if (buf[i] !== m) return false
79 }
80
81 return true
82}
83
84exports.allz = function allz (buf) {
85 if (buf.byteLength % 16 !== 0) {
86 throw new Error('Buffer length must be a multiple of 16')
87 }
88
89 for (let i = 0, n = buf.length; i < n; i++) {
90 if (buf[i] !== 0) return false
91 }
92
93 return true
94}
95
96exports.and = binary(
97 (a, b, result) => {
98 for (let i = 0, n = result.length; i < n; i++) {
99 result[i] = a[i] & b[i]
100 }
101 }
102)
103
104exports.clear = binary(
105 (a, b, result) => {
106 for (let i = 0, n = result.length; i < n; i++) {
107 result[i] = a[i] & ~b[i]
108 }
109 }
110)
111
112exports.clo = unary(
113 (buf, result) => {
114 for (let i = 0, n = buf.length; i < n; i++) {
115 result[i] = 24 - scalar.clo(buf[i])
116 }
117 },
118 (buf, result) => {
119 for (let i = 0, n = buf.length; i < n; i++) {
120 result[i] = 16 - scalar.clo(buf[i])
121 }
122 },
123 (buf, result) => {
124 for (let i = 0, n = buf.length; i < n; i++) {
125 result[i] = scalar.clo(buf[i])
126 }
127 }
128)
129
130exports.clz = unary(
131 (buf, result) => {
132 for (let i = 0, n = buf.length; i < n; i++) {
133 result[i] = 24 - scalar.clz(buf[i])
134 }
135 },
136 (buf, result) => {
137 for (let i = 0, n = buf.length; i < n; i++) {
138 result[i] = 16 - scalar.clz(buf[i])
139 }
140 },
141 (buf, result) => {
142 for (let i = 0, n = buf.length; i < n; i++) {
143 result[i] = scalar.clz(buf[i])
144 }
145 }
146)
147
148exports.cnt = unary(
149 (buf, result) => {
150 for (let i = 0, n = buf.length; i < n; i++) {
151 result[i] = scalar.cnt(buf[i]) & 0xff
152 }
153 },
154 (buf, result) => {
155 for (let i = 0, n = buf.length; i < n; i++) {
156 result[i] = scalar.cnt(buf[i]) & 0xffff
157 }
158 },
159 (buf, result) => {
160 for (let i = 0, n = buf.length; i < n; i++) {
161 result[i] = scalar.cnt(buf[i])
162 }
163 }
164)
165
166exports.cto = unary(
167 (buf, result) => {
168 for (let i = 0, n = buf.length; i < n; i++) {
169 result[i] = Math.min(scalar.cto(buf[i]), 8)
170 }
171 },
172 (buf, result) => {
173 for (let i = 0, n = buf.length; i < n; i++) {
174 result[i] = Math.min(scalar.cto(buf[i]), 16)
175 }
176 },
177 (buf, result) => {
178 for (let i = 0, n = buf.length; i < n; i++) {
179 result[i] = scalar.cto(buf[i])
180 }
181 }
182)
183
184exports.ctz = unary(
185 (buf, result) => {
186 for (let i = 0, n = buf.length; i < n; i++) {
187 result[i] = Math.min(scalar.ctz(buf[i]), 8)
188 }
189 },
190 (buf, result) => {
191 for (let i = 0, n = buf.length; i < n; i++) {
192 result[i] = Math.min(scalar.ctz(buf[i]), 16)
193 }
194 },
195 (buf, result) => {
196 for (let i = 0, n = buf.length; i < n; i++) {
197 result[i] = scalar.ctz(buf[i])
198 }
199 }
200)
201
202exports.not = unary(
203 (buf, result) => {
204 for (let i = 0, n = buf.length; i < n; i++) {
205 result[i] = ~buf[i]
206 }
207 }
208)
209
210exports.or = binary(
211 (a, b, result) => {
212 for (let i = 0, n = result.length; i < n; i++) {
213 result[i] = a[i] | b[i]
214 }
215 }
216)
217
218exports.sum = reduce(
219 (buf) => {
220 let result = 0n
221
222 for (let i = 0, n = buf.length; i < n; i++) {
223 result += BigInt(buf[i])
224 }
225
226 return result
227 }
228)
229
230exports.xor = binary(
231 (a, b, result) => {
232 for (let i = 0, n = result.length; i < n; i++) {
233 result[i] = a[i] ^ b[i]
234 }
235 }
236)
node_modules/simdle-universal/index.js +5 -0
……@@ -0,0 +1,5 @@
1try {
2 module.exports = require('simdle-native')
3} catch {
4 module.exports = require('./fallback')
5}
node_modules/simdle-universal/package.json +37 -0
……@@ -0,0 +1,37 @@
1{
2 "name": "simdle-universal",
3 "version": "1.1.2",
4 "description": "Universal wrapper for libsimdle with a JavaScript fallback",
5 "main": "index.js",
6 "files": [
7 "fallback.js",
8 "index.js",
9 "scalar.js"
10 ],
11 "browser": {
12 "./index.js": "./fallback.js"
13 },
14 "scripts": {
15 "test": "standard && brittle test.mjs"
16 },
17 "repository": {
18 "type": "git",
19 "url": "git+https://github.com/holepunchto/simdle-universal.git"
20 },
21 "author": "Kasper Isager Dalsgarð <kasper@funktionel.co>",
22 "license": "ISC",
23 "bugs": {
24 "url": "https://github.com/holepunchto/simdle-universal/issues"
25 },
26 "homepage": "https://github.com/holepunchto/simdle-universal#readme",
27 "dependencies": {
28 "b4a": "^1.6.0"
29 },
30 "optionalDependencies": {
31 "simdle-native": "^1.1.1"
32 },
33 "devDependencies": {
34 "brittle": "^3.1.0",
35 "standard": "^17.0.0"
36 }
37}
node_modules/simdle-universal/scalar.js +23 -0
……@@ -0,0 +1,23 @@
1const clz = exports.clz = function clz (n) {
2 return Math.clz32(n)
3}
4
5exports.clo = function clo (n) {
6 return clz(~n)
7}
8
9const ctz = exports.ctz = function ctz (n) {
10 return 32 - (n === 0 ? 0 : (clz(n & -n) + 1))
11}
12
13exports.cto = function cto (n) {
14 return ctz(~n)
15}
16
17exports.cnt = function cnt (n) {
18 n = n - ((n >>> 1) & 0x55555555)
19 n = (n & 0x33333333) + ((n >>> 2) & 0x33333333)
20 n = (n + (n >>> 4)) & 0x0f0f0f0f
21 n = (n * 0x01010101) >>> 24
22 return n
23}
node_modules/sodium-native/CMakeLists.txt +249 -0
……@@ -0,0 +1,249 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6
7set(CMAKE_POSITION_INDEPENDENT_CODE ON)
8
9project(sodium_native C ASM)
10
11fetch_package("github:jedisct1/libsodium#stable" SOURCE_DIR sodium)
12
13bare_target(target)
14
15if(target MATCHES "win32")
16 add_compile_options(/MT$<$<CONFIG:Debug>:d>)
17endif()
18
19file(COPY_FILE "${sodium}/builds/msvc/version.h" "${sodium}/src/libsodium/include/sodium/version.h")
20
21file(GLOB_RECURSE sodium_headers CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.h")
22file(GLOB_RECURSE sodium_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.c")
23file(GLOB_RECURSE sodium_asm_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.S")
24
25add_library(sodium OBJECT)
26
27target_sources(
28 sodium
29 INTERFACE
30 ${sodium_headers}
31 PRIVATE
32 ${sodium_sources}
33)
34
35target_include_directories(
36 sodium
37 INTERFACE
38 "${sodium}/src/libsodium/include"
39 PRIVATE
40 "${sodium}/src/libsodium/include/sodium"
41)
42
43if(NOT target MATCHES "win32")
44 target_compile_options(
45 sodium
46 PRIVATE
47 -fvisibility=hidden
48 -fno-strict-aliasing
49 -fwrapv
50 -flax-vector-conversions
51 )
52endif()
53
54target_compile_definitions(
55 sodium
56 PUBLIC
57 SODIUM_STATIC=1
58 PRIVATE
59 _GNU_SOURCE=1
60 CONFIGURED=1
61 DEV_MODE=1
62 HAVE_ATOMIC_OPS=1
63 HAVE_C11_MEMORY_FENCES=1
64 HAVE_CET_H=1
65 HAVE_GCC_MEMORY_FENCES=1
66 HAVE_INLINE_ASM=1
67 HAVE_INTTYPES_H=1
68 HAVE_STDINT_H=1
69 HAVE_TI_MODE=1
70)
71
72if(target MATCHES "darwin|ios")
73 target_compile_definitions(
74 sodium
75 PRIVATE
76 ASM_HIDE_SYMBOL=.private_extern
77 TLS=_Thread_local
78 HAVE_ARC4RANDOM=1
79 HAVE_ARC4RANDOM_BUF=1
80 HAVE_CATCHABLE_ABRT=1
81 HAVE_CATCHABLE_SEGV=1
82 HAVE_CLOCK_GETTIME=1
83 HAVE_GETPID=1
84 HAVE_MADVISE=1
85 HAVE_MEMSET_S=1
86 HAVE_MLOCK=1
87 HAVE_MMAP=1
88 HAVE_MPROTECT=1
89 HAVE_NANOSLEEP=1
90 HAVE_POSIX_MEMALIGN=1
91 HAVE_PTHREAD=1
92 HAVE_PTHREAD_PRIO_INHERIT=1
93 HAVE_RAISE=1
94 HAVE_SYSCONF=1
95 HAVE_SYS_MMAN_H=1
96 HAVE_SYS_PARAM_H=1
97 HAVE_WEAK_SYMBOLS=1
98 )
99
100 if(NOT target MATCHES "ios")
101 target_compile_definitions(
102 sodium
103 PRIVATE
104 HAVE_GETENTROPY=1
105 HAVE_SYS_RANDOM_H=1
106 )
107 endif()
108endif()
109
110if(target MATCHES "linux")
111 target_compile_definitions(
112 sodium
113 PRIVATE
114 ASM_HIDE_SYMBOL=.hidden
115 TLS=_Thread_local
116 HAVE_CATCHABLE_ABRT=1
117 HAVE_CATCHABLE_SEGV=1
118 HAVE_CLOCK_GETTIME=1
119 HAVE_GETPID=1
120 HAVE_MADVISE=1
121 HAVE_MLOCK=1
122 HAVE_MMAP=1
123 HAVE_MPROTECT=1
124 HAVE_NANOSLEEP=1
125 HAVE_POSIX_MEMALIGN=1
126 HAVE_PTHREAD_PRIO_INHERIT=1
127 HAVE_PTHREAD=1
128 HAVE_RAISE=1
129 HAVE_SYSCONF=1
130 HAVE_SYS_AUXV_H=1
131 HAVE_SYS_MMAN_H=1
132 HAVE_SYS_PARAM_H=1
133 HAVE_SYS_RANDOM_H=1
134 HAVE_WEAK_SYMBOLS=1
135 )
136endif()
137
138if(target MATCHES "win32")
139 target_compile_definitions(
140 sodium
141 PRIVATE
142 _CRT_SECURE_NO_WARNINGS=1
143 HAVE_RAISE=1
144 )
145endif()
146
147if(target MATCHES "x64")
148 target_compile_definitions(
149 sodium
150 PRIVATE
151 HAVE_CPUID=1
152 HAVE_RDRAND=1
153 HAVE_EMMINTRIN_H=1 # SSE2
154 HAVE_PMMINTRIN_H=1 # SSE3
155 HAVE_TMMINTRIN_H=1 # SSSE3
156 HAVE_SMMINTRIN_H=1 # SSE4.1
157 HAVE_WMMINTRIN_H=1 # AES
158 HAVE_AVXINTRIN_H=1 # AVX
159 HAVE_AVX2INTRIN_H=1 # AVX2
160 HAVE_AVX512FINTRIN_H # AVX512F
161 )
162
163 if(NOT target MATCHES "win32")
164 target_compile_definitions(
165 sodium
166 PRIVATE
167 HAVE_AMD64_ASM=1
168 HAVE_AVX_ASM=1
169 )
170
171 target_sources(
172 sodium
173 PRIVATE
174 ${sodium_asm_sources}
175 )
176 endif()
177endif()
178
179if(target MATCHES "arm64")
180 target_compile_definitions(
181 sodium
182 PRIVATE
183 HAVE_ARMCRYPTO=1
184 )
185endif()
186
187if(CMAKE_C_BYTE_ORDER MATCHES "BIG_ENDIAN")
188 target_compile_definitions(
189 sodium
190 PRIVATE
191 NATIVE_BIG_ENDIAN=1
192 )
193else()
194 target_compile_definitions(
195 sodium
196 PRIVATE
197 NATIVE_LITTLE_ENDIAN=1
198 )
199endif()
200
201if(target MATCHES "linux|android")
202 target_link_options(
203 sodium
204 PUBLIC
205 -Wl,-z,noexecstack
206 )
207endif()
208
209add_bare_module(sodium_native_bare)
210
211target_sources(
212 ${sodium_native_bare}
213 PRIVATE
214 binding.c
215 macros.h
216 extensions/tweak/tweak.c
217 extensions/tweak/tweak.h
218 extensions/pbkdf2/pbkdf2.c
219 extensions/pbkdf2/pbkdf2.h
220)
221
222target_link_libraries(
223 ${sodium_native_bare}
224 PRIVATE
225 $<TARGET_OBJECTS:sodium>
226 PUBLIC
227 sodium
228)
229
230add_napi_module(sodium_native_node)
231
232target_sources(
233 ${sodium_native_node}
234 PRIVATE
235 binding.c
236 macros.h
237 extensions/tweak/tweak.c
238 extensions/tweak/tweak.h
239 extensions/pbkdf2/pbkdf2.c
240 extensions/pbkdf2/pbkdf2.h
241)
242
243target_link_libraries(
244 ${sodium_native_node}
245 PRIVATE
246 $<TARGET_OBJECTS:sodium>
247 PUBLIC
248 sodium
249)
node_modules/sodium-native/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2016 Mathias Buus and Emil Bay
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/sodium-native/README.md +51 -0
……@@ -0,0 +1,51 @@
1# sodium-native
2
3Low level bindings for [libsodium](https://github.com/jedisct1/libsodium).
4
5```
6npm install sodium-native
7```
8
9The goal of this project is to be thin, stable, unopionated wrapper around libsodium.
10
11All methods exposed are more or less a direct translation of the libsodium c-api.
12This means that most data types are buffers and you have to manage allocating return values and passing them in as arguments instead of receiving them as return values.
13
14This makes this API harder to use than other libsodium wrappers out there, but also means that you'll be able to get a lot of perf / memory improvements as you can do stuff like inline encryption / decryption, reuse buffers etc.
15
16This also makes this library useful as a foundation for more high level crypto abstractions that you want to make.
17
18## Usage
19
20``` js
21var sodium = require('sodium-native')
22
23var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
24var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) // secure buffer
25var message = Buffer.from('Hello, World!')
26var ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
27
28sodium.randombytes_buf(nonce) // insert random data into nonce
29sodium.randombytes_buf(key) // insert random data into key
30
31// encrypted message is stored in ciphertext.
32sodium.crypto_secretbox_easy(ciphertext, message, nonce, key)
33
34console.log('Encrypted message:', ciphertext)
35
36var plainText = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES)
37
38if (!sodium.crypto_secretbox_open_easy(plainText, ciphertext, nonce, key)) {
39 console.log('Decryption failed!')
40} else {
41 console.log('Decrypted message:', plainText, '(' + plainText.toString() + ')')
42}
43```
44
45## Documentation
46
47Complete documentation may be found on the [sodium-friends website](https://sodium-friends.github.io/docs/docs/getstarted)
48
49## License
50
51MIT
node_modules/sodium-native/binding.c +3470 -0
……@@ -0,0 +1,3470 @@
1#include <node_api.h>
2#include <uv.h>
3#include <string.h>
4#include <sodium.h>
5#include "macros.h"
6#include "extensions/tweak/tweak.h"
7#include "extensions/pbkdf2/pbkdf2.h"
8
9static uint8_t typedarray_width (napi_typedarray_type type) {
10 switch (type) {
11 case napi_int8_array: return 1;
12 case napi_uint8_array: return 1;
13 case napi_uint8_clamped_array: return 1;
14 case napi_int16_array: return 2;
15 case napi_uint16_array: return 2;
16 case napi_int32_array: return 4;
17 case napi_uint32_array: return 4;
18 case napi_float32_array: return 4;
19 case napi_float64_array: return 8;
20 case napi_bigint64_array: return 8;
21 case napi_biguint64_array: return 8;
22 default: return 0;
23 }
24}
25
26static void sn_sodium_free_finalise (napi_env env, void *finalise_data, void *finalise_hint) {
27 napi_adjust_external_memory(env, -4 * 4096, NULL);
28 sodium_free(finalise_data);
29}
30
31napi_value sn_sodium_memzero (napi_env env, napi_callback_info info) {
32 SN_ARGV(1, sodium_memzero)
33
34 SN_ARGV_TYPEDARRAY(buf, 0)
35
36 sodium_memzero(buf_data, buf_size);
37
38 return NULL;
39}
40
41napi_value sn_sodium_mlock (napi_env env, napi_callback_info info) {
42 SN_ARGV(1, sodium_mlock)
43
44 SN_ARGV_TYPEDARRAY(buf, 0)
45
46 SN_RETURN(sodium_mlock(buf_data, buf_size), "memory lock failed")
47}
48
49napi_value sn_sodium_munlock (napi_env env, napi_callback_info info) {
50 SN_ARGV(1, sodium_munlock)
51
52 SN_ARGV_TYPEDARRAY(buf, 0)
53
54 SN_RETURN(sodium_munlock(buf_data, buf_size), "memory unlock failed")
55}
56
57napi_value sn_sodium_free (napi_env env, napi_callback_info info) {
58 SN_ARGV(1, sodium_free)
59
60 SN_ARGV_TYPEDARRAY_PTR(buf, 0)
61
62 if (buf_data == NULL) return NULL;
63
64 napi_value array_buf;
65
66 SN_STATUS_THROWS(napi_get_named_property(env, argv[0], "buffer", &array_buf), "failed to get arraybuffer");
67 SN_STATUS_THROWS(napi_remove_wrap(env, array_buf, NULL), "failed to remove wrap"); // remove the finalizer
68 SN_STATUS_THROWS(napi_detach_arraybuffer(env, array_buf), "failed to detach array buffer");
69 napi_adjust_external_memory(env, -4 * 4096, NULL);
70 sodium_free(buf_data);
71
72 return NULL;
73}
74
75napi_value sn_sodium_malloc (napi_env env, napi_callback_info info) {
76 SN_ARGV(1, sodium_malloc);
77
78 SN_ARGV_UINT32(size, 0)
79
80 void *ptr = sodium_malloc(size);
81
82 SN_THROWS(ptr == NULL, "ENOMEM")
83 napi_adjust_external_memory(env, 4 * 4096, NULL);
84
85 SN_THROWS(ptr == NULL, "sodium_malloc failed");
86
87 napi_value buf, value, array_buf;
88
89 SN_STATUS_THROWS(napi_create_external_buffer(env, size, ptr, NULL, NULL, &buf), "failed to create a n-api buffer")
90 SN_STATUS_THROWS(napi_get_boolean(env, true, &value), "failed to create boolean")
91
92 SN_STATUS_THROWS(napi_get_named_property(env, buf, "buffer", &array_buf), "failed to get arraybuffer")
93 SN_STATUS_THROWS(napi_set_named_property(env, buf, "secure", value), "failed to set secure property")
94
95 SN_STATUS_THROWS(napi_wrap(env, array_buf, ptr, sn_sodium_free_finalise, NULL, NULL), "failed to wrap")
96
97 return buf;
98}
99
100napi_value sn_sodium_mprotect_noaccess (napi_env env, napi_callback_info info) {
101 SN_ARGV(1, sodium_mprotect_noaccess);
102
103 SN_ARGV_TYPEDARRAY_PTR(buf, 0)
104
105 SN_RETURN(sodium_mprotect_noaccess(buf_data), "failed to lock buffer")
106}
107
108
109napi_value sn_sodium_mprotect_readonly (napi_env env, napi_callback_info info) {
110 SN_ARGV(1, sodium_readonly);
111
112 SN_ARGV_TYPEDARRAY_PTR(buf, 0)
113
114 SN_RETURN(sodium_mprotect_readonly(buf_data), "failed to unlock buffer")
115}
116
117
118napi_value sn_sodium_mprotect_readwrite (napi_env env, napi_callback_info info) {
119 SN_ARGV(1, sodium_readwrite);
120
121 SN_ARGV_TYPEDARRAY_PTR(buf, 0)
122
123 SN_RETURN(sodium_mprotect_readwrite(buf_data), "failed to unlock buffer")
124}
125
126napi_value sn_randombytes_random (napi_env env, napi_callback_info info) {
127 napi_value result;
128
129 napi_create_uint32(env, randombytes_random(), &result);
130 return result;
131}
132
133napi_value sn_randombytes_uniform (napi_env env, napi_callback_info info) {
134 SN_ARGV(1, randombytes_uniform);
135
136 SN_ARGV_UINT32(upper_bound, 0)
137
138 napi_value result;
139 napi_create_uint32(env, randombytes_uniform(upper_bound), &result);
140 return result;
141}
142
143napi_value sn_randombytes_buf (napi_env env, napi_callback_info info) {
144 SN_ARGV(1, randombytes_buf)
145
146 SN_ARGV_TYPEDARRAY(buf, 0)
147
148 randombytes_buf(buf_data, buf_size);
149
150 return NULL;
151}
152
153napi_value sn_randombytes_buf_deterministic (napi_env env, napi_callback_info info) {
154 SN_ARGV(2, randombytes_buf)
155
156 SN_ARGV_TYPEDARRAY(buf, 0)
157 SN_ARGV_TYPEDARRAY(seed, 1)
158
159 SN_ASSERT_LENGTH(seed_size, randombytes_SEEDBYTES, "seed")
160
161 randombytes_buf_deterministic(buf_data, buf_size, seed_data);
162
163 return NULL;
164}
165
166napi_value sn_sodium_memcmp(napi_env env, napi_callback_info info) {
167 SN_ARGV(2, sodium_memcmp);
168
169 SN_ARGV_TYPEDARRAY(b1, 0)
170 SN_ARGV_TYPEDARRAY(b2, 1)
171
172 SN_THROWS(b1_size != b2_size, "buffers must be of same length")
173
174 SN_RETURN_BOOLEAN(sodium_memcmp(b1_data, b2_data, b1_size))
175}
176
177napi_value sn_sodium_increment(napi_env env, napi_callback_info info) {
178 SN_ARGV(1, sodium_increment);
179 SN_ARGV_TYPEDARRAY(n, 0)
180
181 sodium_increment(n_data, n_size);
182
183 return NULL;
184}
185
186napi_value sn_sodium_add(napi_env env, napi_callback_info info) {
187 SN_ARGV(2, sodium_add);
188
189 SN_ARGV_TYPEDARRAY(a, 0)
190 SN_ARGV_TYPEDARRAY(b, 1)
191
192 SN_THROWS(a_size != b_size, "buffers must be of same length")
193 sodium_add(a_data, b_data, a_size);
194
195 return NULL;
196}
197
198napi_value sn_sodium_sub(napi_env env, napi_callback_info info) {
199 SN_ARGV(2, sodium_sub);
200
201 SN_ARGV_TYPEDARRAY(a, 0)
202 SN_ARGV_TYPEDARRAY(b, 1)
203
204 SN_THROWS(a_size != b_size, "buffers must be of same length")
205 sodium_sub(a_data, b_data, a_size);
206
207 return NULL;
208}
209
210napi_value sn_sodium_compare(napi_env env, napi_callback_info info) {
211 SN_ARGV(2, sodium_compare);
212
213 SN_ARGV_TYPEDARRAY(a, 0)
214 SN_ARGV_TYPEDARRAY(b, 1)
215
216 SN_THROWS(a_size != b_size, "buffers must be of same length")
217 int cmp = sodium_compare(a_data, b_data, a_size);
218
219 napi_value result;
220 napi_create_int32(env, cmp, &result);
221
222 return result;
223}
224
225napi_value sn_sodium_is_zero(napi_env env, napi_callback_info info) {
226 SN_ARGV_OPTS(1, 2, sodium_is_zero);
227
228 SN_ARGV_TYPEDARRAY(a, 0)
229
230 size_t a_full = a_size;
231
232 if (argc == 2) {
233 SN_OPT_ARGV_UINT32(a_size, 1)
234 SN_THROWS(a_size > a_full, "len must be shorter than 'buf.byteLength'")
235 }
236
237 SN_RETURN_BOOLEAN_FROM_1(sodium_is_zero(a_data, a_size))
238}
239
240napi_value sn_sodium_pad(napi_env env, napi_callback_info info) {
241 SN_ARGV(3, sodium_pad);
242
243 SN_ARGV_TYPEDARRAY(buf, 0)
244 SN_ARGV_UINT32(unpadded_buflen, 1)
245 SN_ARGV_UINT32(blocksize, 2)
246
247 SN_THROWS(unpadded_buflen > buf_size, "unpadded length cannot exceed buffer length")
248 SN_THROWS(blocksize > buf_size, "block size cannot exceed buffer length")
249 SN_THROWS(blocksize < 1, "block sizemust be at least 1 byte")
250 SN_THROWS(buf_size < unpadded_buflen + (blocksize - (unpadded_buflen % blocksize)), "buf not long enough")
251
252 napi_value result;
253 size_t padded_buflen;
254 sodium_pad(&padded_buflen, buf_data, unpadded_buflen, blocksize, buf_size);
255 napi_create_uint32(env, padded_buflen, &result);
256 return result;
257}
258
259napi_value sn_sodium_unpad(napi_env env, napi_callback_info info) {
260 SN_ARGV(3, sodium_unpad);
261
262 SN_ARGV_TYPEDARRAY(buf, 0)
263 SN_ARGV_UINT32(padded_buflen, 1)
264 SN_ARGV_UINT32(blocksize, 2)
265
266 SN_THROWS(padded_buflen > buf_size, "unpadded length cannot exceed buffer length")
267 SN_THROWS(blocksize > buf_size, "block size cannot exceed buffer length")
268 SN_THROWS(blocksize < 1, "block size must be at least 1 byte")
269
270 napi_value result;
271 size_t unpadded_buflen;
272 sodium_unpad(&unpadded_buflen, buf_data, padded_buflen, blocksize);
273 napi_create_uint32(env, unpadded_buflen, &result);
274 return result;
275}
276
277napi_value sn_crypto_sign_keypair(napi_env env, napi_callback_info info) {
278 SN_ARGV(2, crypto_sign_keypair)
279
280 SN_ARGV_TYPEDARRAY(pk, 0)
281 SN_ARGV_TYPEDARRAY(sk, 1)
282
283 SN_ASSERT_LENGTH(pk_size, crypto_sign_PUBLICKEYBYTES, "pk")
284 SN_ASSERT_LENGTH(sk_size, crypto_sign_SECRETKEYBYTES, "sk")
285
286 SN_RETURN(crypto_sign_keypair(pk_data, sk_data), "keypair generation failed")
287}
288
289napi_value sn_crypto_sign_seed_keypair(napi_env env, napi_callback_info info) {
290 SN_ARGV(3, crypto_sign_seed_keypair)
291
292 SN_ARGV_TYPEDARRAY(pk, 0)
293 SN_ARGV_TYPEDARRAY(sk, 1)
294 SN_ARGV_TYPEDARRAY(seed, 2)
295
296 SN_ASSERT_LENGTH(pk_size, crypto_sign_PUBLICKEYBYTES, "pk")
297 SN_ASSERT_LENGTH(sk_size, crypto_sign_SECRETKEYBYTES, "sk")
298 SN_ASSERT_LENGTH(seed_size, crypto_sign_SEEDBYTES, "seed")
299
300 SN_RETURN(crypto_sign_seed_keypair(pk_data, sk_data, seed_data), "keypair generation failed")
301}
302
303napi_value sn_crypto_sign(napi_env env, napi_callback_info info) {
304 SN_ARGV(3, crypto_sign)
305
306 SN_ARGV_TYPEDARRAY(sm, 0)
307 SN_ARGV_TYPEDARRAY(m, 1)
308 SN_ARGV_TYPEDARRAY(sk, 2)
309
310 SN_THROWS(sm_size != crypto_sign_BYTES + m_size, "sm must be 'm.byteLength + crypto_sign_BYTES' bytes")
311 SN_ASSERT_LENGTH(sk_size, crypto_sign_SECRETKEYBYTES, "sk")
312
313 SN_RETURN(crypto_sign(sm_data, NULL, m_data, m_size, sk_data), "signature failed")
314}
315
316napi_value sn_crypto_sign_open(napi_env env, napi_callback_info info) {
317 SN_ARGV(3, crypto_sign_open)
318
319 SN_ARGV_TYPEDARRAY(m, 0)
320 SN_ARGV_TYPEDARRAY(sm, 1)
321 SN_ARGV_TYPEDARRAY(pk, 2)
322
323 SN_THROWS(m_size != sm_size - crypto_sign_BYTES, "m must be 'sm.byteLength - crypto_sign_BYTES' bytes")
324 SN_ASSERT_MIN_LENGTH(sm_size, crypto_sign_BYTES, "sm")
325 SN_ASSERT_LENGTH(pk_size, crypto_sign_PUBLICKEYBYTES, "pk")
326
327 SN_RETURN_BOOLEAN(crypto_sign_open(m_data, NULL, sm_data, sm_size, pk_data))
328}
329
330napi_value sn_crypto_sign_detached(napi_env env, napi_callback_info info) {
331 SN_ARGV(3, crypto_sign_detached)
332
333 SN_ARGV_TYPEDARRAY(sig, 0)
334 SN_ARGV_TYPEDARRAY(m, 1)
335 SN_ARGV_TYPEDARRAY(sk, 2)
336
337 SN_ASSERT_LENGTH(sig_size, crypto_sign_BYTES, "sm")
338 SN_ASSERT_LENGTH(sk_size, crypto_sign_SECRETKEYBYTES, "sk")
339
340 SN_RETURN(crypto_sign_detached(sig_data, NULL, m_data, m_size, sk_data), "signature failed")
341}
342
343napi_value sn_crypto_sign_verify_detached(napi_env env, napi_callback_info info) {
344 SN_ARGV(3, crypto_sign_verify_detached)
345
346 SN_ARGV_TYPEDARRAY(sig, 0)
347 SN_ARGV_TYPEDARRAY(m, 1)
348 SN_ARGV_TYPEDARRAY(pk, 2)
349
350 SN_ASSERT_MIN_LENGTH(sig_size, crypto_sign_BYTES, "sig")
351 SN_ASSERT_LENGTH(pk_size, crypto_sign_PUBLICKEYBYTES, "pk")
352
353 SN_RETURN_BOOLEAN(crypto_sign_verify_detached(sig_data, m_data, m_size, pk_data))
354}
355
356napi_value sn_crypto_sign_ed25519_sk_to_pk(napi_env env, napi_callback_info info) {
357 SN_ARGV(2, crypto_sign_ed25519_sk_to_pk)
358
359 SN_ARGV_TYPEDARRAY(pk, 0)
360 SN_ARGV_TYPEDARRAY(sk, 1)
361
362 SN_ASSERT_LENGTH(pk_size, crypto_sign_PUBLICKEYBYTES, "pk")
363 SN_ASSERT_LENGTH(sk_size, crypto_sign_SECRETKEYBYTES, "sk")
364
365 SN_RETURN(crypto_sign_ed25519_sk_to_pk(pk_data, sk_data), "public key generation failed")
366}
367
368napi_value sn_crypto_sign_ed25519_pk_to_curve25519(napi_env env, napi_callback_info info) {
369 SN_ARGV(2, crypto_sign_ed25519_sk_to_pk)
370
371 SN_ARGV_TYPEDARRAY(x25519_pk, 0)
372 SN_ARGV_TYPEDARRAY(ed25519_pk, 1)
373
374 SN_ASSERT_LENGTH(x25519_pk_size, crypto_box_PUBLICKEYBYTES, "x25519_pk")
375 SN_ASSERT_LENGTH(ed25519_pk_size, crypto_sign_PUBLICKEYBYTES, "ed25519_pk")
376
377 SN_RETURN(crypto_sign_ed25519_pk_to_curve25519(x25519_pk_data, ed25519_pk_data), "public key conversion failed")
378}
379
380napi_value sn_crypto_sign_ed25519_sk_to_curve25519(napi_env env, napi_callback_info info) {
381 SN_ARGV(2, crypto_sign_ed25519_sk_to_pk)
382
383 SN_ARGV_TYPEDARRAY(x25519_sk, 0)
384 SN_ARGV_TYPEDARRAY(ed25519_sk, 1)
385
386 SN_ASSERT_LENGTH(x25519_sk_size, crypto_box_SECRETKEYBYTES, "x25519_sk")
387 SN_THROWS(ed25519_sk_size != crypto_sign_SECRETKEYBYTES && ed25519_sk_size != crypto_box_SECRETKEYBYTES, "ed25519_sk should either be 'crypto_sign_SECRETKEYBYTES' bytes or 'crypto_sign_SECRETKEYBYTES - crypto_sign_PUBLICKEYBYTES' bytes")
388
389 SN_RETURN(crypto_sign_ed25519_sk_to_curve25519(x25519_sk_data, ed25519_sk_data), "secret key conversion failed")
390}
391
392napi_value sn_crypto_generichash(napi_env env, napi_callback_info info) {
393 SN_ARGV_OPTS(2, 3, crypto_generichash)
394
395 SN_ARGV_TYPEDARRAY(out, 0)
396 SN_ARGV_TYPEDARRAY(in, 1)
397
398 SN_ASSERT_MIN_LENGTH(out_size, crypto_generichash_BYTES_MIN, "out")
399 SN_ASSERT_MAX_LENGTH(out_size, crypto_generichash_BYTES_MAX, "out")
400
401 void *key_data = NULL;
402 size_t key_size = 0;
403
404 if (argc == 3) {
405 SN_OPT_ARGV_TYPEDARRAY(key, 2)
406 SN_THROWS(key_size < crypto_generichash_KEYBYTES_MIN, "key")
407 SN_ASSERT_MIN_LENGTH(key_size, crypto_generichash_KEYBYTES_MIN, "key")
408 SN_ASSERT_MAX_LENGTH(key_size, crypto_generichash_KEYBYTES_MAX, "key")
409 }
410
411 SN_RETURN(crypto_generichash(out_data, out_size, in_data, in_size, key_data, key_size), "hash failed")
412}
413
414napi_value sn_crypto_generichash_batch(napi_env env, napi_callback_info info) {
415 SN_ARGV_OPTS(2, 3, crypto_generichash)
416
417 SN_ARGV_TYPEDARRAY(out, 0)
418
419 uint32_t batch_length;
420 napi_get_array_length(env, argv[1], &batch_length);
421
422 SN_ASSERT_MIN_LENGTH(out_size, crypto_generichash_BYTES_MIN, "out")
423 SN_ASSERT_MAX_LENGTH(out_size, crypto_generichash_BYTES_MAX, "out")
424
425 void *key_data = NULL;
426 size_t key_size = 0;
427
428 if (argc == 3) {
429 SN_OPT_ARGV_TYPEDARRAY(key, 2)
430 SN_ASSERT_MIN_LENGTH(key_size, crypto_generichash_KEYBYTES_MIN, "key")
431 SN_ASSERT_MAX_LENGTH(key_size, crypto_generichash_KEYBYTES_MAX, "key")
432 }
433
434 crypto_generichash_state state;
435 crypto_generichash_init(&state, key_data, key_size, out_size);
436 for (uint32_t i = 0; i < batch_length; i++) {
437 napi_value element;
438 napi_get_element(env, argv[1], i, &element);
439 SN_TYPEDARRAY_ASSERT(buf, element, "batch element should be passed as a TypedArray")
440 SN_TYPEDARRAY(buf, element)
441 crypto_generichash_update(&state, buf_data, buf_size);
442 }
443
444 SN_RETURN(crypto_generichash_final(&state, out_data, out_size), "batch failed")
445}
446
447napi_value sn_crypto_generichash_keygen(napi_env env, napi_callback_info info) {
448 SN_ARGV(1, crypto_generichash_keygen)
449
450 SN_ARGV_TYPEDARRAY(key, 0)
451
452 SN_ASSERT_LENGTH(key_size, crypto_generichash_KEYBYTES, "key")
453
454 crypto_generichash_keygen(key_data);
455
456 return NULL;
457}
458
459napi_value sn_crypto_generichash_init(napi_env env, napi_callback_info info) {
460 SN_ARGV(3, crypto_generichash_init)
461
462 SN_ARGV_BUFFER_CAST(crypto_generichash_state *, state, 0)
463 SN_ARGV_OPTS_TYPEDARRAY(key, 1)
464 SN_ARGV_UINT32(outlen, 2)
465
466 SN_THROWS(state_size != sizeof(crypto_generichash_state), "state must be 'crypto_generichash_STATEBYTES' bytes")
467
468 if (key_data != NULL) {
469 SN_ASSERT_MIN_LENGTH(key_size, crypto_generichash_KEYBYTES_MIN, "key")
470 SN_ASSERT_MAX_LENGTH(key_size, crypto_generichash_KEYBYTES_MAX, "key")
471 }
472
473 SN_RETURN(crypto_generichash_init(state, key_data, key_size, outlen), "hash failed to initialise")
474}
475
476napi_value sn_crypto_generichash_update(napi_env env, napi_callback_info info) {
477 SN_ARGV(2, crypto_generichash_update)
478
479 SN_ARGV_BUFFER_CAST(crypto_generichash_state *, state, 0)
480 SN_ARGV_TYPEDARRAY(in, 1)
481
482 SN_THROWS(state_size != sizeof(crypto_generichash_state), "state must be 'crypto_generichash_STATEBYTES' bytes")
483
484 SN_RETURN(crypto_generichash_update(state, in_data, in_size), "update failed")
485}
486
487napi_value sn_crypto_generichash_final(napi_env env, napi_callback_info info) {
488 SN_ARGV(2, crypto_generichash_final)
489
490 SN_ARGV_BUFFER_CAST(crypto_generichash_state *, state, 0)
491 SN_ARGV_TYPEDARRAY(out, 1)
492
493 SN_THROWS(state_size != sizeof(crypto_generichash_state), "state must be 'crypto_generichash_STATEBYTES' bytes")
494
495 SN_RETURN(crypto_generichash_final(state, out_data, out_size), "digest failed")
496}
497
498napi_value sn_crypto_box_keypair(napi_env env, napi_callback_info info) {
499 SN_ARGV(2, crypto_box_keypair)
500
501 SN_ARGV_TYPEDARRAY(pk, 0)
502 SN_ARGV_TYPEDARRAY(sk, 1)
503
504 SN_ASSERT_LENGTH(pk_size, crypto_box_PUBLICKEYBYTES, "pk")
505 SN_ASSERT_LENGTH(sk_size, crypto_box_SECRETKEYBYTES, "sk")
506
507 SN_RETURN(crypto_box_keypair(pk_data, sk_data), "keypair generation failed")
508}
509
510napi_value sn_crypto_box_seed_keypair(napi_env env, napi_callback_info info) {
511 SN_ARGV(3, crypto_box_seed_keypair)
512
513 SN_ARGV_TYPEDARRAY(pk, 0)
514 SN_ARGV_TYPEDARRAY(sk, 1)
515 SN_ARGV_TYPEDARRAY(seed, 2)
516
517 SN_ASSERT_LENGTH(pk_size, crypto_box_PUBLICKEYBYTES, "pk")
518 SN_ASSERT_LENGTH(sk_size, crypto_box_SECRETKEYBYTES, "sk")
519 SN_ASSERT_LENGTH(seed_size, crypto_box_SEEDBYTES, "seed")
520
521 SN_RETURN(crypto_box_seed_keypair(pk_data, sk_data, seed_data), "keypair generation failed")
522}
523
524napi_value sn_crypto_box_easy(napi_env env, napi_callback_info info) {
525 SN_ARGV(5, crypto_box_easy)
526
527 SN_ARGV_TYPEDARRAY(c, 0)
528 SN_ARGV_TYPEDARRAY(m, 1)
529 SN_ARGV_TYPEDARRAY(n, 2)
530 SN_ARGV_TYPEDARRAY(pk, 3)
531 SN_ARGV_TYPEDARRAY(sk, 4)
532
533 SN_THROWS(c_size != m_size + crypto_box_MACBYTES, "c must be 'm.byteLength + crypto_box_MACBYTES' bytes")
534 SN_ASSERT_LENGTH(n_size, crypto_box_NONCEBYTES, "n")
535 SN_ASSERT_LENGTH(sk_size, crypto_box_SECRETKEYBYTES, "sk")
536 SN_ASSERT_LENGTH(pk_size, crypto_box_PUBLICKEYBYTES, "pk")
537
538 SN_RETURN(crypto_box_easy(c_data, m_data, m_size, n_data, pk_data, sk_data), "crypto box failed")
539}
540
541napi_value sn_crypto_box_open_easy(napi_env env, napi_callback_info info) {
542 SN_ARGV(5, crypto_box_open_easy)
543
544 SN_ARGV_TYPEDARRAY(m, 0)
545 SN_ARGV_TYPEDARRAY(c, 1)
546 SN_ARGV_TYPEDARRAY(n, 2)
547 SN_ARGV_TYPEDARRAY(pk, 3)
548 SN_ARGV_TYPEDARRAY(sk, 4)
549
550 SN_THROWS(m_size != c_size - crypto_box_MACBYTES, "m must be 'c.byteLength - crypto_box_MACBYTES' bytes")
551 SN_ASSERT_MIN_LENGTH(c_size, crypto_box_MACBYTES, "c")
552 SN_ASSERT_LENGTH(n_size, crypto_box_NONCEBYTES, "n")
553 SN_ASSERT_LENGTH(sk_size, crypto_box_SECRETKEYBYTES, "sk")
554 SN_ASSERT_LENGTH(pk_size, crypto_box_PUBLICKEYBYTES, "pk")
555
556 SN_RETURN_BOOLEAN(crypto_box_open_easy(m_data, c_data, c_size, n_data, pk_data, sk_data))
557}
558
559napi_value sn_crypto_box_detached(napi_env env, napi_callback_info info) {
560 SN_ARGV(6, crypto_box_detached)
561
562 SN_ARGV_TYPEDARRAY(c, 0)
563 SN_ARGV_TYPEDARRAY(mac, 1)
564 SN_ARGV_TYPEDARRAY(m, 2)
565 SN_ARGV_TYPEDARRAY(n, 3)
566 SN_ARGV_TYPEDARRAY(pk, 4)
567 SN_ARGV_TYPEDARRAY(sk, 5)
568
569 SN_THROWS(c_size != m_size, "c must be 'm.byteLength' bytes")
570 SN_ASSERT_LENGTH(mac_size, crypto_box_MACBYTES, "mac")
571 SN_ASSERT_LENGTH(n_size, crypto_box_NONCEBYTES, "n")
572 SN_ASSERT_LENGTH(sk_size, crypto_box_SECRETKEYBYTES, "sk")
573 SN_ASSERT_LENGTH(pk_size, crypto_box_PUBLICKEYBYTES, "pk")
574
575 SN_RETURN(crypto_box_detached(c_data, mac_data, m_data, m_size, n_data, pk_data, sk_data), "signature failed")
576}
577
578napi_value sn_crypto_box_open_detached(napi_env env, napi_callback_info info) {
579 SN_ARGV(6, crypto_box_open_detached)
580
581 SN_ARGV_TYPEDARRAY(m, 0)
582 SN_ARGV_TYPEDARRAY(c, 1)
583 SN_ARGV_TYPEDARRAY(mac, 2)
584 SN_ARGV_TYPEDARRAY(n, 3)
585 SN_ARGV_TYPEDARRAY(pk, 4)
586 SN_ARGV_TYPEDARRAY(sk, 5)
587
588 SN_THROWS(m_size != c_size, "m must be 'c.byteLength' bytes")
589 SN_ASSERT_LENGTH(mac_size, crypto_box_MACBYTES, "mac")
590 SN_ASSERT_LENGTH(n_size, crypto_box_NONCEBYTES, "n")
591 SN_ASSERT_LENGTH(sk_size, crypto_box_SECRETKEYBYTES, "sk")
592 SN_ASSERT_LENGTH(pk_size, crypto_box_PUBLICKEYBYTES, "pk")
593
594 SN_RETURN_BOOLEAN(crypto_box_open_detached(m_data, c_data, mac_data, c_size, n_data, pk_data, sk_data))
595}
596
597napi_value sn_crypto_box_seal(napi_env env, napi_callback_info info) {
598 SN_ARGV(3, crypto_box_seal)
599
600 SN_ARGV_TYPEDARRAY(c, 0)
601 SN_ARGV_TYPEDARRAY(m, 1)
602 SN_ARGV_TYPEDARRAY(pk, 2)
603
604 SN_THROWS(c_size != m_size + crypto_box_SEALBYTES, "c must be 'm.byteLength + crypto_box_SEALBYTES' bytes")
605 SN_ASSERT_LENGTH(pk_size, crypto_box_PUBLICKEYBYTES, "pk")
606
607 SN_RETURN(crypto_box_seal(c_data, m_data, m_size, pk_data), "failed to create seal")
608}
609
610napi_value sn_crypto_box_seal_open(napi_env env, napi_callback_info info) {
611 SN_ARGV(4, crypto_box_seal_open)
612
613 SN_ARGV_TYPEDARRAY(m, 0)
614 SN_ARGV_TYPEDARRAY(c, 1)
615 SN_ARGV_TYPEDARRAY(pk, 2)
616 SN_ARGV_TYPEDARRAY(sk, 3)
617
618 SN_THROWS(m_size != c_size - crypto_box_SEALBYTES, "m must be 'c.byteLength - crypto_box_SEALBYTES' bytes")
619 SN_ASSERT_MIN_LENGTH(c_size, crypto_box_SEALBYTES, "c")
620 SN_ASSERT_LENGTH(sk_size, crypto_box_SECRETKEYBYTES, "sk")
621 SN_ASSERT_LENGTH(pk_size, crypto_box_PUBLICKEYBYTES, "pk")
622
623 SN_RETURN_BOOLEAN(crypto_box_seal_open(m_data, c_data, c_size, pk_data, sk_data))
624}
625
626napi_value sn_crypto_secretbox_easy(napi_env env, napi_callback_info info) {
627 SN_ARGV(4, crypto_secretbox_easy)
628
629 SN_ARGV_TYPEDARRAY(c, 0)
630 SN_ARGV_TYPEDARRAY(m, 1)
631 SN_ARGV_TYPEDARRAY(n, 2)
632 SN_ARGV_TYPEDARRAY(k, 3)
633
634 SN_THROWS(c_size != m_size + crypto_secretbox_MACBYTES, "c must be 'm.byteLength + crypto_secretbox_MACBYTES' bytes")
635 SN_ASSERT_LENGTH(n_size, crypto_secretbox_NONCEBYTES, "n")
636 SN_ASSERT_LENGTH(k_size, crypto_secretbox_KEYBYTES, "k")
637
638 SN_RETURN(crypto_secretbox_easy(c_data, m_data, m_size, n_data, k_data), "crypto secretbox failed")
639}
640
641napi_value sn_crypto_secretbox_open_easy(napi_env env, napi_callback_info info) {
642 SN_ARGV(4, crypto_secretbox_open_easy)
643
644 SN_ARGV_TYPEDARRAY(m, 0)
645 SN_ARGV_TYPEDARRAY(c, 1)
646 SN_ARGV_TYPEDARRAY(n, 2)
647 SN_ARGV_TYPEDARRAY(k, 3)
648
649 SN_THROWS(m_size != c_size - crypto_secretbox_MACBYTES, "m must be 'c - crypto_secretbox_MACBYTES' bytes")
650 SN_ASSERT_MIN_LENGTH(c_size, crypto_secretbox_MACBYTES, "c")
651 SN_ASSERT_LENGTH(n_size, crypto_secretbox_NONCEBYTES, "n")
652 SN_ASSERT_LENGTH(k_size, crypto_secretbox_KEYBYTES, "k")
653
654 SN_RETURN_BOOLEAN(crypto_secretbox_open_easy(m_data, c_data, c_size, n_data, k_data))
655}
656
657napi_value sn_crypto_secretbox_detached(napi_env env, napi_callback_info info) {
658 SN_ARGV(5, crypto_secretbox_detached)
659
660 SN_ARGV_TYPEDARRAY(c, 0)
661 SN_ARGV_TYPEDARRAY(mac, 1)
662 SN_ARGV_TYPEDARRAY(m, 2)
663 SN_ARGV_TYPEDARRAY(n, 3)
664 SN_ARGV_TYPEDARRAY(k, 4)
665
666 SN_THROWS(c_size != m_size, "c must 'm.byteLength' bytes")
667 SN_ASSERT_LENGTH(mac_size, crypto_secretbox_MACBYTES, "mac")
668 SN_ASSERT_LENGTH(n_size, crypto_secretbox_NONCEBYTES, "n")
669 SN_ASSERT_LENGTH(k_size, crypto_secretbox_KEYBYTES, "k")
670
671 SN_RETURN(crypto_secretbox_detached(c_data, mac_data, m_data, m_size, n_data, k_data), "failed to open box")
672}
673
674napi_value sn_crypto_secretbox_open_detached(napi_env env, napi_callback_info info) {
675 SN_ARGV(5, crypto_secretbox_open_detached)
676
677 SN_ARGV_TYPEDARRAY(m, 0)
678 SN_ARGV_TYPEDARRAY(c, 1)
679 SN_ARGV_TYPEDARRAY(mac, 2)
680 SN_ARGV_TYPEDARRAY(n, 3)
681 SN_ARGV_TYPEDARRAY(k, 4)
682
683 SN_THROWS(m_size != c_size, "m must be 'c.byteLength' bytes")
684 SN_ASSERT_LENGTH(mac_size, crypto_secretbox_MACBYTES, "mac")
685 SN_ASSERT_LENGTH(n_size, crypto_secretbox_NONCEBYTES, "n")
686 SN_ASSERT_LENGTH(k_size, crypto_secretbox_KEYBYTES, "k")
687
688 SN_RETURN_BOOLEAN(crypto_secretbox_open_detached(m_data, c_data, mac_data, c_size, n_data, k_data))
689}
690
691napi_value sn_crypto_stream(napi_env env, napi_callback_info info) {
692 SN_ARGV(3, crypto_stream)
693
694 SN_ARGV_TYPEDARRAY(c, 0)
695 SN_ARGV_TYPEDARRAY(n, 1)
696 SN_ARGV_TYPEDARRAY(k, 2)
697
698 SN_ASSERT_LENGTH(n_size, crypto_stream_NONCEBYTES, "n")
699 SN_ASSERT_LENGTH(k_size, crypto_stream_KEYBYTES, "k")
700
701 SN_RETURN(crypto_stream(c_data, c_size, n_data, k_data), "stream encryption failed")
702}
703
704napi_value sn_crypto_stream_xor(napi_env env, napi_callback_info info) {
705 SN_ARGV(4, crypto_stream_xor)
706
707 SN_ARGV_TYPEDARRAY(c, 0)
708 SN_ARGV_TYPEDARRAY(m, 1)
709 SN_ARGV_TYPEDARRAY(n, 2)
710 SN_ARGV_TYPEDARRAY(k, 3)
711
712 SN_THROWS(c_size != m_size, "m must be 'c.byteLength' bytes")
713 SN_ASSERT_LENGTH(n_size, crypto_stream_NONCEBYTES, "n")
714 SN_ASSERT_LENGTH(k_size, crypto_stream_KEYBYTES, "k")
715
716 SN_RETURN(crypto_stream_xor(c_data, m_data, m_size, n_data, k_data), "stream encryption failed")
717}
718
719napi_value sn_crypto_stream_chacha20(napi_env env, napi_callback_info info) {
720 SN_ARGV(3, crypto_stream_chacha20)
721
722 SN_ARGV_TYPEDARRAY(c, 0)
723 SN_ARGV_TYPEDARRAY(n, 1)
724 SN_ARGV_TYPEDARRAY(k, 2)
725
726 SN_ASSERT_LENGTH(n_size, crypto_stream_chacha20_NONCEBYTES, "n")
727 SN_ASSERT_LENGTH(k_size, crypto_stream_chacha20_KEYBYTES, "k")
728
729 SN_RETURN(crypto_stream_chacha20(c_data, c_size, n_data, k_data), "stream encryption failed")
730}
731
732napi_value sn_crypto_stream_chacha20_xor (napi_env env, napi_callback_info info) {
733 SN_ARGV(4, crypto_stream_chacha20_xor)
734
735 SN_ARGV_TYPEDARRAY(c, 0)
736 SN_ARGV_TYPEDARRAY(m, 1)
737 SN_ARGV_TYPEDARRAY(n, 2)
738 SN_ARGV_TYPEDARRAY(k, 3)
739
740 SN_THROWS(c_size != m_size, "m must be 'c.byteLength' bytes")
741 SN_ASSERT_LENGTH(n_size, crypto_stream_chacha20_NONCEBYTES, "n")
742 SN_ASSERT_LENGTH(k_size, crypto_stream_chacha20_KEYBYTES, "k")
743
744 SN_RETURN(crypto_stream_chacha20_xor(c_data, m_data, m_size, n_data, k_data), "stream encryption failed")
745}
746
747napi_value sn_crypto_stream_chacha20_xor_ic(napi_env env, napi_callback_info info) {
748 SN_ARGV(5, crypto_stream_chacha20_xor_ic)
749
750 SN_ARGV_TYPEDARRAY(c, 0)
751 SN_ARGV_TYPEDARRAY(m, 1)
752 SN_ARGV_TYPEDARRAY(n, 2)
753 SN_ARGV_UINT32(ic, 3)
754 SN_ARGV_TYPEDARRAY(k, 4)
755
756 SN_THROWS(c_size != m_size, "m must be 'c.byteLength' bytes")
757 SN_ASSERT_LENGTH(n_size, crypto_stream_chacha20_NONCEBYTES, "n")
758 SN_ASSERT_LENGTH(k_size, crypto_stream_chacha20_KEYBYTES, "k")
759
760 SN_RETURN(crypto_stream_chacha20_xor_ic(c_data, m_data, m_size, n_data, ic, k_data), "stream encryption failed")
761}
762
763napi_value sn_crypto_stream_chacha20_ietf(napi_env env, napi_callback_info info) {
764 SN_ARGV(3, crypto_stream_chacha20_ietf)
765
766 SN_ARGV_TYPEDARRAY(c, 0)
767 SN_ARGV_TYPEDARRAY(n, 1)
768 SN_ARGV_TYPEDARRAY(k, 2)
769
770 SN_ASSERT_LENGTH(n_size, crypto_stream_chacha20_ietf_NONCEBYTES, "n")
771 SN_ASSERT_LENGTH(k_size, crypto_stream_chacha20_ietf_KEYBYTES, "k")
772
773 SN_RETURN(crypto_stream_chacha20_ietf(c_data, c_size, n_data, k_data), "stream encryption failed")
774}
775
776napi_value sn_crypto_stream_chacha20_ietf_xor(napi_env env, napi_callback_info info) {
777 SN_ARGV(4, crypto_stream_chacha20_ietf_xor)
778
779 SN_ARGV_TYPEDARRAY(c, 0)
780 SN_ARGV_TYPEDARRAY(m, 1)
781 SN_ARGV_TYPEDARRAY(n, 2)
782 SN_ARGV_TYPEDARRAY(k, 3)
783
784 SN_THROWS(c_size != m_size, "m must be 'c.byteLength' bytes")
785 SN_ASSERT_LENGTH(n_size, crypto_stream_chacha20_ietf_NONCEBYTES, "n")
786 SN_ASSERT_LENGTH(k_size, crypto_stream_chacha20_ietf_KEYBYTES, "k")
787
788 SN_RETURN(crypto_stream_chacha20_ietf_xor(c_data, m_data, m_size, n_data, k_data), "stream encryption failed")
789}
790
791napi_value sn_crypto_stream_chacha20_ietf_xor_ic(napi_env env, napi_callback_info info) {
792 SN_ARGV(5, crypto_stream_chacha20_ietf_xor_ic)
793
794 SN_ARGV_TYPEDARRAY(c, 0)
795 SN_ARGV_TYPEDARRAY(m, 1)
796 SN_ARGV_TYPEDARRAY(n, 2)
797 SN_ARGV_UINT32(ic, 3)
798 SN_ARGV_TYPEDARRAY(k, 4)
799
800 SN_THROWS(c_size != m_size, "m must be 'c.byteLength' bytes")
801 SN_ASSERT_LENGTH(n_size, crypto_stream_chacha20_ietf_NONCEBYTES, "n")
802 SN_ASSERT_LENGTH(k_size, crypto_stream_chacha20_ietf_KEYBYTES, "k")
803
804 SN_RETURN(crypto_stream_chacha20_ietf_xor_ic(c_data, m_data, m_size, n_data, ic, k_data), "stream encryption failed")
805}
806
807napi_value sn_crypto_stream_xchacha20(napi_env env, napi_callback_info info) {
808 SN_ARGV(3, crypto_stream_xchacha20)
809
810 SN_ARGV_TYPEDARRAY(c, 0)
811 SN_ARGV_TYPEDARRAY(n, 1)
812 SN_ARGV_TYPEDARRAY(k, 2)
813
814 SN_ASSERT_LENGTH(n_size, crypto_stream_xchacha20_NONCEBYTES, "n")
815 SN_ASSERT_LENGTH(k_size, crypto_stream_xchacha20_KEYBYTES, "k")
816
817 SN_RETURN(crypto_stream_xchacha20(c_data, c_size, n_data, k_data), "stream encryption failed")
818}
819
820napi_value sn_crypto_stream_xchacha20_xor (napi_env env, napi_callback_info info) {
821 SN_ARGV(4, crypto_stream_xchacha20_xor)
822
823 SN_ARGV_TYPEDARRAY(c, 0)
824 SN_ARGV_TYPEDARRAY(m, 1)
825 SN_ARGV_TYPEDARRAY(n, 2)
826 SN_ARGV_TYPEDARRAY(k, 3)
827
828 SN_THROWS(c_size != m_size, "m must be 'c.byteLength' bytes")
829 SN_ASSERT_LENGTH(n_size, crypto_stream_xchacha20_NONCEBYTES, "n")
830 SN_ASSERT_LENGTH(k_size, crypto_stream_xchacha20_KEYBYTES, "k")
831
832 SN_RETURN(crypto_stream_xchacha20_xor(c_data, m_data, m_size, n_data, k_data), "stream encryption failed")
833}
834
835napi_value sn_crypto_stream_xchacha20_xor_ic(napi_env env, napi_callback_info info) {
836 SN_ARGV(5, crypto_stream_xchacha20_xor_ic)
837
838 SN_ARGV_TYPEDARRAY(c, 0)
839 SN_ARGV_TYPEDARRAY(m, 1)
840 SN_ARGV_TYPEDARRAY(n, 2)
841 SN_ARGV_UINT32(ic, 3)
842 SN_ARGV_TYPEDARRAY(k, 4)
843
844 SN_THROWS(c_size != m_size, "m must be 'c.byteLength' bytes")
845 SN_ASSERT_LENGTH(n_size, crypto_stream_xchacha20_NONCEBYTES, "n")
846 SN_ASSERT_LENGTH(k_size, crypto_stream_xchacha20_KEYBYTES, "k")
847
848 SN_RETURN(crypto_stream_xchacha20_xor_ic(c_data, m_data, m_size, n_data, ic, k_data), "stream encryption failed")
849}
850
851napi_value sn_crypto_stream_salsa20(napi_env env, napi_callback_info info) {
852 SN_ARGV(3, crypto_stream_salsa20)
853
854 SN_ARGV_TYPEDARRAY(c, 0)
855 SN_ARGV_TYPEDARRAY(n, 1)
856 SN_ARGV_TYPEDARRAY(k, 2)
857
858 SN_ASSERT_LENGTH(n_size, crypto_stream_salsa20_NONCEBYTES, "n")
859 SN_ASSERT_LENGTH(k_size, crypto_stream_salsa20_KEYBYTES, "k")
860
861 SN_RETURN(crypto_stream_salsa20(c_data, c_size, n_data, k_data), "stream encryption failed")
862}
863
864napi_value sn_crypto_stream_salsa20_xor (napi_env env, napi_callback_info info) {
865 SN_ARGV(4, crypto_stream_salsa20_xor)
866
867 SN_ARGV_TYPEDARRAY(c, 0)
868 SN_ARGV_TYPEDARRAY(m, 1)
869 SN_ARGV_TYPEDARRAY(n, 2)
870 SN_ARGV_TYPEDARRAY(k, 3)
871
872 SN_THROWS(c_size != m_size, "m must be 'c.byteLength' bytes")
873 SN_ASSERT_LENGTH(n_size, crypto_stream_salsa20_NONCEBYTES, "n")
874 SN_ASSERT_LENGTH(k_size, crypto_stream_salsa20_KEYBYTES, "k")
875
876 SN_RETURN(crypto_stream_salsa20_xor(c_data, m_data, m_size, n_data, k_data), "stream encryption failed")
877}
878
879napi_value sn_crypto_stream_salsa20_xor_ic(napi_env env, napi_callback_info info) {
880 SN_ARGV(5, crypto_stream_salsa20_xor_ic)
881
882 SN_ARGV_TYPEDARRAY(c, 0)
883 SN_ARGV_TYPEDARRAY(m, 1)
884 SN_ARGV_TYPEDARRAY(n, 2)
885 SN_ARGV_UINT32(ic, 3)
886 SN_ARGV_TYPEDARRAY(k, 4)
887
888 SN_THROWS(c_size != m_size, "m must be 'c.byteLength' bytes")
889 SN_ASSERT_LENGTH(n_size, crypto_stream_salsa20_NONCEBYTES, "n")
890 SN_ASSERT_LENGTH(k_size, crypto_stream_salsa20_KEYBYTES, "k")
891
892 SN_RETURN(crypto_stream_salsa20_xor_ic(c_data, m_data, m_size, n_data, ic, k_data), "stream encryption failed")
893}
894
895napi_value sn_crypto_auth (napi_env env, napi_callback_info info) {
896 SN_ARGV(3, crypto_auth)
897
898 SN_ARGV_TYPEDARRAY(out, 0)
899 SN_ARGV_TYPEDARRAY(in, 1)
900 SN_ARGV_TYPEDARRAY(k, 2)
901
902 SN_ASSERT_LENGTH(out_size, crypto_auth_BYTES, "out")
903 SN_ASSERT_LENGTH(k_size, crypto_auth_KEYBYTES, "k")
904
905 SN_RETURN(crypto_auth(out_data, in_data, in_size, k_data), "failed to generate authentication tag")
906}
907
908napi_value sn_crypto_auth_verify (napi_env env, napi_callback_info info) {
909 SN_ARGV(3, crypto_auth_verify)
910
911 SN_ARGV_TYPEDARRAY(h, 0)
912 SN_ARGV_TYPEDARRAY(in, 1)
913 SN_ARGV_TYPEDARRAY(k, 2)
914
915 SN_ASSERT_LENGTH(h_size, crypto_auth_BYTES, "h")
916 SN_ASSERT_LENGTH(k_size, crypto_auth_KEYBYTES, "k")
917
918 SN_RETURN_BOOLEAN(crypto_auth_verify(h_data, in_data, in_size, k_data))
919}
920
921napi_value sn_crypto_onetimeauth (napi_env env, napi_callback_info info) {
922 SN_ARGV(3, crypto_onetimeauth)
923
924 SN_ARGV_TYPEDARRAY(out, 0)
925 SN_ARGV_TYPEDARRAY(in, 1)
926 SN_ARGV_TYPEDARRAY(k, 2)
927
928 SN_ASSERT_LENGTH(out_size, crypto_onetimeauth_BYTES, "out")
929 SN_ASSERT_LENGTH(k_size, crypto_onetimeauth_KEYBYTES, "k")
930
931 SN_RETURN(crypto_onetimeauth(out_data, in_data, in_size, k_data), "failed to generate onetime authentication tag")
932}
933
934napi_value sn_crypto_onetimeauth_init (napi_env env, napi_callback_info info) {
935 SN_ARGV(2, crypto_onetimeauth_init)
936
937 SN_ARGV_BUFFER_CAST(crypto_onetimeauth_state *, state, 0)
938 SN_ARGV_TYPEDARRAY(k, 1)
939
940 SN_THROWS(state_size != sizeof(crypto_onetimeauth_state), "state must be 'crypto_onetimeauth_STATEBYTES' bytes")
941 SN_ASSERT_LENGTH(k_size, crypto_onetimeauth_KEYBYTES, "k")
942
943 SN_RETURN(crypto_onetimeauth_init(state, k_data), "failed to initialise onetime authentication")
944}
945
946napi_value sn_crypto_onetimeauth_update(napi_env env, napi_callback_info info) {
947 SN_ARGV(2, crypto_onetimeauth_update)
948
949 SN_ARGV_BUFFER_CAST(crypto_onetimeauth_state *, state, 0)
950 SN_ARGV_TYPEDARRAY(in, 1)
951
952 SN_THROWS(state_size != sizeof(crypto_onetimeauth_state), "state must be 'crypto_onetimeauth_STATEBYTES' bytes")
953
954 SN_RETURN(crypto_onetimeauth_update(state, in_data, in_size), "update failed")
955}
956
957napi_value sn_crypto_onetimeauth_final(napi_env env, napi_callback_info info) {
958 SN_ARGV(2, crypto_onetimeauth_final)
959
960 SN_ARGV_BUFFER_CAST(crypto_onetimeauth_state *, state, 0)
961 SN_ARGV_TYPEDARRAY(out, 1)
962
963 SN_THROWS(state_size != sizeof(crypto_onetimeauth_state), "state must be 'crypto_onetimeauth_STATEBYTES' bytes")
964 SN_ASSERT_LENGTH(out_size, crypto_onetimeauth_BYTES, "out")
965
966 SN_RETURN(crypto_onetimeauth_final(state, out_data), "failed to generate authentication tag")
967}
968
969napi_value sn_crypto_onetimeauth_verify (napi_env env, napi_callback_info info) {
970 SN_ARGV(3, crypto_onetimeauth_verify)
971
972 SN_ARGV_TYPEDARRAY(h, 0)
973 SN_ARGV_TYPEDARRAY(in, 1)
974 SN_ARGV_TYPEDARRAY(k, 2)
975
976 SN_ASSERT_LENGTH(h_size, crypto_onetimeauth_BYTES, "h")
977 SN_ASSERT_LENGTH(k_size, crypto_onetimeauth_KEYBYTES, "k")
978
979 SN_RETURN_BOOLEAN(crypto_onetimeauth_verify(h_data, in_data, in_size, k_data))
980}
981
982// CHECK: memlimit can be >32bit
983napi_value sn_crypto_pwhash (napi_env env, napi_callback_info info) {
984 SN_ARGV(6, crypto_pwhash)
985
986 SN_ARGV_TYPEDARRAY(out, 0)
987 SN_ARGV_TYPEDARRAY(passwd, 1)
988 SN_ARGV_TYPEDARRAY(salt, 2)
989 SN_ARGV_UINT64(opslimit, 3)
990 SN_ARGV_UINT64(memlimit, 4)
991 SN_ARGV_UINT8(alg, 5)
992
993 SN_ASSERT_MIN_LENGTH(out_size, crypto_pwhash_BYTES_MIN, "out")
994 SN_ASSERT_MAX_LENGTH(out_size, crypto_pwhash_BYTES_MAX, "out")
995 SN_ASSERT_LENGTH(salt_size, crypto_pwhash_SALTBYTES, "salt")
996 SN_ASSERT_MIN_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MIN, "opslimit")
997 SN_ASSERT_MAX_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MAX, "opslimit")
998 SN_ASSERT_MIN_LENGTH(memlimit, crypto_pwhash_MEMLIMIT_MIN, "memlimit")
999 SN_ASSERT_MAX_LENGTH(memlimit, (int64_t) crypto_pwhash_MEMLIMIT_MAX, "memlimit")
1000 SN_THROWS(alg < 1 || alg > 2, "alg must be either Argon2i 1.3 or Argon2id 1.3")
1001
1002 SN_RETURN(crypto_pwhash(out_data, out_size, passwd_data, passwd_size, salt_data, opslimit, memlimit, alg), "password hashing failed, check memory requirements.")
1003}
1004
1005napi_value sn_crypto_pwhash_str (napi_env env, napi_callback_info info) {
1006 SN_ARGV(4, crypto_pwhash_str)
1007
1008 SN_ARGV_TYPEDARRAY(out, 0)
1009 SN_ARGV_TYPEDARRAY(passwd, 1)
1010 SN_ARGV_UINT64(opslimit, 2)
1011 SN_ARGV_UINT64(memlimit, 3)
1012
1013 SN_ASSERT_LENGTH(out_size, crypto_pwhash_STRBYTES, "out")
1014 SN_ASSERT_MIN_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MIN, "opslimit")
1015 SN_ASSERT_MAX_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MAX, "opslimit")
1016 SN_ASSERT_MIN_LENGTH(memlimit, crypto_pwhash_MEMLIMIT_MIN, "memlimit")
1017 SN_ASSERT_MAX_LENGTH(memlimit, (int64_t) crypto_pwhash_MEMLIMIT_MAX, "memlimit")
1018
1019 SN_RETURN(crypto_pwhash_str(out_data, passwd_data, passwd_size, opslimit, memlimit), "password hashing failed, check memory requirements.")
1020}
1021
1022napi_value sn_crypto_pwhash_str_verify (napi_env env, napi_callback_info info) {
1023 SN_ARGV(2, crypto_pwhash_str_verify)
1024
1025 SN_ARGV_TYPEDARRAY(str, 0)
1026 SN_ARGV_TYPEDARRAY(passwd, 1)
1027
1028 SN_ASSERT_LENGTH(str_size, crypto_pwhash_STRBYTES, "str")
1029
1030 SN_RETURN_BOOLEAN(crypto_pwhash_str_verify(str_data, passwd_data, passwd_size))
1031}
1032
1033// CHECK: returns 1, 0, -1
1034napi_value sn_crypto_pwhash_str_needs_rehash (napi_env env, napi_callback_info info) {
1035 SN_ARGV(3, crypto_pwhash_str_needs_rehash)
1036
1037 SN_ARGV_TYPEDARRAY(str, 0)
1038 SN_ARGV_UINT64(opslimit, 1)
1039 SN_ARGV_UINT64(memlimit, 2)
1040
1041 SN_ASSERT_LENGTH(str_size, crypto_pwhash_STRBYTES, "str")
1042 SN_ASSERT_MIN_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MIN, "opslimit")
1043 SN_ASSERT_MAX_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MAX, "opslimit")
1044 SN_ASSERT_MIN_LENGTH(memlimit, crypto_pwhash_MEMLIMIT_MIN, "memlimit")
1045 SN_ASSERT_MAX_LENGTH(memlimit, (int64_t) crypto_pwhash_MEMLIMIT_MAX, "memlimit")
1046
1047 SN_RETURN_BOOLEAN_FROM_1(crypto_pwhash_str_needs_rehash(str_data, opslimit, memlimit))
1048}
1049
1050// CHECK: memlimit can be >32bit
1051napi_value sn_crypto_pwhash_scryptsalsa208sha256 (napi_env env, napi_callback_info info) {
1052 SN_ARGV(5, crypto_pwhash_scryptsalsa208sha256)
1053
1054 SN_ARGV_TYPEDARRAY(out, 0)
1055 SN_ARGV_TYPEDARRAY(passwd, 1)
1056 SN_ARGV_TYPEDARRAY(salt, 2)
1057 SN_ARGV_UINT64(opslimit, 3)
1058 SN_ARGV_UINT64(memlimit, 4)
1059
1060 SN_ASSERT_MIN_LENGTH(out_size, crypto_pwhash_scryptsalsa208sha256_BYTES_MIN, "out")
1061 SN_ASSERT_MAX_LENGTH(out_size, crypto_pwhash_scryptsalsa208sha256_BYTES_MAX, "out")
1062 SN_ASSERT_LENGTH(salt_size, crypto_pwhash_scryptsalsa208sha256_SALTBYTES, "salt")
1063 SN_ASSERT_MIN_LENGTH(opslimit, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN, "opslimit")
1064 SN_ASSERT_MAX_LENGTH(opslimit, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX, "opslimit")
1065 SN_ASSERT_MIN_LENGTH(memlimit, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN, "memlimit")
1066 SN_ASSERT_MAX_LENGTH(memlimit, (int64_t) crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX, "memlimit")
1067
1068 SN_RETURN(crypto_pwhash_scryptsalsa208sha256(out_data, out_size, passwd_data, passwd_size, salt_data, opslimit, memlimit), "password hashing failed, check memory requirements.")
1069}
1070
1071napi_value sn_crypto_pwhash_scryptsalsa208sha256_str (napi_env env, napi_callback_info info) {
1072 SN_ARGV(4, crypto_pwhash_scryptsalsa208sha256_str)
1073
1074 SN_ARGV_TYPEDARRAY(out, 0)
1075 SN_ARGV_TYPEDARRAY(passwd, 1)
1076 SN_ARGV_UINT64(opslimit, 2)
1077 SN_ARGV_UINT64(memlimit, 3)
1078
1079 SN_ASSERT_LENGTH(out_size, crypto_pwhash_scryptsalsa208sha256_STRBYTES, "out")
1080 SN_ASSERT_MIN_LENGTH(opslimit, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN, "opslimit")
1081 SN_ASSERT_MAX_LENGTH(opslimit, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX, "opslimit")
1082 SN_ASSERT_MIN_LENGTH(memlimit, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN, "memlimit")
1083 SN_ASSERT_MAX_LENGTH(memlimit, (int64_t) crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX, "memlimit")
1084
1085 SN_RETURN(crypto_pwhash_scryptsalsa208sha256_str(out_data, passwd_data, passwd_size, opslimit, memlimit), "password hashing failed, check memory requirements.")
1086}
1087
1088napi_value sn_crypto_pwhash_scryptsalsa208sha256_str_verify (napi_env env, napi_callback_info info) {
1089 SN_ARGV(2, crypto_pwhash_scryptsalsa208sha256_str_verify)
1090
1091 SN_ARGV_TYPEDARRAY(str, 0)
1092 SN_ARGV_TYPEDARRAY(passwd, 1)
1093
1094 SN_ASSERT_LENGTH(str_size, crypto_pwhash_scryptsalsa208sha256_STRBYTES, "str")
1095
1096 SN_RETURN_BOOLEAN(crypto_pwhash_scryptsalsa208sha256_str_verify(str_data, passwd_data, passwd_size))
1097}
1098
1099napi_value sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash (napi_env env, napi_callback_info info) {
1100 SN_ARGV(3, crypto_pwhash_scryptsalsa208sha256_str_needs_rehash)
1101
1102 SN_ARGV_TYPEDARRAY(str, 0)
1103 SN_ARGV_UINT64(opslimit, 1)
1104 SN_ARGV_UINT64(memlimit, 2)
1105
1106 SN_ASSERT_LENGTH(str_size, crypto_pwhash_scryptsalsa208sha256_STRBYTES, "str")
1107 SN_ASSERT_MIN_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MIN, "opslimit")
1108 SN_ASSERT_MAX_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MAX, "opslimit")
1109 SN_ASSERT_MIN_LENGTH(memlimit, crypto_pwhash_MEMLIMIT_MIN, "memlimit")
1110 SN_ASSERT_MAX_LENGTH(memlimit, (int64_t) crypto_pwhash_MEMLIMIT_MAX, "memlimit")
1111
1112 SN_RETURN_BOOLEAN_FROM_1(crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str_data, opslimit, memlimit))
1113}
1114
1115napi_value sn_crypto_kx_keypair (napi_env env, napi_callback_info info) {
1116 SN_ARGV(2, crypto_kx_keypair)
1117
1118 SN_ARGV_TYPEDARRAY(pk, 0)
1119 SN_ARGV_TYPEDARRAY(sk, 1)
1120
1121 SN_ASSERT_LENGTH(pk_size, crypto_kx_PUBLICKEYBYTES, "pk")
1122 SN_ASSERT_LENGTH(sk_size, crypto_kx_SECRETKEYBYTES, "sk")
1123
1124 SN_RETURN(crypto_kx_keypair(pk_data, sk_data), "failed to generate keypair")
1125}
1126
1127napi_value sn_crypto_kx_seed_keypair (napi_env env, napi_callback_info info) {
1128 SN_ARGV(3, crypto_kx_seed_keypair)
1129
1130 SN_ARGV_TYPEDARRAY(pk, 0)
1131 SN_ARGV_TYPEDARRAY(sk, 1)
1132 SN_ARGV_TYPEDARRAY(seed, 2)
1133
1134 SN_ASSERT_LENGTH(pk_size, crypto_kx_PUBLICKEYBYTES, "pk")
1135 SN_ASSERT_LENGTH(sk_size, crypto_kx_SECRETKEYBYTES, "sk")
1136 SN_ASSERT_LENGTH(seed_size, crypto_kx_SEEDBYTES, "seed")
1137
1138 SN_RETURN(crypto_kx_seed_keypair(pk_data, sk_data, seed_data), "failed to derive keypair from seed")
1139}
1140
1141napi_value sn_crypto_kx_client_session_keys (napi_env env, napi_callback_info info) {
1142 SN_ARGV(5, crypto_kx_client_session_keys)
1143
1144 SN_ARGV_OPTS_TYPEDARRAY(rx, 0)
1145 SN_ARGV_OPTS_TYPEDARRAY(tx, 1)
1146
1147 SN_THROWS(rx_data == NULL && tx_data == NULL, "at least one session key must be specified")
1148
1149 SN_ARGV_TYPEDARRAY(client_pk, 2)
1150 SN_ARGV_TYPEDARRAY(client_sk, 3)
1151 SN_ARGV_TYPEDARRAY(server_pk, 4)
1152
1153 SN_ASSERT_LENGTH(client_pk_size, crypto_kx_PUBLICKEYBYTES, "client_pk")
1154 SN_ASSERT_LENGTH(client_sk_size, crypto_kx_SECRETKEYBYTES, "client_sk")
1155 SN_ASSERT_LENGTH(server_pk_size, crypto_kx_PUBLICKEYBYTES, "server_pk")
1156
1157 SN_THROWS(tx_size != crypto_kx_SESSIONKEYBYTES && tx_data != NULL, "transmitting key buffer must be 'crypto_kx_SESSIONKEYBYTES' bytes or null")
1158 SN_THROWS(rx_size != crypto_kx_SESSIONKEYBYTES && rx_data != NULL, "receiving key buffer must be 'crypto_kx_SESSIONKEYBYTES' bytes or null")
1159
1160 SN_RETURN(crypto_kx_client_session_keys(rx_data, tx_data, client_pk_data, client_sk_data, server_pk_data), "failed to derive session keys")
1161}
1162
1163napi_value sn_crypto_kx_server_session_keys (napi_env env, napi_callback_info info) {
1164 SN_ARGV(5, crypto_kx_server_session_keys)
1165
1166 SN_ARGV_OPTS_TYPEDARRAY(rx, 0)
1167 SN_ARGV_OPTS_TYPEDARRAY(tx, 1)
1168
1169 SN_THROWS(rx_data == NULL && tx_data == NULL, "at least one session key must be specified")
1170
1171 SN_ARGV_TYPEDARRAY(server_pk, 2)
1172 SN_ARGV_TYPEDARRAY(server_sk, 3)
1173 SN_ARGV_TYPEDARRAY(client_pk, 4)
1174
1175 SN_ASSERT_LENGTH(server_pk_size, crypto_kx_PUBLICKEYBYTES, "server_pk")
1176 SN_ASSERT_LENGTH(server_sk_size, crypto_kx_SECRETKEYBYTES, "server_sk")
1177 SN_ASSERT_LENGTH(client_pk_size, crypto_kx_PUBLICKEYBYTES, "client_pk")
1178
1179 SN_THROWS(tx_size != crypto_kx_SESSIONKEYBYTES && tx_data != NULL, "transmitting key buffer must be 'crypto_kx_SESSIONKEYBYTES' bytes or null")
1180 SN_THROWS(rx_size != crypto_kx_SESSIONKEYBYTES && rx_data != NULL, "receiving key buffer must be 'crypto_kx_SESSIONKEYBYTES' bytes or null")
1181
1182 SN_RETURN(crypto_kx_server_session_keys(rx_data, tx_data, server_pk_data, server_sk_data, client_pk_data), "failed to derive session keys")
1183}
1184
1185napi_value sn_crypto_scalarmult_base (napi_env env, napi_callback_info info) {
1186 SN_ARGV(2, crypto_scalarmult_base)
1187
1188 SN_ARGV_TYPEDARRAY(q, 0)
1189 SN_ARGV_TYPEDARRAY(n, 1)
1190
1191 SN_ASSERT_LENGTH(q_size, crypto_scalarmult_BYTES, "q")
1192 SN_ASSERT_LENGTH(n_size, crypto_scalarmult_SCALARBYTES, "n")
1193
1194 SN_RETURN(crypto_scalarmult_base(q_data, n_data), "failed to derive public key")
1195}
1196
1197napi_value sn_crypto_scalarmult (napi_env env, napi_callback_info info) {
1198 SN_ARGV(3, crypto_scalarmult)
1199
1200 SN_ARGV_TYPEDARRAY(q, 0)
1201 SN_ARGV_TYPEDARRAY(n, 1)
1202 SN_ARGV_TYPEDARRAY(p, 2)
1203
1204 SN_ASSERT_LENGTH(q_size, crypto_scalarmult_BYTES, "q")
1205 SN_ASSERT_LENGTH(n_size, crypto_scalarmult_SCALARBYTES, "n")
1206 SN_ASSERT_LENGTH(p_size, crypto_scalarmult_BYTES, "p")
1207
1208 SN_RETURN(crypto_scalarmult(q_data, n_data, p_data), "failed to derive shared secret")
1209}
1210
1211napi_value sn_crypto_scalarmult_ed25519_base (napi_env env, napi_callback_info info) {
1212 SN_ARGV(2, crypto_scalarmult_ed25519_base)
1213
1214 SN_ARGV_TYPEDARRAY(q, 0)
1215 SN_ARGV_TYPEDARRAY(n, 1)
1216
1217 SN_ASSERT_LENGTH(q_size, crypto_scalarmult_ed25519_BYTES, "q")
1218 SN_ASSERT_LENGTH(n_size, crypto_scalarmult_ed25519_SCALARBYTES, "n")
1219
1220 SN_RETURN(crypto_scalarmult_ed25519_base(q_data, n_data), "failed to derive public key")
1221}
1222
1223napi_value sn_crypto_scalarmult_ed25519 (napi_env env, napi_callback_info info) {
1224 SN_ARGV(3, crypto_scalarmult_ed25519)
1225
1226 SN_ARGV_TYPEDARRAY(q, 0)
1227 SN_ARGV_TYPEDARRAY(n, 1)
1228 SN_ARGV_TYPEDARRAY(p, 2)
1229
1230 SN_ASSERT_LENGTH(q_size, crypto_scalarmult_ed25519_BYTES, "q")
1231 SN_ASSERT_LENGTH(n_size, crypto_scalarmult_ed25519_SCALARBYTES, "n")
1232 SN_ASSERT_LENGTH(p_size, crypto_scalarmult_ed25519_BYTES, "p")
1233
1234 SN_RETURN(crypto_scalarmult_ed25519(q_data, n_data, p_data), "failed to derive shared secret")
1235}
1236
1237napi_value sn_crypto_core_ed25519_is_valid_point (napi_env env, napi_callback_info info) {
1238 SN_ARGV(1, crypto_core_ed25519_is_valid_point)
1239
1240 SN_ARGV_TYPEDARRAY(p, 0)
1241
1242 SN_ASSERT_LENGTH(p_size, crypto_core_ed25519_BYTES, "p")
1243
1244 SN_RETURN_BOOLEAN_FROM_1(crypto_core_ed25519_is_valid_point(p_data))
1245}
1246
1247napi_value sn_crypto_core_ed25519_from_uniform (napi_env env, napi_callback_info info) {
1248 SN_ARGV(2, crypto_core_ed25519_from_uniform)
1249
1250 SN_ARGV_TYPEDARRAY(p, 0)
1251 SN_ARGV_TYPEDARRAY(r, 1)
1252
1253 SN_ASSERT_LENGTH(p_size, crypto_core_ed25519_BYTES, "p")
1254 SN_ASSERT_LENGTH(r_size, crypto_core_ed25519_UNIFORMBYTES, "r")
1255
1256 SN_RETURN(crypto_core_ed25519_from_uniform(p_data, r_data), "could not generate curve point from input")
1257}
1258
1259napi_value sn_crypto_scalarmult_ed25519_base_noclamp (napi_env env, napi_callback_info info) {
1260 SN_ARGV(2, crypto_scalarmult_ed25519_base_noclamp)
1261
1262 SN_ARGV_TYPEDARRAY(q, 0)
1263 SN_ARGV_TYPEDARRAY(n, 1)
1264
1265 SN_ASSERT_LENGTH(q_size, crypto_scalarmult_ed25519_BYTES, "q")
1266 SN_ASSERT_LENGTH(n_size, crypto_scalarmult_ed25519_SCALARBYTES, "n")
1267
1268 SN_RETURN(crypto_scalarmult_ed25519_base_noclamp(q_data, n_data), "failed to derive public key")
1269}
1270
1271napi_value sn_crypto_scalarmult_ed25519_noclamp (napi_env env, napi_callback_info info) {
1272 SN_ARGV(3, crypto_scalarmult_ed25519_noclamp)
1273
1274 SN_ARGV_TYPEDARRAY(q, 0)
1275 SN_ARGV_TYPEDARRAY(n, 1)
1276 SN_ARGV_TYPEDARRAY(p, 2)
1277
1278 SN_ASSERT_LENGTH(q_size, crypto_scalarmult_ed25519_BYTES, "q")
1279 SN_ASSERT_LENGTH(n_size, crypto_scalarmult_ed25519_SCALARBYTES, "n")
1280 SN_ASSERT_LENGTH(p_size, crypto_scalarmult_ed25519_BYTES, "p")
1281
1282 SN_RETURN(crypto_scalarmult_ed25519_noclamp(q_data, n_data, p_data), "failed to derive shared secret")
1283}
1284
1285napi_value sn_crypto_core_ed25519_add (napi_env env, napi_callback_info info) {
1286 SN_ARGV(3, crypto_core_ed25519_add)
1287
1288 SN_ARGV_TYPEDARRAY(r, 0)
1289 SN_ARGV_TYPEDARRAY(p, 1)
1290 SN_ARGV_TYPEDARRAY(q, 2)
1291
1292 SN_ASSERT_LENGTH(r_size, crypto_core_ed25519_BYTES, "r")
1293 SN_ASSERT_LENGTH(p_size, crypto_core_ed25519_BYTES, "p")
1294 SN_ASSERT_LENGTH(q_size, crypto_core_ed25519_BYTES, "q")
1295
1296 SN_RETURN(crypto_core_ed25519_add(r_data, p_data, q_data), "could not add curve points")
1297}
1298
1299napi_value sn_crypto_core_ed25519_sub (napi_env env, napi_callback_info info) {
1300 SN_ARGV(3, crypto_core_ed25519_sub)
1301
1302 SN_ARGV_TYPEDARRAY(r, 0)
1303 SN_ARGV_TYPEDARRAY(p, 1)
1304 SN_ARGV_TYPEDARRAY(q, 2)
1305
1306 SN_ASSERT_LENGTH(r_size, crypto_core_ed25519_BYTES, "r")
1307 SN_ASSERT_LENGTH(p_size, crypto_core_ed25519_BYTES, "p")
1308 SN_ASSERT_LENGTH(q_size, crypto_core_ed25519_BYTES, "q")
1309
1310 SN_RETURN(crypto_core_ed25519_sub(r_data, p_data, q_data), "could not add curve points")
1311}
1312
1313napi_value sn_crypto_core_ed25519_scalar_random (napi_env env, napi_callback_info info) {
1314 SN_ARGV(1, crypto_core_ed25519_scalar_random)
1315
1316 SN_ARGV_TYPEDARRAY(r, 0)
1317
1318 SN_ASSERT_LENGTH(r_size, crypto_core_ed25519_SCALARBYTES, "r")
1319
1320 crypto_core_ed25519_scalar_random(r_data);
1321
1322 return NULL;
1323}
1324
1325napi_value sn_crypto_core_ed25519_scalar_reduce (napi_env env, napi_callback_info info) {
1326 SN_ARGV(2, crypto_core_ed25519_scalar_reduce)
1327
1328 SN_ARGV_TYPEDARRAY(r, 0)
1329 SN_ARGV_TYPEDARRAY(s, 1)
1330
1331 SN_ASSERT_LENGTH(r_size, crypto_core_ed25519_SCALARBYTES, "r")
1332 SN_ASSERT_LENGTH(s_size, crypto_core_ed25519_NONREDUCEDSCALARBYTES, "s")
1333
1334 crypto_core_ed25519_scalar_reduce(r_data, s_data);
1335
1336 return NULL;
1337}
1338
1339napi_value sn_crypto_core_ed25519_scalar_invert (napi_env env, napi_callback_info info) {
1340 SN_ARGV(2, crypto_core_ed25519_scalar_invert)
1341
1342 SN_ARGV_TYPEDARRAY(recip, 0)
1343 SN_ARGV_TYPEDARRAY(s, 1)
1344
1345 SN_ASSERT_LENGTH(recip_size, crypto_core_ed25519_SCALARBYTES, "recip")
1346 SN_ASSERT_LENGTH(s_size, crypto_core_ed25519_SCALARBYTES, "s")
1347
1348 crypto_core_ed25519_scalar_invert(recip_data, s_data);
1349
1350 return NULL;
1351}
1352
1353napi_value sn_crypto_core_ed25519_scalar_negate (napi_env env, napi_callback_info info) {
1354 SN_ARGV(2, crypto_core_ed25519_scalar_negate)
1355
1356 SN_ARGV_TYPEDARRAY(neg, 0)
1357 SN_ARGV_TYPEDARRAY(s, 1)
1358
1359 SN_ASSERT_LENGTH(neg_size, crypto_core_ed25519_SCALARBYTES, "neg")
1360 SN_ASSERT_LENGTH(s_size, crypto_core_ed25519_SCALARBYTES, "s")
1361
1362 crypto_core_ed25519_scalar_negate(neg_data, s_data);
1363
1364 return NULL;
1365}
1366
1367napi_value sn_crypto_core_ed25519_scalar_complement (napi_env env, napi_callback_info info) {
1368 SN_ARGV(2, crypto_core_ed25519_scalar_complement)
1369
1370 SN_ARGV_TYPEDARRAY(comp, 0)
1371 SN_ARGV_TYPEDARRAY(s, 1)
1372
1373 SN_ASSERT_LENGTH(comp_size, crypto_core_ed25519_SCALARBYTES, "comp")
1374 SN_ASSERT_LENGTH(s_size, crypto_core_ed25519_SCALARBYTES, "s")
1375
1376 crypto_core_ed25519_scalar_complement(comp_data, s_data);
1377
1378 return NULL;
1379}
1380
1381napi_value sn_crypto_core_ed25519_scalar_add (napi_env env, napi_callback_info info) {
1382 SN_ARGV(3, crypto_core_ed25519_scalar_add)
1383
1384 SN_ARGV_TYPEDARRAY(z, 0)
1385 SN_ARGV_TYPEDARRAY(x, 1)
1386 SN_ARGV_TYPEDARRAY(y, 2)
1387
1388 SN_ASSERT_LENGTH(z_size, crypto_core_ed25519_SCALARBYTES, "z")
1389 SN_ASSERT_LENGTH(x_size, crypto_core_ed25519_SCALARBYTES, "x")
1390 SN_ASSERT_LENGTH(y_size, crypto_core_ed25519_SCALARBYTES, "y")
1391
1392 crypto_core_ed25519_scalar_add(z_data, x_data, y_data);
1393
1394 return NULL;
1395}
1396
1397napi_value sn_crypto_core_ed25519_scalar_sub (napi_env env, napi_callback_info info) {
1398 SN_ARGV(3, crypto_core_ed25519_scalar_sub)
1399
1400 SN_ARGV_TYPEDARRAY(z, 0)
1401 SN_ARGV_TYPEDARRAY(x, 1)
1402 SN_ARGV_TYPEDARRAY(y, 2)
1403
1404 SN_ASSERT_LENGTH(z_size, crypto_core_ed25519_SCALARBYTES, "z")
1405 SN_ASSERT_LENGTH(x_size, crypto_core_ed25519_SCALARBYTES, "x")
1406 SN_ASSERT_LENGTH(y_size, crypto_core_ed25519_SCALARBYTES, "y")
1407
1408 crypto_core_ed25519_scalar_sub(z_data, x_data, y_data);
1409
1410 return NULL;
1411}
1412
1413napi_value sn_crypto_shorthash (napi_env env, napi_callback_info info) {
1414 SN_ARGV(3, crypto_shorthash)
1415
1416 SN_ARGV_TYPEDARRAY(out, 0)
1417 SN_ARGV_TYPEDARRAY(in, 1)
1418 SN_ARGV_TYPEDARRAY(k, 2)
1419
1420 SN_ASSERT_LENGTH(out_size, crypto_shorthash_BYTES, "out")
1421 SN_ASSERT_LENGTH(k_size, crypto_shorthash_KEYBYTES, "k")
1422
1423 SN_RETURN(crypto_shorthash(out_data, in_data, in_size, k_data), "could not compute hash")
1424}
1425
1426napi_value sn_crypto_kdf_keygen (napi_env env, napi_callback_info info) {
1427 SN_ARGV(1, crypto_kdf_keygen)
1428
1429 SN_ARGV_TYPEDARRAY(key, 0)
1430
1431 SN_ASSERT_LENGTH(key_size, crypto_kdf_KEYBYTES, "key")
1432
1433 crypto_kdf_keygen(key_data);
1434
1435 return NULL;
1436}
1437
1438napi_value sn_crypto_kdf_derive_from_key (napi_env env, napi_callback_info info) {
1439 SN_ARGV(4, crypto_kdf_derive_from_key)
1440
1441 SN_ARGV_TYPEDARRAY(subkey, 0)
1442 SN_ARGV_UINT64(subkey_id, 1)
1443 SN_ARGV_TYPEDARRAY(ctx, 2)
1444 SN_ARGV_TYPEDARRAY(key, 3)
1445
1446 SN_ASSERT_MIN_LENGTH(subkey_size, crypto_kdf_BYTES_MIN, "subkey")
1447 SN_ASSERT_MAX_LENGTH(subkey_size, crypto_kdf_BYTES_MAX, "subkey")
1448 SN_ASSERT_LENGTH(ctx_size, crypto_kdf_CONTEXTBYTES, "ctx")
1449 SN_ASSERT_LENGTH(key_size, crypto_kdf_KEYBYTES, "key")
1450
1451 SN_RETURN(crypto_kdf_derive_from_key(subkey_data, subkey_size, subkey_id, ctx_data, key_data), "could not generate key")
1452}
1453
1454napi_value sn_crypto_hash (napi_env env, napi_callback_info info) {
1455 SN_ARGV(2, crypto_hash_sha256)
1456
1457 SN_ARGV_TYPEDARRAY(out, 0)
1458 SN_ARGV_TYPEDARRAY(in, 1)
1459
1460 SN_ASSERT_LENGTH(out_size, crypto_hash_BYTES, "out")
1461
1462 SN_RETURN(crypto_hash(out_data, in_data, in_size), "could not compute hash")
1463}
1464
1465napi_value sn_crypto_hash_sha256 (napi_env env, napi_callback_info info) {
1466 SN_ARGV(2, crypto_hash_sha256)
1467
1468 SN_ARGV_TYPEDARRAY(out, 0)
1469 SN_ARGV_TYPEDARRAY(in, 1)
1470
1471 SN_ASSERT_LENGTH(out_size, crypto_hash_sha256_BYTES, "out")
1472
1473 SN_RETURN(crypto_hash_sha256(out_data, in_data, in_size), "could not compute hash")
1474}
1475
1476napi_value sn_crypto_hash_sha256_init (napi_env env, napi_callback_info info) {
1477 SN_ARGV(1, crypto_hash_sha256_init)
1478
1479 SN_ARGV_BUFFER_CAST(crypto_hash_sha256_state *, state, 0)
1480
1481 SN_THROWS(state_size != sizeof(crypto_hash_sha256_state), "state must be 'crypto_hash_sha256_STATEBYTES' bytes")
1482
1483 SN_RETURN(crypto_hash_sha256_init(state), "failed to initialise sha256")
1484}
1485
1486napi_value sn_crypto_hash_sha256_update(napi_env env, napi_callback_info info) {
1487 SN_ARGV(2, crypto_hash_sha256_update)
1488
1489 SN_ARGV_BUFFER_CAST(crypto_hash_sha256_state *, state, 0)
1490 SN_ARGV_TYPEDARRAY(in, 1)
1491
1492 SN_THROWS(state_size != sizeof(crypto_hash_sha256_state), "state must be 'crypto_hash_sha256_STATEBYTES' bytes")
1493
1494 SN_RETURN(crypto_hash_sha256_update(state, in_data, in_size), "update failed")
1495}
1496
1497napi_value sn_crypto_hash_sha256_final(napi_env env, napi_callback_info info) {
1498 SN_ARGV(2, crypto_hash_sha256_final)
1499
1500 SN_ARGV_BUFFER_CAST(crypto_hash_sha256_state *, state, 0)
1501 SN_ARGV_TYPEDARRAY(out, 1)
1502
1503 SN_THROWS(state_size != sizeof(crypto_hash_sha256_state), "state must be 'crypto_hash_sha256_STATEBYTES' bytes")
1504 SN_ASSERT_LENGTH(out_size, crypto_hash_sha256_BYTES, "state")
1505
1506 SN_RETURN(crypto_hash_sha256_final(state, out_data), "failed to finalise")
1507}
1508
1509napi_value sn_crypto_hash_sha512 (napi_env env, napi_callback_info info) {
1510 SN_ARGV(2, crypto_hash_sha512)
1511
1512 SN_ARGV_TYPEDARRAY(out, 0)
1513 SN_ARGV_TYPEDARRAY(in, 1)
1514
1515 SN_ASSERT_LENGTH(out_size, crypto_hash_sha512_BYTES, "out")
1516
1517 SN_RETURN(crypto_hash_sha512(out_data, in_data, in_size), "could not compute hash")
1518}
1519
1520napi_value sn_crypto_hash_sha512_init (napi_env env, napi_callback_info info) {
1521 SN_ARGV(1, crypto_hash_sha512_init)
1522
1523 SN_ARGV_BUFFER_CAST(crypto_hash_sha512_state *, state, 0)
1524
1525 SN_THROWS(state_size != sizeof(crypto_hash_sha512_state), "state must be 'crypto_hash_sha256_STATEBYTES' bytes")
1526
1527 SN_RETURN(crypto_hash_sha512_init(state), "failed to initialise sha512")
1528}
1529
1530napi_value sn_crypto_hash_sha512_update(napi_env env, napi_callback_info info) {
1531 SN_ARGV(2, crypto_hash_sha512_update)
1532
1533 SN_ARGV_BUFFER_CAST(crypto_hash_sha512_state *, state, 0)
1534 SN_ARGV_TYPEDARRAY(in, 1)
1535
1536 SN_THROWS(state_size != sizeof(crypto_hash_sha512_state), "state must be 'crypto_hash_sha256_STATEBYTES' bytes")
1537
1538 SN_RETURN(crypto_hash_sha512_update(state, in_data, in_size), "update failed")
1539}
1540
1541napi_value sn_crypto_hash_sha512_final(napi_env env, napi_callback_info info) {
1542 SN_ARGV(2, crypto_hash_sha512_final)
1543
1544 SN_ARGV_BUFFER_CAST(crypto_hash_sha512_state *, state, 0)
1545 SN_ARGV_TYPEDARRAY(out, 1)
1546
1547 SN_THROWS(state_size != sizeof(crypto_hash_sha512_state), "state must be 'crypto_hash_sha256_STATEBYTES' bytes")
1548 SN_ASSERT_LENGTH(out_size, crypto_hash_sha512_BYTES, "out")
1549
1550 SN_RETURN(crypto_hash_sha512_final(state, out_data), "failed to finalise hash")
1551}
1552
1553napi_value sn_crypto_aead_xchacha20poly1305_ietf_keygen (napi_env env, napi_callback_info info) {
1554 SN_ARGV(1, crypto_aead_xchacha20poly1305_ietf_keygen)
1555
1556 SN_ARGV_TYPEDARRAY(k, 0)
1557
1558 SN_ASSERT_LENGTH(k_size, crypto_aead_xchacha20poly1305_ietf_KEYBYTES, "k")
1559
1560 crypto_aead_xchacha20poly1305_ietf_keygen(k_data);
1561 return NULL;
1562}
1563
1564napi_value sn_crypto_aead_xchacha20poly1305_ietf_encrypt (napi_env env, napi_callback_info info) {
1565 SN_ARGV(6, crypto_aead_xchacha20poly1305_ietf_encrypt)
1566
1567 SN_ARGV_TYPEDARRAY(c, 0)
1568 SN_ARGV_TYPEDARRAY(m, 1)
1569 SN_ARGV_OPTS_TYPEDARRAY(ad, 2)
1570 SN_ARGV_CHECK_NULL(nsec, 3)
1571 SN_ARGV_TYPEDARRAY(npub, 4)
1572 SN_ARGV_TYPEDARRAY(k, 5)
1573
1574 SN_THROWS(!nsec_is_null, "nsec must always be set to null")
1575
1576 SN_THROWS(c_size != m_size + crypto_aead_xchacha20poly1305_ietf_ABYTES, "c must 'm.byteLength + crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes")
1577 SN_THROWS(c_size > 0xffffffff, "c.byteLength must be a 32bit integer")
1578 SN_ASSERT_LENGTH(npub_size, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, "npub")
1579 SN_ASSERT_LENGTH(k_size, crypto_aead_xchacha20poly1305_ietf_KEYBYTES, "k")
1580
1581 unsigned long long clen;
1582 SN_CALL(crypto_aead_xchacha20poly1305_ietf_encrypt(c_data, &clen, m_data, m_size, ad_data, ad_size, NULL, npub_data, k_data), "could not encrypt data")
1583
1584 napi_value result;
1585 SN_STATUS_THROWS(napi_create_uint32(env, (uint32_t) clen, &result), "")
1586 return result;
1587}
1588
1589napi_value sn_crypto_aead_xchacha20poly1305_ietf_decrypt (napi_env env, napi_callback_info info) {
1590 SN_ARGV(6, crypto_aead_xchacha20poly1305_ietf_decrypt)
1591
1592 SN_ARGV_TYPEDARRAY(m, 0)
1593 SN_ARGV_CHECK_NULL(nsec, 1)
1594 SN_ARGV_TYPEDARRAY(c, 2)
1595 SN_ARGV_OPTS_TYPEDARRAY(ad, 3)
1596 SN_ARGV_TYPEDARRAY(npub, 4)
1597 SN_ARGV_TYPEDARRAY(k, 5)
1598
1599 SN_THROWS(!nsec_is_null, "nsec must always be set to null")
1600
1601 SN_THROWS(m_size != c_size - crypto_aead_xchacha20poly1305_ietf_ABYTES, "m must 'c.byteLength - crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes")
1602 SN_ASSERT_LENGTH(npub_size, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, "npub")
1603 SN_ASSERT_LENGTH(k_size, crypto_aead_xchacha20poly1305_ietf_KEYBYTES, "k")
1604 SN_THROWS(m_size > 0xffffffff, "m.byteLength must be a 32bit integer")
1605
1606 unsigned long long mlen;
1607 SN_CALL(crypto_aead_xchacha20poly1305_ietf_decrypt(m_data, &mlen, NULL, c_data, c_size, ad_data, ad_size, npub_data, k_data), "could not verify data")
1608
1609 napi_value result;
1610 SN_STATUS_THROWS(napi_create_uint32(env, (uint32_t) mlen, &result), "")
1611 return result;
1612}
1613
1614napi_value sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached (napi_env env, napi_callback_info info) {
1615 SN_ARGV(7, crypto_aead_xchacha20poly1305_ietf_encrypt_detached)
1616
1617 SN_ARGV_TYPEDARRAY(c, 0)
1618 SN_ARGV_TYPEDARRAY(mac, 1)
1619 SN_ARGV_TYPEDARRAY(m, 2)
1620 SN_ARGV_OPTS_TYPEDARRAY(ad, 3)
1621 SN_ARGV_CHECK_NULL(nsec, 4)
1622 SN_ARGV_TYPEDARRAY(npub, 5)
1623 SN_ARGV_TYPEDARRAY(k, 6)
1624
1625 SN_THROWS(!nsec_is_null, "nsec must always be set to null")
1626
1627 SN_THROWS(c_size != m_size, "c must be 'm.byteLength' bytes")
1628 SN_ASSERT_LENGTH(mac_size, crypto_aead_xchacha20poly1305_ietf_ABYTES, "mac")
1629 SN_ASSERT_LENGTH(npub_size, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, "npub")
1630 SN_ASSERT_LENGTH(k_size, crypto_aead_xchacha20poly1305_ietf_KEYBYTES, "k")
1631
1632 unsigned long long maclen;
1633 SN_CALL(crypto_aead_xchacha20poly1305_ietf_encrypt_detached(c_data, mac_data, &maclen, m_data, m_size, ad_data, ad_size, NULL, npub_data, k_data), "could not encrypt data")
1634
1635 napi_value result;
1636 SN_STATUS_THROWS(napi_create_uint32(env, (uint32_t) maclen, &result), "")
1637 return result;
1638}
1639
1640napi_value sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached (napi_env env, napi_callback_info info) {
1641 SN_ARGV(7, crypto_aead_xchacha20poly1305_ietf_decrypt_detached)
1642
1643 SN_ARGV_TYPEDARRAY(m, 0)
1644 SN_ARGV_CHECK_NULL(nsec, 1)
1645 SN_ARGV_TYPEDARRAY(c, 2)
1646 SN_ARGV_TYPEDARRAY(mac, 3)
1647 SN_ARGV_OPTS_TYPEDARRAY(ad, 4)
1648 SN_ARGV_TYPEDARRAY(npub, 5)
1649 SN_ARGV_TYPEDARRAY(k, 6)
1650
1651 SN_THROWS(!nsec_is_null, "nsec must always be set to null")
1652
1653 SN_THROWS(m_size != c_size, "m must be 'c.byteLength' bytes")
1654 SN_ASSERT_LENGTH(mac_size, crypto_aead_xchacha20poly1305_ietf_ABYTES, "mac")
1655 SN_ASSERT_LENGTH(npub_size, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, "npub")
1656 SN_ASSERT_LENGTH(k_size, crypto_aead_xchacha20poly1305_ietf_KEYBYTES, "k")
1657
1658 SN_RETURN(crypto_aead_xchacha20poly1305_ietf_decrypt_detached(m_data, NULL, c_data, c_size, mac_data, ad_data, ad_size, npub_data, k_data), "could not verify data")
1659}
1660
1661napi_value sn_crypto_aead_chacha20poly1305_ietf_keygen (napi_env env, napi_callback_info info) {
1662 SN_ARGV(1, crypto_aead_chacha20poly1305_ietf_keygen)
1663
1664 SN_ARGV_TYPEDARRAY(k, 0)
1665
1666 SN_ASSERT_LENGTH(k_size, crypto_aead_chacha20poly1305_ietf_KEYBYTES, "k")
1667
1668 crypto_aead_chacha20poly1305_ietf_keygen(k_data);
1669 return NULL;
1670}
1671
1672napi_value sn_crypto_aead_chacha20poly1305_ietf_encrypt (napi_env env, napi_callback_info info) {
1673 SN_ARGV(6, crypto_aead_chacha20poly1305_ietf_encrypt)
1674
1675 SN_ARGV_TYPEDARRAY(c, 0)
1676 SN_ARGV_TYPEDARRAY(m, 1)
1677 SN_ARGV_OPTS_TYPEDARRAY(ad, 2)
1678 SN_ARGV_CHECK_NULL(nsec, 3)
1679 SN_ARGV_TYPEDARRAY(npub, 4)
1680 SN_ARGV_TYPEDARRAY(k, 5)
1681
1682 SN_THROWS(!nsec_is_null, "nsec must always be set to null")
1683
1684 SN_THROWS(c_size != m_size + crypto_aead_chacha20poly1305_ietf_ABYTES, "c must 'm.byteLength + crypto_aead_chacha20poly1305_ietf_ABYTES' bytes")
1685 SN_THROWS(c_size > 0xffffffff, "c.byteLength must be a 32bit integer")
1686 SN_ASSERT_LENGTH(npub_size, crypto_aead_chacha20poly1305_ietf_NPUBBYTES, "npub")
1687 SN_ASSERT_LENGTH(k_size, crypto_aead_chacha20poly1305_ietf_KEYBYTES, "k")
1688
1689 unsigned long long clen;
1690 SN_CALL(crypto_aead_chacha20poly1305_ietf_encrypt(c_data, &clen, m_data, m_size, ad_data, ad_size, NULL, npub_data, k_data), "could not encrypt data")
1691
1692 napi_value result;
1693 SN_STATUS_THROWS(napi_create_uint32(env, (uint32_t) clen, &result), "")
1694 return result;
1695}
1696
1697napi_value sn_crypto_aead_chacha20poly1305_ietf_decrypt (napi_env env, napi_callback_info info) {
1698 SN_ARGV(6, crypto_aead_chacha20poly1305_ietf_decrypt)
1699
1700 SN_ARGV_TYPEDARRAY(m, 0)
1701 SN_ARGV_CHECK_NULL(nsec, 1)
1702 SN_ARGV_TYPEDARRAY(c, 2)
1703 SN_ARGV_OPTS_TYPEDARRAY(ad, 3)
1704 SN_ARGV_TYPEDARRAY(npub, 4)
1705 SN_ARGV_TYPEDARRAY(k, 5)
1706
1707 SN_THROWS(!nsec_is_null, "nsec must always be set to null")
1708
1709 SN_THROWS(m_size != c_size - crypto_aead_chacha20poly1305_ietf_ABYTES, "m must 'c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES' bytes")
1710 SN_ASSERT_LENGTH(npub_size, crypto_aead_chacha20poly1305_ietf_NPUBBYTES, "npub")
1711 SN_ASSERT_LENGTH(k_size, crypto_aead_chacha20poly1305_ietf_KEYBYTES, "k")
1712 SN_THROWS(m_size > 0xffffffff, "m.byteLength must be a 32bit integer")
1713
1714 unsigned long long mlen;
1715 SN_CALL(crypto_aead_chacha20poly1305_ietf_decrypt(m_data, &mlen, NULL, c_data, c_size, ad_data, ad_size, npub_data, k_data), "could not verify data")
1716
1717 napi_value result;
1718 SN_STATUS_THROWS(napi_create_uint32(env, (uint32_t) mlen, &result), "")
1719 return result;
1720}
1721
1722napi_value sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached (napi_env env, napi_callback_info info) {
1723 SN_ARGV(7, crypto_aead_chacha20poly1305_ietf_encrypt_detached)
1724
1725 SN_ARGV_TYPEDARRAY(c, 0)
1726 SN_ARGV_TYPEDARRAY(mac, 1)
1727 SN_ARGV_TYPEDARRAY(m, 2)
1728 SN_ARGV_OPTS_TYPEDARRAY(ad, 3)
1729 SN_ARGV_CHECK_NULL(nsec, 4)
1730 SN_ARGV_TYPEDARRAY(npub, 5)
1731 SN_ARGV_TYPEDARRAY(k, 6)
1732
1733 SN_THROWS(!nsec_is_null, "nsec must always be set to null")
1734
1735 SN_THROWS(c_size != m_size, "c must be 'm.byteLength' bytes")
1736 SN_ASSERT_LENGTH(mac_size, crypto_aead_chacha20poly1305_ietf_ABYTES, "mac")
1737 SN_ASSERT_LENGTH(npub_size, crypto_aead_chacha20poly1305_ietf_NPUBBYTES, "npub")
1738 SN_ASSERT_LENGTH(k_size, crypto_aead_chacha20poly1305_ietf_KEYBYTES, "k")
1739
1740 unsigned long long maclen;
1741 SN_CALL(crypto_aead_chacha20poly1305_ietf_encrypt_detached(c_data, mac_data, &maclen, m_data, m_size, ad_data, ad_size, NULL, npub_data, k_data), "could not encrypt data")
1742
1743 napi_value result;
1744 SN_STATUS_THROWS(napi_create_uint32(env, (uint32_t) maclen, &result), "")
1745 return result;
1746}
1747
1748napi_value sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached (napi_env env, napi_callback_info info) {
1749 SN_ARGV(7, crypto_aead_chacha20poly1305_ietf_decrypt_detached)
1750
1751 SN_ARGV_TYPEDARRAY(m, 0)
1752 SN_ARGV_CHECK_NULL(nsec, 1)
1753 SN_ARGV_TYPEDARRAY(c, 2)
1754 SN_ARGV_TYPEDARRAY(mac, 3)
1755 SN_ARGV_OPTS_TYPEDARRAY(ad, 4)
1756 SN_ARGV_TYPEDARRAY(npub, 5)
1757 SN_ARGV_TYPEDARRAY(k, 6)
1758
1759 SN_THROWS(!nsec_is_null, "nsec must always be set to null")
1760
1761 SN_THROWS(m_size != c_size, "m must be 'c.byteLength' bytes")
1762 SN_ASSERT_LENGTH(mac_size, crypto_aead_chacha20poly1305_ietf_ABYTES, "mac")
1763 SN_ASSERT_LENGTH(npub_size, crypto_aead_chacha20poly1305_ietf_NPUBBYTES, "npub")
1764 SN_ASSERT_LENGTH(k_size, crypto_aead_chacha20poly1305_ietf_KEYBYTES, "k")
1765
1766 SN_RETURN(crypto_aead_chacha20poly1305_ietf_decrypt_detached(m_data, NULL, c_data, c_size, mac_data, ad_data, ad_size, npub_data, k_data), "could not verify data")
1767}
1768
1769napi_value sn_crypto_secretstream_xchacha20poly1305_keygen (napi_env env, napi_callback_info info) {
1770 SN_ARGV(1, crypto_secretstream_xchacha20poly1305_keygen)
1771
1772 SN_ARGV_TYPEDARRAY(k, 0)
1773
1774 SN_ASSERT_LENGTH(k_size, crypto_secretstream_xchacha20poly1305_KEYBYTES, "k")
1775
1776 crypto_secretstream_xchacha20poly1305_keygen(k_data);
1777
1778 return NULL;
1779}
1780
1781napi_value sn_crypto_secretstream_xchacha20poly1305_init_push (napi_env env, napi_callback_info info) {
1782 SN_ARGV(3, crypto_secretstream_xchacha20poly1305_init_push)
1783
1784 SN_ARGV_BUFFER_CAST(crypto_secretstream_xchacha20poly1305_state *, state, 0)
1785 SN_ARGV_TYPEDARRAY(header, 1)
1786 SN_ARGV_TYPEDARRAY(k, 2)
1787
1788 SN_THROWS(state_size != sizeof(crypto_secretstream_xchacha20poly1305_state), "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes")
1789 SN_ASSERT_LENGTH(header_size, crypto_secretstream_xchacha20poly1305_HEADERBYTES, "header")
1790 SN_ASSERT_LENGTH(k_size, crypto_secretstream_xchacha20poly1305_KEYBYTES, "k")
1791
1792 SN_RETURN(crypto_secretstream_xchacha20poly1305_init_push(state, header_data, k_data), "initial push failed")
1793}
1794
1795napi_value sn_crypto_secretstream_xchacha20poly1305_push (napi_env env, napi_callback_info info) {
1796 SN_ARGV(5, crypto_secretstream_xchacha20poly1305_push)
1797
1798 SN_ARGV_BUFFER_CAST(crypto_secretstream_xchacha20poly1305_state *, state, 0)
1799 SN_ARGV_TYPEDARRAY(c, 1)
1800 SN_ARGV_TYPEDARRAY(m, 2)
1801 SN_ARGV_OPTS_TYPEDARRAY(ad, 3)
1802 SN_ARGV_UINT8(tag, 4)
1803
1804 SN_THROWS(state_size != sizeof(crypto_secretstream_xchacha20poly1305_state), "state must be state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes")
1805 SN_ASSERT_MAX_LENGTH(m_size, crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX, "m")
1806 SN_THROWS(c_size != m_size + crypto_secretstream_xchacha20poly1305_ABYTES, "c must be 'm.byteLength + crypto_secretstream_xchacha20poly1305_ABYTES' bytes")
1807 SN_THROWS(c_size > 0xffffffff, "c.byteLength must be a 32bit integer")
1808
1809 unsigned long long clen;
1810 SN_CALL(crypto_secretstream_xchacha20poly1305_push(state, c_data, &clen, m_data, m_size, ad_data, ad_size, tag), "push failed")
1811
1812 napi_value result;
1813 SN_STATUS_THROWS(napi_create_uint32(env, (uint32_t) clen, &result), "")
1814 return result;
1815}
1816
1817napi_value sn_crypto_secretstream_xchacha20poly1305_init_pull (napi_env env, napi_callback_info info) {
1818 SN_ARGV(3, crypto_secretstream_xchacha20poly1305_init_pull)
1819
1820 SN_ARGV_BUFFER_CAST(crypto_secretstream_xchacha20poly1305_state *, state, 0)
1821 SN_ARGV_TYPEDARRAY(header, 1)
1822 SN_ARGV_TYPEDARRAY(k, 2)
1823
1824 SN_THROWS(state_size != sizeof(crypto_secretstream_xchacha20poly1305_state), "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes")
1825 SN_ASSERT_LENGTH(header_size, crypto_secretstream_xchacha20poly1305_HEADERBYTES, "header")
1826 SN_ASSERT_LENGTH(k_size, crypto_secretstream_xchacha20poly1305_KEYBYTES, "k")
1827
1828 SN_RETURN(crypto_secretstream_xchacha20poly1305_init_pull(state, header_data, k_data), "initial pull failed")
1829}
1830
1831napi_value sn_crypto_secretstream_xchacha20poly1305_pull (napi_env env, napi_callback_info info) {
1832 SN_ARGV(5, crypto_secretstream_xchacha20poly1305_pull)
1833
1834 SN_ARGV_BUFFER_CAST(crypto_secretstream_xchacha20poly1305_state *, state, 0)
1835 SN_ARGV_TYPEDARRAY(m, 1)
1836 SN_ARGV_TYPEDARRAY(tag, 2)
1837 SN_ARGV_TYPEDARRAY(c, 3)
1838 SN_ARGV_OPTS_TYPEDARRAY(ad, 4)
1839
1840 SN_THROWS(state_size != sizeof(crypto_secretstream_xchacha20poly1305_state), "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes")
1841 SN_ASSERT_MIN_LENGTH(c_size, crypto_secretstream_xchacha20poly1305_ABYTES, "c")
1842 SN_ASSERT_LENGTH(tag_size, 1, "tag")
1843 SN_THROWS(m_size != c_size - crypto_secretstream_xchacha20poly1305_ABYTES, "m must be 'c.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES")
1844 SN_THROWS(m_size > 0xffffffff, "m.byteLength must be a 32bit integer")
1845
1846 unsigned long long mlen;
1847 SN_CALL(crypto_secretstream_xchacha20poly1305_pull(state, m_data, &mlen, tag_data, c_data, c_size, ad_data, ad_size), "pull failed")
1848
1849 napi_value result;
1850 SN_STATUS_THROWS(napi_create_uint32(env, (uint32_t) mlen, &result), "")
1851 return result;
1852}
1853
1854napi_value sn_crypto_secretstream_xchacha20poly1305_rekey (napi_env env, napi_callback_info info) {
1855 SN_ARGV(1, crypto_secretstream_xchacha20poly1305_rekey)
1856
1857 SN_ARGV_BUFFER_CAST(crypto_secretstream_xchacha20poly1305_state *, state, 0)
1858
1859 SN_THROWS(state_size != sizeof(crypto_secretstream_xchacha20poly1305_state), "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes")
1860
1861 crypto_secretstream_xchacha20poly1305_rekey(state);
1862
1863 return NULL;
1864}
1865
1866typedef struct sn_async_task_t {
1867 uv_work_t task;
1868
1869 enum {
1870 sn_async_task_promise,
1871 sn_async_task_callback
1872 } type;
1873
1874 void *req;
1875 int code;
1876
1877 napi_deferred deferred;
1878 napi_ref cb;
1879} sn_async_task_t;
1880
1881typedef struct sn_async_pwhash_request {
1882 napi_env env;
1883 napi_ref out_ref;
1884 unsigned char *out_data;
1885 size_t out_size;
1886 napi_ref pwd_ref;
1887 const char *pwd_data;
1888 size_t pwd_size;
1889 napi_ref salt_ref;
1890 unsigned char *salt;
1891 uint32_t opslimit;
1892 uint32_t memlimit;
1893 uint32_t alg;
1894} sn_async_pwhash_request;
1895
1896static void async_pwhash_execute (uv_work_t *uv_req) {
1897 sn_async_task_t *task = (sn_async_task_t *) uv_req;
1898 sn_async_pwhash_request *req = (sn_async_pwhash_request *) task->req;
1899 task->code = crypto_pwhash(req->out_data,
1900 req->out_size,
1901 req->pwd_data,
1902 req->pwd_size,
1903 req->salt,
1904 req->opslimit,
1905 req->memlimit,
1906 req->alg);
1907}
1908
1909static void async_pwhash_complete (uv_work_t *uv_req, int status) {
1910 sn_async_task_t *task = (sn_async_task_t *) uv_req;
1911 sn_async_pwhash_request *req = (sn_async_pwhash_request *) task->req;
1912
1913 napi_handle_scope scope;
1914 napi_open_handle_scope(req->env, &scope);
1915
1916 napi_value global;
1917 napi_get_global(req->env, &global);
1918
1919 SN_ASYNC_COMPLETE("failed to compute password hash")
1920
1921 napi_close_handle_scope(req->env, scope);
1922
1923 napi_delete_reference(req->env, req->out_ref);
1924 napi_delete_reference(req->env, req->pwd_ref);
1925 napi_delete_reference(req->env, req->salt_ref);
1926
1927 free(req);
1928 free(task);
1929}
1930
1931napi_value sn_crypto_pwhash_async (napi_env env, napi_callback_info info) {
1932 SN_ARGV_OPTS(6, 7, crypto_pwhash_async)
1933
1934 SN_ARGV_BUFFER_CAST(unsigned char *, out, 0)
1935 SN_ARGV_BUFFER_CAST(char *, pwd, 1)
1936 SN_ARGV_BUFFER_CAST(unsigned char *, salt, 2)
1937 SN_ARGV_UINT64(opslimit, 3)
1938 SN_ARGV_UINT64(memlimit, 4)
1939 SN_ARGV_UINT8(alg, 5)
1940
1941 SN_ASSERT_MIN_LENGTH(out_size, crypto_pwhash_BYTES_MIN, "out")
1942 SN_ASSERT_MAX_LENGTH(out_size, crypto_pwhash_BYTES_MAX, "out")
1943 SN_ASSERT_LENGTH(salt_size, crypto_pwhash_SALTBYTES, "salt")
1944 SN_ASSERT_MIN_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MIN, "opslimit")
1945 SN_ASSERT_MAX_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MAX, "opslimit")
1946 SN_ASSERT_MIN_LENGTH(memlimit, crypto_pwhash_MEMLIMIT_MIN, "memlimit")
1947 SN_ASSERT_MAX_LENGTH(memlimit, (int64_t) crypto_pwhash_MEMLIMIT_MAX, "memlimit")
1948 SN_THROWS(alg < 1 || alg > 2, "alg must be either Argon2i 1.3 or Argon2id 1.3")
1949
1950 sn_async_pwhash_request *req = (sn_async_pwhash_request *) malloc(sizeof(sn_async_pwhash_request));
1951
1952 req->env = env;
1953 req->out_data = out;
1954 req->out_size = out_size;
1955 req->pwd_data = pwd;
1956 req->pwd_size = pwd_size;
1957 req->salt = salt;
1958 req->opslimit = opslimit;
1959 req->memlimit = memlimit;
1960 req->alg = alg;
1961
1962 sn_async_task_t *task = (sn_async_task_t *) malloc(sizeof(sn_async_task_t));
1963 SN_ASYNC_TASK(6)
1964
1965 SN_STATUS_THROWS(napi_create_reference(env, out_argv, 1, &req->out_ref), "")
1966 SN_STATUS_THROWS(napi_create_reference(env, pwd_argv, 1, &req->pwd_ref), "")
1967 SN_STATUS_THROWS(napi_create_reference(env, salt_argv, 1, &req->salt_ref), "")
1968
1969 SN_QUEUE_TASK(task, async_pwhash_execute, async_pwhash_complete)
1970
1971 return promise;
1972}
1973
1974typedef struct sn_async_pwhash_str_request {
1975 uv_work_t task;
1976 napi_env env;
1977 napi_ref out_ref;
1978 char *out_data;
1979 napi_ref pwd_ref;
1980 const char *pwd_data;
1981 size_t pwd_size;
1982 uint32_t opslimit;
1983 uint32_t memlimit;
1984} sn_async_pwhash_str_request;
1985
1986static void async_pwhash_str_execute (uv_work_t *uv_req) {
1987 sn_async_task_t *task = (sn_async_task_t *) uv_req;
1988 sn_async_pwhash_str_request *req = (sn_async_pwhash_str_request *) task->req;
1989 task->code = crypto_pwhash_str(req->out_data,
1990 req->pwd_data,
1991 req->pwd_size,
1992 req->opslimit,
1993 req->memlimit);
1994}
1995
1996static void async_pwhash_str_complete (uv_work_t *uv_req, int status) {
1997 sn_async_task_t *task = (sn_async_task_t *) uv_req;
1998 sn_async_pwhash_str_request *req = (sn_async_pwhash_str_request *) task->req;
1999
2000 napi_handle_scope scope;
2001 napi_open_handle_scope(req->env, &scope);
2002
2003 napi_value global;
2004 napi_get_global(req->env, &global);
2005
2006 SN_ASYNC_COMPLETE("failed to compute password hash")
2007
2008 napi_close_handle_scope(req->env, scope);
2009
2010 napi_delete_reference(req->env, req->out_ref);
2011 napi_delete_reference(req->env, req->pwd_ref);
2012
2013 free(req);
2014 free(task);
2015}
2016
2017napi_value sn_crypto_pwhash_str_async (napi_env env, napi_callback_info info) {
2018 SN_ARGV_OPTS(4, 5, crypto_pwhash_str_async)
2019
2020 SN_ARGV_BUFFER_CAST(char *, out, 0)
2021 SN_ARGV_BUFFER_CAST(char *, pwd, 1)
2022 SN_ARGV_UINT64(opslimit, 2)
2023 SN_ARGV_UINT64(memlimit, 3)
2024
2025 SN_ASSERT_LENGTH(out_size, crypto_pwhash_STRBYTES, "out")
2026 SN_ASSERT_MIN_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MIN, "opslimit")
2027 SN_ASSERT_MAX_LENGTH(opslimit, crypto_pwhash_OPSLIMIT_MAX, "opslimit")
2028 SN_ASSERT_MIN_LENGTH(memlimit, crypto_pwhash_MEMLIMIT_MIN, "memlimit")
2029 SN_ASSERT_MAX_LENGTH(memlimit, (int64_t) crypto_pwhash_MEMLIMIT_MAX, "memlimit")
2030
2031 sn_async_pwhash_str_request *req = (sn_async_pwhash_str_request *) malloc(sizeof(sn_async_pwhash_str_request));
2032 req->env = env;
2033 req->out_data = out;
2034 req->pwd_data = pwd;
2035 req->pwd_size = pwd_size;
2036 req->opslimit = opslimit;
2037 req->memlimit = memlimit;
2038
2039 sn_async_task_t *task = (sn_async_task_t *) malloc(sizeof(sn_async_task_t));
2040 SN_ASYNC_TASK(4)
2041
2042 SN_STATUS_THROWS(napi_create_reference(env, out_argv, 1, &req->out_ref), "")
2043 SN_STATUS_THROWS(napi_create_reference(env, pwd_argv, 1, &req->pwd_ref), "")
2044
2045 SN_QUEUE_TASK(task, async_pwhash_str_execute, async_pwhash_str_complete)
2046
2047 return promise;
2048}
2049
2050typedef struct sn_async_pwhash_str_verify_request {
2051 uv_work_t task;
2052 napi_env env;
2053 napi_ref str_ref;
2054 char *str_data;
2055 napi_ref pwd_ref;
2056 const char *pwd_data;
2057 size_t pwd_size;
2058} sn_async_pwhash_str_verify_request;
2059
2060static void async_pwhash_str_verify_execute (uv_work_t *uv_req) {
2061 sn_async_task_t *task = (sn_async_task_t *) uv_req;
2062 sn_async_pwhash_str_verify_request *req = (sn_async_pwhash_str_verify_request *) task->req;
2063 task->code = crypto_pwhash_str_verify(req->str_data, req->pwd_data, req->pwd_size);
2064}
2065
2066static void async_pwhash_str_verify_complete (uv_work_t *uv_req, int status) {
2067 sn_async_task_t *task = (sn_async_task_t *) uv_req;
2068 sn_async_pwhash_str_verify_request *req = (sn_async_pwhash_str_verify_request *) task->req;
2069
2070 napi_handle_scope scope;
2071 napi_open_handle_scope(req->env, &scope);
2072
2073 napi_value global;
2074 napi_get_global(req->env, &global);
2075
2076 napi_value argv[2];
2077
2078 // Due to the way that crypto_pwhash_str_verify signals error different
2079 // from a verification mismatch, we will count all errors as mismatch.
2080 // The other possible error is wrong argument sizes, which is protected
2081 // by macros above
2082 napi_get_null(req->env, &argv[0]);
2083 napi_get_boolean(req->env, task->code == 0, &argv[1]);
2084
2085 switch (task->type) {
2086 case sn_async_task_promise: {
2087 napi_resolve_deferred(req->env, task->deferred, argv[1]);
2088 task->deferred = NULL;
2089 break;
2090 }
2091
2092 case sn_async_task_callback: {
2093 napi_value callback;
2094 napi_get_reference_value(req->env, task->cb, &callback);
2095
2096 napi_value return_val;
2097 SN_CALL_FUNCTION(req->env, global, callback, 2, argv, &return_val)
2098 break;
2099 }
2100 }
2101
2102 napi_close_handle_scope(req->env, scope);
2103
2104 napi_delete_reference(req->env, req->str_ref);
2105 napi_delete_reference(req->env, req->pwd_ref);
2106
2107 free(req);
2108 free(task);
2109}
2110
2111napi_value sn_crypto_pwhash_str_verify_async (napi_env env, napi_callback_info info) {
2112 SN_ARGV_OPTS(2, 3, crypto_pwhash_str_async)
2113
2114 SN_ARGV_BUFFER_CAST(char *, str, 0)
2115 SN_ARGV_BUFFER_CAST(char *, pwd, 1)
2116
2117 SN_ASSERT_LENGTH(str_size, crypto_pwhash_STRBYTES, "str")
2118
2119 sn_async_pwhash_str_verify_request *req = (sn_async_pwhash_str_verify_request *) malloc(sizeof(sn_async_pwhash_str_verify_request));
2120 req->env = env;
2121 req->str_data = str;
2122 req->pwd_data = pwd;
2123 req->pwd_size = pwd_size;
2124
2125 sn_async_task_t *task = (sn_async_task_t *) malloc(sizeof(sn_async_task_t));
2126 SN_ASYNC_TASK(2)
2127
2128 SN_STATUS_THROWS(napi_create_reference(env, str_argv, 1, &req->str_ref), "")
2129 SN_STATUS_THROWS(napi_create_reference(env, pwd_argv, 1, &req->pwd_ref), "")
2130
2131 SN_QUEUE_TASK(task, async_pwhash_str_verify_execute, async_pwhash_str_verify_complete)
2132
2133 return promise;
2134}
2135
2136typedef struct sn_async_pwhash_scryptsalsa208sha256_request {
2137 uv_work_t task;
2138 napi_env env;
2139 napi_ref out_ref;
2140 unsigned char *out_data;
2141 size_t out_size;
2142 napi_ref pwd_ref;
2143 const char *pwd_data;
2144 size_t pwd_size;
2145 napi_ref salt_ref;
2146 unsigned char *salt;
2147 uint32_t opslimit;
2148 uint32_t memlimit;
2149} sn_async_pwhash_scryptsalsa208sha256_request;
2150
2151static void async_pwhash_scryptsalsa208sha256_execute (uv_work_t *uv_req) {
2152 sn_async_task_t *task = (sn_async_task_t *) uv_req;
2153 sn_async_pwhash_scryptsalsa208sha256_request *req = (sn_async_pwhash_scryptsalsa208sha256_request *) task->req;
2154 task->code = crypto_pwhash_scryptsalsa208sha256(req->out_data,
2155 req->out_size,
2156 req-> pwd_data,
2157 req->pwd_size,
2158 req->salt,
2159 req->opslimit,
2160 req->memlimit);
2161}
2162
2163static void async_pwhash_scryptsalsa208sha256_complete (uv_work_t *uv_req, int status) {
2164 sn_async_task_t *task = (sn_async_task_t *) uv_req;
2165 sn_async_pwhash_scryptsalsa208sha256_request *req = (sn_async_pwhash_scryptsalsa208sha256_request *) task->req;
2166
2167 napi_handle_scope scope;
2168 napi_open_handle_scope(req->env, &scope);
2169
2170 napi_value global;
2171 napi_get_global(req->env, &global);
2172
2173 SN_ASYNC_COMPLETE("failed to compute password hash")
2174
2175 napi_close_handle_scope(req->env, scope);
2176
2177 napi_delete_reference(req->env, req->out_ref);
2178 napi_delete_reference(req->env, req->pwd_ref);
2179 napi_delete_reference(req->env, req->salt_ref);
2180
2181 free(req);
2182 free(task);
2183}
2184
2185napi_value sn_crypto_pwhash_scryptsalsa208sha256_async (napi_env env, napi_callback_info info) {
2186 SN_ARGV_OPTS(5, 6, crypto_pwhash_scryptsalsa208sha256_async)
2187
2188 SN_ARGV_BUFFER_CAST(unsigned char *, out, 0)
2189 SN_ARGV_BUFFER_CAST(char *, pwd, 1)
2190 SN_ARGV_BUFFER_CAST(unsigned char *, salt, 2)
2191 SN_ARGV_UINT64(opslimit, 3)
2192 SN_ARGV_UINT64(memlimit, 4)
2193
2194 SN_ASSERT_MIN_LENGTH(out_size, crypto_pwhash_scryptsalsa208sha256_BYTES_MIN, "out")
2195 SN_ASSERT_MAX_LENGTH(out_size, crypto_pwhash_scryptsalsa208sha256_BYTES_MAX, "out")
2196 SN_ASSERT_LENGTH(salt_size, crypto_pwhash_scryptsalsa208sha256_SALTBYTES, "salt")
2197 SN_ASSERT_MIN_LENGTH(opslimit, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN, "opslimit")
2198 SN_ASSERT_MAX_LENGTH(opslimit, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX, "opslimit")
2199 SN_ASSERT_MIN_LENGTH(memlimit, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN, "memlimit")
2200 SN_ASSERT_MAX_LENGTH(memlimit, (int64_t) crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX, "memlimit")
2201
2202 sn_async_pwhash_scryptsalsa208sha256_request *req = (sn_async_pwhash_scryptsalsa208sha256_request *) malloc(sizeof(sn_async_pwhash_scryptsalsa208sha256_request));
2203 req->env = env;
2204 req->out_data = out;
2205 req->out_size = out_size;
2206 req->pwd_data = pwd;
2207 req->pwd_size = pwd_size;
2208 req-> salt = salt;
2209 req->opslimit = opslimit;
2210 req->memlimit = memlimit;
2211
2212 sn_async_task_t *task = (sn_async_task_t *) malloc(sizeof(sn_async_task_t));
2213 SN_ASYNC_TASK(5)
2214
2215 SN_STATUS_THROWS(napi_create_reference(env, out_argv, 1, &req->out_ref), "")
2216 SN_STATUS_THROWS(napi_create_reference(env, pwd_argv, 1, &req->pwd_ref), "")
2217 SN_STATUS_THROWS(napi_create_reference(env, salt_argv, 1, &req->salt_ref), "")
2218
2219 SN_QUEUE_TASK(task, async_pwhash_scryptsalsa208sha256_execute, async_pwhash_scryptsalsa208sha256_complete)
2220
2221 return promise;
2222}
2223
2224typedef struct sn_async_pwhash_scryptsalsa208sha256_str_request {
2225 uv_work_t task;
2226 napi_env env;
2227 napi_ref out_ref;
2228 char *out_data;
2229 napi_ref pwd_ref;
2230 const char *pwd_data;
2231 size_t pwd_size;
2232 uint32_t opslimit;
2233 uint32_t memlimit;
2234} sn_async_pwhash_scryptsalsa208sha256_str_request;
2235
2236static void async_pwhash_scryptsalsa208sha256_str_execute (uv_work_t *uv_req) {
2237 sn_async_task_t *task = (sn_async_task_t *) uv_req;
2238 sn_async_pwhash_scryptsalsa208sha256_str_request *req = (sn_async_pwhash_scryptsalsa208sha256_str_request *) task->req;
2239 task->code = crypto_pwhash_scryptsalsa208sha256_str(req->out_data,
2240 req->pwd_data,
2241 req->pwd_size,
2242 req->opslimit,
2243 req->memlimit);
2244}
2245
2246static void async_pwhash_scryptsalsa208sha256_str_complete (uv_work_t *uv_req, int status) {
2247 sn_async_task_t *task = (sn_async_task_t *) uv_req;
2248 sn_async_pwhash_scryptsalsa208sha256_str_request *req = (sn_async_pwhash_scryptsalsa208sha256_str_request *) task->req;
2249
2250 napi_handle_scope scope;
2251 napi_open_handle_scope(req->env, &scope);
2252
2253 napi_value global;
2254 napi_get_global(req->env, &global);
2255
2256 SN_ASYNC_COMPLETE("failed to compute password hash")
2257
2258 napi_close_handle_scope(req->env, scope);
2259
2260 napi_delete_reference(req->env, req->out_ref);
2261 napi_delete_reference(req->env, req->pwd_ref);
2262
2263 free(req);
2264 free(task);
2265}
2266
2267napi_value sn_crypto_pwhash_scryptsalsa208sha256_str_async (napi_env env, napi_callback_info info) {
2268 SN_ARGV_OPTS(4, 5, crypto_pwhash_scryptsalsa208sha256_str_async)
2269
2270 SN_ARGV_BUFFER_CAST(char *, out, 0)
2271 SN_ARGV_BUFFER_CAST(char *, pwd, 1)
2272 SN_ARGV_UINT64(opslimit, 2)
2273 SN_ARGV_UINT64(memlimit, 3)
2274
2275 SN_ASSERT_LENGTH(out_size, crypto_pwhash_scryptsalsa208sha256_STRBYTES, "out")
2276 SN_ASSERT_MIN_LENGTH(opslimit, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN, "opslimit")
2277 SN_ASSERT_MAX_LENGTH(opslimit, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX, "opslimit")
2278 SN_ASSERT_MIN_LENGTH(memlimit, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN, "memlimit")
2279 SN_ASSERT_MAX_LENGTH(memlimit, (int64_t) crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX, "memlimit")
2280
2281 sn_async_pwhash_scryptsalsa208sha256_str_request *req = (sn_async_pwhash_scryptsalsa208sha256_str_request *) malloc(sizeof(sn_async_pwhash_scryptsalsa208sha256_str_request));
2282 req->env = env;
2283 req->out_data = out;
2284 req->pwd_data = pwd;
2285 req->pwd_size = pwd_size;
2286 req->opslimit = opslimit;
2287 req->memlimit = memlimit;
2288
2289 sn_async_task_t *task = (sn_async_task_t *) malloc(sizeof(sn_async_task_t));
2290 SN_ASYNC_TASK(4)
2291
2292 SN_STATUS_THROWS(napi_create_reference(env, out_argv, 1, &req->out_ref), "")
2293 SN_STATUS_THROWS(napi_create_reference(env, pwd_argv, 1, &req->pwd_ref), "")
2294
2295 SN_QUEUE_TASK(task, async_pwhash_scryptsalsa208sha256_str_execute, async_pwhash_scryptsalsa208sha256_str_complete)
2296
2297 return promise;
2298}
2299
2300typedef struct sn_async_pwhash_scryptsalsa208sha256_str_verify_request {
2301 uv_work_t task;
2302 napi_env env;
2303 napi_ref str_ref;
2304 char *str_data;
2305 napi_ref pwd_ref;
2306 const char *pwd_data;
2307 size_t pwd_size;
2308} sn_async_pwhash_scryptsalsa208sha256_str_verify_request;
2309
2310static void async_pwhash_scryptsalsa208sha256_str_verify_execute (uv_work_t *uv_req) {
2311 sn_async_task_t *task = (sn_async_task_t *) uv_req;
2312 sn_async_pwhash_scryptsalsa208sha256_str_verify_request *req = (sn_async_pwhash_scryptsalsa208sha256_str_verify_request *) task->req;
2313 task->code = crypto_pwhash_scryptsalsa208sha256_str_verify(req->str_data, req->pwd_data, req->pwd_size);
2314}
2315
2316static void async_pwhash_scryptsalsa208sha256_str_verify_complete (uv_work_t *uv_req, int status) {
2317 sn_async_task_t *task = (sn_async_task_t *) uv_req;
2318 sn_async_pwhash_scryptsalsa208sha256_str_verify_request *req = (sn_async_pwhash_scryptsalsa208sha256_str_verify_request *) task->req;
2319
2320 napi_handle_scope scope;
2321 napi_open_handle_scope(req->env, &scope);
2322
2323 napi_value global;
2324 napi_get_global(req->env, &global);
2325
2326 napi_value argv[2];
2327
2328 // Due to the way that crypto_pwhash_scryptsalsa208sha256_str_verify
2329 // signal serror different from a verification mismatch, we will count
2330 // all errors as mismatch. The other possible error is wrong argument
2331 // sizes, which is protected by macros above
2332 napi_get_null(req->env, &argv[0]);
2333 napi_get_boolean(req->env, task->code == 0, &argv[1]);
2334
2335 switch (task->type) {
2336 case sn_async_task_promise: {
2337 napi_resolve_deferred(req->env, task->deferred, argv[1]);
2338 task->deferred = NULL;
2339 break;
2340 }
2341
2342 case sn_async_task_callback: {
2343 napi_value callback;
2344 napi_get_reference_value(req->env, task->cb, &callback);
2345
2346 napi_value return_val;
2347 SN_CALL_FUNCTION(req->env, global, callback, 2, argv, &return_val)
2348 break;
2349 }
2350 }
2351
2352 napi_close_handle_scope(req->env, scope);
2353
2354 napi_delete_reference(req->env, req->str_ref);
2355 napi_delete_reference(req->env, req->pwd_ref);
2356
2357 free(req);
2358 free(task);
2359}
2360
2361napi_value sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async (napi_env env, napi_callback_info info) {
2362 SN_ARGV_OPTS(2, 3, crypto_pwhash_scryptsalsa208sha256_str_async)
2363
2364 SN_ARGV_BUFFER_CAST(char *, str, 0)
2365 SN_ARGV_BUFFER_CAST(char *, pwd, 1)
2366
2367 SN_ASSERT_LENGTH(str_size, crypto_pwhash_scryptsalsa208sha256_STRBYTES, "str")
2368
2369 sn_async_pwhash_scryptsalsa208sha256_str_verify_request *req = (sn_async_pwhash_scryptsalsa208sha256_str_verify_request *) malloc(sizeof(sn_async_pwhash_scryptsalsa208sha256_str_verify_request));
2370 req->env = env;
2371 req->str_data = str;
2372 req->pwd_data = pwd;
2373 req->pwd_size = pwd_size;
2374
2375 sn_async_task_t *task = (sn_async_task_t *) malloc(sizeof(sn_async_task_t));
2376 SN_ASYNC_TASK(2)
2377
2378 SN_STATUS_THROWS(napi_create_reference(env, str_argv, 1, &req->str_ref), "")
2379 SN_STATUS_THROWS(napi_create_reference(env, pwd_argv, 1, &req->pwd_ref), "")
2380
2381 SN_QUEUE_TASK(task, async_pwhash_scryptsalsa208sha256_str_verify_execute, async_pwhash_scryptsalsa208sha256_str_verify_complete)
2382
2383 return promise;
2384}
2385
2386typedef struct sn_crypto_stream_xor_state {
2387 unsigned char n[crypto_stream_NONCEBYTES];
2388 unsigned char k[crypto_stream_KEYBYTES];
2389 unsigned char next_block[64];
2390 int remainder;
2391 uint64_t block_counter;
2392} sn_crypto_stream_xor_state;
2393
2394napi_value sn_crypto_stream_xor_wrap_init (napi_env env, napi_callback_info info) {
2395 SN_ARGV(3, crypto_stream_xor_instance_init)
2396
2397 SN_ARGV_BUFFER_CAST(sn_crypto_stream_xor_state *, state, 0)
2398 SN_ARGV_TYPEDARRAY(n, 1)
2399 SN_ARGV_TYPEDARRAY(k, 2)
2400
2401 SN_THROWS(state_size != sizeof(sn_crypto_stream_xor_state), "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes")
2402 SN_ASSERT_LENGTH(n_size, crypto_stream_NONCEBYTES, "n")
2403 SN_ASSERT_LENGTH(k_size, crypto_stream_KEYBYTES, "k")
2404
2405 state->remainder = 0;
2406 state->block_counter = 0;
2407 memcpy(state->n, n_data, crypto_stream_NONCEBYTES);
2408 memcpy(state->k, k_data, crypto_stream_KEYBYTES);
2409
2410 return NULL;
2411}
2412
2413napi_value sn_crypto_stream_xor_wrap_update (napi_env env, napi_callback_info info) {
2414 SN_ARGV(3, crypto_stream_xor_instance_init)
2415
2416 SN_ARGV_BUFFER_CAST(sn_crypto_stream_xor_state *, state, 0)
2417 SN_ARGV_BUFFER_CAST(unsigned char *, c, 1)
2418 SN_ARGV_BUFFER_CAST(unsigned char *, m, 2)
2419
2420 SN_THROWS(state_size != sizeof(sn_crypto_stream_xor_state), "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes")
2421 SN_THROWS(c_size != m_size, "c must be 'm.byteLength' bytes")
2422
2423 unsigned char *next_block = state->next_block;
2424
2425 if (state->remainder) {
2426 uint64_t offset = 0;
2427 int rem = state->remainder;
2428
2429 while (rem < 64 && offset < m_size) {
2430 c[offset] = next_block[rem] ^ m[offset];
2431 offset++;
2432 rem++;
2433 }
2434
2435 c += offset;
2436 m += offset;
2437 m_size -= offset;
2438 state->remainder = rem == 64 ? 0 : rem;
2439
2440 if (!m_size) return NULL;
2441 }
2442
2443 state->remainder = m_size & 63;
2444 m_size -= state->remainder;
2445 crypto_stream_xsalsa20_xor_ic(c, m, m_size, state->n, state->block_counter, state->k);
2446 state->block_counter += m_size / 64;
2447
2448 if (state->remainder) {
2449 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
2450 memcpy(next_block, m + m_size, state->remainder);
2451
2452 crypto_stream_xsalsa20_xor_ic(next_block, next_block, 64, state->n, state->block_counter, state->k);
2453 memcpy(c + m_size, next_block, state->remainder);
2454
2455 state->block_counter++;
2456 }
2457
2458 return NULL;
2459}
2460
2461napi_value sn_crypto_stream_xor_wrap_final (napi_env env, napi_callback_info info) {
2462 SN_ARGV(1, crypto_stream_xor_instance_init)
2463
2464 SN_ARGV_BUFFER_CAST(sn_crypto_stream_xor_state *, state, 0)
2465
2466 SN_THROWS(state_size != sizeof(sn_crypto_stream_xor_state), "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes")
2467
2468 sodium_memzero(state->n, sizeof(state->n));
2469 sodium_memzero(state->k, sizeof(state->k));
2470 sodium_memzero(state->next_block, sizeof(state->next_block));
2471 state->remainder = 0;
2472
2473 return NULL;
2474}
2475
2476typedef struct sn_crypto_stream_chacha20_xor_state {
2477 unsigned char n[crypto_stream_chacha20_NONCEBYTES];
2478 unsigned char k[crypto_stream_chacha20_KEYBYTES];
2479 unsigned char next_block[64];
2480 int remainder;
2481 uint64_t block_counter;
2482} sn_crypto_stream_chacha20_xor_state;
2483
2484napi_value sn_crypto_stream_chacha20_xor_wrap_init (napi_env env, napi_callback_info info) {
2485 SN_ARGV(3, crypto_stream_chacha20_xor_instance_init)
2486
2487 SN_ARGV_BUFFER_CAST(sn_crypto_stream_chacha20_xor_state *, state, 0)
2488 SN_ARGV_TYPEDARRAY(n, 1)
2489 SN_ARGV_TYPEDARRAY(k, 2)
2490
2491 SN_THROWS(state_size != sizeof(sn_crypto_stream_chacha20_xor_state), "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes")
2492 SN_ASSERT_LENGTH(n_size, crypto_stream_chacha20_NONCEBYTES, "n")
2493 SN_ASSERT_LENGTH(k_size, crypto_stream_chacha20_KEYBYTES, "k")
2494
2495 state->remainder = 0;
2496 state->block_counter = 0;
2497 memcpy(state->n, n_data, crypto_stream_chacha20_NONCEBYTES);
2498 memcpy(state->k, k_data, crypto_stream_chacha20_KEYBYTES);
2499
2500 return NULL;
2501}
2502
2503napi_value sn_crypto_stream_chacha20_xor_wrap_update (napi_env env, napi_callback_info info) {
2504 SN_ARGV(3, crypto_stream_chacha20_xor_instance_init)
2505
2506 SN_ARGV_BUFFER_CAST(sn_crypto_stream_chacha20_xor_state *, state, 0)
2507 SN_ARGV_BUFFER_CAST(unsigned char *, c, 1)
2508 SN_ARGV_BUFFER_CAST(unsigned char *, m, 2)
2509
2510 SN_THROWS(state_size != sizeof(sn_crypto_stream_chacha20_xor_state), "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes")
2511 SN_THROWS(c_size != m_size, "c must be 'm.byteLength' bytes")
2512
2513 unsigned char *next_block = state->next_block;
2514
2515 if (state->remainder) {
2516 uint64_t offset = 0;
2517 int rem = state->remainder;
2518
2519 while (rem < 64 && offset < m_size) {
2520 c[offset] = next_block[rem] ^ m[offset];
2521 offset++;
2522 rem++;
2523 }
2524
2525 c += offset;
2526 m += offset;
2527 m_size -= offset;
2528 state->remainder = rem == 64 ? 0 : rem;
2529
2530 if (!m_size) return NULL;
2531 }
2532
2533 state->remainder = m_size & 63;
2534 m_size -= state->remainder;
2535 crypto_stream_chacha20_xor_ic(c, m, m_size, state->n, state->block_counter, state->k);
2536 state->block_counter += m_size / 64;
2537
2538 if (state->remainder) {
2539 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
2540 memcpy(next_block, m + m_size, state->remainder);
2541
2542 crypto_stream_chacha20_xor_ic(next_block, next_block, 64, state->n, state->block_counter, state->k);
2543 memcpy(c + m_size, next_block, state->remainder);
2544
2545 state->block_counter++;
2546 }
2547
2548 return NULL;
2549}
2550
2551napi_value sn_crypto_stream_chacha20_xor_wrap_final (napi_env env, napi_callback_info info) {
2552 SN_ARGV(1, crypto_stream_chacha20_xor_instance_init)
2553
2554 SN_ARGV_BUFFER_CAST(sn_crypto_stream_chacha20_xor_state *, state, 0)
2555
2556 SN_THROWS(state_size != sizeof(sn_crypto_stream_chacha20_xor_state), "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes")
2557
2558 sodium_memzero(state->n, sizeof(state->n));
2559 sodium_memzero(state->k, sizeof(state->k));
2560 sodium_memzero(state->next_block, sizeof(state->next_block));
2561 state->remainder = 0;
2562
2563 return NULL;
2564}
2565
2566typedef struct sn_crypto_stream_chacha20_ietf_xor_state {
2567 unsigned char n[crypto_stream_chacha20_ietf_NONCEBYTES];
2568 unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES];
2569 unsigned char next_block[64];
2570 int remainder;
2571 uint64_t block_counter;
2572} sn_crypto_stream_chacha20_ietf_xor_state;
2573
2574napi_value sn_crypto_stream_chacha20_ietf_xor_wrap_init (napi_env env, napi_callback_info info) {
2575 SN_ARGV(3, crypto_stream_chacha20_ietf_xor_wrap_init)
2576
2577 SN_ARGV_BUFFER_CAST(sn_crypto_stream_chacha20_ietf_xor_state *, state, 0)
2578 SN_ARGV_TYPEDARRAY(n, 1)
2579 SN_ARGV_TYPEDARRAY(k, 2)
2580
2581 SN_THROWS(state_size != sizeof(sn_crypto_stream_chacha20_ietf_xor_state), "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes")
2582 SN_ASSERT_LENGTH(n_size, crypto_stream_chacha20_ietf_NONCEBYTES, "n")
2583 SN_ASSERT_LENGTH(k_size, crypto_stream_chacha20_ietf_KEYBYTES, "k")
2584
2585 state->remainder = 0;
2586 state->block_counter = 0;
2587 memcpy(state->n, n_data, crypto_stream_chacha20_ietf_NONCEBYTES);
2588 memcpy(state->k, k_data, crypto_stream_chacha20_ietf_KEYBYTES);
2589
2590 return NULL;
2591}
2592
2593napi_value sn_crypto_stream_chacha20_ietf_xor_wrap_update (napi_env env, napi_callback_info info) {
2594 SN_ARGV(3, crypto_stream_chacha20_ietf_xor_wrap_update)
2595
2596 SN_ARGV_BUFFER_CAST(sn_crypto_stream_chacha20_ietf_xor_state *, state, 0)
2597 SN_ARGV_BUFFER_CAST(unsigned char *, c, 1)
2598 SN_ARGV_BUFFER_CAST(unsigned char *, m, 2)
2599
2600 SN_THROWS(state_size != sizeof(sn_crypto_stream_chacha20_ietf_xor_state), "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes")
2601 SN_THROWS(c_size != m_size, "c must be 'm.byteLength' bytes")
2602
2603 unsigned char *next_block = state->next_block;
2604
2605 if (state->remainder) {
2606 uint64_t offset = 0;
2607 int rem = state->remainder;
2608
2609 while (rem < 64 && offset < m_size) {
2610 c[offset] = next_block[rem] ^ m[offset];
2611 offset++;
2612 rem++;
2613 }
2614
2615 c += offset;
2616 m += offset;
2617 m_size -= offset;
2618 state->remainder = rem == 64 ? 0 : rem;
2619
2620 if (!m_size) return NULL;
2621 }
2622
2623 state->remainder = m_size & 63;
2624 m_size -= state->remainder;
2625 crypto_stream_chacha20_ietf_xor_ic(c, m, m_size, state->n, state->block_counter, state->k);
2626 state->block_counter += m_size / 64;
2627
2628 if (state->remainder) {
2629 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
2630 memcpy(next_block, m + m_size, state->remainder);
2631
2632 crypto_stream_chacha20_ietf_xor_ic(next_block, next_block, 64, state->n, state->block_counter, state->k);
2633 memcpy(c + m_size, next_block, state->remainder);
2634
2635 state->block_counter++;
2636 }
2637
2638 return NULL;
2639}
2640
2641napi_value sn_crypto_stream_chacha20_ietf_xor_wrap_final (napi_env env, napi_callback_info info) {
2642 SN_ARGV(1, crypto_stream_chacha20_ietf_xor_wrap_final)
2643
2644 SN_ARGV_BUFFER_CAST(sn_crypto_stream_chacha20_ietf_xor_state *, state, 0)
2645
2646 SN_THROWS(state_size != sizeof(sn_crypto_stream_chacha20_ietf_xor_state), "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes")
2647
2648 sodium_memzero(state->n, sizeof(state->n));
2649 sodium_memzero(state->k, sizeof(state->k));
2650 sodium_memzero(state->next_block, sizeof(state->next_block));
2651 state->remainder = 0;
2652
2653 return NULL;
2654}
2655
2656typedef struct sn_crypto_stream_xchacha20_xor_state {
2657 unsigned char n[crypto_stream_xchacha20_NONCEBYTES];
2658 unsigned char k[crypto_stream_xchacha20_KEYBYTES];
2659 unsigned char next_block[64];
2660 int remainder;
2661 uint64_t block_counter;
2662} sn_crypto_stream_xchacha20_xor_state;
2663
2664napi_value sn_crypto_stream_xchacha20_xor_wrap_init (napi_env env, napi_callback_info info) {
2665 SN_ARGV(3, crypto_stream_xchacha20_xor_wrap_init)
2666
2667 SN_ARGV_BUFFER_CAST(sn_crypto_stream_xchacha20_xor_state *, state, 0)
2668 SN_ARGV_TYPEDARRAY(n, 1)
2669 SN_ARGV_TYPEDARRAY(k, 2)
2670
2671 SN_THROWS(state_size != sizeof(sn_crypto_stream_xchacha20_xor_state), "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes")
2672 SN_ASSERT_LENGTH(n_size, crypto_stream_xchacha20_NONCEBYTES, "n")
2673 SN_ASSERT_LENGTH(k_size, crypto_stream_xchacha20_KEYBYTES, "k")
2674
2675 state->remainder = 0;
2676 state->block_counter = 0;
2677 memcpy(state->n, n_data, crypto_stream_xchacha20_NONCEBYTES);
2678 memcpy(state->k, k_data, crypto_stream_xchacha20_KEYBYTES);
2679
2680 return NULL;
2681}
2682
2683napi_value sn_crypto_stream_xchacha20_xor_wrap_update (napi_env env, napi_callback_info info) {
2684 SN_ARGV(3, crypto_stream_xchacha20_xor_wrap_update)
2685
2686 SN_ARGV_BUFFER_CAST(sn_crypto_stream_xchacha20_xor_state *, state, 0)
2687 SN_ARGV_BUFFER_CAST(unsigned char *, c, 1)
2688 SN_ARGV_BUFFER_CAST(unsigned char *, m, 2)
2689
2690 SN_THROWS(state_size != sizeof(sn_crypto_stream_xchacha20_xor_state), "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes")
2691 SN_THROWS(c_size != m_size, "c must be 'm.byteLength' bytes")
2692
2693 unsigned char *next_block = state->next_block;
2694
2695 if (state->remainder) {
2696 uint64_t offset = 0;
2697 int rem = state->remainder;
2698
2699 while (rem < 64 && offset < m_size) {
2700 c[offset] = next_block[rem] ^ m[offset];
2701 offset++;
2702 rem++;
2703 }
2704
2705 c += offset;
2706 m += offset;
2707 m_size -= offset;
2708 state->remainder = rem == 64 ? 0 : rem;
2709
2710 if (!m_size) return NULL;
2711 }
2712
2713 state->remainder = m_size & 63;
2714 m_size -= state->remainder;
2715 crypto_stream_xchacha20_xor_ic(c, m, m_size, state->n, state->block_counter, state->k);
2716 state->block_counter += m_size / 64;
2717
2718 if (state->remainder) {
2719 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
2720 memcpy(next_block, m + m_size, state->remainder);
2721
2722 crypto_stream_xchacha20_xor_ic(next_block, next_block, 64, state->n, state->block_counter, state->k);
2723 memcpy(c + m_size, next_block, state->remainder);
2724
2725 state->block_counter++;
2726 }
2727
2728 return NULL;
2729}
2730
2731napi_value sn_crypto_stream_xchacha20_xor_wrap_final (napi_env env, napi_callback_info info) {
2732 SN_ARGV(1, crypto_stream_xchacha20_xor_wrap_final)
2733
2734 SN_ARGV_BUFFER_CAST(sn_crypto_stream_xchacha20_xor_state *, state, 0)
2735
2736 SN_THROWS(state_size != sizeof(sn_crypto_stream_xchacha20_xor_state), "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes")
2737
2738 sodium_memzero(state->n, sizeof(state->n));
2739 sodium_memzero(state->k, sizeof(state->k));
2740 sodium_memzero(state->next_block, sizeof(state->next_block));
2741 state->remainder = 0;
2742
2743 return NULL;
2744}
2745
2746typedef struct sn_crypto_stream_salsa20_xor_state {
2747 unsigned char n[crypto_stream_salsa20_NONCEBYTES];
2748 unsigned char k[crypto_stream_salsa20_KEYBYTES];
2749 unsigned char next_block[64];
2750 int remainder;
2751 uint64_t block_counter;
2752} sn_crypto_stream_salsa20_xor_state;
2753
2754napi_value sn_crypto_stream_salsa20_xor_wrap_init (napi_env env, napi_callback_info info) {
2755 SN_ARGV(3, crypto_stream_salsa20_xor_wrap_init)
2756
2757 SN_ARGV_BUFFER_CAST(sn_crypto_stream_salsa20_xor_state *, state, 0)
2758 SN_ARGV_TYPEDARRAY(n, 1)
2759 SN_ARGV_TYPEDARRAY(k, 2)
2760
2761 SN_THROWS(state_size != sizeof(sn_crypto_stream_salsa20_xor_state), "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes")
2762 SN_ASSERT_LENGTH(n_size, crypto_stream_salsa20_NONCEBYTES, "n")
2763 SN_ASSERT_LENGTH(k_size, crypto_stream_salsa20_KEYBYTES, "k")
2764
2765 state->remainder = 0;
2766 state->block_counter = 0;
2767 memcpy(state->n, n_data, crypto_stream_salsa20_NONCEBYTES);
2768 memcpy(state->k, k_data, crypto_stream_salsa20_KEYBYTES);
2769
2770 return NULL;
2771}
2772
2773napi_value sn_crypto_stream_salsa20_xor_wrap_update (napi_env env, napi_callback_info info) {
2774 SN_ARGV(3, crypto_stream_salsa20_xor_wrap_update)
2775
2776 SN_ARGV_BUFFER_CAST(sn_crypto_stream_salsa20_xor_state *, state, 0)
2777 SN_ARGV_BUFFER_CAST(unsigned char *, c, 1)
2778 SN_ARGV_BUFFER_CAST(unsigned char *, m, 2)
2779
2780 SN_THROWS(state_size != sizeof(sn_crypto_stream_salsa20_xor_state), "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes")
2781 SN_THROWS(c_size != m_size, "c must be 'm.byteLength' bytes")
2782
2783 unsigned char *next_block = state->next_block;
2784
2785 if (state->remainder) {
2786 uint64_t offset = 0;
2787 int rem = state->remainder;
2788
2789 while (rem < 64 && offset < m_size) {
2790 c[offset] = next_block[rem] ^ m[offset];
2791 offset++;
2792 rem++;
2793 }
2794
2795 c += offset;
2796 m += offset;
2797 m_size -= offset;
2798 state->remainder = rem == 64 ? 0 : rem;
2799
2800 if (!m_size) return NULL;
2801 }
2802
2803 state->remainder = m_size & 63;
2804 m_size -= state->remainder;
2805 crypto_stream_salsa20_xor_ic(c, m, m_size, state->n, state->block_counter, state->k);
2806 state->block_counter += m_size / 64;
2807
2808 if (state->remainder) {
2809 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
2810 memcpy(next_block, m + m_size, state->remainder);
2811
2812 crypto_stream_salsa20_xor_ic(next_block, next_block, 64, state->n, state->block_counter, state->k);
2813 memcpy(c + m_size, next_block, state->remainder);
2814
2815 state->block_counter++;
2816 }
2817
2818 return NULL;
2819}
2820
2821napi_value sn_crypto_stream_salsa20_xor_wrap_final (napi_env env, napi_callback_info info) {
2822 SN_ARGV(1, crypto_stream_salsa20_xor_wrap_final)
2823
2824 SN_ARGV_BUFFER_CAST(sn_crypto_stream_salsa20_xor_state *, state, 0)
2825
2826 SN_THROWS(state_size != sizeof(sn_crypto_stream_salsa20_xor_state), "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes")
2827
2828 sodium_memzero(state->n, sizeof(state->n));
2829 sodium_memzero(state->k, sizeof(state->k));
2830 sodium_memzero(state->next_block, sizeof(state->next_block));
2831 state->remainder = 0;
2832
2833 return NULL;
2834}
2835
2836// Experimental API
2837
2838napi_value sn_extension_tweak_ed25519_base (napi_env env, napi_callback_info info) {
2839 SN_ARGV(3, extension_tweak_ed25519_base)
2840
2841 SN_ARGV_TYPEDARRAY(n, 0)
2842 SN_ARGV_TYPEDARRAY(p, 1)
2843 SN_ARGV_TYPEDARRAY(ns, 2)
2844
2845 SN_ASSERT_LENGTH(n_size, sn__extension_tweak_ed25519_SCALARBYTES, "n")
2846 SN_ASSERT_LENGTH(p_size, sn__extension_tweak_ed25519_BYTES, "p")
2847
2848 sn__extension_tweak_ed25519_base(p_data, n_data, ns_data, ns_size);
2849
2850 return NULL;
2851}
2852
2853napi_value sn_extension_tweak_ed25519_sign_detached (napi_env env, napi_callback_info info) {
2854 SN_ARGV_OPTS(3, 4, extension_tweak_ed25519_sign_detached)
2855
2856 SN_ARGV_TYPEDARRAY(sig, 0)
2857 SN_ARGV_TYPEDARRAY(m, 1)
2858 SN_ARGV_TYPEDARRAY(scalar, 2)
2859 SN_ARGV_OPTS_TYPEDARRAY(pk, 3)
2860
2861 SN_ASSERT_LENGTH(sig_size, crypto_sign_BYTES, "sig")
2862 SN_ASSERT_LENGTH(scalar_size, sn__extension_tweak_ed25519_SCALARBYTES, "scalar")
2863
2864 if (pk_data != NULL) {
2865 SN_ASSERT_LENGTH(pk_size, crypto_sign_PUBLICKEYBYTES, "pk")
2866 }
2867
2868 SN_RETURN(sn__extension_tweak_ed25519_sign_detached(sig_data, NULL, m_data, m_size, scalar_data, pk_data), "failed to compute signature")
2869}
2870
2871napi_value sn_extension_tweak_ed25519_sk_to_scalar (napi_env env, napi_callback_info info) {
2872 SN_ARGV(2, extension_tweak_ed25519_sk_to_scalar)
2873
2874 SN_ARGV_TYPEDARRAY(n, 0)
2875 SN_ARGV_TYPEDARRAY(sk, 1)
2876
2877 SN_ASSERT_LENGTH(n_size, sn__extension_tweak_ed25519_SCALARBYTES, "n")
2878 SN_ASSERT_LENGTH(sk_size, crypto_sign_SECRETKEYBYTES, "sk")
2879
2880 sn__extension_tweak_ed25519_sk_to_scalar(n_data, sk_data);
2881
2882 return NULL;
2883}
2884
2885napi_value sn_extension_tweak_ed25519_scalar (napi_env env, napi_callback_info info) {
2886 SN_ARGV(3, extension_tweak_ed25519_scalar)
2887
2888 SN_ARGV_TYPEDARRAY(scalar_out, 0)
2889 SN_ARGV_TYPEDARRAY(scalar, 1)
2890 SN_ARGV_TYPEDARRAY(ns, 2)
2891
2892 SN_ASSERT_LENGTH(scalar_out_size, sn__extension_tweak_ed25519_SCALARBYTES, "scalar_out")
2893 SN_ASSERT_LENGTH(scalar_size, sn__extension_tweak_ed25519_SCALARBYTES, "scalar")
2894
2895 sn__extension_tweak_ed25519_scalar(scalar_out_data, scalar_data, ns_data, ns_size);
2896
2897 return NULL;
2898}
2899
2900napi_value sn_extension_tweak_ed25519_pk (napi_env env, napi_callback_info info) {
2901 SN_ARGV(3, extension_tweak_ed25519_pk)
2902
2903 SN_ARGV_TYPEDARRAY(tpk, 0)
2904 SN_ARGV_TYPEDARRAY(pk, 1)
2905 SN_ARGV_TYPEDARRAY(ns, 2)
2906
2907 SN_ASSERT_LENGTH(tpk_size, crypto_sign_PUBLICKEYBYTES, "tpk")
2908 SN_ASSERT_LENGTH(pk_size, crypto_sign_PUBLICKEYBYTES, "pk")
2909
2910 SN_RETURN(sn__extension_tweak_ed25519_pk(tpk_data, pk_data, ns_data, ns_size), "failed to tweak public key")
2911}
2912
2913napi_value sn_extension_tweak_ed25519_keypair (napi_env env, napi_callback_info info) {
2914 SN_ARGV(4, extension_tweak_ed25519_keypair)
2915
2916 SN_ARGV_TYPEDARRAY(pk, 0)
2917 SN_ARGV_TYPEDARRAY(scalar_out, 1)
2918 SN_ARGV_TYPEDARRAY(scalar_in, 2)
2919 SN_ARGV_TYPEDARRAY(ns, 3)
2920
2921 SN_ASSERT_LENGTH(pk_size, sn__extension_tweak_ed25519_BYTES, "pk")
2922 SN_ASSERT_LENGTH(scalar_out_size, sn__extension_tweak_ed25519_SCALARBYTES, "scalar_out")
2923 SN_ASSERT_LENGTH(scalar_in_size, sn__extension_tweak_ed25519_SCALARBYTES, "scalar_in")
2924
2925 sn__extension_tweak_ed25519_keypair(pk_data, scalar_out_data, scalar_in_data, ns_data, ns_size);
2926
2927 return NULL;
2928}
2929
2930napi_value sn_extension_tweak_ed25519_scalar_add (napi_env env, napi_callback_info info) {
2931 SN_ARGV(3, extension_tweak_ed25519_scalar_add)
2932
2933 SN_ARGV_TYPEDARRAY(scalar_out, 0)
2934 SN_ARGV_TYPEDARRAY(scalar, 1)
2935 SN_ARGV_TYPEDARRAY(n, 2)
2936
2937 SN_ASSERT_LENGTH(scalar_out_size, sn__extension_tweak_ed25519_SCALARBYTES, "scalar_out")
2938 SN_ASSERT_LENGTH(scalar_size, sn__extension_tweak_ed25519_SCALARBYTES, "scalar")
2939 SN_ASSERT_LENGTH(n_size, sn__extension_tweak_ed25519_SCALARBYTES, "n")
2940
2941 sn__extension_tweak_ed25519_scalar_add(scalar_out_data, scalar_data, n_data);
2942
2943 return NULL;
2944}
2945
2946napi_value sn_extension_tweak_ed25519_pk_add (napi_env env, napi_callback_info info) {
2947 SN_ARGV(3, extension_tweak_ed25519_pk)
2948
2949 SN_ARGV_TYPEDARRAY(tpk, 0)
2950 SN_ARGV_TYPEDARRAY(pk, 1)
2951 SN_ARGV_TYPEDARRAY(p, 2)
2952
2953 SN_ASSERT_LENGTH(tpk_size, crypto_sign_PUBLICKEYBYTES, "tpk")
2954 SN_ASSERT_LENGTH(pk_size, crypto_sign_PUBLICKEYBYTES, "pk")
2955 SN_ASSERT_LENGTH(p_size, crypto_sign_PUBLICKEYBYTES, "p")
2956
2957 SN_RETURN(sn__extension_tweak_ed25519_pk_add(tpk_data, pk_data, p_data), "failed to add tweak to public key")
2958}
2959
2960napi_value sn_extension_tweak_ed25519_keypair_add (napi_env env, napi_callback_info info) {
2961 SN_ARGV(4, extension_tweak_ed25519_keypair_add)
2962
2963 SN_ARGV_TYPEDARRAY(pk, 0)
2964 SN_ARGV_TYPEDARRAY(scalar_out, 1)
2965 SN_ARGV_TYPEDARRAY(scalar_in, 2)
2966 SN_ARGV_TYPEDARRAY(tweak, 3)
2967
2968 SN_ASSERT_LENGTH(pk_size, sn__extension_tweak_ed25519_BYTES, "pk")
2969 SN_ASSERT_LENGTH(scalar_out_size, sn__extension_tweak_ed25519_SCALARBYTES, "scalar_out")
2970 SN_ASSERT_LENGTH(scalar_in_size, sn__extension_tweak_ed25519_SCALARBYTES, "scalar_in")
2971 SN_ASSERT_LENGTH(tweak_size, sn__extension_tweak_ed25519_SCALARBYTES, "tweak")
2972
2973 SN_RETURN(sn__extension_tweak_ed25519_keypair_add(pk_data, scalar_out_data, scalar_in_data, tweak_data), "failed to add tweak to keypair")
2974}
2975
2976napi_value sn_extension_pbkdf2_sha512 (napi_env env, napi_callback_info info) {
2977 SN_ARGV(5, extension_pbkdf2_sha512)
2978
2979 SN_ARGV_BUFFER_CAST(unsigned char *, out, 0)
2980 SN_ARGV_BUFFER_CAST(unsigned char *, passwd, 1)
2981 SN_ARGV_BUFFER_CAST(unsigned char *, salt, 2)
2982 SN_ARGV_UINT64(iter, 3)
2983 SN_ARGV_UINT64(outlen, 4)
2984
2985 SN_ASSERT_MIN_LENGTH(iter, sn__extension_pbkdf2_sha512_ITERATIONS_MIN, "iterations")
2986 SN_ASSERT_MAX_LENGTH(outlen, sn__extension_pbkdf2_sha512_BYTES_MAX, "outlen")
2987
2988 SN_ASSERT_MIN_LENGTH(out_size, outlen, "out")
2989
2990 SN_RETURN(sn__extension_pbkdf2_sha512(passwd, passwd_size, salt, salt_size, iter, out, outlen), "failed to add tweak to public key")
2991}
2992
2993typedef struct sn_async_pbkdf2_sha512_request {
2994 napi_env env;
2995 unsigned char *out_data;
2996 size_t out_size;
2997 napi_ref out_ref;
2998 size_t outlen;
2999 napi_ref pwd_ref;
3000 const unsigned char *pwd_data;
3001 size_t pwd_size;
3002 napi_ref salt_ref;
3003 unsigned char *salt_data;
3004 size_t salt_size;
3005 uint64_t iter;
3006} sn_async_pbkdf2_sha512_request;
3007
3008static void async_pbkdf2_sha512_execute (uv_work_t *uv_req) {
3009 sn_async_task_t *task = (sn_async_task_t *) uv_req;
3010 sn_async_pbkdf2_sha512_request *req = (sn_async_pbkdf2_sha512_request *) task->req;
3011 task->code = sn__extension_pbkdf2_sha512(req->pwd_data,
3012 req->pwd_size,
3013 req->salt_data,
3014 req->salt_size,
3015 req->iter,
3016 req->out_data,
3017 req->outlen);
3018}
3019
3020static void async_pbkdf2_sha512_complete (uv_work_t *uv_req, int status) {
3021 sn_async_task_t *task = (sn_async_task_t *) uv_req;
3022 sn_async_pbkdf2_sha512_request *req = (sn_async_pbkdf2_sha512_request *) task->req;
3023
3024 napi_handle_scope scope;
3025 napi_open_handle_scope(req->env, &scope);
3026
3027 napi_value global;
3028 napi_get_global(req->env, &global);
3029
3030 SN_ASYNC_COMPLETE("failed to compute kdf")
3031
3032 napi_close_handle_scope(req->env, scope);
3033
3034 napi_delete_reference(req->env, req->out_ref);
3035 napi_delete_reference(req->env, req->pwd_ref);
3036 napi_delete_reference(req->env, req->salt_ref);
3037
3038 free(req);
3039 free(task);
3040}
3041
3042napi_value sn_extension_pbkdf2_sha512_async (napi_env env, napi_callback_info info) {
3043 SN_ARGV_OPTS(5, 6, extension_pbkdf2_sha512_async)
3044
3045 SN_ARGV_BUFFER_CAST(unsigned char *, out, 0)
3046 SN_ARGV_BUFFER_CAST(unsigned char *, pwd, 1)
3047 SN_ARGV_BUFFER_CAST(unsigned char *, salt, 2)
3048 SN_ARGV_UINT64(iter, 3)
3049 SN_ARGV_UINT64(outlen, 4)
3050
3051 SN_ASSERT_MIN_LENGTH(iter, sn__extension_pbkdf2_sha512_ITERATIONS_MIN, "iterations")
3052 SN_ASSERT_MAX_LENGTH(outlen, sn__extension_pbkdf2_sha512_BYTES_MAX, "outlen")
3053 SN_ASSERT_MIN_LENGTH(out_size, outlen, "output")
3054
3055 sn_async_pbkdf2_sha512_request *req = (sn_async_pbkdf2_sha512_request *) malloc(sizeof(sn_async_pbkdf2_sha512_request));
3056
3057 req->env = env;
3058 req->out_data = out;
3059 req->out_size = out_size;
3060 req->pwd_data = pwd;
3061 req->pwd_size = pwd_size;
3062 req->salt_data = salt;
3063 req->salt_size = salt_size;
3064 req->iter = iter;
3065 req->outlen = outlen;
3066
3067 sn_async_task_t *task = (sn_async_task_t *) malloc(sizeof(sn_async_task_t));
3068 SN_ASYNC_TASK(5);
3069
3070 SN_STATUS_THROWS(napi_create_reference(env, out_argv, 1, &req->out_ref), "")
3071 SN_STATUS_THROWS(napi_create_reference(env, pwd_argv, 1, &req->pwd_ref), "")
3072 SN_STATUS_THROWS(napi_create_reference(env, salt_argv, 1, &req->salt_ref), "")
3073
3074 SN_QUEUE_TASK(task, async_pbkdf2_sha512_execute, async_pbkdf2_sha512_complete)
3075
3076 return promise;
3077}
3078
3079static napi_value create_sodium_native (napi_env env) {
3080 SN_THROWS(sodium_init() == -1, "sodium_init() failed")
3081
3082 napi_value exports;
3083 napi_create_object(env, &exports);
3084
3085 // memory
3086
3087 SN_EXPORT_FUNCTION(sodium_memzero, sn_sodium_memzero)
3088 SN_EXPORT_FUNCTION(sodium_mlock, sn_sodium_mlock)
3089 SN_EXPORT_FUNCTION(sodium_munlock, sn_sodium_munlock)
3090 SN_EXPORT_FUNCTION(sodium_malloc, sn_sodium_malloc)
3091 SN_EXPORT_FUNCTION(sodium_free, sn_sodium_free)
3092 SN_EXPORT_FUNCTION(sodium_mprotect_noaccess, sn_sodium_mprotect_noaccess)
3093 SN_EXPORT_FUNCTION(sodium_mprotect_readonly, sn_sodium_mprotect_readonly)
3094 SN_EXPORT_FUNCTION(sodium_mprotect_readwrite, sn_sodium_mprotect_readwrite)
3095
3096 // randombytes
3097
3098 SN_EXPORT_FUNCTION(randombytes_buf, sn_randombytes_buf)
3099 SN_EXPORT_FUNCTION(randombytes_buf_deterministic, sn_randombytes_buf_deterministic)
3100 SN_EXPORT_FUNCTION(randombytes_uniform, sn_randombytes_uniform)
3101 SN_EXPORT_FUNCTION(randombytes_random, sn_randombytes_random)
3102 SN_EXPORT_UINT32(randombytes_SEEDBYTES, randombytes_SEEDBYTES)
3103
3104 // sodium helpers
3105
3106 SN_EXPORT_FUNCTION(sodium_memcmp, sn_sodium_memcmp)
3107 SN_EXPORT_FUNCTION(sodium_increment, sn_sodium_increment)
3108 SN_EXPORT_FUNCTION(sodium_add, sn_sodium_add)
3109 SN_EXPORT_FUNCTION(sodium_sub, sn_sodium_sub)
3110 SN_EXPORT_FUNCTION(sodium_compare, sn_sodium_compare)
3111 SN_EXPORT_FUNCTION(sodium_is_zero, sn_sodium_is_zero)
3112 SN_EXPORT_FUNCTION(sodium_pad, sn_sodium_pad)
3113 SN_EXPORT_FUNCTION(sodium_unpad, sn_sodium_unpad)
3114
3115 // crypto_aead
3116
3117 SN_EXPORT_FUNCTION(crypto_aead_xchacha20poly1305_ietf_keygen, sn_crypto_aead_xchacha20poly1305_ietf_keygen)
3118 SN_EXPORT_FUNCTION(crypto_aead_xchacha20poly1305_ietf_encrypt, sn_crypto_aead_xchacha20poly1305_ietf_encrypt)
3119 SN_EXPORT_FUNCTION(crypto_aead_xchacha20poly1305_ietf_decrypt, sn_crypto_aead_xchacha20poly1305_ietf_decrypt)
3120 SN_EXPORT_FUNCTION(crypto_aead_xchacha20poly1305_ietf_encrypt_detached, sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached)
3121 SN_EXPORT_FUNCTION(crypto_aead_xchacha20poly1305_ietf_decrypt_detached, sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached)
3122 SN_EXPORT_UINT32(crypto_aead_xchacha20poly1305_ietf_ABYTES, crypto_aead_xchacha20poly1305_ietf_ABYTES)
3123 SN_EXPORT_UINT32(crypto_aead_xchacha20poly1305_ietf_KEYBYTES, crypto_aead_xchacha20poly1305_ietf_KEYBYTES)
3124 SN_EXPORT_UINT32(crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)
3125 SN_EXPORT_UINT32(crypto_aead_xchacha20poly1305_ietf_NSECBYTES, crypto_aead_xchacha20poly1305_ietf_NSECBYTES)
3126 SN_EXPORT_UINT64(crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX, crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX)
3127
3128 SN_EXPORT_FUNCTION(crypto_aead_chacha20poly1305_ietf_keygen, sn_crypto_aead_chacha20poly1305_ietf_keygen)
3129 SN_EXPORT_FUNCTION(crypto_aead_chacha20poly1305_ietf_encrypt, sn_crypto_aead_chacha20poly1305_ietf_encrypt)
3130 SN_EXPORT_FUNCTION(crypto_aead_chacha20poly1305_ietf_decrypt, sn_crypto_aead_chacha20poly1305_ietf_decrypt)
3131 SN_EXPORT_FUNCTION(crypto_aead_chacha20poly1305_ietf_encrypt_detached, sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached)
3132 SN_EXPORT_FUNCTION(crypto_aead_chacha20poly1305_ietf_decrypt_detached, sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached)
3133 SN_EXPORT_UINT32(crypto_aead_chacha20poly1305_ietf_ABYTES, crypto_aead_chacha20poly1305_ietf_ABYTES)
3134 SN_EXPORT_UINT32(crypto_aead_chacha20poly1305_ietf_KEYBYTES, crypto_aead_chacha20poly1305_ietf_KEYBYTES)
3135 SN_EXPORT_UINT32(crypto_aead_chacha20poly1305_ietf_NPUBBYTES, crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
3136 SN_EXPORT_UINT32(crypto_aead_chacha20poly1305_ietf_NSECBYTES, crypto_aead_chacha20poly1305_ietf_NSECBYTES)
3137 SN_EXPORT_UINT64(crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX, crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX)
3138
3139 // crypto_auth
3140
3141 SN_EXPORT_FUNCTION(crypto_auth, sn_crypto_auth)
3142 SN_EXPORT_FUNCTION(crypto_auth_verify, sn_crypto_auth_verify)
3143 SN_EXPORT_UINT32(crypto_auth_BYTES, crypto_auth_BYTES)
3144 SN_EXPORT_UINT32(crypto_auth_KEYBYTES, crypto_auth_KEYBYTES)
3145 SN_EXPORT_STRING(crypto_auth_PRIMITIVE, crypto_auth_PRIMITIVE)
3146
3147 // crypto_box
3148
3149 SN_EXPORT_FUNCTION(crypto_box_keypair, sn_crypto_box_keypair)
3150 SN_EXPORT_FUNCTION(crypto_box_seed_keypair, sn_crypto_box_seed_keypair)
3151 SN_EXPORT_FUNCTION(crypto_box_easy, sn_crypto_box_easy)
3152 SN_EXPORT_FUNCTION(crypto_box_open_easy, sn_crypto_box_open_easy)
3153 SN_EXPORT_FUNCTION(crypto_box_detached, sn_crypto_box_detached)
3154 SN_EXPORT_FUNCTION(crypto_box_open_detached, sn_crypto_box_open_detached)
3155 SN_EXPORT_FUNCTION(crypto_box_seal, sn_crypto_box_seal)
3156 SN_EXPORT_FUNCTION(crypto_box_seal_open, sn_crypto_box_seal_open)
3157 SN_EXPORT_UINT32(crypto_box_SEEDBYTES, crypto_box_SEEDBYTES)
3158 SN_EXPORT_UINT32(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES)
3159 SN_EXPORT_UINT32(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES)
3160 SN_EXPORT_UINT32(crypto_box_NONCEBYTES, crypto_box_NONCEBYTES)
3161 SN_EXPORT_UINT32(crypto_box_MACBYTES, crypto_box_MACBYTES)
3162 SN_EXPORT_UINT32(crypto_box_SEALBYTES, crypto_box_SEALBYTES)
3163 SN_EXPORT_STRING(crypto_box_PRIMITIVE, crypto_box_PRIMITIVE)
3164
3165 // crypto_core
3166
3167 SN_EXPORT_FUNCTION(crypto_core_ed25519_is_valid_point, sn_crypto_core_ed25519_is_valid_point)
3168 SN_EXPORT_FUNCTION(crypto_core_ed25519_from_uniform, sn_crypto_core_ed25519_from_uniform)
3169 SN_EXPORT_FUNCTION(crypto_core_ed25519_add, sn_crypto_core_ed25519_add)
3170 SN_EXPORT_FUNCTION(crypto_core_ed25519_sub, sn_crypto_core_ed25519_sub)
3171 SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_random, sn_crypto_core_ed25519_scalar_random)
3172 SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_reduce, sn_crypto_core_ed25519_scalar_reduce)
3173 SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_invert, sn_crypto_core_ed25519_scalar_invert)
3174 SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_negate, sn_crypto_core_ed25519_scalar_negate)
3175 SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_complement, sn_crypto_core_ed25519_scalar_complement)
3176 SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_add, sn_crypto_core_ed25519_scalar_add)
3177 SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_sub, sn_crypto_core_ed25519_scalar_sub)
3178 SN_EXPORT_UINT32(crypto_core_ed25519_BYTES, crypto_core_ed25519_BYTES)
3179 SN_EXPORT_UINT32(crypto_core_ed25519_UNIFORMBYTES, crypto_core_ed25519_UNIFORMBYTES)
3180 SN_EXPORT_UINT32(crypto_core_ed25519_SCALARBYTES, crypto_core_ed25519_SCALARBYTES)
3181 SN_EXPORT_UINT32(crypto_core_ed25519_NONREDUCEDSCALARBYTES, crypto_core_ed25519_NONREDUCEDSCALARBYTES)
3182
3183 // crypto_kdf
3184
3185 SN_EXPORT_FUNCTION(crypto_kdf_keygen, sn_crypto_kdf_keygen)
3186 SN_EXPORT_FUNCTION(crypto_kdf_derive_from_key, sn_crypto_kdf_derive_from_key)
3187 SN_EXPORT_UINT32(crypto_kdf_BYTES_MIN, crypto_kdf_BYTES_MIN)
3188 SN_EXPORT_UINT32(crypto_kdf_BYTES_MAX, crypto_kdf_BYTES_MAX)
3189 SN_EXPORT_UINT32(crypto_kdf_CONTEXTBYTES, crypto_kdf_CONTEXTBYTES)
3190 SN_EXPORT_UINT32(crypto_kdf_KEYBYTES, crypto_kdf_KEYBYTES)
3191 SN_EXPORT_STRING(crypto_kdf_PRIMITIVE, crypto_kdf_PRIMITIVE)
3192
3193 // crypto_kx
3194
3195 SN_EXPORT_FUNCTION(crypto_kx_keypair, sn_crypto_kx_keypair)
3196 SN_EXPORT_FUNCTION(crypto_kx_seed_keypair, sn_crypto_kx_seed_keypair)
3197 SN_EXPORT_FUNCTION(crypto_kx_client_session_keys, sn_crypto_kx_client_session_keys)
3198 SN_EXPORT_FUNCTION(crypto_kx_server_session_keys, sn_crypto_kx_server_session_keys)
3199 SN_EXPORT_UINT32(crypto_kx_PUBLICKEYBYTES, crypto_kx_PUBLICKEYBYTES)
3200 SN_EXPORT_UINT32(crypto_kx_SECRETKEYBYTES, crypto_kx_SECRETKEYBYTES)
3201 SN_EXPORT_UINT32(crypto_kx_SEEDBYTES, crypto_kx_SEEDBYTES)
3202 SN_EXPORT_UINT32(crypto_kx_SESSIONKEYBYTES, crypto_kx_SESSIONKEYBYTES)
3203 SN_EXPORT_STRING(crypto_kx_PRIMITIVE, crypto_kx_PRIMITIVE)
3204
3205 // crypto_generichash
3206
3207 SN_EXPORT_FUNCTION(crypto_generichash, sn_crypto_generichash)
3208 SN_EXPORT_FUNCTION(crypto_generichash_batch, sn_crypto_generichash_batch)
3209 SN_EXPORT_FUNCTION(crypto_generichash_keygen, sn_crypto_generichash_keygen)
3210 SN_EXPORT_FUNCTION(crypto_generichash_init, sn_crypto_generichash_init)
3211 SN_EXPORT_FUNCTION(crypto_generichash_update, sn_crypto_generichash_update)
3212 SN_EXPORT_FUNCTION(crypto_generichash_final, sn_crypto_generichash_final)
3213 SN_EXPORT_UINT32(crypto_generichash_STATEBYTES, sizeof(crypto_generichash_state))
3214 SN_EXPORT_STRING(crypto_generichash_PRIMITIVE, crypto_generichash_PRIMITIVE)
3215 SN_EXPORT_UINT32(crypto_generichash_BYTES_MIN, crypto_generichash_BYTES_MIN)
3216 SN_EXPORT_UINT32(crypto_generichash_BYTES_MAX, crypto_generichash_BYTES_MAX)
3217 SN_EXPORT_UINT32(crypto_generichash_BYTES, crypto_generichash_BYTES)
3218 SN_EXPORT_UINT32(crypto_generichash_KEYBYTES_MIN, crypto_generichash_KEYBYTES_MIN)
3219 SN_EXPORT_UINT32(crypto_generichash_KEYBYTES_MAX, crypto_generichash_KEYBYTES_MAX)
3220 SN_EXPORT_UINT32(crypto_generichash_KEYBYTES, crypto_generichash_KEYBYTES)
3221
3222 // crypto_hash
3223
3224 SN_EXPORT_FUNCTION(crypto_hash, sn_crypto_hash)
3225 SN_EXPORT_UINT32(crypto_hash_BYTES, crypto_hash_BYTES)
3226 SN_EXPORT_STRING(crypto_hash_PRIMITIVE, crypto_hash_PRIMITIVE)
3227
3228 SN_EXPORT_FUNCTION(crypto_hash_sha256, sn_crypto_hash_sha256)
3229 SN_EXPORT_FUNCTION(crypto_hash_sha256_init, sn_crypto_hash_sha256_init)
3230 SN_EXPORT_FUNCTION(crypto_hash_sha256_update, sn_crypto_hash_sha256_update)
3231 SN_EXPORT_FUNCTION(crypto_hash_sha256_final, sn_crypto_hash_sha256_final)
3232 SN_EXPORT_UINT32(crypto_hash_sha256_STATEBYTES, sizeof(crypto_hash_sha256_state))
3233 SN_EXPORT_UINT32(crypto_hash_sha256_BYTES, crypto_hash_sha256_BYTES)
3234
3235 SN_EXPORT_FUNCTION(crypto_hash_sha512, sn_crypto_hash_sha512)
3236 SN_EXPORT_FUNCTION(crypto_hash_sha512_init, sn_crypto_hash_sha512_init)
3237 SN_EXPORT_FUNCTION(crypto_hash_sha512_update, sn_crypto_hash_sha512_update)
3238 SN_EXPORT_FUNCTION(crypto_hash_sha512_final, sn_crypto_hash_sha512_final)
3239 SN_EXPORT_UINT32(crypto_hash_sha512_STATEBYTES, sizeof(crypto_hash_sha512_state))
3240 SN_EXPORT_UINT32(crypto_hash_sha512_BYTES, crypto_hash_sha512_BYTES)
3241
3242 // crypto_onetimeauth
3243
3244 SN_EXPORT_FUNCTION(crypto_onetimeauth, sn_crypto_onetimeauth)
3245 SN_EXPORT_FUNCTION(crypto_onetimeauth_verify, sn_crypto_onetimeauth_verify)
3246 SN_EXPORT_FUNCTION(crypto_onetimeauth_init, sn_crypto_onetimeauth_init)
3247 SN_EXPORT_FUNCTION(crypto_onetimeauth_update, sn_crypto_onetimeauth_update)
3248 SN_EXPORT_FUNCTION(crypto_onetimeauth_final, sn_crypto_onetimeauth_final)
3249 SN_EXPORT_UINT32(crypto_onetimeauth_STATEBYTES, sizeof(crypto_onetimeauth_state))
3250 SN_EXPORT_UINT32(crypto_onetimeauth_BYTES, crypto_onetimeauth_BYTES)
3251 SN_EXPORT_UINT32(crypto_onetimeauth_KEYBYTES, crypto_onetimeauth_KEYBYTES)
3252 SN_EXPORT_STRING(crypto_onetimeauth_PRIMITIVE, crypto_onetimeauth_PRIMITIVE)
3253
3254 // crypto_pwhash
3255
3256 SN_EXPORT_FUNCTION(crypto_pwhash, sn_crypto_pwhash)
3257 SN_EXPORT_FUNCTION(crypto_pwhash_str, sn_crypto_pwhash_str)
3258 SN_EXPORT_FUNCTION(crypto_pwhash_str_verify, sn_crypto_pwhash_str_verify)
3259 SN_EXPORT_FUNCTION(crypto_pwhash_str_needs_rehash, sn_crypto_pwhash_str_needs_rehash)
3260 SN_EXPORT_FUNCTION(crypto_pwhash_async, sn_crypto_pwhash_async)
3261 SN_EXPORT_FUNCTION(crypto_pwhash_str_async, sn_crypto_pwhash_str_async)
3262 SN_EXPORT_FUNCTION(crypto_pwhash_str_verify_async, sn_crypto_pwhash_str_verify_async)
3263 SN_EXPORT_UINT32(crypto_pwhash_ALG_ARGON2I13, crypto_pwhash_ALG_ARGON2I13)
3264 SN_EXPORT_UINT32(crypto_pwhash_ALG_ARGON2ID13, crypto_pwhash_ALG_ARGON2ID13)
3265 SN_EXPORT_UINT32(crypto_pwhash_ALG_DEFAULT, crypto_pwhash_ALG_DEFAULT)
3266 SN_EXPORT_UINT32(crypto_pwhash_BYTES_MIN, crypto_pwhash_BYTES_MIN)
3267 SN_EXPORT_UINT32(crypto_pwhash_BYTES_MAX, crypto_pwhash_BYTES_MAX)
3268 SN_EXPORT_UINT32(crypto_pwhash_PASSWD_MIN, crypto_pwhash_PASSWD_MIN)
3269 SN_EXPORT_UINT32(crypto_pwhash_PASSWD_MAX, crypto_pwhash_PASSWD_MAX)
3270 SN_EXPORT_UINT32(crypto_pwhash_SALTBYTES, crypto_pwhash_SALTBYTES)
3271 SN_EXPORT_UINT32(crypto_pwhash_STRBYTES, crypto_pwhash_STRBYTES)
3272 SN_EXPORT_STRING(crypto_pwhash_STRPREFIX, crypto_pwhash_STRPREFIX)
3273 SN_EXPORT_UINT32(crypto_pwhash_OPSLIMIT_MIN, crypto_pwhash_OPSLIMIT_MIN)
3274 SN_EXPORT_UINT32(crypto_pwhash_OPSLIMIT_MAX, crypto_pwhash_OPSLIMIT_MAX)
3275 SN_EXPORT_UINT32(crypto_pwhash_MEMLIMIT_MIN, crypto_pwhash_MEMLIMIT_MIN)
3276 SN_EXPORT_UINT32(crypto_pwhash_MEMLIMIT_MAX, crypto_pwhash_MEMLIMIT_MAX)
3277 SN_EXPORT_UINT32(crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_OPSLIMIT_INTERACTIVE)
3278 SN_EXPORT_UINT32(crypto_pwhash_MEMLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE)
3279 SN_EXPORT_UINT32(crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_OPSLIMIT_MODERATE)
3280 SN_EXPORT_UINT32(crypto_pwhash_MEMLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE)
3281 SN_EXPORT_UINT32(crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_OPSLIMIT_SENSITIVE)
3282 SN_EXPORT_UINT32(crypto_pwhash_MEMLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE)
3283 SN_EXPORT_STRING(crypto_pwhash_PRIMITIVE, crypto_pwhash_PRIMITIVE)
3284
3285 SN_EXPORT_FUNCTION(crypto_pwhash_scryptsalsa208sha256, sn_crypto_pwhash_scryptsalsa208sha256)
3286 SN_EXPORT_FUNCTION(crypto_pwhash_scryptsalsa208sha256_str, sn_crypto_pwhash_scryptsalsa208sha256_str)
3287 SN_EXPORT_FUNCTION(crypto_pwhash_scryptsalsa208sha256_str_verify, sn_crypto_pwhash_scryptsalsa208sha256_str_verify)
3288 SN_EXPORT_FUNCTION(crypto_pwhash_scryptsalsa208sha256_str_needs_rehash, sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash)
3289 SN_EXPORT_FUNCTION(crypto_pwhash_scryptsalsa208sha256_async, sn_crypto_pwhash_scryptsalsa208sha256_async)
3290 SN_EXPORT_FUNCTION(crypto_pwhash_scryptsalsa208sha256_str_async, sn_crypto_pwhash_scryptsalsa208sha256_str_async)
3291 SN_EXPORT_FUNCTION(crypto_pwhash_scryptsalsa208sha256_str_verify_async, sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async)
3292 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_BYTES_MIN, crypto_pwhash_scryptsalsa208sha256_BYTES_MIN)
3293 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_BYTES_MAX, crypto_pwhash_scryptsalsa208sha256_BYTES_MAX)
3294 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN, crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN)
3295 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX, crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX)
3296 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_SALTBYTES, crypto_pwhash_scryptsalsa208sha256_SALTBYTES)
3297 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_STRBYTES, crypto_pwhash_scryptsalsa208sha256_STRBYTES)
3298 SN_EXPORT_STRING(crypto_pwhash_scryptsalsa208sha256_STRPREFIX, crypto_pwhash_scryptsalsa208sha256_STRPREFIX)
3299 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN)
3300 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX)
3301 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN)
3302 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX)
3303 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE)
3304 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE)
3305 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE)
3306 SN_EXPORT_UINT32(crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE)
3307
3308 // crypto_scalarmult
3309
3310 SN_EXPORT_FUNCTION(crypto_scalarmult_base, sn_crypto_scalarmult_base)
3311 SN_EXPORT_FUNCTION(crypto_scalarmult, sn_crypto_scalarmult)
3312 SN_EXPORT_STRING(crypto_scalarmult_PRIMITIVE, crypto_scalarmult_PRIMITIVE)
3313 SN_EXPORT_UINT32(crypto_scalarmult_BYTES, crypto_scalarmult_BYTES)
3314 SN_EXPORT_UINT32(crypto_scalarmult_SCALARBYTES, crypto_scalarmult_SCALARBYTES)
3315
3316 SN_EXPORT_FUNCTION(crypto_scalarmult_ed25519_base, sn_crypto_scalarmult_ed25519_base)
3317 SN_EXPORT_FUNCTION(crypto_scalarmult_ed25519, sn_crypto_scalarmult_ed25519)
3318 SN_EXPORT_FUNCTION(crypto_scalarmult_ed25519_base_noclamp, sn_crypto_scalarmult_ed25519_base_noclamp)
3319 SN_EXPORT_FUNCTION(crypto_scalarmult_ed25519_noclamp, sn_crypto_scalarmult_ed25519_noclamp)
3320 SN_EXPORT_UINT32(crypto_scalarmult_ed25519_BYTES, crypto_scalarmult_ed25519_BYTES)
3321 SN_EXPORT_UINT32(crypto_scalarmult_ed25519_SCALARBYTES, crypto_scalarmult_ed25519_SCALARBYTES)
3322
3323 // crypto_secretbox
3324
3325 SN_EXPORT_FUNCTION(crypto_secretbox_easy, sn_crypto_secretbox_easy)
3326 SN_EXPORT_FUNCTION(crypto_secretbox_open_easy, sn_crypto_secretbox_open_easy)
3327 SN_EXPORT_FUNCTION(crypto_secretbox_detached, sn_crypto_secretbox_detached)
3328 SN_EXPORT_FUNCTION(crypto_secretbox_open_detached, sn_crypto_secretbox_open_detached)
3329 SN_EXPORT_UINT32(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES)
3330 SN_EXPORT_UINT32(crypto_secretbox_NONCEBYTES, crypto_secretbox_NONCEBYTES)
3331 SN_EXPORT_UINT32(crypto_secretbox_MACBYTES, crypto_secretbox_MACBYTES)
3332 SN_EXPORT_STRING(crypto_secretbox_PRIMITIVE, crypto_secretbox_PRIMITIVE)
3333
3334 // crypto_secretstream
3335
3336 SN_EXPORT_FUNCTION(crypto_secretstream_xchacha20poly1305_keygen, sn_crypto_secretstream_xchacha20poly1305_keygen)
3337 SN_EXPORT_FUNCTION(crypto_secretstream_xchacha20poly1305_init_push, sn_crypto_secretstream_xchacha20poly1305_init_push)
3338 SN_EXPORT_FUNCTION(crypto_secretstream_xchacha20poly1305_init_pull, sn_crypto_secretstream_xchacha20poly1305_init_pull)
3339 SN_EXPORT_FUNCTION(crypto_secretstream_xchacha20poly1305_push, sn_crypto_secretstream_xchacha20poly1305_push)
3340 SN_EXPORT_FUNCTION(crypto_secretstream_xchacha20poly1305_pull, sn_crypto_secretstream_xchacha20poly1305_pull)
3341 SN_EXPORT_FUNCTION(crypto_secretstream_xchacha20poly1305_rekey, sn_crypto_secretstream_xchacha20poly1305_rekey)
3342 SN_EXPORT_UINT32(crypto_secretstream_xchacha20poly1305_STATEBYTES, sizeof(crypto_secretstream_xchacha20poly1305_state))
3343 SN_EXPORT_UINT32(crypto_secretstream_xchacha20poly1305_ABYTES, crypto_secretstream_xchacha20poly1305_ABYTES)
3344 SN_EXPORT_UINT32(crypto_secretstream_xchacha20poly1305_HEADERBYTES, crypto_secretstream_xchacha20poly1305_HEADERBYTES)
3345 SN_EXPORT_UINT32(crypto_secretstream_xchacha20poly1305_KEYBYTES, crypto_secretstream_xchacha20poly1305_KEYBYTES)
3346 SN_EXPORT_UINT32(crypto_secretstream_xchacha20poly1305_TAGBYTES, 1)
3347 SN_EXPORT_UINT64(crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX, crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX)
3348 SN_EXPORT_UINT32(crypto_secretstream_xchacha20poly1305_TAG_MESSAGE, crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
3349 SN_EXPORT_UINT32(crypto_secretstream_xchacha20poly1305_TAG_PUSH, crypto_secretstream_xchacha20poly1305_TAG_PUSH)
3350 SN_EXPORT_UINT32(crypto_secretstream_xchacha20poly1305_TAG_REKEY, crypto_secretstream_xchacha20poly1305_TAG_REKEY)
3351 SN_EXPORT_UINT32(crypto_secretstream_xchacha20poly1305_TAG_FINAL, crypto_secretstream_xchacha20poly1305_TAG_FINAL)
3352
3353 // crypto_shorthash
3354
3355 SN_EXPORT_FUNCTION(crypto_shorthash, sn_crypto_shorthash)
3356 SN_EXPORT_UINT32(crypto_shorthash_BYTES, crypto_shorthash_BYTES)
3357 SN_EXPORT_UINT32(crypto_shorthash_KEYBYTES, crypto_shorthash_KEYBYTES)
3358 SN_EXPORT_STRING(crypto_shorthash_PRIMITIVE, crypto_shorthash_PRIMITIVE)
3359
3360 // crypto_sign
3361
3362 SN_EXPORT_FUNCTION(crypto_sign_keypair, sn_crypto_sign_keypair)
3363 SN_EXPORT_FUNCTION(crypto_sign_seed_keypair, sn_crypto_sign_seed_keypair)
3364 SN_EXPORT_FUNCTION(crypto_sign, sn_crypto_sign)
3365 SN_EXPORT_FUNCTION(crypto_sign_open, sn_crypto_sign_open)
3366 SN_EXPORT_FUNCTION(crypto_sign_detached, sn_crypto_sign_detached)
3367 SN_EXPORT_FUNCTION(crypto_sign_verify_detached, sn_crypto_sign_verify_detached)
3368 SN_EXPORT_FUNCTION(crypto_sign_ed25519_sk_to_pk, sn_crypto_sign_ed25519_sk_to_pk)
3369 SN_EXPORT_FUNCTION(crypto_sign_ed25519_pk_to_curve25519, sn_crypto_sign_ed25519_pk_to_curve25519)
3370 SN_EXPORT_FUNCTION(crypto_sign_ed25519_sk_to_curve25519, sn_crypto_sign_ed25519_sk_to_curve25519)
3371 SN_EXPORT_UINT32(crypto_sign_SEEDBYTES, crypto_sign_SEEDBYTES)
3372 SN_EXPORT_UINT32(crypto_sign_PUBLICKEYBYTES, crypto_sign_PUBLICKEYBYTES)
3373 SN_EXPORT_UINT32(crypto_sign_SECRETKEYBYTES, crypto_sign_SECRETKEYBYTES)
3374 SN_EXPORT_UINT32(crypto_sign_BYTES, crypto_sign_BYTES)
3375
3376 // crypto_stream
3377
3378 SN_EXPORT_FUNCTION(crypto_stream, sn_crypto_stream)
3379 SN_EXPORT_UINT32(crypto_stream_KEYBYTES, crypto_stream_KEYBYTES)
3380 SN_EXPORT_UINT32(crypto_stream_NONCEBYTES, crypto_stream_NONCEBYTES)
3381 SN_EXPORT_STRING(crypto_stream_PRIMITIVE, crypto_stream_PRIMITIVE)
3382
3383 SN_EXPORT_FUNCTION(crypto_stream_xor, sn_crypto_stream_xor)
3384 SN_EXPORT_FUNCTION(crypto_stream_xor_init, sn_crypto_stream_xor_wrap_init)
3385 SN_EXPORT_FUNCTION(crypto_stream_xor_update, sn_crypto_stream_xor_wrap_update)
3386 SN_EXPORT_FUNCTION(crypto_stream_xor_final, sn_crypto_stream_xor_wrap_final)
3387 SN_EXPORT_UINT32(crypto_stream_xor_STATEBYTES, sizeof(sn_crypto_stream_xor_state))
3388
3389 SN_EXPORT_FUNCTION(crypto_stream_chacha20, sn_crypto_stream_chacha20)
3390 SN_EXPORT_UINT32(crypto_stream_chacha20_KEYBYTES, crypto_stream_chacha20_KEYBYTES)
3391 SN_EXPORT_UINT32(crypto_stream_chacha20_NONCEBYTES, crypto_stream_chacha20_NONCEBYTES)
3392 SN_EXPORT_UINT64(crypto_stream_chacha20_MESSAGEBYTES_MAX, crypto_stream_chacha20_MESSAGEBYTES_MAX)
3393
3394 SN_EXPORT_FUNCTION(crypto_stream_chacha20_xor, sn_crypto_stream_chacha20_xor)
3395 SN_EXPORT_FUNCTION(crypto_stream_chacha20_xor_ic, sn_crypto_stream_chacha20_xor_ic)
3396 SN_EXPORT_FUNCTION(crypto_stream_chacha20_xor_init, sn_crypto_stream_chacha20_xor_wrap_init)
3397 SN_EXPORT_FUNCTION(crypto_stream_chacha20_xor_update, sn_crypto_stream_chacha20_xor_wrap_update)
3398 SN_EXPORT_FUNCTION(crypto_stream_chacha20_xor_final, sn_crypto_stream_chacha20_xor_wrap_final)
3399 SN_EXPORT_UINT32(crypto_stream_chacha20_xor_STATEBYTES, sizeof(sn_crypto_stream_chacha20_xor_state))
3400
3401 SN_EXPORT_FUNCTION(crypto_stream_chacha20_ietf, sn_crypto_stream_chacha20_ietf)
3402 SN_EXPORT_UINT32(crypto_stream_chacha20_ietf_KEYBYTES, crypto_stream_chacha20_ietf_KEYBYTES)
3403 SN_EXPORT_UINT32(crypto_stream_chacha20_ietf_NONCEBYTES, crypto_stream_chacha20_ietf_NONCEBYTES)
3404 SN_EXPORT_UINT64(crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX, crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX)
3405 SN_EXPORT_UINT32(crypto_stream_chacha20_ietf_xor_STATEBYTES, sizeof(sn_crypto_stream_chacha20_ietf_xor_state))
3406
3407 SN_EXPORT_FUNCTION(crypto_stream_chacha20_ietf_xor, sn_crypto_stream_chacha20_ietf_xor)
3408 SN_EXPORT_FUNCTION(crypto_stream_chacha20_ietf_xor_ic, sn_crypto_stream_chacha20_ietf_xor_ic)
3409 SN_EXPORT_FUNCTION(crypto_stream_chacha20_ietf_xor_init, sn_crypto_stream_chacha20_ietf_xor_wrap_init)
3410 SN_EXPORT_FUNCTION(crypto_stream_chacha20_ietf_xor_update, sn_crypto_stream_chacha20_ietf_xor_wrap_update)
3411 SN_EXPORT_FUNCTION(crypto_stream_chacha20_ietf_xor_final, sn_crypto_stream_chacha20_ietf_xor_wrap_final)
3412
3413 SN_EXPORT_FUNCTION(crypto_stream_xchacha20, sn_crypto_stream_xchacha20)
3414 SN_EXPORT_UINT32(crypto_stream_xchacha20_KEYBYTES, crypto_stream_xchacha20_KEYBYTES)
3415 SN_EXPORT_UINT32(crypto_stream_xchacha20_NONCEBYTES, crypto_stream_xchacha20_NONCEBYTES)
3416 SN_EXPORT_UINT64(crypto_stream_xchacha20_MESSAGEBYTES_MAX, crypto_stream_xchacha20_MESSAGEBYTES_MAX)
3417
3418 SN_EXPORT_FUNCTION(crypto_stream_xchacha20_xor, sn_crypto_stream_xchacha20_xor)
3419 SN_EXPORT_FUNCTION(crypto_stream_xchacha20_xor_ic, sn_crypto_stream_xchacha20_xor_ic)
3420 SN_EXPORT_FUNCTION(crypto_stream_xchacha20_xor_init, sn_crypto_stream_xchacha20_xor_wrap_init)
3421 SN_EXPORT_FUNCTION(crypto_stream_xchacha20_xor_update, sn_crypto_stream_xchacha20_xor_wrap_update)
3422 SN_EXPORT_FUNCTION(crypto_stream_xchacha20_xor_final, sn_crypto_stream_xchacha20_xor_wrap_final)
3423 SN_EXPORT_FUNCTION(crypto_stream_xchacha20, sn_crypto_stream_xchacha20)
3424 SN_EXPORT_UINT32(crypto_stream_xchacha20_xor_STATEBYTES, sizeof(sn_crypto_stream_xchacha20_xor_state))
3425
3426 SN_EXPORT_FUNCTION(crypto_stream_salsa20, sn_crypto_stream_salsa20)
3427 SN_EXPORT_UINT32(crypto_stream_salsa20_KEYBYTES, crypto_stream_salsa20_KEYBYTES)
3428 SN_EXPORT_UINT32(crypto_stream_salsa20_NONCEBYTES, crypto_stream_salsa20_NONCEBYTES)
3429 SN_EXPORT_UINT64(crypto_stream_salsa20_MESSAGEBYTES_MAX, crypto_stream_salsa20_MESSAGEBYTES_MAX)
3430
3431 SN_EXPORT_FUNCTION(crypto_stream_salsa20_xor, sn_crypto_stream_salsa20_xor)
3432 SN_EXPORT_FUNCTION(crypto_stream_salsa20_xor_ic, sn_crypto_stream_salsa20_xor_ic)
3433 SN_EXPORT_FUNCTION(crypto_stream_salsa20_xor_init, sn_crypto_stream_salsa20_xor_wrap_init)
3434 SN_EXPORT_FUNCTION(crypto_stream_salsa20_xor_update, sn_crypto_stream_salsa20_xor_wrap_update)
3435 SN_EXPORT_FUNCTION(crypto_stream_salsa20_xor_final, sn_crypto_stream_salsa20_xor_wrap_final)
3436 SN_EXPORT_UINT32(crypto_stream_salsa20_xor_STATEBYTES, sizeof(sn_crypto_stream_salsa20_xor_state))
3437
3438 // extensions
3439
3440 // tweak
3441
3442 SN_EXPORT_FUNCTION(extension_tweak_ed25519_base, sn_extension_tweak_ed25519_base)
3443 SN_EXPORT_FUNCTION(extension_tweak_ed25519_sign_detached, sn_extension_tweak_ed25519_sign_detached)
3444 SN_EXPORT_FUNCTION(extension_tweak_ed25519_sk_to_scalar, sn_extension_tweak_ed25519_sk_to_scalar)
3445 SN_EXPORT_FUNCTION(extension_tweak_ed25519_scalar, sn_extension_tweak_ed25519_scalar)
3446 SN_EXPORT_FUNCTION(extension_tweak_ed25519_pk, sn_extension_tweak_ed25519_pk)
3447 SN_EXPORT_FUNCTION(extension_tweak_ed25519_keypair, sn_extension_tweak_ed25519_keypair)
3448 SN_EXPORT_FUNCTION(extension_tweak_ed25519_scalar_add, sn_extension_tweak_ed25519_scalar_add)
3449 SN_EXPORT_FUNCTION(extension_tweak_ed25519_pk_add, sn_extension_tweak_ed25519_pk_add)
3450 SN_EXPORT_FUNCTION(extension_tweak_ed25519_keypair_add, sn_extension_tweak_ed25519_keypair_add)
3451 SN_EXPORT_UINT32(extension_tweak_ed25519_BYTES, sn__extension_tweak_ed25519_BYTES)
3452 SN_EXPORT_UINT32(extension_tweak_ed25519_SCALARBYTES, sn__extension_tweak_ed25519_SCALARBYTES)
3453
3454 // pbkdf2
3455
3456 SN_EXPORT_FUNCTION(extension_pbkdf2_sha512, sn_extension_pbkdf2_sha512)
3457 SN_EXPORT_FUNCTION(extension_pbkdf2_sha512_async, sn_extension_pbkdf2_sha512_async)
3458 SN_EXPORT_UINT32(extension_pbkdf2_sha512_SALTBYTES, sn__extension_pbkdf2_sha512_SALTBYTES)
3459 SN_EXPORT_UINT32(extension_pbkdf2_sha512_HASHBYTES, sn__extension_pbkdf2_sha512_HASHBYTES)
3460 SN_EXPORT_UINT32(extension_pbkdf2_sha512_ITERATIONS_MIN, sn__extension_pbkdf2_sha512_ITERATIONS_MIN)
3461 SN_EXPORT_UINT64(extension_pbkdf2_sha512_BYTES_MAX, sn__extension_pbkdf2_sha512_BYTES_MAX)
3462
3463 return exports;
3464}
3465
3466static napi_value Init(napi_env env, napi_value exports) {
3467 return create_sodium_native(env);
3468}
3469
3470NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
node_modules/sodium-native/extensions/pbkdf2/pbkdf2.c +90 -0
……@@ -0,0 +1,90 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
29 */
30
31#include <string.h>
32#include <sodium.h>
33
34#include "pbkdf2.h"
35
36/**
37 * pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
38 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
39 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
40 */
41int
42sn__extension_pbkdf2_sha512(const unsigned char *passwd, size_t passwdlen,
43 const unsigned char *salt, size_t saltlen, uint64_t c,
44 unsigned char *buf, size_t dkLen)
45{
46 crypto_auth_hmacsha512_state PShctx, hctx;
47 size_t i;
48 unsigned char ivec[4];
49 unsigned char U[64];
50 unsigned char T[64];
51 uint64_t j;
52 unsigned int k;
53 size_t clen;
54
55 if (dkLen > sn__extension_pbkdf2_sha512_BYTES_MAX) {
56 return -1;
57 }
58
59 crypto_auth_hmacsha512_init(&PShctx, passwd, passwdlen);
60 crypto_auth_hmacsha512_update(&PShctx, salt, saltlen);
61
62 for (i = 0; i * crypto_auth_hmacsha512_BYTES < dkLen; i++) {
63 SN_PBKDF2_STORE32_BE(ivec, (uint32_t)(i + 1));
64 memcpy(&hctx, &PShctx, sizeof(crypto_auth_hmacsha512_state));
65 crypto_auth_hmacsha512_update(&hctx, ivec, 4);
66 crypto_auth_hmacsha512_final(&hctx, U);
67
68 memcpy(T, U, crypto_auth_hmacsha512_BYTES);
69 /* LCOV_EXCL_START */
70 for (j = 2; j <= c; j++) {
71 crypto_auth_hmacsha512_init(&hctx, passwd, passwdlen);
72 crypto_auth_hmacsha512_update(&hctx, U, crypto_auth_hmacsha512_BYTES);
73 crypto_auth_hmacsha512_final(&hctx, U);
74
75 for (k = 0; k < crypto_auth_hmacsha512_BYTES; k++) {
76 T[k] ^= U[k];
77 }
78 }
79 /* LCOV_EXCL_STOP */
80
81 clen = dkLen - i * crypto_auth_hmacsha512_BYTES;
82 if (clen > crypto_auth_hmacsha512_BYTES) {
83 clen = crypto_auth_hmacsha512_BYTES;
84 }
85 memcpy(&buf[i * crypto_auth_hmacsha512_BYTES], T, clen);
86 }
87 sodium_memzero((void *) &PShctx, sizeof PShctx);
88
89 return 0;
90}
node_modules/sodium-native/extensions/pbkdf2/pbkdf2.h +54 -0
……@@ -0,0 +1,54 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28/*
29 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
30 */
31
32#include <sodium.h>
33
34#define SN_PBKDF2_STORE32_BE(buf, n32) \
35 buf[0] = n32 >> 24 & 0xff; \
36 buf[1] = n32 >> 16 & 0xff; \
37 buf[2] = n32 >> 8 & 0xff; \
38 buf[3] = n32 >> 0 & 0xff;
39
40#define sn__extension_pbkdf2_sha512_SALTBYTES 16U
41
42#define sn__extension_pbkdf2_sha512_HASHBYTES crypto_hash_sha512_BYTES
43
44#define sn__extension_pbkdf2_sha512_ITERATIONS_MIN 1U
45
46#define sn__extension_pbkdf2_sha512_BYTES_MAX 0x3fffffffc0ULL
47
48/**
49 * extension_pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
50 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
51 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
52 */
53int sn__extension_pbkdf2_sha512(const unsigned char *, size_t, const unsigned char *, size_t,
54 uint64_t, unsigned char *, size_t);
node_modules/sodium-native/extensions/tweak/tweak.c +206 -0
……@@ -0,0 +1,206 @@
1#include "tweak.h"
2
3/*
4 *EXPERIMENTAL API*
5
6 This module is an experimental implementation of a key tweaking protocol
7 over ed25519 keys. The signature algorithm has been reimplemented from
8 libsodium, but the nonce generation algorithm is *non-standard*.
9
10 Use at your own risk
11*/
12
13static void _extension_tweak_nonce (unsigned char *nonce, const unsigned char *n,
14 const unsigned char *m, unsigned long long mlen)
15{
16 // dom2(x, y) with x = 0 (not prehashed) and y = "crypto_tweak_ed25519"
17 static const unsigned char TWEAK_PREFIX[32 + 2 + 20] = {
18 'S', 'i', 'g', 'E', 'd', '2', '5', '5', '1', '9', ' ',
19 'n', 'o', ' ', 'E', 'd', '2', '5', '5', '1', '9', ' ',
20 'c', 'o', 'l', 'l', 'i', 's', 'i', 'o', 'n', 's', 0,
21 20, 'c', 'r', 'y', 'p', 't', 'o', '_', 't', 'w', 'e',
22 'a', 'k', '_', 'e', 'd', '2', '5', '5', '1', '9'
23 };
24
25 crypto_hash_sha512_state hs;
26
27 crypto_hash_sha512_init(&hs);
28 crypto_hash_sha512_update(&hs, TWEAK_PREFIX, sizeof TWEAK_PREFIX);
29 crypto_hash_sha512_update(&hs, n, 32);
30 crypto_hash_sha512_update(&hs, m, mlen);
31 crypto_hash_sha512_final(&hs, nonce);
32}
33
34static inline void
35_crypto_sign_ed25519_clamp(unsigned char k[32])
36{
37 k[0] &= 248;
38 k[31] &= 127;
39 k[31] |= 64;
40}
41
42static void _extension_tweak_ed25519(unsigned char *q, unsigned char *n,
43 const unsigned char *ns, unsigned long long nslen)
44{
45 sodium_memzero(q, sizeof q);
46
47 crypto_hash(n, ns, nslen);
48 n[31] &= 127; // clear highest bit
49
50 crypto_scalarmult_ed25519_base_noclamp(q, n);
51
52 // hash tweak until we get a valid tweaked q
53 while (crypto_core_ed25519_is_valid_point(q) != 1) {
54 crypto_hash(n, n, 32);
55 n[31] &= 127; // clear highest bit
56
57 crypto_scalarmult_ed25519_base_noclamp(q, n);
58 }
59}
60
61void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
62 const unsigned char *ns, unsigned long long nslen)
63{
64 unsigned char n64[64];
65
66 _extension_tweak_ed25519(pk, n64, ns, nslen);
67
68 SN_TWEAK_COPY_32(scalar, n64)
69}
70
71int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
72 const unsigned char *m, unsigned long long mlen,
73 const unsigned char *n, unsigned char *pk)
74{
75 crypto_hash_sha512_state hs;
76
77 unsigned char nonce[64];
78 unsigned char R[32];
79 unsigned char hram[64];
80 unsigned char _pk[32];
81
82 // check if pk was passed
83 if (pk == NULL) {
84 pk = _pk;
85
86 // derive pk from scalar
87 if (crypto_scalarmult_ed25519_base_noclamp(pk, n) != 0) {
88 return -1;
89 }
90 }
91
92 _extension_tweak_nonce(nonce, n, m, mlen);
93 crypto_core_ed25519_scalar_reduce(nonce, nonce);
94
95 // R = G ^ nonce : curve point from nonce
96 if (crypto_scalarmult_ed25519_base_noclamp(R, nonce) != 0) {
97 return -1;
98 }
99
100 // generate challenge as h(ram) = hash(R, pk, message)
101 crypto_hash_sha512_init(&hs);
102 crypto_hash_sha512_update(&hs, R, 32);
103 crypto_hash_sha512_update(&hs, pk, 32);
104 crypto_hash_sha512_update(&hs, m, mlen);
105
106 crypto_hash_sha512_final(&hs, hram);
107
108 crypto_core_ed25519_scalar_reduce(hram, hram);
109
110 // sig = nonce + n * h(ram)
111 crypto_core_ed25519_scalar_mul(sig, hram, n);
112 crypto_core_ed25519_scalar_add(sig + 32, nonce, sig);
113
114 SN_TWEAK_COPY_32(sig, R)
115
116 if (siglen_p != NULL) {
117 *siglen_p = 64U;
118 }
119
120 return 0;
121}
122
123// tweak a secret key
124void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *n, const unsigned char *sk)
125{
126 unsigned char n64[64];
127
128 // get sk scalar from seed, cf. crypto_sign_keypair_seed
129 crypto_hash(n64, sk, 32);
130 _crypto_sign_ed25519_clamp(n64);
131
132 SN_TWEAK_COPY_32(n, n64)
133}
134
135// tweak a secret key
136void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
137 const unsigned char *scalar,
138 const unsigned char *ns,
139 unsigned long long nslen)
140{
141 unsigned char n[64];
142 unsigned char q[32];
143
144 _extension_tweak_ed25519(q, n, ns, nslen);
145 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
146}
147
148// tweak a public key
149int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
150 const unsigned char *pk,
151 const unsigned char *ns,
152 unsigned long long nslen)
153{
154 unsigned char n[64];
155 unsigned char q[32];
156
157 _extension_tweak_ed25519(q, n, ns, nslen);
158 return crypto_core_ed25519_add(tpk, q, pk);
159}
160
161
162void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
163 unsigned char *scalar, const unsigned char *ns,
164 unsigned long long nslen)
165{
166 unsigned char n64[64];
167
168 crypto_hash(n64, ns, nslen);
169 n64[31] &= 127; // clear highest bit
170
171 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
172 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
173
174 // hash tweak until we get a valid tweaked point
175 while (crypto_core_ed25519_is_valid_point(pk) != 1) {
176 crypto_hash(n64, n64, 32);
177 n64[31] &= 127; // clear highest bit
178
179 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
180 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
181 }
182}
183
184// add tweak to scalar
185void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
186 const unsigned char *scalar,
187 const unsigned char *n)
188{
189 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
190}
191
192// add tweak point to public key
193int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
194 const unsigned char *pk,
195 const unsigned char *q)
196{
197 return crypto_core_ed25519_add(tpk, pk, q);
198}
199
200
201int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
202 unsigned char *scalar, const unsigned char *tweak)
203{
204 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, tweak);
205 return crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
206}
node_modules/sodium-native/extensions/tweak/tweak.h +54 -0
……@@ -0,0 +1,54 @@
1#include <sodium.h>
2
3// copy 32 bytes using int64_t pointers
4#define SN_TWEAK_COPY_32(a, b) \
5 { \
6 long long *dst = (long long *) a; \
7 long long *src = (long long *) b; \
8 dst[0] = src[0]; \
9 dst[1] = src[1]; \
10 dst[2] = src[2]; \
11 dst[3] = src[3]; \
12 }
13
14#define sn__extension_tweak_ed25519_BYTES crypto_sign_ed25519_PUBLICKEYBYTES
15
16#define sn__extension_tweak_ed25519_SCALARBYTES crypto_scalarmult_ed25519_SCALARBYTES
17
18int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
19 const unsigned char *m, unsigned long long mlen,
20 const unsigned char *n, unsigned char *pk);
21
22void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
23 const unsigned char *ns, unsigned long long nslen);
24
25void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *scalar, const unsigned char *sk);
26
27// tweak a secret key
28void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
29 const unsigned char *scalar,
30 const unsigned char *ns,
31 unsigned long long nslen);
32
33// tweak a public key
34int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
35 const unsigned char *pk,
36 const unsigned char *ns,
37 unsigned long long nslen);
38
39void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
40 unsigned char *scalar, const unsigned char *ns,
41 unsigned long long nslen);
42
43// add tweak scalar to private key
44void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
45 const unsigned char *scalar,
46 const unsigned char *n);
47
48// add tweak point to public key
49int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
50 const unsigned char *pk,
51 const unsigned char *q);
52
53int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
54 unsigned char *scalar, const unsigned char *tweak);
node_modules/sodium-native/index.js +3 -0
……@@ -0,0 +1,3 @@
1require.addon = require('require-addon')
2
3module.exports = require.addon('.', __filename)
node_modules/sodium-native/macros.h +319 -0
……@@ -0,0 +1,319 @@
1#define SN_STATUS_THROWS(call, message) \
2 if ((call) != napi_ok) { \
3 napi_throw_error(env, NULL, message); \
4 return NULL; \
5 }
6
7#define SN_STATUS_THROWS_VOID(call, message) \
8 if ((call) != napi_ok) { \
9 napi_throw_error(env, NULL, message); \
10 return; \
11 }
12
13#define SN_THROWS(condition, message) \
14 if ((condition)) { \
15 napi_throw_error(env, NULL, message); \
16 return NULL; \
17 }
18
19#define SN_BUFFER_CAST(type, name, val) \
20 type name; \
21 size_t name##_size; \
22 SN_STATUS_THROWS(napi_get_buffer_info(env, val, (void **) &name, &name##_size), "")
23
24#define SN_TYPE_ASSERT(name, var, type, message) \
25 napi_valuetype name##_valuetype; \
26 SN_STATUS_THROWS(napi_typeof(env, var, &name##_valuetype), ""); \
27 if (name##_valuetype != type) { \
28 napi_throw_type_error(env, NULL, message); \
29 return NULL; \
30 }
31
32#define SN_TYPEDARRAY_ASSERT(name, var, message) \
33 bool name##_is_typedarray; \
34 SN_STATUS_THROWS(napi_is_typedarray(env, var, &name##_is_typedarray), ""); \
35 if (name##_is_typedarray != true) { \
36 napi_throw_type_error(env, NULL, message); \
37 return NULL; \
38 }
39
40#define SN_ASSERT_MIN_LENGTH(length, constant, name) \
41 SN_THROWS(length < constant, #name " must be at least " #constant " bytes long")
42
43
44#define SN_ASSERT_MAX_LENGTH(length, constant, name) \
45 SN_THROWS(length > constant, #name " must be at most " #constant " bytes long")
46
47
48#define SN_ASSERT_LENGTH(length, constant, name) \
49 SN_THROWS(length != constant, #name " must be " #constant " bytes long")
50
51#define SN_RANGE_THROWS(condition, message) \
52 if (condition) { \
53 napi_throw_range_error(env, NULL, message); \
54 return NULL; \
55 }
56
57#define SN_ARGV(n, method_name) \
58 napi_value argv[n]; \
59 size_t argc = n; \
60 SN_STATUS_THROWS(napi_get_cb_info(env, info, &argc, argv, NULL, NULL), ""); \
61 if (argc != n) { \
62 napi_throw_type_error(env, NULL, #method_name " requires " #n " argument(s)"); \
63 return NULL; \
64 }
65
66#define SN_ARGV_OPTS(required, total, method_name) \
67 napi_value argv[total]; \
68 size_t argc = total; \
69 SN_STATUS_THROWS(napi_get_cb_info(env, info, &argc, argv, NULL, NULL), ""); \
70 if (argc < required) { \
71 napi_throw_type_error(env, NULL, #method_name " requires at least " #required " argument(s)"); \
72 return NULL; \
73 }
74
75#define SN_EXPORT_FUNCTION(name, cb) \
76 { \
77 napi_value name##_fn; \
78 SN_STATUS_THROWS(napi_create_function(env, #name, NAPI_AUTO_LENGTH, cb, NULL, &name##_fn), "") \
79 SN_STATUS_THROWS(napi_set_named_property(env, exports, #name, name##_fn), "") \
80 }
81
82#define SN_EXPORT_UINT32(name, num) \
83 { \
84 napi_value name##_num; \
85 SN_STATUS_THROWS(napi_create_uint32(env, (uint32_t) num, &name##_num), "") \
86 SN_STATUS_THROWS(napi_set_named_property(env, exports, #name, name##_num), "") \
87 }
88
89#define SN_EXPORT_UINT64(name, num) \
90 { \
91 napi_value name##_num; \
92 uint64_t max = 0x1fffffffffffffULL; \
93 SN_STATUS_THROWS(napi_create_int64(env, (uint64_t) (max < num ? max : num), &name##_num), "") \
94 SN_STATUS_THROWS(napi_set_named_property(env, exports, #name, name##_num), "") \
95 }
96
97#define SN_EXPORT_STRING(name, string) \
98 { \
99 napi_value name##_string; \
100 SN_STATUS_THROWS(napi_create_string_utf8(env, string, NAPI_AUTO_LENGTH, &name##_string), "") \
101 SN_STATUS_THROWS(napi_set_named_property(env, exports, #name, name##_string), "") \
102 }
103
104#define SN_ARGV_CHECK_NULL(name, index) \
105 napi_valuetype name##_valuetype; \
106 SN_STATUS_THROWS(napi_typeof(env, argv[index], &name##_valuetype), "") \
107 bool name##_is_null = name##_valuetype == napi_null;
108
109#define SN_ARGV_OPTS_TYPEDARRAY(name, index) \
110 napi_valuetype name##_valuetype; \
111 void *name##_data = NULL; \
112 size_t name##_size = 0; \
113 SN_STATUS_THROWS(napi_typeof(env, argv[index], &name##_valuetype), "") \
114 if (name##_valuetype != napi_null && name##_valuetype != napi_undefined) { \
115 napi_value name##_argv = argv[index]; \
116 SN_TYPEDARRAY_ASSERT(name, name##_argv, #name " must be an instance of TypedArray") \
117 SN_OPT_TYPEDARRAY(name, name##_argv) \
118 }
119
120#define SN_TYPEDARRAY(name, var) \
121 napi_typedarray_type name##_type; \
122 size_t name##_length; \
123 void *name##_data; \
124 napi_get_typedarray_info(env, (var), &name##_type, &name##_length, &name##_data, NULL, NULL); \
125 uint8_t name##_width = typedarray_width(name##_type); \
126 SN_THROWS(name##_width == 0, "Unexpected TypedArray type") \
127 size_t name##_size = name##_length * name##_width;
128
129#define SN_TYPEDARRAY_PTR(name, var) \
130 napi_typedarray_type name##_type; \
131 size_t name##_length; \
132 void *name##_data; \
133 napi_get_typedarray_info(env, (var), &name##_type, &name##_length, &name##_data, NULL, NULL); \
134 uint8_t name##_width = typedarray_width(name##_type); \
135 SN_THROWS(name##_width == 0, "Unexpected TypedArray type") \
136
137#define SN_OPT_TYPEDARRAY(name, var) \
138 napi_typedarray_type name##_type; \
139 size_t name##_length; \
140 napi_get_typedarray_info(env, (var), &name##_type, &name##_length, &name##_data, NULL, NULL); \
141 uint8_t name##_width = typedarray_width(name##_type); \
142 SN_THROWS(name##_width == 0, "Unexpected TypedArray type") \
143 name##_size = name##_length * name##_width;
144
145#define SN_UINT8(name, val) \
146 uint32_t name##_int32; \
147 if (napi_get_value_uint32(env, val, &name##_int32) != napi_ok) { \
148 napi_throw_error(env, "EINVAL", "Expected number"); \
149 return NULL; \
150 } \
151 SN_THROWS(name##_int32 > 255, "expect uint8") \
152 unsigned char name = 0xff & name##_int32;
153
154#define SN_UINT32(name, val) \
155 uint32_t name; \
156 if (napi_get_value_uint32(env, val, &name) != napi_ok) { \
157 napi_throw_error(env, "EINVAL", "Expected number"); \
158 return NULL; \
159 }
160
161#define SN_OPT_UINT32(name, val) \
162 if (napi_get_value_uint32(env, val, (uint32_t *) &name) != napi_ok) { \
163 napi_throw_error(env, "EINVAL", "Expected number"); \
164 return NULL; \
165 }
166
167#define SN_UINT64(name, val) \
168 int64_t name##_i64; \
169 if (napi_get_value_int64(env, val, &name##_i64) != napi_ok) { \
170 napi_throw_error(env, "EINVAL", "Expected number"); \
171 return NULL; \
172 } \
173 if (name##_i64 < 0) { \
174 napi_throw_error(env, "EINVAL", "Expected positive number"); \
175 return NULL; \
176 } \
177 uint64_t name = (uint64_t) name##_i64;
178
179#define SN_ARGV_TYPEDARRAY(name, index) \
180 napi_value name##_argv = argv[index]; \
181 SN_TYPEDARRAY_ASSERT(name, name##_argv, #name " must be an instance of TypedArray") \
182 SN_TYPEDARRAY(name, name##_argv)
183
184#define SN_ARGV_TYPEDARRAY_PTR(name, index) \
185 napi_value name##_argv = argv[index]; \
186 SN_TYPEDARRAY_ASSERT(name, name##_argv, #name " must be an instance of TypedArray") \
187 SN_TYPEDARRAY_PTR(name, name##_argv)
188
189#define SN_ARGV_BUFFER_CAST(type, name, index) \
190 napi_value name##_argv = argv[index]; \
191 SN_BUFFER_CAST(type, name, name##_argv)
192
193#define SN_OPT_ARGV_TYPEDARRAY(name, index) \
194 napi_value name##_argv = argv[index]; \
195 SN_TYPEDARRAY_ASSERT(name, name##_argv, #name " must be an instance of TypedArray") \
196 SN_OPT_TYPEDARRAY(name, name##_argv)
197
198#define SN_ARGV_UINT8(name, index) \
199 napi_value name##_argv = argv[index]; \
200 SN_TYPE_ASSERT(name, name##_argv, napi_number, #name " must be an instance of Number") \
201 SN_UINT8(name, name##_argv)
202
203#define SN_ARGV_UINT32(name, index) \
204 napi_value name##_argv = argv[index]; \
205 SN_TYPE_ASSERT(name, name##_argv, napi_number, #name " must be an instance of Number") \
206 SN_UINT32(name, name##_argv)
207
208#define SN_ARGV_UINT64(name, index) \
209 napi_value name##_argv = argv[index]; \
210 SN_TYPE_ASSERT(name, name##_argv, napi_number, #name " must be an instance of Number") \
211 SN_UINT64(name, name##_argv)
212
213#define SN_OPT_ARGV_UINT32(name, index) \
214 napi_value name##_argv = argv[index]; \
215 SN_TYPE_ASSERT(name, name##_argv, napi_number, #name " must be an instance of Number") \
216 SN_OPT_UINT32(name, name##_argv)
217
218#define SN_CALL(call, message) \
219 int success = call; \
220 SN_THROWS(success != 0, message)
221
222#define SN_CALL_FUNCTION(env, ctx, cb, n, argv, res) \
223 if (napi_make_callback(env, NULL, ctx, cb, n, argv, res) == napi_pending_exception) { \
224 napi_value fatal_exception; \
225 napi_get_and_clear_last_exception(env, &fatal_exception); \
226 napi_fatal_exception(env, fatal_exception); \
227 }
228
229#define SN_RETURN(call, message) \
230 int success = call; \
231 SN_THROWS(success != 0, message) \
232 return NULL;
233
234#define SN_RETURN_BOOLEAN(call) \
235 int success = call; \
236 napi_value result; \
237 SN_THROWS(napi_get_boolean(env, success == 0, &result) != napi_ok, "result not boolean") \
238 return result;
239
240#define SN_RETURN_BOOLEAN_FROM_1(call) \
241 int success = call; \
242 napi_value result; \
243 SN_THROWS(napi_get_boolean(env, success != 0, &result) != napi_ok, "result not boolean") \
244 return result;
245
246#define SN_ASYNC_CHECK_FOR_ERROR(message) \
247 if (req->n == 0) { \
248 napi_get_null(req->env, &argv[0]); \
249 } else { \
250 napi_value err_msg; \
251 napi_create_string_utf8(req->env, #message, NAPI_AUTO_LENGTH, &err_msg); \
252 napi_create_error(req->env, NULL, err_msg, &argv[0]); \
253 }
254
255#define SN_CALLBACK_CHECK_FOR_ERROR(message) \
256 if (task->code == 0) { \
257 napi_get_null(req->env, &argv[0]); \
258 } else { \
259 napi_value err_msg; \
260 napi_create_string_utf8(req->env, #message, NAPI_AUTO_LENGTH, &err_msg); \
261 napi_create_error(req->env, NULL, err_msg, &argv[0]); \
262 }
263
264#define SN_QUEUE_WORK(req, execute, complete) \
265 uv_loop_t *loop; \
266 napi_get_uv_event_loop(env, &loop); \
267 uv_queue_work(loop, (uv_work_t *) req, execute, complete);
268
269#define SN_QUEUE_TASK(task, execute, complete) \
270 uv_loop_t *loop; \
271 napi_get_uv_event_loop(env, &loop); \
272 uv_queue_work(loop, (uv_work_t *) task, execute, complete);
273
274#define SN_ASYNC_TASK(cb_pos) \
275 task->req = (void *) req; \
276 napi_value promise; \
277 if (argc > cb_pos) { \
278 task->type = sn_async_task_callback; \
279 promise = NULL; \
280 napi_value cb = argv[cb_pos]; \
281 napi_valuetype type; \
282 SN_STATUS_THROWS(napi_typeof(env, cb, &type), "") \
283 if (type != napi_function) { \
284 napi_throw_error(env, "EINVAL", "Callback must be a function"); \
285 return NULL; \
286 } \
287 SN_STATUS_THROWS(napi_create_reference(env, cb, 1, &task->cb), "") \
288 } else { \
289 task->type = sn_async_task_promise; \
290 napi_create_promise(env, &task->deferred, &promise); \
291 }
292
293#define SN_ASYNC_COMPLETE(message) \
294 napi_value argv[1]; \
295 switch (task->type) { \
296 case sn_async_task_promise: { \
297 if (task->code == 0) { \
298 napi_get_null(req->env, &argv[0]); \
299 napi_resolve_deferred(req->env, task->deferred, argv[0]); \
300 } else { \
301 napi_value err_msg; \
302 napi_create_string_utf8(req->env, #message, NAPI_AUTO_LENGTH, &err_msg); \
303 napi_create_error(req->env, NULL, err_msg, &argv[0]); \
304 napi_reject_deferred(req->env, task->deferred, argv[0]); \
305 } \
306 task->deferred = NULL; \
307 break; \
308 } \
309 case sn_async_task_callback: { \
310 SN_CALLBACK_CHECK_FOR_ERROR(#message) \
311 napi_value callback; \
312 napi_get_reference_value(req->env, task->cb, &callback); \
313 napi_value return_val; \
314 SN_CALL_FUNCTION(req->env, global, callback, 1, argv, &return_val) \
315 napi_close_handle_scope(req->env, scope); \
316 napi_delete_reference(req->env, task->cb); \
317 break; \
318 } \
319 }
node_modules/sodium-native/package.json +47 -0
……@@ -0,0 +1,47 @@
1{
2 "name": "sodium-native",
3 "version": "4.3.3",
4 "description": "Low level bindings for libsodium",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "binding.c",
9 "macros.h",
10 "extensions",
11 "prebuilds",
12 "CMakeLists.txt"
13 ],
14 "addon": true,
15 "dependencies": {
16 "require-addon": "^1.1.0"
17 },
18 "devDependencies": {
19 "brittle": "^3.5.0",
20 "cmake-bare": "^1.1.10",
21 "cmake-fetch": "^1.0.1",
22 "cmake-napi": "^1.0.5",
23 "standard": "^17.1.0"
24 },
25 "scripts": {
26 "test": "standard && brittle test/*.js"
27 },
28 "standard": {
29 "ignore": [
30 "/test/fixtures/*.js"
31 ]
32 },
33 "repository": {
34 "type": "git",
35 "url": "https://github.com/holepunchto/sodium-native.git"
36 },
37 "contributors": [
38 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
39 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
40 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
41 ],
42 "license": "MIT",
43 "bugs": {
44 "url": "https://github.com/holepunchto/sodium-native/issues"
45 },
46 "homepage": "https://github.com/holepunchto/sodium-native"
47}
node_modules/sodium-native/prebuilds/android-arm/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/android-arm/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/android-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/android-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/android-ia32/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/android-ia32/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/android-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/android-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/ios-arm64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/ios-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/ios-x64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/linux-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/linux-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/win32-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-native/prebuilds/win32-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2021 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/sodium-secretstream/README.md +49 -0
……@@ -0,0 +1,49 @@
1# sodium-secretstream
2
3Wraps libsodium's secretstream in a higher level abstraction
4
5```
6npm install sodium-secretstream
7```
8
9## Usage
10
11``` js
12const { Pull, Push, keygen } = require('sodium-secretstream')
13
14const key = keygen()
15
16// the sender
17const push = new Push(key)
18
19// the receiver
20const pull = new Pull(key)
21
22// send header to the other side
23pull.init(push.header)
24
25// send the cipher to the other side
26const cipher1 = push.next(Buffer.from('test'))
27
28// prints "test"
29console.log(pull.next(cipher1))
30
31// send the cipher to the other side
32const cipher2 = push.next(Buffer.from('test 2'))
33
34// prints "test 2"
35console.log(pull.next(cipher2))
36
37// when done send a final signal
38const cipher3 = push.final()
39
40// prints <empty buffer>
41console.log(pull.next(cipher3))
42
43// but sets pull.final to true
44console.log(pull.final)
45```
46
47## License
48
49MIT
node_modules/sodium-secretstream/example.js +33 -0
……@@ -0,0 +1,33 @@
1const { Pull, Push, keygen } = require('./')
2
3const key = keygen()
4
5// the sender
6const push = new Push(key)
7
8// the receiver
9const pull = new Pull(key)
10
11// send header to the other side
12pull.init(push.header)
13
14// send the cipher to the other side
15const cipher1 = push.next(Buffer.from('test'))
16
17// prints "test"
18console.log(pull.next(cipher1))
19
20// send the cipher to the other side
21const cipher2 = push.next(Buffer.from('test 2'))
22
23// prints "test 2"
24console.log(pull.next(cipher2))
25
26// when done send a final signal
27const cipher3 = push.final()
28
29// prints <empty buffer>
30console.log(pull.next(cipher3))
31
32// but sets pull.final to true
33console.log(pull.final)
node_modules/sodium-secretstream/index.js +70 -0
……@@ -0,0 +1,70 @@
1const sodium = require('sodium-universal')
2const b4a = require('b4a')
3
4const ABYTES = sodium.crypto_secretstream_xchacha20poly1305_ABYTES
5const TAG_MESSAGE = sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
6const TAG_FINAL = sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL
7const STATEBYTES = sodium.crypto_secretstream_xchacha20poly1305_STATEBYTES
8const HEADERBYTES = sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES
9const KEYBYTES = sodium.crypto_secretstream_xchacha20poly1305_KEYBYTES
10const TAG_FINAL_BYTE = b4a.isBuffer(TAG_FINAL) ? TAG_FINAL[0] : TAG_FINAL
11
12const EMPTY = b4a.alloc(0)
13const TAG = b4a.alloc(1)
14
15class Push {
16 constructor (key, state = b4a.allocUnsafeSlow(STATEBYTES), header = b4a.allocUnsafeSlow(HEADERBYTES)) {
17 if (!TAG_FINAL) throw new Error('JavaScript sodium version needs to support crypto_secretstream_xchacha20poly')
18
19 this.key = key
20 this.state = state
21 this.header = header
22
23 sodium.crypto_secretstream_xchacha20poly1305_init_push(this.state, this.header, this.key)
24 }
25
26 next (message, cipher = b4a.allocUnsafe(message.byteLength + ABYTES)) {
27 sodium.crypto_secretstream_xchacha20poly1305_push(this.state, cipher, message, null, TAG_MESSAGE)
28 return cipher
29 }
30
31 final (message = EMPTY, cipher = b4a.allocUnsafe(ABYTES)) {
32 sodium.crypto_secretstream_xchacha20poly1305_push(this.state, cipher, message, null, TAG_FINAL)
33 return cipher
34 }
35}
36
37class Pull {
38 constructor (key, state = b4a.allocUnsafeSlow(STATEBYTES)) {
39 if (!TAG_FINAL) throw new Error('JavaScript sodium version needs to support crypto_secretstream_xchacha20poly')
40
41 this.key = key
42 this.state = state
43 this.final = false
44 }
45
46 init (header) {
47 sodium.crypto_secretstream_xchacha20poly1305_init_pull(this.state, header, this.key)
48 }
49
50 next (cipher, message = b4a.allocUnsafe(cipher.byteLength - ABYTES)) {
51 sodium.crypto_secretstream_xchacha20poly1305_pull(this.state, message, TAG, cipher, null)
52 this.final = TAG[0] === TAG_FINAL_BYTE
53 return message
54 }
55}
56
57function keygen (buf = b4a.alloc(KEYBYTES)) {
58 sodium.crypto_secretstream_xchacha20poly1305_keygen(buf)
59 return buf
60}
61
62module.exports = {
63 keygen,
64 KEYBYTES,
65 ABYTES,
66 STATEBYTES,
67 HEADERBYTES,
68 Push,
69 Pull
70}
node_modules/sodium-secretstream/node_modules/sodium-native/CMakeLists.txt +279 -0
……@@ -0,0 +1,279 @@
1cmake_minimum_required(VERSION 3.25)
2
3find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5find_package(cmake-napi REQUIRED PATHS node_modules/cmake-napi)
6find_package(cmake-npm REQUIRED PATHS node_modules/cmake-npm)
7
8set(CMAKE_POSITION_INDEPENDENT_CODE ON)
9
10project(sodium_native C ASM CXX)
11
12fetch_package("github:jedisct1/libsodium#e18eee6" SOURCE_DIR sodium)
13
14fetch_package("github:holepunchto/libjstl#098664c")
15
16bare_target(target)
17
18if(target MATCHES "win32")
19 add_compile_options(/MT$<$<CONFIG:Debug>:d>)
20endif()
21
22file(COPY_FILE "${sodium}/builds/msvc/version.h" "${sodium}/src/libsodium/include/sodium/version.h")
23
24file(GLOB_RECURSE sodium_headers CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.h")
25file(GLOB_RECURSE sodium_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.c")
26file(GLOB_RECURSE sodium_asm_sources CONFIGURE_DEPENDS "${sodium}/src/libsodium/**/*.S")
27
28add_library(sodium OBJECT)
29
30target_sources(
31 sodium
32 INTERFACE
33 ${sodium_headers}
34 PRIVATE
35 ${sodium_sources}
36)
37
38target_include_directories(
39 sodium
40 INTERFACE
41 "${sodium}/src/libsodium/include"
42 PRIVATE
43 "${sodium}/src/libsodium/include/sodium"
44)
45
46if(NOT target MATCHES "win32")
47 target_compile_options(
48 sodium
49 PRIVATE
50 -fvisibility=hidden
51 -fno-strict-aliasing
52 -fwrapv
53 -flax-vector-conversions
54 )
55endif()
56
57target_compile_definitions(
58 sodium
59 PUBLIC
60 SODIUM_STATIC=1
61 PRIVATE
62 _GNU_SOURCE=1
63 CONFIGURED=1
64 DEV_MODE=1
65 HAVE_ATOMIC_OPS=1
66 HAVE_C11_MEMORY_FENCES=1
67 HAVE_CET_H=1
68 HAVE_GCC_MEMORY_FENCES=1
69 HAVE_INLINE_ASM=1
70 HAVE_INTTYPES_H=1
71 HAVE_STDINT_H=1
72 HAVE_TI_MODE=1
73)
74
75if(target MATCHES "darwin|ios")
76 target_compile_definitions(
77 sodium
78 PRIVATE
79 ASM_HIDE_SYMBOL=.private_extern
80 TLS=_Thread_local
81 HAVE_ARC4RANDOM=1
82 HAVE_ARC4RANDOM_BUF=1
83 HAVE_CATCHABLE_ABRT=1
84 HAVE_CATCHABLE_SEGV=1
85 HAVE_CLOCK_GETTIME=1
86 HAVE_GETPID=1
87 HAVE_MADVISE=1
88 HAVE_MEMSET_S=1
89 HAVE_MLOCK=1
90 HAVE_MMAP=1
91 HAVE_MPROTECT=1
92 HAVE_NANOSLEEP=1
93 HAVE_POSIX_MEMALIGN=1
94 HAVE_PTHREAD=1
95 HAVE_PTHREAD_PRIO_INHERIT=1
96 HAVE_RAISE=1
97 HAVE_SYSCONF=1
98 HAVE_SYS_MMAN_H=1
99 HAVE_SYS_PARAM_H=1
100 HAVE_WEAK_SYMBOLS=1
101 )
102
103 if(NOT target MATCHES "ios")
104 target_compile_definitions(
105 sodium
106 PRIVATE
107 HAVE_GETENTROPY=1
108 HAVE_SYS_RANDOM_H=1
109 )
110 endif()
111endif()
112
113if(target MATCHES "linux")
114 target_compile_definitions(
115 sodium
116 PRIVATE
117 ASM_HIDE_SYMBOL=.hidden
118 TLS=_Thread_local
119 HAVE_CATCHABLE_ABRT=1
120 HAVE_CATCHABLE_SEGV=1
121 HAVE_CLOCK_GETTIME=1
122 HAVE_GETPID=1
123 HAVE_MADVISE=1
124 HAVE_MLOCK=1
125 HAVE_MMAP=1
126 HAVE_MPROTECT=1
127 HAVE_NANOSLEEP=1
128 HAVE_POSIX_MEMALIGN=1
129 HAVE_PTHREAD_PRIO_INHERIT=1
130 HAVE_PTHREAD=1
131 HAVE_RAISE=1
132 HAVE_SYSCONF=1
133 HAVE_SYS_AUXV_H=1
134 HAVE_SYS_MMAN_H=1
135 HAVE_SYS_PARAM_H=1
136 HAVE_SYS_RANDOM_H=1
137 HAVE_WEAK_SYMBOLS=1
138 )
139endif()
140
141if(target MATCHES "win32")
142 target_compile_definitions(
143 sodium
144 PRIVATE
145 _CRT_SECURE_NO_WARNINGS=1
146 HAVE_RAISE=1
147 )
148endif()
149
150if(target MATCHES "x64")
151 target_compile_definitions(
152 sodium
153 PRIVATE
154 HAVE_CPUID=1
155 HAVE_RDRAND=1
156 HAVE_EMMINTRIN_H=1 # SSE2
157 HAVE_PMMINTRIN_H=1 # SSE3
158 HAVE_TMMINTRIN_H=1 # SSSE3
159 HAVE_SMMINTRIN_H=1 # SSE4.1
160 HAVE_WMMINTRIN_H=1 # AES
161 HAVE_AVXINTRIN_H=1 # AVX
162 HAVE_AVX2INTRIN_H=1 # AVX2
163 HAVE_AVX512FINTRIN_H # AVX512F
164 )
165
166 if(NOT target MATCHES "win32")
167 target_compile_definitions(
168 sodium
169 PRIVATE
170 HAVE_AMD64_ASM=1
171 HAVE_AVX_ASM=1
172 )
173
174 target_sources(
175 sodium
176 PRIVATE
177 ${sodium_asm_sources}
178 )
179 endif()
180endif()
181
182if(target MATCHES "arm64")
183 target_compile_definitions(
184 sodium
185 PRIVATE
186 HAVE_ARMCRYPTO=1
187 )
188endif()
189
190if(CMAKE_C_BYTE_ORDER MATCHES "BIG_ENDIAN")
191 target_compile_definitions(
192 sodium
193 PRIVATE
194 NATIVE_BIG_ENDIAN=1
195 )
196else()
197 target_compile_definitions(
198 sodium
199 PRIVATE
200 NATIVE_LITTLE_ENDIAN=1
201 )
202endif()
203
204if(target MATCHES "linux|android")
205 target_link_options(
206 sodium
207 PUBLIC
208 -Wl,-z,noexecstack
209 )
210endif()
211
212add_library(sodium_extensions OBJECT)
213
214target_sources(
215 sodium_extensions
216 PRIVATE
217 extensions/tweak/tweak.c
218 extensions/tweak/tweak.h
219 extensions/pbkdf2/pbkdf2.c
220 extensions/pbkdf2/pbkdf2.h
221)
222
223target_link_libraries(
224 sodium_extensions
225 PUBLIC
226 sodium
227)
228
229add_bare_module(sodium_native_bare)
230
231target_sources(
232 ${sodium_native_bare}
233 PRIVATE
234 binding.cc
235)
236
237target_link_libraries(
238 ${sodium_native_bare}
239 PRIVATE
240 $<TARGET_OBJECTS:sodium>
241 $<TARGET_OBJECTS:sodium_extensions>
242 jstl
243 PUBLIC
244 sodium
245 sodium_extensions
246)
247
248add_napi_module(sodium_native_node)
249
250target_sources(
251 ${sodium_native_node}
252 PRIVATE
253 binding.cc
254)
255
256target_compile_definitions(
257 ${sodium_native_node}
258 PRIVATE
259 NAPI_VERSION=9
260)
261
262target_link_libraries(
263 ${sodium_native_node}
264 PRIVATE
265 $<TARGET_OBJECTS:sodium>
266 $<TARGET_OBJECTS:sodium_extensions>
267 jstl
268 PUBLIC
269 sodium
270 sodium_extensions
271)
272
273resolve_node_module(bare-compat-napi compat)
274
275target_include_directories(
276 ${sodium_native_node}
277 PRIVATE
278 "${compat}/include"
279)
node_modules/sodium-secretstream/node_modules/sodium-native/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2016 Mathias Buus and Emil Bay
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/sodium-secretstream/node_modules/sodium-native/README.md +51 -0
……@@ -0,0 +1,51 @@
1# sodium-native
2
3Low level bindings for [libsodium](https://github.com/jedisct1/libsodium).
4
5```
6npm install sodium-native
7```
8
9The goal of this project is to be thin, stable, unopionated wrapper around libsodium.
10
11All methods exposed are more or less a direct translation of the libsodium c-api.
12This means that most data types are buffers and you have to manage allocating return values and passing them in as arguments instead of receiving them as return values.
13
14This makes this API harder to use than other libsodium wrappers out there, but also means that you'll be able to get a lot of perf / memory improvements as you can do stuff like inline encryption / decryption, reuse buffers etc.
15
16This also makes this library useful as a foundation for more high level crypto abstractions that you want to make.
17
18## Usage
19
20```js
21var sodium = require('sodium-native')
22
23var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
24var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) // secure buffer
25var message = Buffer.from('Hello, World!')
26var ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
27
28sodium.randombytes_buf(nonce) // insert random data into nonce
29sodium.randombytes_buf(key) // insert random data into key
30
31// encrypted message is stored in ciphertext.
32sodium.crypto_secretbox_easy(ciphertext, message, nonce, key)
33
34console.log('Encrypted message:', ciphertext)
35
36var plainText = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES)
37
38if (!sodium.crypto_secretbox_open_easy(plainText, ciphertext, nonce, key)) {
39 console.log('Decryption failed!')
40} else {
41 console.log('Decrypted message:', plainText, '(' + plainText.toString() + ')')
42}
43```
44
45## Documentation
46
47Complete documentation may be found on the [sodium-friends website](https://sodium-friends.github.io/docs/docs/getstarted)
48
49## License
50
51MIT
node_modules/sodium-secretstream/node_modules/sodium-native/binding.cc +4094 -0
……@@ -0,0 +1,4094 @@
1#include <assert.h>
2#include <bare.h>
3#include <js.h>
4#include <jstl.h>
5#include <sodium.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <string.h>
9#include <uv.h>
10
11#include "extensions/pbkdf2/pbkdf2.h"
12#include "extensions/tweak/tweak.h"
13
14#define assert_bounds(arraybuffer) \
15 assert(arraybuffer##_offset + arraybuffer##_len <= arraybuffer.size())
16
17static inline void
18sn_sodium_memzero(
19 js_env_t *,
20 js_receiver_t,
21 js_typedarray_span_t<> buf
22) {
23 sodium_memzero(buf.data(), buf.size_bytes());
24}
25
26static inline int
27sn_sodium_mlock(
28 js_env_t *,
29 js_receiver_t,
30 js_typedarray_span_t<> buf
31) {
32 return sodium_mlock(buf.data(), buf.size_bytes());
33}
34
35static inline int
36sn_sodium_munlock(
37 js_env_t *,
38 js_receiver_t,
39 js_typedarray_span_t<> buf
40) {
41 return sodium_munlock(buf.data(), buf.size_bytes());
42}
43
44static void
45sn_external_arraybuffer_finalize(js_env_t *env, uint8_t *ptr) {
46 sodium_free(ptr);
47}
48
49static js_arraybuffer_t
50sn_sodium_malloc(js_env_t *env, js_receiver_t, uint32_t len) {
51 int err;
52
53 auto ptr = reinterpret_cast<uint8_t *>(sodium_malloc(len));
54
55 js_arraybuffer_t buffer;
56
57 err = js_create_external_arraybuffer<sn_external_arraybuffer_finalize>(env, ptr, len, buffer);
58 assert(err == 0);
59
60 return buffer;
61}
62
63static void
64sn_sodium_free(js_env_t *env, js_receiver_t, js_arraybuffer_t buf) {
65 int err;
66
67 std::span<uint8_t> view;
68 err = js_get_arraybuffer_info(env, buf, view);
69 assert(err == 0);
70
71 if (view.empty()) return;
72
73 err = js_detach_arraybuffer(env, buf);
74 assert(err == 0);
75}
76
77static inline int
78sn_sodium_mprotect_noaccess(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
79 return sodium_mprotect_noaccess(buf.data());
80}
81
82static inline int
83sn_sodium_mprotect_readonly(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
84 return sodium_mprotect_readonly(buf.data());
85}
86
87static inline int
88sn_sodium_mprotect_readwrite(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
89 return sodium_mprotect_readwrite(buf.data());
90}
91
92static inline uint32_t // TODO: test envless
93sn_randombytes_random(js_env_t *env, js_receiver_t) {
94 return randombytes_random();
95}
96
97static inline uint32_t // TODO: test envless
98sn_randombytes_uniform(js_env_t *env, js_receiver_t, uint32_t upper_bound) {
99 return randombytes_uniform(upper_bound);
100}
101
102static inline void
103sn_randombytes_buf(
104 js_env_t *env,
105 js_receiver_t,
106 js_arraybuffer_span_t buf,
107 uint32_t buf_offset,
108 uint32_t buf_len
109) {
110 assert_bounds(buf);
111
112 randombytes_buf(&buf[buf_offset], buf_len);
113}
114
115static inline void
116sn_randombytes_buf_deterministic(
117 js_env_t *env,
118 js_receiver_t,
119
120 js_arraybuffer_span_t buf,
121 uint32_t buf_offset,
122 uint32_t buf_len,
123
124 js_arraybuffer_span_t seed,
125 uint32_t seed_offset,
126 uint32_t seed_len
127) {
128 assert_bounds(buf);
129 assert_bounds(seed);
130
131 assert(seed_len == randombytes_SEEDBYTES);
132
133 randombytes_buf_deterministic(&buf[buf_offset], buf_len, &seed[seed_offset]);
134}
135
136static inline bool
137sn_sodium_memcmp(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
138 if (a.size_bytes() != b.size_bytes()) return false;
139
140 return sodium_memcmp(a.data(), b.data(), a.size_bytes()) == 0;
141}
142
143static inline void
144sn_sodium_increment(js_env_t *, js_receiver_t, js_typedarray_span_t<> n) {
145 sodium_increment(n.data(), n.size_bytes());
146}
147
148static inline void
149sn_sodium_add(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
150 sodium_add(a.data(), b.data(), a.size_bytes());
151}
152
153static inline void
154sn_sodium_sub(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
155 sodium_sub(a.data(), b.data(), a.size_bytes());
156}
157
158static inline int32_t
159sn_sodium_compare(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
160 return sodium_compare(a.data(), b.data(), a.size_bytes());
161}
162
163static inline bool
164sn_sodium_is_zero(js_env_t *, js_receiver_t, js_typedarray_span_t<> buffer, uint32_t len) {
165 assert(len <= buffer.size_bytes());
166
167 return sodium_is_zero(buffer.data(), len) != 0;
168}
169
170static inline uint32_t
171sn_sodium_pad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t unpadded_buflen, uint32_t blocksize) {
172 size_t padded_buflen;
173
174 sodium_pad(&padded_buflen, buf.data(), unpadded_buflen, blocksize, buf.size_bytes());
175
176 return padded_buflen;
177}
178
179static inline uint32_t
180sn_sodium_unpad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t padded_buflen, uint32_t blocksize) {
181 size_t unpadded_buflen;
182
183 sodium_unpad(&unpadded_buflen, buf.data(), padded_buflen, blocksize);
184
185 return unpadded_buflen;
186}
187
188static inline int
189sn_crypto_sign_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
190 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
191 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
192
193 return crypto_sign_keypair(pk.data(), sk.data());
194}
195
196static inline int
197sn_crypto_sign_seed_keypair(
198 js_env_t *,
199 js_receiver_t,
200 js_typedarray_span_t<> pk,
201 js_typedarray_span_t<> sk,
202 js_typedarray_span_t<> seed
203) {
204 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
205 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
206 assert(seed.size_bytes() == crypto_sign_SEEDBYTES);
207
208 return crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data());
209}
210
211static inline int
212sn_crypto_sign(
213 js_env_t *,
214 js_receiver_t,
215 js_typedarray_span_t<> sm,
216 js_typedarray_span_t<> m,
217 js_typedarray_span_t<> sk
218) {
219 assert(sm.size_bytes() == crypto_sign_BYTES + m.size_bytes());
220 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
221
222 return crypto_sign(sm.data(), NULL, m.data(), m.size_bytes(), sk.data());
223}
224
225static inline bool
226sn_crypto_sign_open(
227 js_env_t *,
228 js_receiver_t,
229 js_typedarray_span_t<> m,
230 js_typedarray_span_t<> sm,
231 js_typedarray_span_t<> pk
232) {
233 assert(m.size_bytes() == sm.size_bytes() - crypto_sign_BYTES);
234 assert(sm.size_bytes() >= crypto_sign_BYTES);
235 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
236
237 return crypto_sign_open(m.data(), NULL, sm.data(), sm.size_bytes(), pk.data()) == 0;
238}
239
240static inline int
241sn_crypto_sign_detached(
242 js_env_t *env,
243 js_receiver_t,
244 js_typedarray_span_t<> sig,
245 js_typedarray_span_t<> m,
246 js_typedarray_span_t<> sk
247) {
248 assert(sig.size_bytes() == crypto_sign_BYTES);
249 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
250
251 return crypto_sign_detached(sig.data(), NULL, m.data(), m.size_bytes(), sk.data());
252}
253
254static inline bool
255sn_crypto_sign_verify_detached(
256 js_env_t *env,
257 js_receiver_t,
258
259 js_arraybuffer_span_t sig,
260 uint32_t sig_offset,
261 uint32_t sig_len,
262
263 js_arraybuffer_span_t m,
264 uint32_t m_offset,
265 uint32_t m_len,
266
267 js_arraybuffer_span_t pk,
268 uint32_t pk_offset,
269 uint32_t pk_len
270) {
271 assert_bounds(sig);
272 assert_bounds(m);
273 assert_bounds(pk);
274
275 assert(sig_len >= crypto_sign_BYTES);
276 assert(pk_len == crypto_sign_PUBLICKEYBYTES);
277
278 return crypto_sign_verify_detached(&sig[sig_offset], &m[m_offset], m_len, &pk[pk_offset]) == 0;
279}
280
281static inline int
282sn_crypto_sign_ed25519_sk_to_pk(
283 js_env_t *,
284 js_receiver_t,
285 js_typedarray_span_t<> pk,
286 js_typedarray_span_t<> sk
287) {
288 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
289 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
290
291 return crypto_sign_ed25519_sk_to_pk(pk.data(), sk.data());
292}
293
294static inline int
295sn_crypto_sign_ed25519_pk_to_curve25519(
296 js_env_t *,
297 js_receiver_t,
298 js_typedarray_span_t<> x25519_pk,
299 js_typedarray_span_t<> ed25519_pk
300) {
301 assert(x25519_pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
302 assert(ed25519_pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
303
304 return crypto_sign_ed25519_pk_to_curve25519(x25519_pk.data(), ed25519_pk.data());
305}
306
307static inline int
308sn_crypto_sign_ed25519_sk_to_curve25519(
309 js_env_t *,
310 js_receiver_t,
311 js_typedarray_span_t<> x25519_sk,
312 js_typedarray_span_t<> ed25519_sk
313) {
314 assert(x25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES);
315 assert(
316 ed25519_sk.size_bytes() == crypto_sign_SECRETKEYBYTES ||
317 ed25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES
318 );
319
320 return crypto_sign_ed25519_sk_to_curve25519(x25519_sk.data(), ed25519_sk.data());
321}
322
323static inline int
324sn_crypto_generichash(
325 js_env_t *env,
326 js_receiver_t,
327
328 js_arraybuffer_span_t out,
329 uint32_t out_offset,
330 uint32_t out_len,
331
332 js_arraybuffer_span_t in,
333 uint32_t in_offset,
334 uint32_t in_len,
335
336 js_arraybuffer_span_t key,
337 uint32_t key_offset,
338 uint32_t key_len
339) {
340 assert_bounds(out);
341 assert(
342 out_len >= crypto_generichash_BYTES_MIN &&
343 out_len <= crypto_generichash_BYTES_MAX
344 );
345
346 assert_bounds(in);
347
348 uint8_t *key_data = NULL;
349 if (key_len) {
350 assert_bounds(key);
351 assert(
352 key_len >= crypto_generichash_KEYBYTES_MIN &&
353 key_len <= crypto_generichash_KEYBYTES_MAX
354 );
355 key_data = &key[key_offset];
356 }
357
358 return crypto_generichash(&out[out_offset], out_len, &in[in_offset], in_len, key_data, key_len);
359}
360
361static inline int
362sn_crypto_generichash_batch(
363 js_env_t *env,
364 js_receiver_t,
365 js_typedarray_t<uint8_t> out,
366 std::vector<js_typedarray_span_t<>> batch,
367 bool use_key,
368 js_typedarray_t<uint8_t> key
369) {
370 int err;
371
372 uint8_t *out_data;
373 size_t out_len;
374 err = js_get_typedarray_info(env, out, out_data, out_len);
375 assert(err == 0);
376 assert(
377 out_len >= crypto_generichash_BYTES_MIN &&
378 out_len <= crypto_generichash_BYTES_MAX
379 );
380
381 uint8_t *key_data = NULL;
382 size_t key_len = 0;
383 if (use_key) {
384 err = js_get_typedarray_info(env, key, key_data, key_len);
385 assert(err == 0);
386 assert(
387 key_len >= crypto_generichash_KEYBYTES_MIN &&
388 key_len <= crypto_generichash_KEYBYTES_MAX
389 );
390 }
391
392 crypto_generichash_state state;
393 err = crypto_generichash_init(&state, key_data, key_len, out_len);
394 if (err != 0) return err;
395
396 for (auto &buf : batch) {
397 err = crypto_generichash_update(&state, buf.data(), buf.size());
398 if (err != 0) return err;
399 }
400
401 return crypto_generichash_final(&state, out_data, out_len);
402}
403
404static inline void
405sn_crypto_generichash_keygen(
406 js_env_t *env,
407 js_receiver_t,
408
409 js_arraybuffer_span_t key,
410 uint32_t key_offset,
411 uint32_t key_len
412) {
413 assert_bounds(key);
414 assert(key_len == crypto_generichash_KEYBYTES);
415
416 crypto_generichash_keygen(&key[key_offset]);
417}
418
419static inline int
420sn_crypto_generichash_init(
421 js_env_t *env,
422 js_receiver_t,
423
424 js_arraybuffer_span_t state,
425 uint32_t state_offset,
426 uint32_t state_len,
427
428 js_arraybuffer_span_t key,
429 uint32_t key_offset,
430 uint32_t key_len,
431
432 uint32_t out_len
433) {
434 assert_bounds(state);
435
436 assert(state_len == sizeof(crypto_generichash_state));
437
438 uint8_t *key_data = NULL;
439 if (key_len) {
440 assert_bounds(key);
441 assert(
442 key_len >= crypto_generichash_KEYBYTES_MIN &&
443 key_len <= crypto_generichash_KEYBYTES_MAX
444 );
445 key_data = &key[key_offset];
446 }
447
448 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
449
450 return crypto_generichash_init(state_data, key_data, key_len, out_len);
451}
452
453static inline int
454sn_crypto_generichash_update(
455 js_env_t *env,
456 js_receiver_t,
457
458 js_arraybuffer_span_t state,
459 uint32_t state_offset,
460 uint32_t state_len,
461
462 js_arraybuffer_span_t in,
463 uint32_t in_offset,
464 uint32_t in_len
465) {
466 assert_bounds(state);
467 assert_bounds(in);
468
469 assert(state_len == sizeof(crypto_generichash_state));
470
471 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
472
473 return crypto_generichash_update(state_data, &in[in_offset], in_len);
474}
475
476static inline int
477sn_crypto_generichash_final(
478 js_env_t *env,
479 js_receiver_t,
480
481 js_arraybuffer_span_t state,
482 uint32_t state_offset,
483 uint32_t state_len,
484
485 js_arraybuffer_span_t out,
486 uint32_t out_offset,
487 uint32_t out_len
488) {
489 assert_bounds(state);
490 assert_bounds(out);
491
492 assert(state_len == sizeof(crypto_generichash_state));
493
494 auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
495
496 return crypto_generichash_final(state_data, &out[out_offset], out_len);
497}
498
499static inline int
500sn_crypto_box_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
501 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
502 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
503
504 return crypto_box_keypair(pk.data(), sk.data());
505}
506
507static inline int
508sn_crypto_box_seed_keypair(
509 js_env_t *,
510 js_receiver_t,
511 js_typedarray_span_t<> pk,
512 js_typedarray_span_t<> sk,
513 js_typedarray_span_t<> seed
514) {
515 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
516 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
517 assert(seed.size_bytes() == crypto_box_SEEDBYTES);
518
519 return crypto_box_seed_keypair(pk.data(), sk.data(), seed.data());
520}
521
522static inline int
523sn_crypto_box_easy(
524 js_env_t *,
525 js_receiver_t,
526 js_typedarray_span_t<> c,
527 js_typedarray_span_t<> m,
528 js_typedarray_span_t<> n,
529 js_typedarray_span_t<> pk,
530 js_typedarray_span_t<> sk
531) {
532 assert(c.size_bytes() == m.size_bytes() + crypto_box_MACBYTES);
533 assert(n.size_bytes() == crypto_box_NONCEBYTES);
534 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
535 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
536
537 return crypto_box_easy(c.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
538}
539
540static inline bool
541sn_crypto_box_open_easy(
542 js_env_t *,
543 js_receiver_t,
544 js_typedarray_span_t<> m,
545 js_typedarray_span_t<> c,
546 js_typedarray_span_t<> n,
547 js_typedarray_span_t<> pk,
548 js_typedarray_span_t<> sk
549) {
550 assert(c.size_bytes() >= crypto_box_MACBYTES);
551 assert(m.size_bytes() == c.size_bytes() - crypto_box_MACBYTES);
552 assert(n.size_bytes() == crypto_box_NONCEBYTES);
553 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
554 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
555
556 return crypto_box_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
557}
558
559static inline int
560sn_crypto_box_detached(
561 js_env_t *,
562 js_receiver_t,
563 js_typedarray_span_t<> c,
564 js_typedarray_span_t<> mac,
565 js_typedarray_span_t<> m,
566 js_typedarray_span_t<> n,
567 js_typedarray_span_t<> pk,
568 js_typedarray_span_t<> sk
569) {
570 assert(c.size_bytes() == m.size_bytes());
571 assert(mac.size_bytes() == crypto_box_MACBYTES);
572 assert(n.size_bytes() == crypto_box_NONCEBYTES);
573 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
574 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
575
576 return crypto_box_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
577}
578
579static inline bool
580sn_crypto_box_open_detached(
581 js_env_t *,
582 js_receiver_t,
583 js_typedarray_span_t<> m,
584 js_typedarray_span_t<> c,
585 js_typedarray_span_t<> mac,
586 js_typedarray_span_t<> n,
587 js_typedarray_span_t<> pk,
588 js_typedarray_span_t<> sk
589) {
590 assert(m.size_bytes() == c.size_bytes());
591 assert(mac.size_bytes() == crypto_box_MACBYTES);
592 assert(n.size_bytes() == crypto_box_NONCEBYTES);
593 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
594 assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
595
596 return crypto_box_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
597}
598
599static inline int
600sn_crypto_box_seal(
601 js_env_t *,
602 js_receiver_t,
603 js_typedarray_span_t<> c,
604 js_typedarray_span_t<> m,
605 js_typedarray_span_t<> pk
606) {
607 assert(c.size_bytes() == m.size_bytes() + crypto_box_SEALBYTES);
608 assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
609
610 return crypto_box_seal(c.data(), m.data(), m.size_bytes(), pk.data());
611}
612
613static inline bool
614sn_crypto_box_seal_open(
615 js_env_t *env,
616 js_receiver_t,
617
618 js_arraybuffer_span_t m,
619 uint32_t m_offset,
620 uint32_t m_len,
621
622 js_arraybuffer_span_t c,
623 uint32_t c_offset,
624 uint32_t c_len,
625
626 js_arraybuffer_span_t pk,
627 uint32_t pk_offset,
628 uint32_t pk_len,
629
630 js_arraybuffer_span_t sk,
631 uint32_t sk_offset,
632 uint32_t sk_len
633) {
634 assert_bounds(m);
635 assert_bounds(c);
636 assert_bounds(pk);
637 assert_bounds(sk);
638
639 assert(m_len == c_len - crypto_box_SEALBYTES);
640 assert(c_len >= crypto_box_SEALBYTES);
641 assert(sk_len == crypto_box_SECRETKEYBYTES);
642 assert(pk_len == crypto_box_PUBLICKEYBYTES);
643
644 return crypto_box_seal_open(&m[m_offset], &c[c_offset], c_len, &pk[pk_offset], &sk[sk_offset]) == 0;
645}
646
647static inline int
648sn_crypto_secretbox_easy(
649 js_env_t *,
650 js_receiver_t,
651 js_typedarray_span_t<> c,
652 js_typedarray_span_t<> m,
653 js_typedarray_span_t<> n,
654 js_typedarray_span_t<> k
655) {
656 assert(c.size_bytes() == m.size_bytes() + crypto_secretbox_MACBYTES);
657 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
658 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
659
660 return crypto_secretbox_easy(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
661}
662
663static inline bool
664sn_crypto_secretbox_open_easy(
665 js_env_t *,
666 js_receiver_t,
667 js_typedarray_span_t<> m,
668 js_typedarray_span_t<> c,
669 js_typedarray_span_t<> n,
670 js_typedarray_span_t<> k
671) {
672 assert(m.size_bytes() == c.size_bytes() - crypto_secretbox_MACBYTES);
673 assert(c.size_bytes() >= crypto_secretbox_MACBYTES);
674 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
675 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
676
677 return crypto_secretbox_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), k.data()) == 0;
678}
679
680static inline int
681sn_crypto_secretbox_detached(
682 js_env_t *,
683 js_receiver_t,
684 js_typedarray_span_t<> c,
685 js_typedarray_span_t<> mac,
686 js_typedarray_span_t<> m,
687 js_typedarray_span_t<> n,
688 js_typedarray_span_t<> k
689) {
690 assert(c.size_bytes() == m.size_bytes());
691 assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
692 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
693 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
694
695 return crypto_secretbox_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), k.data());
696}
697
698static inline bool
699sn_crypto_secretbox_open_detached(
700 js_env_t *,
701 js_receiver_t,
702 js_typedarray_span_t<> m,
703 js_typedarray_span_t<> c,
704 js_typedarray_span_t<> mac,
705 js_typedarray_span_t<> n,
706 js_typedarray_span_t<> k
707) {
708 assert(m.size_bytes() == c.size_bytes());
709 assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
710 assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
711 assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
712
713 return crypto_secretbox_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), k.data()) == 0;
714}
715
716static inline int
717sn_crypto_stream(
718 js_env_t *,
719 js_receiver_t,
720 js_typedarray_span_t<> c,
721 js_typedarray_span_t<> n,
722 js_typedarray_span_t<> k
723) {
724 assert(n.size_bytes() == crypto_stream_NONCEBYTES);
725 assert(k.size_bytes() == crypto_stream_KEYBYTES);
726
727 return crypto_stream(c.data(), c.size_bytes(), n.data(), k.data());
728}
729
730static inline int
731sn_crypto_stream_xor(
732 js_env_t *env,
733 js_receiver_t,
734
735 js_arraybuffer_span_t c,
736 uint32_t c_offset,
737 uint32_t c_len,
738
739 js_arraybuffer_span_t m,
740 uint32_t m_offset,
741 uint32_t m_len,
742
743 js_arraybuffer_span_t n,
744 uint32_t n_offset,
745 uint32_t n_len,
746
747 js_arraybuffer_span_t k,
748 uint32_t k_offset,
749 uint32_t k_len
750) {
751 assert_bounds(c);
752 assert_bounds(m);
753 assert_bounds(n);
754 assert_bounds(k);
755
756 assert(c_len == m_len);
757 assert(n_len == crypto_stream_NONCEBYTES);
758 assert(k_len == crypto_stream_KEYBYTES);
759
760 return crypto_stream_xor(&c[c_offset], &m[m_offset], m_len, &n[n_offset], &k[k_offset]);
761}
762
763static inline int
764sn_crypto_stream_chacha20(
765 js_env_t *,
766 js_receiver_t,
767 js_typedarray_span_t<> c,
768 js_typedarray_span_t<> n,
769 js_typedarray_span_t<> k
770) {
771 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
772 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
773
774 return crypto_stream_chacha20(c.data(), c.size_bytes(), n.data(), k.data());
775}
776
777static inline int
778sn_crypto_stream_chacha20_xor(
779 js_env_t *,
780 js_receiver_t,
781 js_typedarray_span_t<> c,
782 js_typedarray_span_t<> m,
783 js_typedarray_span_t<> n,
784 js_typedarray_span_t<> k
785) {
786 assert(c.size_bytes() == m.size_bytes());
787 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
788 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
789
790 return crypto_stream_chacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
791}
792
793static inline int
794sn_crypto_stream_chacha20_xor_ic(
795 js_env_t *,
796 js_receiver_t,
797 js_typedarray_span_t<> c,
798 js_typedarray_span_t<> m,
799 js_typedarray_span_t<> n,
800 uint32_t ic,
801 js_typedarray_span_t<> k
802) {
803 assert(c.size_bytes() == m.size_bytes());
804 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
805 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
806
807 return crypto_stream_chacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
808}
809
810static inline int
811sn_crypto_stream_chacha20_ietf(
812 js_env_t *,
813 js_receiver_t,
814 js_typedarray_span_t<> c,
815 js_typedarray_span_t<> n,
816 js_typedarray_span_t<> k
817) {
818 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
819 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
820
821 return crypto_stream_chacha20_ietf(c.data(), c.size_bytes(), n.data(), k.data());
822}
823
824static inline int
825sn_crypto_stream_chacha20_ietf_xor(
826 js_env_t *,
827 js_receiver_t,
828 js_typedarray_span_t<> c,
829 js_typedarray_span_t<> m,
830 js_typedarray_span_t<> n,
831 js_typedarray_span_t<> k
832) {
833 assert(c.size_bytes() == m.size_bytes());
834 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
835 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
836
837 return crypto_stream_chacha20_ietf_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
838}
839
840static inline int
841sn_crypto_stream_chacha20_ietf_xor_ic(
842 js_env_t *,
843 js_receiver_t,
844 js_typedarray_span_t<> c,
845 js_typedarray_span_t<> m,
846 js_typedarray_span_t<> n,
847 uint32_t ic,
848 js_typedarray_span_t<> k
849) {
850 assert(c.size_bytes() == m.size_bytes());
851 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
852 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
853
854 return crypto_stream_chacha20_ietf_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
855}
856
857static inline int
858sn_crypto_stream_xchacha20(
859 js_env_t *,
860 js_receiver_t,
861 js_typedarray_span_t<> c,
862 js_typedarray_span_t<> n,
863 js_typedarray_span_t<> k
864) {
865 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
866 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
867
868 return crypto_stream_xchacha20(c.data(), c.size_bytes(), n.data(), k.data());
869}
870
871static inline int
872sn_crypto_stream_xchacha20_xor(
873 js_env_t *,
874 js_receiver_t,
875 js_typedarray_span_t<> c,
876 js_typedarray_span_t<> m,
877 js_typedarray_span_t<> n,
878 js_typedarray_span_t<> k
879) {
880 assert(c.size_bytes() == m.size_bytes());
881 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
882 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
883
884 return crypto_stream_xchacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
885}
886
887static inline int
888sn_crypto_stream_xchacha20_xor_ic(
889 js_env_t *,
890 js_receiver_t,
891 js_typedarray_span_t<> c,
892 js_typedarray_span_t<> m,
893 js_typedarray_span_t<> n,
894 uint32_t ic,
895 js_typedarray_span_t<> k
896) {
897 assert(c.size_bytes() == m.size_bytes());
898 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
899 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
900
901 return crypto_stream_xchacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
902}
903
904static inline int
905sn_crypto_stream_salsa20(
906 js_env_t *,
907 js_receiver_t,
908 js_typedarray_span_t<> c,
909 js_typedarray_span_t<> n,
910 js_typedarray_span_t<> k
911) {
912 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
913 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
914
915 return crypto_stream_salsa20(c.data(), c.size_bytes(), n.data(), k.data());
916}
917
918static inline int
919sn_crypto_stream_salsa20_xor(
920 js_env_t *,
921 js_receiver_t,
922 js_typedarray_span_t<> c,
923 js_typedarray_span_t<> m,
924 js_typedarray_span_t<> n,
925 js_typedarray_span_t<> k
926) {
927 assert(c.size_bytes() == m.size_bytes());
928 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
929 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
930
931 return crypto_stream_salsa20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
932}
933
934static inline int
935sn_crypto_stream_salsa20_xor_ic(
936 js_env_t *,
937 js_receiver_t,
938 js_typedarray_span_t<> c,
939 js_typedarray_span_t<> m,
940 js_typedarray_span_t<> n,
941 uint32_t ic,
942 js_typedarray_span_t<> k
943) {
944 assert(c.size_bytes() == m.size_bytes());
945 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
946 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
947
948 return crypto_stream_salsa20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
949}
950
951static inline int
952sn_crypto_auth(
953 js_env_t *,
954 js_receiver_t,
955 js_typedarray_span_t<> out,
956 js_typedarray_span_t<> in,
957 js_typedarray_span_t<> k
958) {
959 assert(out.size_bytes() == crypto_auth_BYTES);
960 assert(k.size_bytes() == crypto_auth_KEYBYTES);
961
962 return crypto_auth(out.data(), in.data(), in.size_bytes(), k.data());
963}
964
965static inline bool
966sn_crypto_auth_verify(
967 js_env_t *,
968 js_receiver_t,
969 js_typedarray_span_t<> h,
970 js_typedarray_span_t<> in,
971 js_typedarray_span_t<> k
972) {
973 assert(h.size_bytes() == crypto_auth_BYTES);
974 assert(k.size_bytes() == crypto_auth_KEYBYTES);
975
976 return crypto_auth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
977}
978
979static inline int
980sn_crypto_onetimeauth(
981 js_env_t *,
982 js_receiver_t,
983 js_typedarray_span_t<> out,
984 js_typedarray_span_t<> in,
985 js_typedarray_span_t<> k
986) {
987 assert(out.size_bytes() == crypto_onetimeauth_BYTES);
988 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
989
990 return crypto_onetimeauth(out.data(), in.data(), in.size_bytes(), k.data());
991}
992
993static inline int
994sn_crypto_onetimeauth_init(
995 js_env_t *,
996 js_receiver_t,
997 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
998 js_typedarray_span_t<> k
999) {
1000 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
1001
1002 return crypto_onetimeauth_init(&*state, k.data());
1003}
1004
1005static inline int
1006sn_crypto_onetimeauth_update(
1007 js_env_t *,
1008 js_receiver_t,
1009 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
1010 js_typedarray_span_t<> in
1011) {
1012 return crypto_onetimeauth_update(&*state, in.data(), in.size_bytes());
1013}
1014
1015static inline int
1016sn_crypto_onetimeauth_final(
1017 js_env_t *,
1018 js_receiver_t,
1019 js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
1020 js_typedarray_span_t<> out
1021) {
1022 assert(out.size_bytes() == crypto_onetimeauth_BYTES);
1023
1024 return crypto_onetimeauth_final(&*state, out.data());
1025}
1026
1027static inline bool
1028sn_crypto_onetimeauth_verify(
1029 js_env_t *,
1030 js_receiver_t,
1031 js_typedarray_span_t<> h,
1032 js_typedarray_span_t<> in,
1033 js_typedarray_span_t<> k
1034) {
1035 assert(h.size_bytes() == crypto_onetimeauth_BYTES);
1036 assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
1037
1038 return crypto_onetimeauth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
1039}
1040
1041// CHECK: memlimit can be >32bit
1042static inline int
1043sn_crypto_pwhash(
1044 js_env_t *,
1045 js_receiver_t,
1046 js_typedarray_span_t<> out,
1047 js_typedarray_span_of_t<char> passwd,
1048 js_typedarray_span_t<> salt,
1049 uint64_t opslimit,
1050 uint64_t memlimit,
1051 int32_t alg
1052) {
1053 assert(out.size_bytes() >= crypto_pwhash_BYTES_MIN);
1054 assert(out.size_bytes() <= crypto_pwhash_BYTES_MAX);
1055 assert(salt.size_bytes() == crypto_pwhash_SALTBYTES);
1056 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1057 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1058 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1059 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1060 assert(alg == 1 || alg == 2); // Argon2i or Argon2id
1061
1062 return crypto_pwhash(
1063 out.data(),
1064 out.size_bytes(),
1065 passwd.data(),
1066 passwd.size_bytes(),
1067 salt.data(),
1068 opslimit,
1069 memlimit,
1070 alg
1071 );
1072}
1073
1074static inline int
1075sn_crypto_pwhash_str(
1076 js_env_t *,
1077 js_receiver_t,
1078 js_typedarray_span_of_t<char> out,
1079 js_typedarray_span_of_t<char> passwd,
1080 uint64_t opslimit,
1081 uint64_t memlimit
1082) {
1083 assert(out.size_bytes() == crypto_pwhash_STRBYTES);
1084 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1085 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1086 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1087 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1088
1089 return crypto_pwhash_str(
1090 out.data(),
1091 passwd.data(),
1092 passwd.size_bytes(),
1093 opslimit,
1094 memlimit
1095 );
1096}
1097
1098static inline bool
1099sn_crypto_pwhash_str_verify(
1100 js_env_t *,
1101 js_receiver_t,
1102 js_typedarray_span_of_t<char> str,
1103 js_typedarray_span_of_t<char> passwd
1104) {
1105 assert(str.size_bytes() == crypto_pwhash_STRBYTES);
1106
1107 return crypto_pwhash_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
1108}
1109
1110// CHECK: returns 1, 0, -1
1111static inline bool
1112sn_crypto_pwhash_str_needs_rehash(
1113 js_env_t *,
1114 js_receiver_t,
1115 js_typedarray_span_of_t<char> str,
1116 uint64_t opslimit,
1117 uint64_t memlimit
1118) {
1119 assert(str.size_bytes() == crypto_pwhash_STRBYTES);
1120 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1121 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1122 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1123 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1124
1125 return crypto_pwhash_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
1126}
1127
1128// CHECK: memlimit can be >32bit
1129static inline int
1130sn_crypto_pwhash_scryptsalsa208sha256(
1131 js_env_t *,
1132 js_receiver_t,
1133 js_typedarray_span_t<> out,
1134 js_typedarray_span_of_t<char> passwd,
1135 js_typedarray_span_t<> salt,
1136 uint64_t opslimit,
1137 uint64_t memlimit
1138) {
1139 assert(out.size_bytes() >= crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
1140 assert(out.size_bytes() <= crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
1141 assert(salt.size_bytes() == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
1142 assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
1143 assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
1144 assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
1145 assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
1146
1147 return crypto_pwhash_scryptsalsa208sha256(
1148 out.data(),
1149 out.size_bytes(),
1150 passwd.data(),
1151 passwd.size_bytes(),
1152 salt.data(),
1153 opslimit,
1154 memlimit
1155 );
1156}
1157
1158static inline int
1159sn_crypto_pwhash_scryptsalsa208sha256_str(
1160 js_env_t *,
1161 js_receiver_t,
1162 js_typedarray_span_of_t<char> out,
1163 js_typedarray_span_of_t<char> passwd,
1164 uint64_t opslimit,
1165 uint64_t memlimit
1166) {
1167 assert(out.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1168 assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
1169 assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
1170 assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
1171 assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
1172
1173 return crypto_pwhash_scryptsalsa208sha256_str(
1174 out.data(),
1175 passwd.data(),
1176 passwd.size_bytes(),
1177 opslimit,
1178 memlimit
1179 );
1180}
1181
1182static inline bool
1183sn_crypto_pwhash_scryptsalsa208sha256_str_verify(
1184 js_env_t *,
1185 js_receiver_t,
1186 js_typedarray_span_of_t<char> str,
1187 js_typedarray_span_of_t<char> passwd
1188) {
1189 assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1190
1191 return crypto_pwhash_scryptsalsa208sha256_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
1192}
1193
1194static inline bool
1195sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
1196 js_env_t *,
1197 js_receiver_t,
1198 js_typedarray_span_of_t<char> str,
1199 uint64_t opslimit,
1200 uint64_t memlimit
1201) {
1202 assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
1203 assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
1204 assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
1205 assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
1206 assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
1207
1208 return crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
1209}
1210
1211static inline int
1212sn_crypto_kx_keypair(
1213 js_env_t *,
1214 js_receiver_t,
1215 js_typedarray_span_t<> pk,
1216 js_typedarray_span_t<> sk
1217) {
1218 assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1219 assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1220
1221 return crypto_kx_keypair(pk.data(), sk.data());
1222}
1223
1224static inline int
1225sn_crypto_kx_seed_keypair(
1226 js_env_t *,
1227 js_receiver_t,
1228 js_typedarray_span_t<> pk,
1229 js_typedarray_span_t<> sk,
1230 js_typedarray_span_t<> seed
1231) {
1232 assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1233 assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1234 assert(seed.size_bytes() == crypto_kx_SEEDBYTES);
1235
1236 return crypto_kx_seed_keypair(pk.data(), sk.data(), seed.data());
1237}
1238
1239static inline int
1240sn_crypto_kx_client_session_keys(
1241 js_env_t *,
1242 js_receiver_t,
1243 std::optional<js_typedarray_span_t<>> rx,
1244 std::optional<js_typedarray_span_t<>> tx,
1245 js_typedarray_span_t<> client_pk,
1246 js_typedarray_span_t<> client_sk,
1247 js_typedarray_span_t<> server_pk
1248) {
1249 assert(rx.has_value() || tx.has_value());
1250
1251 if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1252 if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1253
1254 assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1255 assert(client_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1256 assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1257
1258 return crypto_kx_client_session_keys(
1259 rx ? rx->data() : nullptr,
1260 tx ? tx->data() : nullptr,
1261 client_pk.data(),
1262 client_sk.data(),
1263 server_pk.data()
1264 );
1265}
1266
1267static inline int
1268sn_crypto_kx_server_session_keys(
1269 js_env_t *,
1270 js_receiver_t,
1271 std::optional<js_typedarray_span_t<>> rx,
1272 std::optional<js_typedarray_span_t<>> tx,
1273 js_typedarray_span_t<> server_pk,
1274 js_typedarray_span_t<> server_sk,
1275 js_typedarray_span_t<> client_pk
1276) {
1277 assert(rx.has_value() || tx.has_value());
1278
1279 if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1280 if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
1281
1282 assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1283 assert(server_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
1284 assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
1285
1286 return crypto_kx_server_session_keys(
1287 rx ? rx->data() : nullptr,
1288 tx ? tx->data() : nullptr,
1289 server_pk.data(),
1290 server_sk.data(),
1291 client_pk.data()
1292 );
1293}
1294
1295static inline int
1296sn_crypto_scalarmult_base(
1297 js_env_t *,
1298 js_receiver_t,
1299 js_typedarray_span_t<> q,
1300 js_typedarray_span_t<> n
1301) {
1302 assert(q.size_bytes() == crypto_scalarmult_BYTES);
1303 assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
1304
1305 return crypto_scalarmult_base(q.data(), n.data());
1306}
1307
1308static inline int
1309sn_crypto_scalarmult(
1310 js_env_t *,
1311 js_receiver_t,
1312 js_typedarray_span_t<> q,
1313 js_typedarray_span_t<> n,
1314 js_typedarray_span_t<> p
1315) {
1316 assert(q.size_bytes() == crypto_scalarmult_BYTES);
1317 assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
1318 assert(p.size_bytes() == crypto_scalarmult_BYTES);
1319
1320 return crypto_scalarmult(q.data(), n.data(), p.data());
1321}
1322
1323static inline int
1324sn_crypto_scalarmult_ed25519_base(
1325 js_env_t *,
1326 js_receiver_t,
1327 js_typedarray_span_t<> q,
1328 js_typedarray_span_t<> n
1329) {
1330 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1331 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1332
1333 return crypto_scalarmult_ed25519_base(q.data(), n.data());
1334}
1335
1336static inline int
1337sn_crypto_scalarmult_ed25519(
1338 js_env_t *,
1339 js_receiver_t,
1340 js_typedarray_span_t<> q,
1341 js_typedarray_span_t<> n,
1342 js_typedarray_span_t<> p
1343) {
1344 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1345 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1346 assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1347
1348 return crypto_scalarmult_ed25519(q.data(), n.data(), p.data());
1349}
1350
1351static inline bool
1352sn_crypto_core_ed25519_is_valid_point(
1353 js_env_t *,
1354 js_receiver_t,
1355 js_typedarray_span_t<> p
1356) {
1357 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1358
1359 return crypto_core_ed25519_is_valid_point(p.data()) != 0;
1360}
1361
1362static inline int
1363sn_crypto_core_ed25519_from_uniform(
1364 js_env_t *,
1365 js_receiver_t,
1366 js_typedarray_span_t<> p,
1367 js_typedarray_span_t<> r
1368) {
1369 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1370 assert(r.size_bytes() == crypto_core_ed25519_UNIFORMBYTES);
1371
1372 return crypto_core_ed25519_from_uniform(p.data(), r.data());
1373}
1374
1375static inline int
1376sn_crypto_scalarmult_ed25519_base_noclamp(
1377 js_env_t *,
1378 js_receiver_t,
1379 js_typedarray_span_t<> q,
1380 js_typedarray_span_t<> n
1381) {
1382 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1383 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1384
1385 return crypto_scalarmult_ed25519_base_noclamp(q.data(), n.data());
1386}
1387
1388static inline int
1389sn_crypto_scalarmult_ed25519_noclamp(
1390 js_env_t *,
1391 js_receiver_t,
1392 js_typedarray_span_t<> q,
1393 js_typedarray_span_t<> n,
1394 js_typedarray_span_t<> p
1395) {
1396 assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1397 assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
1398 assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
1399
1400 return crypto_scalarmult_ed25519_noclamp(q.data(), n.data(), p.data());
1401}
1402
1403static inline int
1404sn_crypto_core_ed25519_add(
1405 js_env_t *,
1406 js_receiver_t,
1407 js_typedarray_span_t<> r,
1408 js_typedarray_span_t<> p,
1409 js_typedarray_span_t<> q
1410) {
1411 assert(r.size_bytes() == crypto_core_ed25519_BYTES);
1412 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1413 assert(q.size_bytes() == crypto_core_ed25519_BYTES);
1414
1415 return crypto_core_ed25519_add(r.data(), p.data(), q.data());
1416}
1417
1418static inline int
1419sn_crypto_core_ed25519_sub(
1420 js_env_t *,
1421 js_receiver_t,
1422 js_typedarray_span_t<> r,
1423 js_typedarray_span_t<> p,
1424 js_typedarray_span_t<> q
1425) {
1426 assert(r.size_bytes() == crypto_core_ed25519_BYTES);
1427 assert(p.size_bytes() == crypto_core_ed25519_BYTES);
1428 assert(q.size_bytes() == crypto_core_ed25519_BYTES);
1429
1430 return crypto_core_ed25519_sub(r.data(), p.data(), q.data());
1431}
1432
1433static inline void
1434sn_crypto_core_ed25519_scalar_random(
1435 js_env_t *,
1436 js_receiver_t,
1437 js_typedarray_span_t<> r
1438) {
1439 assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1440
1441 crypto_core_ed25519_scalar_random(r.data());
1442}
1443
1444static inline void
1445sn_crypto_core_ed25519_scalar_reduce(
1446 js_env_t *,
1447 js_receiver_t,
1448 js_typedarray_span_t<> r,
1449 js_typedarray_span_t<> s
1450) {
1451 assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1452 assert(s.size_bytes() == crypto_core_ed25519_NONREDUCEDSCALARBYTES);
1453
1454 crypto_core_ed25519_scalar_reduce(r.data(), s.data());
1455}
1456
1457static inline void
1458sn_crypto_core_ed25519_scalar_invert(
1459 js_env_t *,
1460 js_receiver_t,
1461 js_typedarray_span_t<> recip,
1462 js_typedarray_span_t<> s
1463) {
1464 assert(recip.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1465 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1466
1467 crypto_core_ed25519_scalar_invert(recip.data(), s.data());
1468}
1469
1470static inline void
1471sn_crypto_core_ed25519_scalar_negate(
1472 js_env_t *,
1473 js_receiver_t,
1474 js_typedarray_span_t<> neg,
1475 js_typedarray_span_t<> s
1476) {
1477 assert(neg.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1478 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1479
1480 crypto_core_ed25519_scalar_negate(neg.data(), s.data());
1481}
1482
1483static inline void
1484sn_crypto_core_ed25519_scalar_complement(
1485 js_env_t *,
1486 js_receiver_t,
1487 js_typedarray_span_t<> comp,
1488 js_typedarray_span_t<> s
1489) {
1490 assert(comp.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1491 assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1492
1493 crypto_core_ed25519_scalar_complement(comp.data(), s.data());
1494}
1495
1496static inline void
1497sn_crypto_core_ed25519_scalar_add(
1498 js_env_t *,
1499 js_receiver_t,
1500 js_typedarray_span_t<> z,
1501 js_typedarray_span_t<> x,
1502 js_typedarray_span_t<> y
1503) {
1504 assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1505 assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1506 assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1507
1508 crypto_core_ed25519_scalar_add(z.data(), x.data(), y.data());
1509}
1510
1511static inline void
1512sn_crypto_core_ed25519_scalar_sub(
1513 js_env_t *,
1514 js_receiver_t,
1515 js_typedarray_span_t<> z,
1516 js_typedarray_span_t<> x,
1517 js_typedarray_span_t<> y
1518) {
1519 assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1520 assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1521 assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
1522
1523 crypto_core_ed25519_scalar_sub(z.data(), x.data(), y.data());
1524}
1525
1526static inline int
1527sn_crypto_shorthash(
1528 js_env_t *,
1529 js_receiver_t,
1530 js_typedarray_span_t<> out,
1531 js_typedarray_span_t<> in,
1532 js_typedarray_span_t<> k
1533) {
1534 assert(out.size_bytes() == crypto_shorthash_BYTES);
1535 assert(k.size_bytes() == crypto_shorthash_KEYBYTES);
1536
1537 return crypto_shorthash(out.data(), in.data(), in.size_bytes(), k.data());
1538}
1539
1540static inline void
1541sn_crypto_kdf_keygen(
1542 js_env_t *,
1543 js_receiver_t,
1544 js_typedarray_span_t<> key
1545) {
1546 assert(key.size_bytes() == crypto_kdf_KEYBYTES);
1547
1548 crypto_kdf_keygen(key.data());
1549}
1550
1551static inline int
1552sn_crypto_kdf_derive_from_key(
1553 js_env_t *,
1554 js_receiver_t,
1555 js_typedarray_span_t<> subkey,
1556 uint64_t subkey_id,
1557 js_typedarray_span_of_t<char> ctx,
1558 js_typedarray_span_t<> key
1559) {
1560 assert(subkey.size_bytes() >= crypto_kdf_BYTES_MIN);
1561 assert(subkey.size_bytes() <= crypto_kdf_BYTES_MAX);
1562 assert(ctx.size_bytes() == crypto_kdf_CONTEXTBYTES);
1563 assert(key.size_bytes() == crypto_kdf_KEYBYTES);
1564
1565 return crypto_kdf_derive_from_key(
1566 subkey.data(),
1567 subkey.size_bytes(),
1568 subkey_id,
1569 ctx.data(),
1570 key.data()
1571 );
1572}
1573
1574static inline int
1575sn_crypto_hash(
1576 js_env_t *,
1577 js_receiver_t,
1578 js_typedarray_span_t<> out,
1579 js_typedarray_span_t<> in
1580) {
1581 assert(out.size_bytes() == crypto_hash_BYTES);
1582
1583 return crypto_hash(out.data(), in.data(), in.size_bytes());
1584}
1585
1586static inline int
1587sn_crypto_hash_sha256(
1588 js_env_t *,
1589 js_receiver_t,
1590 js_typedarray_span_t<> out,
1591 js_typedarray_span_t<> in
1592) {
1593 assert(out.size_bytes() == crypto_hash_sha256_BYTES);
1594
1595 return crypto_hash_sha256(out.data(), in.data(), in.size_bytes());
1596}
1597
1598static inline int
1599sn_crypto_hash_sha256_init(
1600 js_env_t *,
1601 js_receiver_t,
1602 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state
1603) {
1604 return crypto_hash_sha256_init(&*state);
1605}
1606
1607static inline int
1608sn_crypto_hash_sha256_update(
1609 js_env_t *,
1610 js_receiver_t,
1611 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
1612 js_typedarray_span_t<> in
1613) {
1614 return crypto_hash_sha256_update(&*state, in.data(), in.size_bytes());
1615}
1616
1617static inline int
1618sn_crypto_hash_sha256_final(
1619 js_env_t *,
1620 js_receiver_t,
1621 js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
1622 js_typedarray_span_t<> out
1623) {
1624 assert(out.size_bytes() == crypto_hash_sha256_BYTES);
1625
1626 return crypto_hash_sha256_final(&*state, out.data());
1627}
1628
1629static inline int
1630sn_crypto_hash_sha512(
1631 js_env_t *,
1632 js_receiver_t,
1633 js_typedarray_span_t<> out,
1634 js_typedarray_span_t<> in
1635) {
1636 assert(out.size_bytes() == crypto_hash_sha512_BYTES);
1637
1638 return crypto_hash_sha512(out.data(), in.data(), in.size_bytes());
1639}
1640
1641static inline int
1642sn_crypto_hash_sha512_init(
1643 js_env_t *,
1644 js_receiver_t,
1645 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state
1646) {
1647 return crypto_hash_sha512_init(&*state);
1648}
1649
1650static inline int
1651sn_crypto_hash_sha512_update(
1652 js_env_t *,
1653 js_receiver_t,
1654 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
1655 js_typedarray_span_t<> in
1656) {
1657 return crypto_hash_sha512_update(&*state, in.data(), in.size_bytes());
1658}
1659
1660static inline int
1661sn_crypto_hash_sha512_final(
1662 js_env_t *,
1663 js_receiver_t,
1664 js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
1665 js_typedarray_span_t<> out
1666) {
1667 assert(out.size_bytes() == crypto_hash_sha512_BYTES);
1668
1669 return crypto_hash_sha512_final(&*state, out.data());
1670}
1671
1672static inline void
1673sn_crypto_aead_xchacha20poly1305_ietf_keygen(
1674 js_env_t *,
1675 js_receiver_t,
1676 js_typedarray_span_t<> k
1677) {
1678 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1679
1680 crypto_aead_xchacha20poly1305_ietf_keygen(k.data());
1681}
1682
1683static inline uint64_t
1684sn_crypto_aead_xchacha20poly1305_ietf_encrypt(
1685 js_env_t *,
1686 js_receiver_t,
1687 js_typedarray_span_t<> c,
1688 js_typedarray_span_t<> m,
1689 std::optional<js_typedarray_span_t<>> ad,
1690 js_typedarray_span_t<> npub,
1691 js_typedarray_span_t<> k
1692) {
1693 assert(c.size_bytes() == m.size_bytes() + crypto_aead_xchacha20poly1305_ietf_ABYTES);
1694 assert(c.size_bytes() <= 0xffffffff);
1695 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1696 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1697
1698 uint8_t *ad_data = nullptr;
1699 size_t ad_size = 0;
1700 if (ad) {
1701 ad_data = ad->data();
1702 ad_size = ad->size_bytes();
1703 }
1704
1705 unsigned long long clen = 0;
1706 int status = crypto_aead_xchacha20poly1305_ietf_encrypt(
1707 c.data(),
1708 &clen,
1709 m.data(),
1710 m.size_bytes(),
1711 ad_data,
1712 ad_size,
1713 nullptr,
1714 npub.data(),
1715 k.data()
1716 );
1717
1718 if (status < 0) return status;
1719
1720 return clen;
1721}
1722
1723static inline uint64_t
1724sn_crypto_aead_xchacha20poly1305_ietf_decrypt(
1725 js_env_t *,
1726 js_receiver_t,
1727 js_typedarray_span_t<> m,
1728 js_typedarray_span_t<> c,
1729 std::optional<js_typedarray_span_t<>> ad,
1730 js_typedarray_span_t<> npub,
1731 js_typedarray_span_t<> k
1732) {
1733 assert(m.size_bytes() == c.size_bytes() - crypto_aead_xchacha20poly1305_ietf_ABYTES);
1734 assert(m.size_bytes() <= 0xffffffff);
1735 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1736 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1737
1738 uint8_t *ad_data = nullptr;
1739 size_t ad_size = 0;
1740 if (ad) {
1741 ad_data = ad->data();
1742 ad_size = ad->size_bytes();
1743 }
1744
1745 unsigned long long mlen = 0;
1746 int status = crypto_aead_xchacha20poly1305_ietf_decrypt(
1747 m.data(),
1748 &mlen,
1749 nullptr,
1750 c.data(),
1751 c.size_bytes(),
1752 ad_data,
1753 ad_size,
1754 npub.data(),
1755 k.data()
1756 );
1757
1758 if (status < 0) return status;
1759
1760 return mlen;
1761}
1762
1763static inline uint64_t
1764sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
1765 js_env_t *,
1766 js_receiver_t,
1767 js_typedarray_span_t<> c,
1768 js_typedarray_span_t<> mac,
1769 js_typedarray_span_t<> m,
1770 std::optional<js_typedarray_span_t<>> ad,
1771 js_typedarray_span_t<> npub,
1772 js_typedarray_span_t<> k
1773) {
1774 assert(c.size_bytes() == m.size_bytes());
1775 assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
1776 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1777 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1778
1779 uint8_t *ad_data = nullptr;
1780 size_t ad_size = 0;
1781 if (ad) {
1782 ad_data = ad->data();
1783 ad_size = ad->size_bytes();
1784 }
1785
1786 unsigned long long maclen = 0;
1787 int status = crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
1788 c.data(),
1789 mac.data(),
1790 &maclen,
1791 m.data(),
1792 m.size_bytes(),
1793 ad_data,
1794 ad_size,
1795 nullptr,
1796 npub.data(),
1797 k.data()
1798 );
1799
1800 if (status < 0) return status;
1801
1802 return maclen;
1803}
1804
1805static inline int
1806sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
1807 js_env_t *,
1808 js_receiver_t,
1809 js_typedarray_span_t<> m,
1810 js_typedarray_span_t<> c,
1811 js_typedarray_span_t<> mac,
1812 std::optional<js_typedarray_span_t<>> ad,
1813 js_typedarray_span_t<> npub,
1814 js_typedarray_span_t<> k
1815) {
1816 assert(m.size_bytes() == c.size_bytes());
1817 assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
1818 assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
1819 assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
1820
1821 uint8_t *ad_data = nullptr;
1822 size_t ad_size = 0;
1823 if (ad) {
1824 ad_data = ad->data();
1825 ad_size = ad->size_bytes();
1826 }
1827
1828 return crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
1829 m.data(),
1830 nullptr,
1831 c.data(),
1832 c.size_bytes(),
1833 mac.data(),
1834 ad_data,
1835 ad_size,
1836 npub.data(),
1837 k.data()
1838 );
1839}
1840
1841static inline void
1842sn_crypto_aead_chacha20poly1305_ietf_keygen(
1843 js_env_t *,
1844 js_receiver_t,
1845 js_typedarray_span_t<> k
1846) {
1847 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1848
1849 crypto_aead_chacha20poly1305_ietf_keygen(k.data());
1850}
1851
1852static inline uint64_t
1853sn_crypto_aead_chacha20poly1305_ietf_encrypt(
1854 js_env_t *,
1855 js_receiver_t,
1856 js_typedarray_span_t<> c,
1857 js_typedarray_span_t<> m,
1858 std::optional<js_typedarray_span_t<>> ad,
1859 js_typedarray_span_t<> npub,
1860 js_typedarray_span_t<> k
1861) {
1862 assert(c.size_bytes() == m.size_bytes() + crypto_aead_chacha20poly1305_ietf_ABYTES);
1863 assert(c.size_bytes() <= 0xffffffff);
1864 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1865 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1866
1867 uint8_t *ad_data = nullptr;
1868 size_t ad_size = 0;
1869 if (ad) {
1870 ad_data = ad->data();
1871 ad_size = ad->size_bytes();
1872 }
1873
1874 unsigned long long clen = 0;
1875 int status = crypto_aead_chacha20poly1305_ietf_encrypt(
1876 c.data(),
1877 &clen,
1878 m.data(),
1879 m.size_bytes(),
1880 ad_data,
1881 ad_size,
1882 nullptr,
1883 npub.data(),
1884 k.data()
1885 );
1886
1887 if (status < 0) return status;
1888
1889 return clen;
1890}
1891
1892static inline uint64_t
1893sn_crypto_aead_chacha20poly1305_ietf_decrypt(
1894 js_env_t *,
1895 js_receiver_t,
1896 js_typedarray_span_t<> m,
1897 js_typedarray_span_t<> c,
1898 std::optional<js_typedarray_span_t<>> ad,
1899 js_typedarray_span_t<> npub,
1900 js_typedarray_span_t<> k
1901) {
1902 assert(m.size_bytes() == c.size_bytes() - crypto_aead_chacha20poly1305_ietf_ABYTES);
1903 assert(m.size_bytes() <= 0xffffffff);
1904 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1905 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1906
1907 uint8_t *ad_data = nullptr;
1908 size_t ad_size = 0;
1909 if (ad) {
1910 ad_data = ad->data();
1911 ad_size = ad->size_bytes();
1912 }
1913
1914 unsigned long long mlen = 0;
1915 int status = crypto_aead_chacha20poly1305_ietf_decrypt(
1916 m.data(),
1917 &mlen,
1918 nullptr,
1919 c.data(),
1920 c.size_bytes(),
1921 ad_data,
1922 ad_size,
1923 npub.data(),
1924 k.data()
1925 );
1926
1927 if (status < 0) return status;
1928
1929 return mlen;
1930}
1931
1932static inline uint64_t
1933sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached(
1934 js_env_t *,
1935 js_receiver_t,
1936 js_typedarray_span_t<> c,
1937 js_typedarray_span_t<> mac,
1938 js_typedarray_span_t<> m,
1939 std::optional<js_typedarray_span_t<>> ad,
1940 js_typedarray_span_t<> npub,
1941 js_typedarray_span_t<> k
1942) {
1943 assert(c.size_bytes() == m.size_bytes());
1944 assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
1945 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1946 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1947
1948 uint8_t *ad_data = nullptr;
1949 size_t ad_size = 0;
1950 if (ad) {
1951 ad_data = ad->data();
1952 ad_size = ad->size_bytes();
1953 }
1954
1955 unsigned long long maclen = 0;
1956 int status = crypto_aead_chacha20poly1305_ietf_encrypt_detached(
1957 c.data(),
1958 mac.data(),
1959 &maclen,
1960 m.data(),
1961 m.size_bytes(),
1962 ad_data,
1963 ad_size,
1964 nullptr,
1965 npub.data(),
1966 k.data()
1967 );
1968
1969 if (status < 0) return status;
1970
1971 return maclen;
1972}
1973
1974static inline int
1975sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached(
1976 js_env_t *,
1977 js_receiver_t,
1978 js_typedarray_span_t<> m,
1979 js_typedarray_span_t<> c,
1980 js_typedarray_span_t<> mac,
1981 std::optional<js_typedarray_span_t<>> ad,
1982 js_typedarray_span_t<> npub,
1983 js_typedarray_span_t<> k
1984) {
1985 assert(m.size_bytes() == c.size_bytes());
1986 assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
1987 assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
1988 assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
1989
1990 uint8_t *ad_data = nullptr;
1991 size_t ad_size = 0;
1992 if (ad) {
1993 ad_data = ad->data();
1994 ad_size = ad->size_bytes();
1995 }
1996
1997 return crypto_aead_chacha20poly1305_ietf_decrypt_detached(
1998 m.data(),
1999 nullptr,
2000 c.data(),
2001 c.size_bytes(),
2002 mac.data(),
2003 ad_data,
2004 ad_size,
2005 npub.data(),
2006 k.data()
2007 );
2008}
2009
2010static inline void
2011sn_crypto_secretstream_xchacha20poly1305_keygen(
2012 js_env_t *env,
2013 js_receiver_t,
2014
2015 js_arraybuffer_span_t k,
2016 uint32_t k_offset,
2017 uint32_t k_len
2018) {
2019 assert_bounds(k);
2020 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2021
2022 crypto_secretstream_xchacha20poly1305_keygen(&k[k_offset]);
2023}
2024
2025static inline int
2026sn_crypto_secretstream_xchacha20poly1305_init_push(
2027 js_env_t *env,
2028 js_receiver_t,
2029
2030 js_arraybuffer_span_t state,
2031 uint32_t state_offset,
2032 uint32_t state_len,
2033
2034 js_arraybuffer_span_t header,
2035 uint32_t header_offset,
2036 uint32_t header_len,
2037
2038 js_arraybuffer_span_t k,
2039 uint32_t k_offset,
2040 uint32_t k_len
2041) {
2042 assert_bounds(state);
2043 assert_bounds(header);
2044 assert_bounds(k);
2045
2046 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2047 assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
2048 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2049
2050 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2051
2052 return crypto_secretstream_xchacha20poly1305_init_push(state_data, &header[header_offset], &k[k_offset]);
2053}
2054
2055static inline uint64_t
2056sn_crypto_secretstream_xchacha20poly1305_push(
2057 js_env_t *env,
2058 js_receiver_t,
2059
2060 js_arraybuffer_span_t state,
2061 uint32_t state_offset,
2062 uint32_t state_len,
2063
2064 js_arraybuffer_span_t c,
2065 uint32_t c_offset,
2066 uint32_t c_len,
2067
2068 js_arraybuffer_span_t m,
2069 uint32_t m_offset,
2070 uint32_t m_len,
2071
2072 js_arraybuffer_span_t ad,
2073 uint32_t ad_offset,
2074 uint32_t ad_len,
2075
2076 uint32_t tag
2077) {
2078 assert_bounds(state);
2079 assert_bounds(c);
2080 assert_bounds(m);
2081
2082 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2083 assert(c_len == m_len + crypto_secretstream_xchacha20poly1305_ABYTES);
2084 assert(c_len <= 0xffffffff && "32bit integer");
2085
2086 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2087
2088 uint8_t *ad_data = NULL;
2089 if (ad_len) {
2090 assert_bounds(ad);
2091 ad_data = &ad[ad_offset];
2092 }
2093
2094 unsigned long long clen = 0;
2095 int status = crypto_secretstream_xchacha20poly1305_push(
2096 state_data,
2097 &c[c_offset],
2098 &clen,
2099 &m[m_offset],
2100 m_len,
2101 ad_data,
2102 ad_len,
2103 tag
2104 );
2105
2106 if (status < 0) return status;
2107
2108 return clen;
2109}
2110
2111static inline int
2112sn_crypto_secretstream_xchacha20poly1305_init_pull(
2113 js_env_t *,
2114 js_receiver_t,
2115
2116 js_arraybuffer_span_t state,
2117 uint32_t state_offset,
2118 uint32_t state_len,
2119
2120 js_arraybuffer_span_t header,
2121 uint32_t header_offset,
2122 uint32_t header_len,
2123
2124 js_arraybuffer_span_t k,
2125 uint32_t k_offset,
2126 uint32_t k_len
2127) {
2128 assert_bounds(state);
2129 assert_bounds(header);
2130 assert_bounds(k);
2131
2132 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2133 assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
2134 assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
2135
2136 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2137
2138 return crypto_secretstream_xchacha20poly1305_init_pull(state_data, &header[header_offset], &k[k_offset]);
2139}
2140
2141static inline uint64_t
2142sn_crypto_secretstream_xchacha20poly1305_pull(
2143 js_env_t *env,
2144 js_receiver_t,
2145
2146 js_arraybuffer_span_t state,
2147 uint32_t state_offset,
2148 uint32_t state_len,
2149
2150 js_arraybuffer_span_t m,
2151 uint32_t m_offset,
2152 uint32_t m_len,
2153
2154 js_arraybuffer_span_t tag,
2155 uint32_t tag_offset,
2156 uint32_t tag_len,
2157
2158 js_arraybuffer_span_t c,
2159 uint32_t c_offset,
2160 uint32_t c_len,
2161
2162 js_arraybuffer_span_t ad,
2163 uint32_t ad_offset,
2164 uint32_t ad_len
2165) {
2166 assert_bounds(state);
2167 assert_bounds(m);
2168 assert_bounds(tag);
2169 assert_bounds(c);
2170
2171 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2172 assert(c_len >= crypto_secretstream_xchacha20poly1305_ABYTES);
2173 assert(tag_len == 1);
2174 assert(m_len == c_len - crypto_secretstream_xchacha20poly1305_ABYTES);
2175 assert(m_len <= 0xffffffff);
2176
2177 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2178
2179 uint8_t *ad_data = NULL;
2180 if (ad_len) {
2181 assert_bounds(ad);
2182 ad_data = &ad[ad_offset];
2183 }
2184
2185 unsigned long long mlen = 0;
2186 int status = crypto_secretstream_xchacha20poly1305_pull(
2187 state_data,
2188 &m[m_offset],
2189 &mlen,
2190 &tag[tag_offset],
2191 &c[c_offset],
2192 c_len,
2193 ad_data,
2194 ad_len
2195 );
2196
2197 if (status < 0) return status;
2198
2199 return mlen;
2200}
2201
2202static inline void
2203sn_crypto_secretstream_xchacha20poly1305_rekey(
2204 js_env_t *,
2205 js_receiver_t,
2206
2207 js_arraybuffer_span_t state,
2208 uint32_t state_offset,
2209 uint32_t state_len
2210) {
2211 assert_bounds(state);
2212
2213 assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
2214
2215 auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
2216
2217 crypto_secretstream_xchacha20poly1305_rekey(state_data);
2218}
2219
2220struct sn_async_task {
2221 uv_work_t task;
2222 js_env_t *env;
2223 js_persistent_t<js_function_t<void, int>> cb;
2224 js_deferred_teardown_t *teardown;
2225 int code = 0;
2226 bool exiting = false;
2227
2228 sn_async_task(js_env_t *env) : env(env) {
2229 int err;
2230 err = js_add_teardown_callback<on_teardown, sn_async_task>(env, this, teardown);
2231 assert(err == 0);
2232 }
2233
2234 ~sn_async_task() {
2235 int err;
2236 err = js_finish_teardown_callback(teardown);
2237 assert(err == 0);
2238 }
2239
2240private:
2241 static void
2242 on_teardown(js_deferred_teardown_t *teardown, sn_async_task *req) {
2243 req->exiting = true;
2244 }
2245};
2246
2247struct sn_async_pwhash_request : sn_async_task {
2248 js_persistent_t<js_arraybuffer_t> out_ref;
2249 std::span<uint8_t> out;
2250
2251 js_persistent_t<js_arraybuffer_t> pwd_ref;
2252 std::span<char> pwd;
2253
2254 js_persistent_t<js_arraybuffer_t> salt_ref;
2255 std::span<uint8_t> salt;
2256
2257 uint64_t opslimit;
2258 size_t memlimit;
2259 int alg;
2260
2261 sn_async_pwhash_request(js_env_t *env) : sn_async_task(env) {}
2262};
2263
2264static void
2265async_pwhash_execute(uv_work_t *uv_req) {
2266 auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
2267
2268 req->code = crypto_pwhash(
2269 req->out.data(),
2270 req->out.size(),
2271 req->pwd.data(),
2272 req->pwd.size(),
2273 req->salt.data(),
2274 req->opslimit,
2275 req->memlimit,
2276 req->alg
2277 );
2278}
2279
2280static void
2281async_pwhash_complete(uv_work_t *uv_req, int status) {
2282 int err;
2283
2284 auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
2285
2286 if (req->exiting) return delete req;
2287
2288 js_handle_scope_t *scope;
2289 err = js_open_handle_scope(req->env, &scope);
2290 assert(err == 0);
2291
2292 js_function_t<void, int> callback;
2293 err = js_get_reference_value(req->env, req->cb, callback);
2294 assert(err == 0);
2295
2296 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2297 assert(err != js_pending_exception);
2298
2299 err = js_close_handle_scope(req->env, scope);
2300 assert(err == 0);
2301
2302 delete req;
2303}
2304
2305static inline void
2306sn_crypto_pwhash_async(
2307 js_env_t *env,
2308 js_receiver_t,
2309
2310 js_arraybuffer_t out,
2311 uint32_t out_offset,
2312 uint32_t out_len,
2313
2314 js_arraybuffer_t pwd,
2315 uint32_t pwd_offset,
2316 uint32_t pwd_len,
2317
2318 js_arraybuffer_t salt,
2319 uint32_t salt_offset,
2320 uint32_t salt_len,
2321
2322 uint64_t opslimit,
2323 uint64_t memlimit,
2324 uint32_t alg,
2325
2326 js_function_t<void, int> callback
2327) {
2328 int err;
2329
2330 auto *req = new sn_async_pwhash_request(env);
2331
2332 std::span<uint8_t> out_view;
2333 err = js_get_arraybuffer_info(env, out, out_view);
2334 assert(err == 0);
2335 assert(out_offset + out_len <= out_view.size());
2336
2337 req->out = {&out_view[out_offset], out_len};
2338
2339 std::span<char> pwd_view;
2340 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2341 assert(err == 0);
2342 assert(pwd_offset + pwd_len <= pwd_view.size());
2343
2344 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2345
2346 std::span<uint8_t> salt_view;
2347 err = js_get_arraybuffer_info(env, salt, salt_view);
2348 assert(err == 0);
2349 assert(salt_offset + salt_len <= salt_view.size());
2350
2351 req->salt = {&salt_view[salt_offset], salt_len};
2352
2353 req->opslimit = opslimit;
2354 req->memlimit = memlimit;
2355 req->alg = alg;
2356
2357 err = js_create_reference(env, out, req->out_ref);
2358 assert(err == 0);
2359
2360 err = js_create_reference(env, pwd, req->pwd_ref);
2361 assert(err == 0);
2362
2363 err = js_create_reference(env, salt, req->salt_ref);
2364 assert(err == 0);
2365
2366 err = js_create_reference(env, callback, req->cb);
2367 assert(err == 0);
2368
2369 uv_loop_t *loop;
2370 err = js_get_env_loop(env, &loop);
2371 assert(err == 0);
2372
2373 err = uv_queue_work(loop, &req->task, async_pwhash_execute, async_pwhash_complete);
2374 assert(err == 0);
2375}
2376
2377struct sn_async_pwhash_str_request : sn_async_task {
2378 js_persistent_t<js_arraybuffer_t> out_ref;
2379 std::span<char> out;
2380
2381 js_persistent_t<js_arraybuffer_t> pwd_ref;
2382 std::span<char> pwd;
2383
2384 uint64_t opslimit;
2385 size_t memlimit;
2386
2387 sn_async_pwhash_str_request(js_env_t *env) : sn_async_task(env) {}
2388};
2389
2390static void
2391async_pwhash_str_execute(uv_work_t *uv_req) {
2392 auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
2393
2394 req->code = crypto_pwhash_str(
2395 req->out.data(),
2396 req->pwd.data(),
2397 req->pwd.size(),
2398 req->opslimit,
2399 req->memlimit
2400 );
2401}
2402
2403static void
2404async_pwhash_str_complete(uv_work_t *uv_req, int status) {
2405 int err;
2406
2407 auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
2408
2409 if (req->exiting) return delete req;
2410
2411 js_handle_scope_t *scope;
2412 err = js_open_handle_scope(req->env, &scope);
2413 assert(err == 0);
2414
2415 js_function_t<void, int> callback;
2416 err = js_get_reference_value(req->env, req->cb, callback);
2417 assert(err == 0);
2418
2419 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2420 assert(err != js_pending_exception);
2421
2422 err = js_close_handle_scope(req->env, scope);
2423 assert(err == 0);
2424
2425 delete req;
2426}
2427
2428static inline void
2429sn_crypto_pwhash_str_async(
2430 js_env_t *env,
2431 js_receiver_t,
2432
2433 js_arraybuffer_t out,
2434 uint32_t out_offset,
2435 uint32_t out_len,
2436
2437 js_arraybuffer_t pwd,
2438 uint32_t pwd_offset,
2439 uint32_t pwd_len,
2440
2441 uint64_t opslimit,
2442 uint64_t memlimit,
2443 js_function_t<void, int> callback
2444) {
2445 int err;
2446
2447 auto *req = new sn_async_pwhash_str_request(env);
2448
2449 std::span<char> out_view;
2450 err = js_get_arraybuffer_info(env, out, out_view);
2451 assert(err == 0);
2452 assert(out_offset + out_len <= out_view.size());
2453
2454 req->out = {&out_view[out_offset], out_len};
2455
2456 std::span<char> pwd_view;
2457 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2458 assert(err == 0);
2459 assert(pwd_offset + pwd_len <= pwd_view.size());
2460
2461 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2462
2463 req->opslimit = opslimit;
2464 req->memlimit = memlimit;
2465
2466 err = js_create_reference(env, out, req->out_ref);
2467 assert(err == 0);
2468
2469 err = js_create_reference(env, pwd, req->pwd_ref);
2470 assert(err == 0);
2471
2472 err = js_create_reference(env, callback, req->cb);
2473 assert(err == 0);
2474
2475 uv_loop_t *loop;
2476 err = js_get_env_loop(env, &loop);
2477 assert(err == 0);
2478
2479 err = uv_queue_work(loop, &req->task, async_pwhash_str_execute, async_pwhash_str_complete);
2480 assert(err == 0);
2481}
2482
2483struct sn_async_pwhash_str_verify_request : sn_async_task {
2484 js_persistent_t<js_arraybuffer_t> str_ref;
2485 std::span<char> str;
2486
2487 js_persistent_t<js_arraybuffer_t> pwd_ref;
2488 std::span<char> pwd;
2489
2490 sn_async_pwhash_str_verify_request(js_env_t *env) : sn_async_task(env) {}
2491};
2492
2493static void
2494async_pwhash_str_verify_execute(uv_work_t *uv_req) {
2495 auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
2496
2497 req->code = crypto_pwhash_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
2498}
2499
2500static void
2501async_pwhash_str_verify_complete(uv_work_t *uv_req, int status) {
2502 int err;
2503
2504 auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
2505
2506 if (req->exiting) return delete req;
2507
2508 js_handle_scope_t *scope;
2509 err = js_open_handle_scope(req->env, &scope);
2510 assert(err == 0);
2511
2512 js_function_t<void, int> callback;
2513 err = js_get_reference_value(req->env, req->cb, callback);
2514 assert(err == 0);
2515
2516 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2517 assert(err != js_pending_exception);
2518
2519 err = js_close_handle_scope(req->env, scope);
2520 assert(err == 0);
2521
2522 delete req;
2523}
2524
2525static inline void
2526sn_crypto_pwhash_str_verify_async(
2527 js_env_t *env,
2528 js_receiver_t,
2529
2530 js_arraybuffer_t str,
2531 uint32_t str_offset,
2532 uint32_t str_len,
2533
2534 js_arraybuffer_t pwd,
2535 uint32_t pwd_offset,
2536 uint32_t pwd_len,
2537
2538 js_function_t<void, int> callback
2539) {
2540 int err;
2541
2542 auto *req = new sn_async_pwhash_str_verify_request(env);
2543
2544 std::span<char> str_view;
2545 err = js_get_arraybuffer_info(env, str, str_view);
2546 assert(err == 0);
2547 assert(str_offset + str_len <= str_view.size());
2548
2549 req->str = {&str_view[str_offset], str_len};
2550
2551 std::span<char> pwd_view;
2552 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2553 assert(err == 0);
2554 assert(pwd_offset + pwd_len <= pwd_view.size());
2555
2556 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2557
2558 err = js_create_reference(env, str, req->str_ref);
2559 assert(err == 0);
2560
2561 err = js_create_reference(env, pwd, req->pwd_ref);
2562 assert(err == 0);
2563
2564 err = js_create_reference(env, callback, req->cb);
2565 assert(err == 0);
2566
2567 uv_loop_t *loop;
2568 err = js_get_env_loop(env, &loop);
2569 assert(err == 0);
2570
2571 err = uv_queue_work(loop, &req->task, async_pwhash_str_verify_execute, async_pwhash_str_verify_complete);
2572 assert(err == 0);
2573}
2574
2575struct sn_async_pwhash_scryptsalsa208sha256_request : sn_async_task {
2576 js_persistent_t<js_arraybuffer_t> out_ref;
2577 std::span<uint8_t> out;
2578
2579 js_persistent_t<js_arraybuffer_t> pwd_ref;
2580 std::span<char> pwd;
2581
2582 js_persistent_t<js_arraybuffer_t> salt_ref;
2583 std::span<uint8_t> salt;
2584
2585 uint64_t opslimit;
2586 size_t memlimit;
2587
2588 sn_async_pwhash_scryptsalsa208sha256_request(js_env_t *env) : sn_async_task(env) {}
2589};
2590
2591static void
2592async_pwhash_scryptsalsa208sha256_execute(uv_work_t *uv_req) {
2593 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
2594
2595 req->code = crypto_pwhash_scryptsalsa208sha256(
2596 req->out.data(),
2597 req->out.size(),
2598 req->pwd.data(),
2599 req->pwd.size(),
2600 req->salt.data(),
2601 req->opslimit,
2602 req->memlimit
2603 );
2604}
2605
2606static void
2607async_pwhash_scryptsalsa208sha256_complete(uv_work_t *uv_req, int status) {
2608 int err;
2609
2610 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
2611
2612 if (req->exiting) return delete req;
2613
2614 js_handle_scope_t *scope;
2615 err = js_open_handle_scope(req->env, &scope);
2616 assert(err == 0);
2617
2618 js_function_t<void, int> callback;
2619 err = js_get_reference_value(req->env, req->cb, callback);
2620 assert(err == 0);
2621
2622 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2623 assert(err != js_pending_exception);
2624
2625 err = js_close_handle_scope(req->env, scope);
2626 assert(err == 0);
2627
2628 delete req;
2629}
2630
2631static inline void
2632sn_crypto_pwhash_scryptsalsa208sha256_async(
2633 js_env_t *env,
2634 js_receiver_t,
2635
2636 js_arraybuffer_t out,
2637 uint32_t out_offset,
2638 uint32_t out_len,
2639
2640 js_arraybuffer_t pwd,
2641 uint32_t pwd_offset,
2642 uint32_t pwd_len,
2643
2644 js_arraybuffer_t salt,
2645 uint32_t salt_offset,
2646 uint32_t salt_len,
2647
2648 uint64_t opslimit,
2649 uint64_t memlimit,
2650
2651 js_function_t<void, int> callback
2652) {
2653 int err;
2654
2655 auto *req = new sn_async_pwhash_scryptsalsa208sha256_request(env);
2656
2657 std::span<uint8_t> out_view;
2658 err = js_get_arraybuffer_info(env, out, out_view);
2659 assert(err == 0);
2660 assert(out_offset + out_len <= out_view.size());
2661
2662 req->out = {&out_view[out_offset], out_len};
2663
2664 std::span<char> pwd_view;
2665 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2666 assert(err == 0);
2667 assert(pwd_offset + pwd_len <= pwd_view.size());
2668
2669 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2670
2671 std::span<uint8_t> salt_view;
2672 err = js_get_arraybuffer_info(env, salt, salt_view);
2673 assert(err == 0);
2674 assert(salt_offset + salt_len <= salt_view.size());
2675 assert(salt_len == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
2676
2677 req->salt = {&salt_view[salt_offset], salt_len};
2678
2679 req->opslimit = opslimit;
2680 req->memlimit = memlimit;
2681
2682 err = js_create_reference(env, out, req->out_ref);
2683 assert(err == 0);
2684
2685 err = js_create_reference(env, pwd, req->pwd_ref);
2686 assert(err == 0);
2687
2688 err = js_create_reference(env, salt, req->salt_ref);
2689 assert(err == 0);
2690
2691 err = js_create_reference(env, callback, req->cb);
2692 assert(err == 0);
2693
2694 uv_loop_t *loop;
2695 err = js_get_env_loop(env, &loop);
2696 assert(err == 0);
2697
2698 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_execute, async_pwhash_scryptsalsa208sha256_complete);
2699 assert(err == 0);
2700}
2701
2702struct sn_async_pwhash_scryptsalsa208sha256_str_request : sn_async_task {
2703 js_persistent_t<js_arraybuffer_t> out_ref;
2704 std::span<char> out;
2705
2706 js_persistent_t<js_arraybuffer_t> pwd_ref;
2707 std::span<char> pwd;
2708
2709 uint64_t opslimit;
2710 size_t memlimit;
2711
2712 sn_async_pwhash_scryptsalsa208sha256_str_request(js_env_t *env) : sn_async_task(env) {}
2713};
2714
2715static void
2716async_pwhash_scryptsalsa208sha256_str_execute(uv_work_t *uv_req) {
2717 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
2718
2719 req->code = crypto_pwhash_scryptsalsa208sha256_str(
2720 req->out.data(),
2721 req->pwd.data(),
2722 req->pwd.size(),
2723 req->opslimit,
2724 req->memlimit
2725 );
2726}
2727
2728static void
2729async_pwhash_scryptsalsa208sha256_str_complete(uv_work_t *uv_req, int status) {
2730 int err;
2731
2732 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
2733
2734 if (req->exiting) return delete req;
2735
2736 js_handle_scope_t *scope;
2737 err = js_open_handle_scope(req->env, &scope);
2738 assert(err == 0);
2739
2740 js_function_t<void, int> callback;
2741 err = js_get_reference_value(req->env, req->cb, callback);
2742 assert(err == 0);
2743
2744 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2745 assert(err != js_pending_exception);
2746
2747 err = js_close_handle_scope(req->env, scope);
2748 assert(err == 0);
2749
2750 delete req;
2751}
2752
2753static inline void
2754sn_crypto_pwhash_scryptsalsa208sha256_str_async(
2755 js_env_t *env,
2756 js_receiver_t,
2757
2758 js_arraybuffer_t out,
2759 uint32_t out_offset,
2760 uint32_t out_len,
2761
2762 js_arraybuffer_t pwd,
2763 uint32_t pwd_offset,
2764 uint32_t pwd_len,
2765
2766 uint64_t opslimit,
2767 uint64_t memlimit,
2768
2769 js_function_t<void, int> callback
2770) {
2771 int err;
2772
2773 auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_request(env);
2774
2775 std::span<char> out_view;
2776 err = js_get_arraybuffer_info(env, out, out_view);
2777 assert(err == 0);
2778 assert(out_offset + out_len <= out_view.size());
2779
2780 req->out = {&out_view[out_offset], out_len};
2781
2782 std::span<char> pwd_view;
2783 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2784 assert(err == 0);
2785 assert(pwd_offset + pwd_len <= pwd_view.size());
2786
2787 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2788
2789 req->opslimit = opslimit;
2790 req->memlimit = memlimit;
2791
2792 err = js_create_reference(env, out, req->out_ref);
2793 assert(err == 0);
2794
2795 err = js_create_reference(env, pwd, req->pwd_ref);
2796 assert(err == 0);
2797
2798 err = js_create_reference(env, callback, req->cb);
2799 assert(err == 0);
2800
2801 uv_loop_t *loop;
2802 err = js_get_env_loop(env, &loop);
2803 assert(err == 0);
2804
2805 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_execute, async_pwhash_scryptsalsa208sha256_str_complete);
2806 assert(err == 0);
2807}
2808
2809struct sn_async_pwhash_scryptsalsa208sha256_str_verify_request : sn_async_task {
2810 js_persistent_t<js_arraybuffer_t> str_ref;
2811 std::span<char> str;
2812
2813 js_persistent_t<js_arraybuffer_t> pwd_ref;
2814 std::span<char> pwd;
2815
2816 sn_async_pwhash_scryptsalsa208sha256_str_verify_request(js_env_t *env) : sn_async_task(env) {}
2817};
2818
2819static void
2820async_pwhash_scryptsalsa208sha256_str_verify_execute(uv_work_t *uv_req) {
2821 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
2822
2823 req->code = crypto_pwhash_scryptsalsa208sha256_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
2824}
2825
2826static void
2827async_pwhash_scryptsalsa208sha256_str_verify_complete(uv_work_t *uv_req, int status) {
2828 int err;
2829
2830 auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
2831
2832 if (req->exiting) return delete req;
2833
2834 js_handle_scope_t *scope;
2835 err = js_open_handle_scope(req->env, &scope);
2836 assert(err == 0);
2837
2838 js_function_t<void, int> callback;
2839 err = js_get_reference_value(req->env, req->cb, callback);
2840 assert(err == 0);
2841
2842 err = js_call_function_with_checkpoint(req->env, callback, req->code);
2843 assert(err != js_pending_exception);
2844
2845 err = js_close_handle_scope(req->env, scope);
2846 assert(err == 0);
2847
2848 delete req;
2849}
2850
2851static inline void
2852sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async(
2853 js_env_t *env,
2854 js_receiver_t,
2855
2856 js_arraybuffer_t str,
2857 uint32_t str_offset,
2858 uint32_t str_len,
2859
2860 js_arraybuffer_t pwd,
2861 uint32_t pwd_offset,
2862 uint32_t pwd_len,
2863
2864 js_function_t<void, int> callback
2865) {
2866 int err;
2867
2868 auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_verify_request(env);
2869
2870 std::span<char> str_view;
2871 err = js_get_arraybuffer_info(env, str, str_view);
2872 assert(err == 0);
2873 assert(str_offset + str_len <= str_view.size());
2874
2875 req->str = {&str_view[str_offset], str_len};
2876
2877 std::span<char> pwd_view;
2878 err = js_get_arraybuffer_info(env, pwd, pwd_view);
2879 assert(err == 0);
2880 assert(pwd_offset + pwd_len <= pwd_view.size());
2881
2882 req->pwd = {&pwd_view[pwd_offset], pwd_len};
2883
2884 err = js_create_reference(env, str, req->str_ref);
2885 assert(err == 0);
2886
2887 err = js_create_reference(env, pwd, req->pwd_ref);
2888 assert(err == 0);
2889
2890 err = js_create_reference(env, callback, req->cb);
2891 assert(err == 0);
2892
2893 uv_loop_t *loop;
2894 err = js_get_env_loop(env, &loop);
2895 assert(err == 0);
2896
2897 err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_verify_execute, async_pwhash_scryptsalsa208sha256_str_verify_complete);
2898 assert(err == 0);
2899}
2900
2901struct sn_crypto_stream_xor_state {
2902 unsigned char n[crypto_stream_NONCEBYTES];
2903 unsigned char k[crypto_stream_KEYBYTES];
2904 unsigned char next_block[64];
2905 int remainder;
2906 uint64_t block_counter;
2907};
2908
2909static inline void
2910sn_crypto_stream_xor_wrap_init(
2911 js_env_t *,
2912 js_receiver_t,
2913 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
2914 js_typedarray_span_t<> n,
2915 js_typedarray_span_t<> k
2916) {
2917 assert(n.size_bytes() == crypto_stream_NONCEBYTES);
2918 assert(k.size_bytes() == crypto_stream_KEYBYTES);
2919
2920 state->remainder = 0;
2921 state->block_counter = 0;
2922 memcpy(state->n, n.data(), crypto_stream_NONCEBYTES);
2923 memcpy(state->k, k.data(), crypto_stream_KEYBYTES);
2924}
2925
2926static inline void
2927sn_crypto_stream_xor_wrap_update(
2928 js_env_t *,
2929 js_receiver_t,
2930 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
2931 js_typedarray_span_t<> c,
2932 js_typedarray_span_t<> m
2933) {
2934 assert(c.size_bytes() == m.size_bytes());
2935
2936 auto next_block = state->next_block;
2937
2938 size_t m_size = m.size_bytes();
2939 auto *c_ptr = c.data();
2940 auto *m_ptr = m.data();
2941
2942 if (state->remainder) {
2943 uint64_t offset = 0;
2944 int rem = state->remainder;
2945
2946 while (rem < 64 && offset < m_size) {
2947 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
2948 ++offset;
2949 ++rem;
2950 }
2951
2952 c_ptr += offset;
2953 m_ptr += offset;
2954 m_size -= offset;
2955 state->remainder = (rem == 64) ? 0 : rem;
2956
2957 if (m_size == 0) return;
2958 }
2959
2960 state->remainder = m_size & 63;
2961 size_t main_len = m_size - state->remainder;
2962
2963 crypto_stream_xsalsa20_xor_ic(c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k);
2964 state->block_counter += main_len / 64;
2965
2966 if (state->remainder) {
2967 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
2968 memcpy(next_block, m_ptr + main_len, state->remainder);
2969
2970 crypto_stream_xsalsa20_xor_ic(
2971 next_block, next_block, 64, state->n, state->block_counter, state->k
2972 );
2973 memcpy(c_ptr + main_len, next_block, state->remainder);
2974
2975 state->block_counter++;
2976 }
2977}
2978
2979static inline void
2980sn_crypto_stream_xor_wrap_final(
2981 js_env_t *,
2982 js_receiver_t,
2983 js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state
2984) {
2985 sodium_memzero(state->n, sizeof(state->n));
2986 sodium_memzero(state->k, sizeof(state->k));
2987 sodium_memzero(state->next_block, sizeof(state->next_block));
2988 state->remainder = 0;
2989}
2990
2991struct sn_crypto_stream_chacha20_xor_state {
2992 unsigned char n[crypto_stream_chacha20_NONCEBYTES];
2993 unsigned char k[crypto_stream_chacha20_KEYBYTES];
2994 unsigned char next_block[64];
2995 int remainder;
2996 uint64_t block_counter;
2997};
2998
2999static inline void
3000sn_crypto_stream_chacha20_xor_wrap_init(
3001 js_env_t *,
3002 js_receiver_t,
3003 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
3004 js_typedarray_span_t<> n,
3005 js_typedarray_span_t<> k
3006) {
3007 assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
3008 assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
3009
3010 state->remainder = 0;
3011 state->block_counter = 0;
3012 memcpy(state->n, n.data(), crypto_stream_chacha20_NONCEBYTES);
3013 memcpy(state->k, k.data(), crypto_stream_chacha20_KEYBYTES);
3014}
3015
3016static inline void
3017sn_crypto_stream_chacha20_xor_wrap_update(
3018 js_env_t *,
3019 js_receiver_t,
3020 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
3021 js_typedarray_span_t<> c,
3022 js_typedarray_span_t<> m
3023) {
3024 assert(c.size_bytes() == m.size_bytes());
3025
3026 auto *next_block = state->next_block;
3027
3028 size_t m_size = m.size_bytes();
3029 auto *c_ptr = c.data();
3030 auto *m_ptr = m.data();
3031
3032 if (state->remainder) {
3033 uint64_t offset = 0;
3034 int rem = state->remainder;
3035
3036 while (rem < 64 && offset < m_size) {
3037 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3038 offset++;
3039 rem++;
3040 }
3041
3042 c_ptr += offset;
3043 m_ptr += offset;
3044 m_size -= offset;
3045 state->remainder = (rem == 64) ? 0 : rem;
3046
3047 if (m_size == 0) return;
3048 }
3049
3050 state->remainder = m_size & 63;
3051 size_t main_len = m_size - state->remainder;
3052
3053 crypto_stream_chacha20_xor_ic(
3054 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3055 );
3056
3057 state->block_counter += main_len / 64;
3058
3059 if (state->remainder) {
3060 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3061 memcpy(next_block, m_ptr + main_len, state->remainder);
3062
3063 crypto_stream_chacha20_xor_ic(
3064 next_block, next_block, 64, state->n, state->block_counter, state->k
3065 );
3066 memcpy(c_ptr + main_len, next_block, state->remainder);
3067
3068 state->block_counter++;
3069 }
3070}
3071
3072static inline void
3073sn_crypto_stream_chacha20_xor_wrap_final(
3074 js_env_t *,
3075 js_receiver_t,
3076 js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state
3077) {
3078 sodium_memzero(state->n, sizeof(state->n));
3079 sodium_memzero(state->k, sizeof(state->k));
3080 sodium_memzero(state->next_block, sizeof(state->next_block));
3081 state->remainder = 0;
3082}
3083
3084struct sn_crypto_stream_chacha20_ietf_xor_state {
3085 unsigned char n[crypto_stream_chacha20_ietf_NONCEBYTES];
3086 unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES];
3087 unsigned char next_block[64];
3088 int remainder;
3089 uint64_t block_counter;
3090};
3091
3092static inline void
3093sn_crypto_stream_chacha20_ietf_xor_wrap_init(
3094 js_env_t *,
3095 js_receiver_t,
3096 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
3097 js_typedarray_span_t<> n,
3098 js_typedarray_span_t<> k
3099) {
3100 assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
3101 assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
3102
3103 state->remainder = 0;
3104 state->block_counter = 0;
3105 memcpy(state->n, n.data(), crypto_stream_chacha20_ietf_NONCEBYTES);
3106 memcpy(state->k, k.data(), crypto_stream_chacha20_ietf_KEYBYTES);
3107}
3108
3109static inline void
3110sn_crypto_stream_chacha20_ietf_xor_wrap_update(
3111 js_env_t *,
3112 js_receiver_t,
3113 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
3114 js_typedarray_span_t<> c,
3115 js_typedarray_span_t<> m
3116) {
3117 assert(c.size_bytes() == m.size_bytes());
3118
3119 auto *next_block = state->next_block;
3120
3121 size_t m_size = m.size_bytes();
3122 auto *c_ptr = c.data();
3123 auto *m_ptr = m.data();
3124
3125 if (state->remainder) {
3126 uint64_t offset = 0;
3127 int rem = state->remainder;
3128
3129 while (rem < 64 && offset < m_size) {
3130 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3131 offset++;
3132 rem++;
3133 }
3134
3135 c_ptr += offset;
3136 m_ptr += offset;
3137 m_size -= offset;
3138 state->remainder = (rem == 64) ? 0 : rem;
3139
3140 if (m_size == 0) return;
3141 }
3142
3143 state->remainder = m_size & 63;
3144 size_t main_len = m_size - state->remainder;
3145
3146 crypto_stream_chacha20_ietf_xor_ic(
3147 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3148 );
3149
3150 state->block_counter += main_len / 64;
3151
3152 if (state->remainder) {
3153 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3154 memcpy(next_block, m_ptr + main_len, state->remainder);
3155
3156 crypto_stream_chacha20_ietf_xor_ic(
3157 next_block, next_block, 64, state->n, state->block_counter, state->k
3158 );
3159 memcpy(c_ptr + main_len, next_block, state->remainder);
3160
3161 state->block_counter++;
3162 }
3163}
3164
3165static inline void
3166sn_crypto_stream_chacha20_ietf_xor_wrap_final(
3167 js_env_t *,
3168 js_receiver_t,
3169 js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state
3170) {
3171 sodium_memzero(state->n, sizeof(state->n));
3172 sodium_memzero(state->k, sizeof(state->k));
3173 sodium_memzero(state->next_block, sizeof(state->next_block));
3174 state->remainder = 0;
3175}
3176
3177struct sn_crypto_stream_xchacha20_xor_state {
3178 unsigned char n[crypto_stream_xchacha20_NONCEBYTES];
3179 unsigned char k[crypto_stream_xchacha20_KEYBYTES];
3180 unsigned char next_block[64];
3181 int remainder;
3182 uint64_t block_counter;
3183};
3184
3185static inline void
3186sn_crypto_stream_xchacha20_xor_wrap_init(
3187 js_env_t *,
3188 js_receiver_t,
3189 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
3190 js_typedarray_span_t<> n,
3191 js_typedarray_span_t<> k
3192) {
3193 assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
3194 assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
3195
3196 state->remainder = 0;
3197 state->block_counter = 0;
3198 memcpy(state->n, n.data(), crypto_stream_xchacha20_NONCEBYTES);
3199 memcpy(state->k, k.data(), crypto_stream_xchacha20_KEYBYTES);
3200}
3201
3202static inline void
3203sn_crypto_stream_xchacha20_xor_wrap_update(
3204 js_env_t *,
3205 js_receiver_t,
3206 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
3207 js_typedarray_span_t<> c,
3208 js_typedarray_span_t<> m
3209) {
3210 assert(c.size_bytes() == m.size_bytes());
3211
3212 auto *next_block = state->next_block;
3213
3214 size_t m_size = m.size_bytes();
3215 auto *c_ptr = c.data();
3216 auto *m_ptr = m.data();
3217
3218 if (state->remainder) {
3219 uint64_t offset = 0;
3220 int rem = state->remainder;
3221
3222 while (rem < 64 && offset < m_size) {
3223 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3224 ++offset;
3225 ++rem;
3226 }
3227
3228 c_ptr += offset;
3229 m_ptr += offset;
3230 m_size -= offset;
3231 state->remainder = (rem == 64) ? 0 : rem;
3232
3233 if (m_size == 0) return;
3234 }
3235
3236 state->remainder = m_size & 63;
3237 size_t main_len = m_size - state->remainder;
3238
3239 crypto_stream_xchacha20_xor_ic(
3240 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3241 );
3242
3243 state->block_counter += main_len / 64;
3244
3245 if (state->remainder) {
3246 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3247 memcpy(next_block, m_ptr + main_len, state->remainder);
3248
3249 crypto_stream_xchacha20_xor_ic(
3250 next_block, next_block, 64, state->n, state->block_counter, state->k
3251 );
3252 memcpy(c_ptr + main_len, next_block, state->remainder);
3253
3254 state->block_counter++;
3255 }
3256}
3257
3258static inline void
3259sn_crypto_stream_xchacha20_xor_wrap_final(
3260 js_env_t *,
3261 js_receiver_t,
3262 js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state
3263) {
3264 sodium_memzero(state->n, sizeof(state->n));
3265 sodium_memzero(state->k, sizeof(state->k));
3266 sodium_memzero(state->next_block, sizeof(state->next_block));
3267 state->remainder = 0;
3268}
3269
3270struct sn_crypto_stream_salsa20_xor_state {
3271 unsigned char n[crypto_stream_salsa20_NONCEBYTES];
3272 unsigned char k[crypto_stream_salsa20_KEYBYTES];
3273 unsigned char next_block[64];
3274 int remainder;
3275 uint64_t block_counter;
3276};
3277
3278static inline void
3279sn_crypto_stream_salsa20_xor_wrap_init(
3280 js_env_t *,
3281 js_receiver_t,
3282 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
3283 js_typedarray_span_t<> n,
3284 js_typedarray_span_t<> k
3285) {
3286 assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
3287 assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
3288
3289 state->remainder = 0;
3290 state->block_counter = 0;
3291 memcpy(state->n, n.data(), crypto_stream_salsa20_NONCEBYTES);
3292 memcpy(state->k, k.data(), crypto_stream_salsa20_KEYBYTES);
3293}
3294
3295static inline void
3296sn_crypto_stream_salsa20_xor_wrap_update(
3297 js_env_t *,
3298 js_receiver_t,
3299 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
3300 js_typedarray_span_t<> c,
3301 js_typedarray_span_t<> m
3302) {
3303 assert(c.size_bytes() == m.size_bytes());
3304
3305 auto *next_block = state->next_block;
3306
3307 size_t m_size = m.size_bytes();
3308 auto *c_ptr = c.data();
3309 auto *m_ptr = m.data();
3310
3311 if (state->remainder) {
3312 uint64_t offset = 0;
3313 int rem = state->remainder;
3314
3315 while (rem < 64 && offset < m_size) {
3316 c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
3317 ++offset;
3318 ++rem;
3319 }
3320
3321 c_ptr += offset;
3322 m_ptr += offset;
3323 m_size -= offset;
3324 state->remainder = (rem == 64) ? 0 : rem;
3325
3326 if (m_size == 0) return;
3327 }
3328
3329 state->remainder = m_size & 63;
3330 size_t main_len = m_size - state->remainder;
3331
3332 crypto_stream_salsa20_xor_ic(
3333 c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
3334 );
3335
3336 state->block_counter += main_len / 64;
3337
3338 if (state->remainder) {
3339 sodium_memzero(next_block + state->remainder, 64 - state->remainder);
3340 memcpy(next_block, m_ptr + main_len, state->remainder);
3341
3342 crypto_stream_salsa20_xor_ic(
3343 next_block, next_block, 64, state->n, state->block_counter, state->k
3344 );
3345 memcpy(c_ptr + main_len, next_block, state->remainder);
3346
3347 state->block_counter++;
3348 }
3349}
3350
3351static inline void
3352sn_crypto_stream_salsa20_xor_wrap_final(
3353 js_env_t *,
3354 js_receiver_t,
3355 js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state
3356) {
3357 sodium_memzero(state->n, sizeof(state->n));
3358 sodium_memzero(state->k, sizeof(state->k));
3359 sodium_memzero(state->next_block, sizeof(state->next_block));
3360 state->remainder = 0;
3361}
3362
3363// Experimental API
3364
3365static inline void
3366sn_extension_tweak_ed25519_base(
3367 js_env_t *,
3368 js_receiver_t,
3369 js_typedarray_span_t<> n,
3370 js_typedarray_span_t<> p,
3371 js_typedarray_span_t<> ns
3372) {
3373 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3374 assert(p.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3375
3376 sn__extension_tweak_ed25519_base(p.data(), n.data(), ns.data(), ns.size_bytes());
3377}
3378
3379static inline int
3380sn_extension_tweak_ed25519_sign_detached(
3381 js_env_t *,
3382 js_receiver_t,
3383 js_typedarray_span_t<> sig,
3384 js_typedarray_span_t<> m,
3385 js_typedarray_span_t<> scalar,
3386 std::optional<js_typedarray_span_t<>> pk
3387) {
3388 assert(sig.size_bytes() == crypto_sign_BYTES);
3389 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3390
3391 uint8_t *pk_data = nullptr;
3392 if (pk) {
3393 assert(pk->size_bytes() == crypto_sign_PUBLICKEYBYTES);
3394 pk_data = pk->data();
3395 }
3396
3397 return sn__extension_tweak_ed25519_sign_detached(
3398 sig.data(),
3399 nullptr,
3400 m.data(),
3401 m.size_bytes(),
3402 scalar.data(),
3403 pk_data
3404 );
3405}
3406
3407static inline void
3408sn_extension_tweak_ed25519_sk_to_scalar(
3409 js_env_t *,
3410 js_receiver_t,
3411 js_typedarray_span_t<> n,
3412 js_typedarray_span_t<> sk
3413) {
3414 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3415 assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
3416
3417 sn__extension_tweak_ed25519_sk_to_scalar(n.data(), sk.data());
3418}
3419
3420static inline void
3421sn_extension_tweak_ed25519_scalar(
3422 js_env_t *,
3423 js_receiver_t,
3424 js_typedarray_span_t<> scalar_out,
3425 js_typedarray_span_t<> scalar,
3426 js_typedarray_span_t<> ns
3427) {
3428 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3429 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3430
3431 sn__extension_tweak_ed25519_scalar(scalar_out.data(), scalar.data(), ns.data(), ns.size_bytes());
3432}
3433
3434static inline int
3435sn_extension_tweak_ed25519_pk(
3436 js_env_t *,
3437 js_receiver_t,
3438 js_typedarray_span_t<> tpk,
3439 js_typedarray_span_t<> pk,
3440 js_typedarray_span_t<> ns
3441) {
3442 assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3443 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3444
3445 return sn__extension_tweak_ed25519_pk(tpk.data(), pk.data(), ns.data(), ns.size_bytes());
3446}
3447
3448static inline void
3449sn_extension_tweak_ed25519_keypair(
3450 js_env_t *,
3451 js_receiver_t,
3452 js_typedarray_span_t<> pk,
3453 js_typedarray_span_t<> scalar_out,
3454 js_typedarray_span_t<> scalar_in,
3455 js_typedarray_span_t<> ns
3456) {
3457 assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3458 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3459 assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3460
3461 sn__extension_tweak_ed25519_keypair(
3462 pk.data(),
3463 scalar_out.data(),
3464 scalar_in.data(),
3465 ns.data(),
3466 ns.size_bytes()
3467 );
3468}
3469
3470static inline void
3471sn_extension_tweak_ed25519_scalar_add(
3472 js_env_t *,
3473 js_receiver_t,
3474 js_typedarray_span_t<> scalar_out,
3475 js_typedarray_span_t<> scalar,
3476 js_typedarray_span_t<> n
3477) {
3478 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3479 assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3480 assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3481
3482 sn__extension_tweak_ed25519_scalar_add(scalar_out.data(), scalar.data(), n.data());
3483}
3484
3485static inline int
3486sn_extension_tweak_ed25519_pk_add(
3487 js_env_t *,
3488 js_receiver_t,
3489 js_typedarray_span_t<> tpk,
3490 js_typedarray_span_t<> pk,
3491 js_typedarray_span_t<> p
3492) {
3493 assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3494 assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3495 assert(p.size_bytes() == crypto_sign_PUBLICKEYBYTES);
3496
3497 return sn__extension_tweak_ed25519_pk_add(tpk.data(), pk.data(), p.data());
3498}
3499
3500static inline int
3501sn_extension_tweak_ed25519_keypair_add(
3502 js_env_t *,
3503 js_receiver_t,
3504 js_typedarray_span_t<> pk,
3505 js_typedarray_span_t<> scalar_out,
3506 js_typedarray_span_t<> scalar_in,
3507 js_typedarray_span_t<> tweak
3508) {
3509 assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
3510 assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3511 assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3512 assert(tweak.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
3513
3514 return sn__extension_tweak_ed25519_keypair_add(
3515 pk.data(),
3516 scalar_out.data(),
3517 scalar_in.data(),
3518 tweak.data()
3519 );
3520}
3521
3522static inline int
3523sn_extension_pbkdf2_sha512(
3524 js_env_t *,
3525 js_receiver_t,
3526 js_typedarray_span_t<> out,
3527 js_typedarray_span_t<> passwd,
3528 js_typedarray_span_t<> salt,
3529 uint64_t iter,
3530 uint64_t outlen
3531) {
3532
3533 assert(iter >= sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
3534 assert(outlen <= sn__extension_pbkdf2_sha512_BYTES_MAX);
3535 assert(out.size_bytes() >= static_cast<size_t>(outlen));
3536
3537 return sn__extension_pbkdf2_sha512(
3538 passwd.data(),
3539 passwd.size_bytes(),
3540 salt.data(),
3541 salt.size_bytes(),
3542 iter,
3543 out.data(),
3544 outlen
3545 );
3546}
3547
3548struct sn_async_pbkdf2_sha512_request : sn_async_task {
3549 js_persistent_t<js_arraybuffer_t> out_ref;
3550 std::span<uint8_t> out;
3551
3552 size_t outlen;
3553
3554 js_persistent_t<js_arraybuffer_t> pwd_ref;
3555 std::span<uint8_t> pwd;
3556
3557 js_persistent_t<js_arraybuffer_t> salt_ref;
3558 std::span<uint8_t> salt;
3559
3560 uint64_t iter;
3561
3562 sn_async_pbkdf2_sha512_request(js_env_t *env) : sn_async_task(env) {}
3563};
3564
3565static void
3566async_pbkdf2_sha512_execute(uv_work_t *uv_req) {
3567 auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
3568
3569 req->code = sn__extension_pbkdf2_sha512(
3570 req->pwd.data(),
3571 req->pwd.size(),
3572 req->salt.data(),
3573 req->salt.size(),
3574 req->iter,
3575 req->out.data(),
3576 req->outlen
3577 );
3578}
3579
3580static void
3581async_pbkdf2_sha512_complete(uv_work_t *uv_req, int status) {
3582 int err;
3583
3584 auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
3585
3586 if (req->exiting) return delete req;
3587
3588 js_handle_scope_t *scope;
3589 err = js_open_handle_scope(req->env, &scope);
3590 assert(err == 0);
3591
3592 js_function_t<void, int> callback;
3593 err = js_get_reference_value(req->env, req->cb, callback);
3594 assert(err == 0);
3595
3596 err = js_call_function_with_checkpoint(req->env, callback, req->code);
3597 assert(err != js_pending_exception);
3598
3599 err = js_close_handle_scope(req->env, scope);
3600 assert(err == 0);
3601
3602 delete req;
3603}
3604
3605static inline void
3606sn_extension_pbkdf2_sha512_async(
3607 js_env_t *env,
3608 js_receiver_t,
3609
3610 js_arraybuffer_t out,
3611 uint32_t out_offset,
3612 uint32_t out_len,
3613
3614 js_arraybuffer_t pwd,
3615 uint32_t pwd_offset,
3616 uint32_t pwd_len,
3617
3618 js_arraybuffer_t salt,
3619 uint32_t salt_offset,
3620 uint32_t salt_len,
3621
3622 uint64_t iter,
3623 uint64_t outlen,
3624
3625 js_function_t<void, int> callback
3626) {
3627 int err;
3628
3629 auto *req = new sn_async_pbkdf2_sha512_request(env);
3630
3631 std::span<uint8_t> out_view;
3632 err = js_get_arraybuffer_info(env, out, out_view);
3633 assert(err == 0);
3634 assert(out_offset + out_len <= out_view.size());
3635
3636 req->out = {&out_view[out_offset], out_len};
3637
3638 std::span<uint8_t> pwd_view;
3639 err = js_get_arraybuffer_info(env, pwd, pwd_view);
3640 assert(err == 0);
3641 assert(pwd_offset + pwd_len <= pwd_view.size());
3642
3643 req->pwd = {&pwd_view[pwd_offset], pwd_len};
3644
3645 std::span<uint8_t> salt_view;
3646 err = js_get_arraybuffer_info(env, salt, salt_view);
3647 assert(err == 0);
3648 assert(salt_offset + salt_len <= salt_view.size());
3649
3650 req->salt = {&salt_view[salt_offset], salt_len};
3651
3652 req->iter = iter;
3653 req->outlen = outlen;
3654
3655 err = js_create_reference(env, out, req->out_ref);
3656 assert(err == 0);
3657
3658 err = js_create_reference(env, pwd, req->pwd_ref);
3659 assert(err == 0);
3660
3661 err = js_create_reference(env, salt, req->salt_ref);
3662 assert(err == 0);
3663
3664 err = js_create_reference(env, callback, req->cb);
3665 assert(err == 0);
3666
3667 uv_loop_t *loop;
3668 err = js_get_env_loop(env, &loop);
3669 assert(err == 0);
3670
3671 err = uv_queue_work(loop, &req->task, async_pbkdf2_sha512_execute, async_pbkdf2_sha512_complete);
3672 assert(err == 0);
3673}
3674
3675static js_value_t *
3676sodium_native_exports(js_env_t *env, js_value_t *exports) {
3677 int err;
3678
3679 err = sodium_init();
3680 assert(err >= 0);
3681
3682#define V_FUNCTION(name, fn) \
3683 err = js_set_property<fn>(env, exports, name); \
3684 assert(err == 0);
3685
3686#define V_FUNCTION_NOSCOPE(name, fn) \
3687 err = js_set_property<fn, js_function_options_t{.scoped = false}>(env, exports, name); \
3688 assert(err == 0);
3689
3690#define V_UINT32(name, constant) \
3691 err = js_set_property(env, exports, name, static_cast<uint32_t>(constant)); \
3692 assert(err == 0);
3693
3694#define V_UINT64(name, constant) \
3695 err = js_set_property(env, exports, name, static_cast<int64_t>(std::min<uint64_t>(constant, js_max_safe_integer))); \
3696 assert(err == 0);
3697
3698#define V_STRING(name, str) \
3699 err = js_set_property(env, exports, name, str); \
3700 assert(err == 0);
3701
3702 // memory
3703
3704 V_FUNCTION("sodium_memzero", sn_sodium_memzero);
3705 V_FUNCTION("sodium_mlock", sn_sodium_mlock);
3706 V_FUNCTION("sodium_munlock", sn_sodium_munlock);
3707 V_FUNCTION("sodium_malloc", sn_sodium_malloc);
3708 V_FUNCTION("sodium_free", sn_sodium_free);
3709 V_FUNCTION("sodium_mprotect_noaccess", sn_sodium_mprotect_noaccess);
3710 V_FUNCTION("sodium_mprotect_readonly", sn_sodium_mprotect_readonly);
3711 V_FUNCTION("sodium_mprotect_readwrite", sn_sodium_mprotect_readwrite);
3712
3713 // randombytes
3714
3715 V_FUNCTION_NOSCOPE("randombytes_buf", sn_randombytes_buf);
3716 V_FUNCTION_NOSCOPE("randombytes_buf_deterministic", sn_randombytes_buf_deterministic);
3717 V_FUNCTION_NOSCOPE("randombytes_random", sn_randombytes_random);
3718 V_FUNCTION_NOSCOPE("randombytes_uniform", sn_randombytes_uniform);
3719
3720 V_UINT32("randombytes_SEEDBYTES", randombytes_SEEDBYTES);
3721
3722 // sodium helpers
3723
3724 V_FUNCTION("sodium_memcmp", sn_sodium_memcmp);
3725 V_FUNCTION("sodium_increment", sn_sodium_increment);
3726 V_FUNCTION("sodium_add", sn_sodium_add);
3727 V_FUNCTION("sodium_sub", sn_sodium_sub);
3728 V_FUNCTION("sodium_compare", sn_sodium_compare);
3729 V_FUNCTION("sodium_is_zero", sn_sodium_is_zero);
3730 V_FUNCTION("sodium_pad", sn_sodium_pad);
3731 V_FUNCTION("sodium_unpad", sn_sodium_unpad);
3732
3733 // crypto_aead
3734
3735 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_keygen", sn_crypto_aead_xchacha20poly1305_ietf_keygen);
3736 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt", sn_crypto_aead_xchacha20poly1305_ietf_encrypt);
3737 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt", sn_crypto_aead_xchacha20poly1305_ietf_decrypt);
3738 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached);
3739 V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached);
3740 V_UINT32("crypto_aead_xchacha20poly1305_ietf_ABYTES", crypto_aead_xchacha20poly1305_ietf_ABYTES);
3741 V_UINT32("crypto_aead_xchacha20poly1305_ietf_KEYBYTES", crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
3742 V_UINT32("crypto_aead_xchacha20poly1305_ietf_NPUBBYTES", crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
3743 V_UINT32("crypto_aead_xchacha20poly1305_ietf_NSECBYTES", crypto_aead_xchacha20poly1305_ietf_NSECBYTES);
3744 V_UINT64("crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX);
3745
3746 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_keygen", sn_crypto_aead_chacha20poly1305_ietf_keygen);
3747 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt", sn_crypto_aead_chacha20poly1305_ietf_encrypt);
3748 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt", sn_crypto_aead_chacha20poly1305_ietf_decrypt);
3749 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached);
3750 V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached);
3751 V_UINT32("crypto_aead_chacha20poly1305_ietf_ABYTES", crypto_aead_chacha20poly1305_ietf_ABYTES);
3752 V_UINT32("crypto_aead_chacha20poly1305_ietf_KEYBYTES", crypto_aead_chacha20poly1305_ietf_KEYBYTES);
3753 V_UINT32("crypto_aead_chacha20poly1305_ietf_NPUBBYTES", crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
3754 V_UINT32("crypto_aead_chacha20poly1305_ietf_NSECBYTES", crypto_aead_chacha20poly1305_ietf_NSECBYTES);
3755 V_UINT64("crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
3756
3757 // crypto_auth
3758
3759 V_FUNCTION("crypto_auth", sn_crypto_auth);
3760 V_FUNCTION("crypto_auth_verify", sn_crypto_auth_verify);
3761 V_UINT32("crypto_auth_BYTES", crypto_auth_BYTES);
3762 V_UINT32("crypto_auth_KEYBYTES", crypto_auth_KEYBYTES);
3763 V_STRING("crypto_auth_PRIMITIVE", crypto_auth_PRIMITIVE);
3764
3765 // crypto_box
3766
3767 V_FUNCTION("crypto_box_keypair", sn_crypto_box_keypair);
3768 V_FUNCTION("crypto_box_seed_keypair", sn_crypto_box_seed_keypair);
3769 V_FUNCTION("crypto_box_easy", sn_crypto_box_easy);
3770 V_FUNCTION("crypto_box_open_easy", sn_crypto_box_open_easy);
3771 V_FUNCTION("crypto_box_detached", sn_crypto_box_detached);
3772 V_FUNCTION("crypto_box_open_detached", sn_crypto_box_open_detached);
3773 V_FUNCTION("crypto_box_seal", sn_crypto_box_seal);
3774 V_FUNCTION_NOSCOPE("crypto_box_seal_open", sn_crypto_box_seal_open);
3775
3776 V_UINT32("crypto_box_SEEDBYTES", crypto_box_SEEDBYTES);
3777 V_UINT32("crypto_box_PUBLICKEYBYTES", crypto_box_PUBLICKEYBYTES);
3778 V_UINT32("crypto_box_SECRETKEYBYTES", crypto_box_SECRETKEYBYTES);
3779 V_UINT32("crypto_box_NONCEBYTES", crypto_box_NONCEBYTES);
3780 V_UINT32("crypto_box_MACBYTES", crypto_box_MACBYTES);
3781 V_UINT32("crypto_box_SEALBYTES", crypto_box_SEALBYTES);
3782 V_STRING("crypto_box_PRIMITIVE", crypto_box_PRIMITIVE);
3783
3784 // crypto_core
3785
3786 V_FUNCTION("crypto_core_ed25519_is_valid_point", sn_crypto_core_ed25519_is_valid_point);
3787 V_FUNCTION("crypto_core_ed25519_from_uniform", sn_crypto_core_ed25519_from_uniform);
3788 V_FUNCTION("crypto_core_ed25519_add", sn_crypto_core_ed25519_add);
3789 V_FUNCTION("crypto_core_ed25519_sub", sn_crypto_core_ed25519_sub);
3790 V_FUNCTION("crypto_core_ed25519_scalar_random", sn_crypto_core_ed25519_scalar_random);
3791 V_FUNCTION("crypto_core_ed25519_scalar_reduce", sn_crypto_core_ed25519_scalar_reduce);
3792 V_FUNCTION("crypto_core_ed25519_scalar_invert", sn_crypto_core_ed25519_scalar_invert);
3793 V_FUNCTION("crypto_core_ed25519_scalar_negate", sn_crypto_core_ed25519_scalar_negate);
3794 V_FUNCTION("crypto_core_ed25519_scalar_complement", sn_crypto_core_ed25519_scalar_complement);
3795 V_FUNCTION("crypto_core_ed25519_scalar_add", sn_crypto_core_ed25519_scalar_add);
3796 V_FUNCTION("crypto_core_ed25519_scalar_sub", sn_crypto_core_ed25519_scalar_sub);
3797 V_UINT32("crypto_core_ed25519_BYTES", crypto_core_ed25519_BYTES);
3798 V_UINT32("crypto_core_ed25519_UNIFORMBYTES", crypto_core_ed25519_UNIFORMBYTES);
3799 V_UINT32("crypto_core_ed25519_SCALARBYTES", crypto_core_ed25519_SCALARBYTES);
3800 V_UINT32("crypto_core_ed25519_NONREDUCEDSCALARBYTES", crypto_core_ed25519_NONREDUCEDSCALARBYTES);
3801
3802 // crypto_kdf
3803
3804 V_FUNCTION("crypto_kdf_keygen", sn_crypto_kdf_keygen);
3805 V_FUNCTION("crypto_kdf_derive_from_key", sn_crypto_kdf_derive_from_key);
3806 V_UINT32("crypto_kdf_BYTES_MIN", crypto_kdf_BYTES_MIN);
3807 V_UINT32("crypto_kdf_BYTES_MAX", crypto_kdf_BYTES_MAX);
3808 V_UINT32("crypto_kdf_CONTEXTBYTES", crypto_kdf_CONTEXTBYTES);
3809 V_UINT32("crypto_kdf_KEYBYTES", crypto_kdf_KEYBYTES);
3810 V_STRING("crypto_kdf_PRIMITIVE", crypto_kdf_PRIMITIVE);
3811
3812 // crypto_kx
3813
3814 V_FUNCTION("crypto_kx_keypair", sn_crypto_kx_keypair);
3815 V_FUNCTION("crypto_kx_seed_keypair", sn_crypto_kx_seed_keypair);
3816 V_FUNCTION("crypto_kx_client_session_keys", sn_crypto_kx_client_session_keys);
3817 V_FUNCTION("crypto_kx_server_session_keys", sn_crypto_kx_server_session_keys);
3818 V_UINT32("crypto_kx_PUBLICKEYBYTES", crypto_kx_PUBLICKEYBYTES);
3819 V_UINT32("crypto_kx_SECRETKEYBYTES", crypto_kx_SECRETKEYBYTES);
3820 V_UINT32("crypto_kx_SEEDBYTES", crypto_kx_SEEDBYTES);
3821 V_UINT32("crypto_kx_SESSIONKEYBYTES", crypto_kx_SESSIONKEYBYTES);
3822 V_STRING("crypto_kx_PRIMITIVE", crypto_kx_PRIMITIVE);
3823
3824 // crypto_generichash
3825
3826 V_FUNCTION_NOSCOPE("crypto_generichash", sn_crypto_generichash);
3827 V_FUNCTION("crypto_generichash_batch", sn_crypto_generichash_batch);
3828 V_FUNCTION_NOSCOPE("crypto_generichash_keygen", sn_crypto_generichash_keygen);
3829 V_FUNCTION_NOSCOPE("crypto_generichash_init", sn_crypto_generichash_init);
3830 V_FUNCTION_NOSCOPE("crypto_generichash_update", sn_crypto_generichash_update);
3831 V_FUNCTION_NOSCOPE("crypto_generichash_final", sn_crypto_generichash_final);
3832
3833 V_UINT32("crypto_generichash_STATEBYTES", sizeof(crypto_generichash_state));
3834 V_STRING("crypto_generichash_PRIMITIVE", crypto_generichash_PRIMITIVE);
3835 V_UINT32("crypto_generichash_BYTES_MIN", crypto_generichash_BYTES_MIN);
3836 V_UINT32("crypto_generichash_BYTES_MAX", crypto_generichash_BYTES_MAX);
3837 V_UINT32("crypto_generichash_BYTES", crypto_generichash_BYTES);
3838 V_UINT32("crypto_generichash_KEYBYTES_MIN", crypto_generichash_KEYBYTES_MIN);
3839 V_UINT32("crypto_generichash_KEYBYTES_MAX", crypto_generichash_KEYBYTES_MAX);
3840 V_UINT32("crypto_generichash_KEYBYTES", crypto_generichash_KEYBYTES);
3841
3842 // crypto_hash
3843
3844 V_FUNCTION("crypto_hash", sn_crypto_hash);
3845 V_UINT32("crypto_hash_BYTES", crypto_hash_BYTES);
3846 V_STRING("crypto_hash_PRIMITIVE", crypto_hash_PRIMITIVE);
3847
3848 V_FUNCTION("crypto_hash_sha256", sn_crypto_hash_sha256);
3849 V_FUNCTION("crypto_hash_sha256_init", sn_crypto_hash_sha256_init);
3850 V_FUNCTION("crypto_hash_sha256_update", sn_crypto_hash_sha256_update);
3851 V_FUNCTION("crypto_hash_sha256_final", sn_crypto_hash_sha256_final);
3852 V_UINT32("crypto_hash_sha256_STATEBYTES", sizeof(crypto_hash_sha256_state));
3853 V_UINT32("crypto_hash_sha256_BYTES", crypto_hash_sha256_BYTES);
3854
3855 V_FUNCTION("crypto_hash_sha512", sn_crypto_hash_sha512);
3856 V_FUNCTION("crypto_hash_sha512_init", sn_crypto_hash_sha512_init);
3857 V_FUNCTION("crypto_hash_sha512_update", sn_crypto_hash_sha512_update);
3858 V_FUNCTION("crypto_hash_sha512_final", sn_crypto_hash_sha512_final);
3859 V_UINT32("crypto_hash_sha512_STATEBYTES", sizeof(crypto_hash_sha512_state));
3860 V_UINT32("crypto_hash_sha512_BYTES", crypto_hash_sha512_BYTES);
3861
3862 // crypto_onetimeauth
3863
3864 V_FUNCTION("crypto_onetimeauth", sn_crypto_onetimeauth);
3865 V_FUNCTION("crypto_onetimeauth_verify", sn_crypto_onetimeauth_verify);
3866 V_FUNCTION("crypto_onetimeauth_init", sn_crypto_onetimeauth_init);
3867 V_FUNCTION("crypto_onetimeauth_update", sn_crypto_onetimeauth_update);
3868 V_FUNCTION("crypto_onetimeauth_final", sn_crypto_onetimeauth_final);
3869 V_UINT32("crypto_onetimeauth_STATEBYTES", sizeof(crypto_onetimeauth_state));
3870 V_UINT32("crypto_onetimeauth_BYTES", crypto_onetimeauth_BYTES);
3871 V_UINT32("crypto_onetimeauth_KEYBYTES", crypto_onetimeauth_KEYBYTES);
3872 V_STRING("crypto_onetimeauth_PRIMITIVE", crypto_onetimeauth_PRIMITIVE);
3873
3874 // crypto_pwhash
3875
3876 V_FUNCTION("crypto_pwhash", sn_crypto_pwhash);
3877 V_FUNCTION("crypto_pwhash_str", sn_crypto_pwhash_str);
3878 V_FUNCTION("crypto_pwhash_str_verify", sn_crypto_pwhash_str_verify);
3879 V_FUNCTION("crypto_pwhash_str_needs_rehash", sn_crypto_pwhash_str_needs_rehash);
3880 V_FUNCTION("crypto_pwhash_async", sn_crypto_pwhash_async);
3881 V_FUNCTION("crypto_pwhash_str_async", sn_crypto_pwhash_str_async);
3882 V_FUNCTION("crypto_pwhash_str_verify_async", sn_crypto_pwhash_str_verify_async);
3883 V_UINT32("crypto_pwhash_ALG_ARGON2I13", crypto_pwhash_ALG_ARGON2I13);
3884 V_UINT32("crypto_pwhash_ALG_ARGON2ID13", crypto_pwhash_ALG_ARGON2ID13);
3885 V_UINT32("crypto_pwhash_ALG_DEFAULT", crypto_pwhash_ALG_DEFAULT);
3886 V_UINT32("crypto_pwhash_BYTES_MIN", crypto_pwhash_BYTES_MIN);
3887 V_UINT32("crypto_pwhash_BYTES_MAX", crypto_pwhash_BYTES_MAX);
3888 V_UINT32("crypto_pwhash_PASSWD_MIN", crypto_pwhash_PASSWD_MIN);
3889 V_UINT32("crypto_pwhash_PASSWD_MAX", crypto_pwhash_PASSWD_MAX);
3890 V_UINT32("crypto_pwhash_SALTBYTES", crypto_pwhash_SALTBYTES);
3891 V_UINT32("crypto_pwhash_STRBYTES", crypto_pwhash_STRBYTES);
3892 V_STRING("crypto_pwhash_STRPREFIX", crypto_pwhash_STRPREFIX);
3893 V_UINT32("crypto_pwhash_OPSLIMIT_MIN", crypto_pwhash_OPSLIMIT_MIN);
3894 V_UINT32("crypto_pwhash_OPSLIMIT_MAX", crypto_pwhash_OPSLIMIT_MAX);
3895 V_UINT64("crypto_pwhash_MEMLIMIT_MIN", crypto_pwhash_MEMLIMIT_MIN);
3896 V_UINT64("crypto_pwhash_MEMLIMIT_MAX", crypto_pwhash_MEMLIMIT_MAX);
3897 V_UINT32("crypto_pwhash_OPSLIMIT_INTERACTIVE", crypto_pwhash_OPSLIMIT_INTERACTIVE);
3898 V_UINT64("crypto_pwhash_MEMLIMIT_INTERACTIVE", crypto_pwhash_MEMLIMIT_INTERACTIVE);
3899 V_UINT32("crypto_pwhash_OPSLIMIT_MODERATE", crypto_pwhash_OPSLIMIT_MODERATE);
3900 V_UINT64("crypto_pwhash_MEMLIMIT_MODERATE", crypto_pwhash_MEMLIMIT_MODERATE);
3901 V_UINT32("crypto_pwhash_OPSLIMIT_SENSITIVE", crypto_pwhash_OPSLIMIT_SENSITIVE);
3902 V_UINT64("crypto_pwhash_MEMLIMIT_SENSITIVE", crypto_pwhash_MEMLIMIT_SENSITIVE);
3903 V_STRING("crypto_pwhash_PRIMITIVE", crypto_pwhash_PRIMITIVE);
3904
3905 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256", sn_crypto_pwhash_scryptsalsa208sha256);
3906 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str", sn_crypto_pwhash_scryptsalsa208sha256_str);
3907 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify", sn_crypto_pwhash_scryptsalsa208sha256_str_verify);
3908 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_needs_rehash", sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash);
3909 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_async", sn_crypto_pwhash_scryptsalsa208sha256_async);
3910 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_async", sn_crypto_pwhash_scryptsalsa208sha256_str_async)
3911 V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify_async", sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async);
3912 V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MIN", crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
3913 V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MAX", crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
3914 V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN", crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN);
3915 V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX", crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX);
3916 V_UINT64("crypto_pwhash_scryptsalsa208sha256_SALTBYTES", crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
3917 V_UINT64("crypto_pwhash_scryptsalsa208sha256_STRBYTES", crypto_pwhash_scryptsalsa208sha256_STRBYTES);
3918 V_STRING("crypto_pwhash_scryptsalsa208sha256_STRPREFIX", crypto_pwhash_scryptsalsa208sha256_STRPREFIX);
3919 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
3920 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
3921 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
3922 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
3923 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
3924 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
3925 V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE);
3926 V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE);
3927
3928 // crypto_scalarmult
3929
3930 V_FUNCTION("crypto_scalarmult_base", sn_crypto_scalarmult_base);
3931 V_FUNCTION("crypto_scalarmult", sn_crypto_scalarmult);
3932 V_STRING("crypto_scalarmult_PRIMITIVE", crypto_scalarmult_PRIMITIVE);
3933 V_UINT32("crypto_scalarmult_BYTES", crypto_scalarmult_BYTES);
3934 V_UINT32("crypto_scalarmult_SCALARBYTES", crypto_scalarmult_SCALARBYTES);
3935
3936 V_FUNCTION("crypto_scalarmult_ed25519_base", sn_crypto_scalarmult_ed25519_base);
3937 V_FUNCTION("crypto_scalarmult_ed25519", sn_crypto_scalarmult_ed25519);
3938 V_FUNCTION("crypto_scalarmult_ed25519_base_noclamp", sn_crypto_scalarmult_ed25519_base_noclamp);
3939 V_FUNCTION("crypto_scalarmult_ed25519_noclamp", sn_crypto_scalarmult_ed25519_noclamp);
3940 V_UINT32("crypto_scalarmult_ed25519_BYTES", crypto_scalarmult_ed25519_BYTES);
3941 V_UINT32("crypto_scalarmult_ed25519_SCALARBYTES", crypto_scalarmult_ed25519_SCALARBYTES);
3942
3943 // crypto_secretbox
3944
3945 V_FUNCTION("crypto_secretbox_easy", sn_crypto_secretbox_easy);
3946 V_FUNCTION("crypto_secretbox_open_easy", sn_crypto_secretbox_open_easy);
3947 V_FUNCTION("crypto_secretbox_detached", sn_crypto_secretbox_detached);
3948 V_FUNCTION("crypto_secretbox_open_detached", sn_crypto_secretbox_open_detached);
3949 V_UINT32("crypto_secretbox_KEYBYTES", crypto_secretbox_KEYBYTES);
3950 V_UINT32("crypto_secretbox_NONCEBYTES", crypto_secretbox_NONCEBYTES);
3951 V_UINT32("crypto_secretbox_MACBYTES", crypto_secretbox_MACBYTES);
3952 V_STRING("crypto_secretbox_PRIMITIVE", crypto_secretbox_PRIMITIVE);
3953
3954 // crypto_secretstream
3955
3956 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_keygen", sn_crypto_secretstream_xchacha20poly1305_keygen);
3957 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_push", sn_crypto_secretstream_xchacha20poly1305_init_push);
3958 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_pull", sn_crypto_secretstream_xchacha20poly1305_init_pull);
3959 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_push", sn_crypto_secretstream_xchacha20poly1305_push);
3960 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_pull", sn_crypto_secretstream_xchacha20poly1305_pull);
3961 V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_rekey", sn_crypto_secretstream_xchacha20poly1305_rekey);
3962
3963 V_UINT32("crypto_secretstream_xchacha20poly1305_STATEBYTES", sizeof(crypto_secretstream_xchacha20poly1305_state));
3964 V_UINT32("crypto_secretstream_xchacha20poly1305_ABYTES", crypto_secretstream_xchacha20poly1305_ABYTES);
3965 V_UINT32("crypto_secretstream_xchacha20poly1305_HEADERBYTES", crypto_secretstream_xchacha20poly1305_HEADERBYTES);
3966 V_UINT32("crypto_secretstream_xchacha20poly1305_KEYBYTES", crypto_secretstream_xchacha20poly1305_KEYBYTES);
3967 V_UINT32("crypto_secretstream_xchacha20poly1305_TAGBYTES", 1);
3968 V_UINT64("crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX", crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX);
3969 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_MESSAGE", crypto_secretstream_xchacha20poly1305_TAG_MESSAGE);
3970 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_PUSH", crypto_secretstream_xchacha20poly1305_TAG_PUSH);
3971 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_REKEY", crypto_secretstream_xchacha20poly1305_TAG_REKEY);
3972 V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_FINAL", crypto_secretstream_xchacha20poly1305_TAG_FINAL);
3973
3974 // crypto_shorthash
3975
3976 V_FUNCTION("crypto_shorthash", sn_crypto_shorthash);
3977 V_UINT32("crypto_shorthash_BYTES", crypto_shorthash_BYTES);
3978 V_UINT32("crypto_shorthash_KEYBYTES", crypto_shorthash_KEYBYTES);
3979 V_STRING("crypto_shorthash_PRIMITIVE", crypto_shorthash_PRIMITIVE);
3980
3981 // crypto_sign
3982
3983 V_FUNCTION("crypto_sign_keypair", sn_crypto_sign_keypair);
3984 V_FUNCTION("crypto_sign_seed_keypair", sn_crypto_sign_seed_keypair);
3985 V_FUNCTION("crypto_sign", sn_crypto_sign);
3986 V_FUNCTION("crypto_sign_open", sn_crypto_sign_open);
3987 V_FUNCTION("crypto_sign_detached", sn_crypto_sign_detached);
3988 V_FUNCTION_NOSCOPE("crypto_sign_verify_detached", sn_crypto_sign_verify_detached);
3989 V_FUNCTION("crypto_sign_ed25519_sk_to_pk", sn_crypto_sign_ed25519_sk_to_pk);
3990 V_FUNCTION("crypto_sign_ed25519_pk_to_curve25519", sn_crypto_sign_ed25519_pk_to_curve25519);
3991 V_FUNCTION("crypto_sign_ed25519_sk_to_curve25519", sn_crypto_sign_ed25519_sk_to_curve25519);
3992
3993 V_UINT32("crypto_sign_SEEDBYTES", crypto_sign_SEEDBYTES);
3994 V_UINT32("crypto_sign_PUBLICKEYBYTES", crypto_sign_PUBLICKEYBYTES);
3995 V_UINT32("crypto_sign_SECRETKEYBYTES", crypto_sign_SECRETKEYBYTES);
3996 V_UINT32("crypto_sign_BYTES", crypto_sign_BYTES);
3997
3998 // crypto_stream
3999
4000 V_FUNCTION("crypto_stream", sn_crypto_stream);
4001 V_UINT32("crypto_stream_KEYBYTES", crypto_stream_KEYBYTES);
4002 V_UINT32("crypto_stream_NONCEBYTES", crypto_stream_NONCEBYTES);
4003 V_STRING("crypto_stream_PRIMITIVE", crypto_stream_PRIMITIVE);
4004
4005 V_FUNCTION_NOSCOPE("crypto_stream_xor", sn_crypto_stream_xor);
4006 V_FUNCTION("crypto_stream_xor_init", sn_crypto_stream_xor_wrap_init);
4007 V_FUNCTION("crypto_stream_xor_update", sn_crypto_stream_xor_wrap_update);
4008 V_FUNCTION("crypto_stream_xor_final", sn_crypto_stream_xor_wrap_final);
4009 V_UINT32("crypto_stream_xor_STATEBYTES", sizeof(sn_crypto_stream_xor_state));
4010
4011 V_FUNCTION("crypto_stream_chacha20", sn_crypto_stream_chacha20);
4012 V_UINT32("crypto_stream_chacha20_KEYBYTES", crypto_stream_chacha20_KEYBYTES);
4013 V_UINT32("crypto_stream_chacha20_NONCEBYTES", crypto_stream_chacha20_NONCEBYTES);
4014 V_UINT64("crypto_stream_chacha20_MESSAGEBYTES_MAX", crypto_stream_chacha20_MESSAGEBYTES_MAX);
4015
4016 V_FUNCTION("crypto_stream_chacha20_xor", sn_crypto_stream_chacha20_xor);
4017 V_FUNCTION("crypto_stream_chacha20_xor_ic", sn_crypto_stream_chacha20_xor_ic);
4018 V_FUNCTION("crypto_stream_chacha20_xor_init", sn_crypto_stream_chacha20_xor_wrap_init);
4019 V_FUNCTION("crypto_stream_chacha20_xor_update", sn_crypto_stream_chacha20_xor_wrap_update);
4020 V_FUNCTION("crypto_stream_chacha20_xor_final", sn_crypto_stream_chacha20_xor_wrap_final);
4021 V_UINT32("crypto_stream_chacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_xor_state));
4022
4023 V_FUNCTION("crypto_stream_chacha20_ietf", sn_crypto_stream_chacha20_ietf);
4024 V_UINT32("crypto_stream_chacha20_ietf_KEYBYTES", crypto_stream_chacha20_ietf_KEYBYTES);
4025 V_UINT32("crypto_stream_chacha20_ietf_NONCEBYTES", crypto_stream_chacha20_ietf_NONCEBYTES);
4026 V_UINT64("crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX", crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX);
4027 V_UINT32("crypto_stream_chacha20_ietf_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_ietf_xor_state));
4028
4029 V_FUNCTION("crypto_stream_chacha20_ietf_xor", sn_crypto_stream_chacha20_ietf_xor);
4030 V_FUNCTION("crypto_stream_chacha20_ietf_xor_ic", sn_crypto_stream_chacha20_ietf_xor_ic);
4031 V_FUNCTION("crypto_stream_chacha20_ietf_xor_init", sn_crypto_stream_chacha20_ietf_xor_wrap_init);
4032 V_FUNCTION("crypto_stream_chacha20_ietf_xor_update", sn_crypto_stream_chacha20_ietf_xor_wrap_update);
4033 V_FUNCTION("crypto_stream_chacha20_ietf_xor_final", sn_crypto_stream_chacha20_ietf_xor_wrap_final);
4034
4035 V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
4036 V_UINT32("crypto_stream_xchacha20_KEYBYTES", crypto_stream_xchacha20_KEYBYTES);
4037 V_UINT32("crypto_stream_xchacha20_NONCEBYTES", crypto_stream_xchacha20_NONCEBYTES);
4038 V_UINT64("crypto_stream_xchacha20_MESSAGEBYTES_MAX", crypto_stream_xchacha20_MESSAGEBYTES_MAX);
4039
4040 V_FUNCTION("crypto_stream_xchacha20_xor", sn_crypto_stream_xchacha20_xor);
4041 V_FUNCTION("crypto_stream_xchacha20_xor_ic", sn_crypto_stream_xchacha20_xor_ic);
4042 V_FUNCTION("crypto_stream_xchacha20_xor_init", sn_crypto_stream_xchacha20_xor_wrap_init);
4043 V_FUNCTION("crypto_stream_xchacha20_xor_update", sn_crypto_stream_xchacha20_xor_wrap_update);
4044 V_FUNCTION("crypto_stream_xchacha20_xor_final", sn_crypto_stream_xchacha20_xor_wrap_final);
4045 V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
4046 V_UINT32("crypto_stream_xchacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_xchacha20_xor_state));
4047
4048 V_FUNCTION("crypto_stream_salsa20", sn_crypto_stream_salsa20);
4049 V_UINT32("crypto_stream_salsa20_KEYBYTES", crypto_stream_salsa20_KEYBYTES);
4050 V_UINT32("crypto_stream_salsa20_NONCEBYTES", crypto_stream_salsa20_NONCEBYTES);
4051 V_UINT64("crypto_stream_salsa20_MESSAGEBYTES_MAX", crypto_stream_salsa20_MESSAGEBYTES_MAX);
4052
4053 V_FUNCTION("crypto_stream_salsa20_xor", sn_crypto_stream_salsa20_xor);
4054 V_FUNCTION("crypto_stream_salsa20_xor_ic", sn_crypto_stream_salsa20_xor_ic);
4055 V_FUNCTION("crypto_stream_salsa20_xor_init", sn_crypto_stream_salsa20_xor_wrap_init);
4056 V_FUNCTION("crypto_stream_salsa20_xor_update", sn_crypto_stream_salsa20_xor_wrap_update);
4057 V_FUNCTION("crypto_stream_salsa20_xor_final", sn_crypto_stream_salsa20_xor_wrap_final);
4058 V_UINT32("crypto_stream_salsa20_xor_STATEBYTES", sizeof(sn_crypto_stream_salsa20_xor_state));
4059
4060 // extensions
4061
4062 // tweak
4063
4064 V_FUNCTION("extension_tweak_ed25519_base", sn_extension_tweak_ed25519_base);
4065 V_FUNCTION("extension_tweak_ed25519_sign_detached", sn_extension_tweak_ed25519_sign_detached);
4066 V_FUNCTION("extension_tweak_ed25519_sk_to_scalar", sn_extension_tweak_ed25519_sk_to_scalar);
4067 V_FUNCTION("extension_tweak_ed25519_scalar", sn_extension_tweak_ed25519_scalar);
4068 V_FUNCTION("extension_tweak_ed25519_pk", sn_extension_tweak_ed25519_pk);
4069 V_FUNCTION("extension_tweak_ed25519_keypair", sn_extension_tweak_ed25519_keypair);
4070 V_FUNCTION("extension_tweak_ed25519_scalar_add", sn_extension_tweak_ed25519_scalar_add);
4071 V_FUNCTION("extension_tweak_ed25519_pk_add", sn_extension_tweak_ed25519_pk_add);
4072 V_FUNCTION("extension_tweak_ed25519_keypair_add", sn_extension_tweak_ed25519_keypair_add);
4073 V_UINT32("extension_tweak_ed25519_BYTES", sn__extension_tweak_ed25519_BYTES);
4074 V_UINT32("extension_tweak_ed25519_SCALARBYTES", sn__extension_tweak_ed25519_SCALARBYTES);
4075
4076 // pbkdf2
4077
4078 V_FUNCTION("extension_pbkdf2_sha512", sn_extension_pbkdf2_sha512);
4079 V_FUNCTION("extension_pbkdf2_sha512_async", sn_extension_pbkdf2_sha512_async);
4080 V_UINT32("extension_pbkdf2_sha512_SALTBYTES", sn__extension_pbkdf2_sha512_SALTBYTES);
4081 V_UINT32("extension_pbkdf2_sha512_HASHBYTES", sn__extension_pbkdf2_sha512_HASHBYTES);
4082 V_UINT32("extension_pbkdf2_sha512_ITERATIONS_MIN", sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
4083 V_UINT64("extension_pbkdf2_sha512_BYTES_MAX", sn__extension_pbkdf2_sha512_BYTES_MAX);
4084
4085#undef V_FUNCTION
4086#undef V_FUNCTION_NOSCOPE
4087#undef V_UINT32
4088#undef V_UINT64
4089#undef V_STRING
4090
4091 return exports;
4092}
4093
4094BARE_MODULE(sodium_native, sodium_native_exports)
node_modules/sodium-secretstream/node_modules/sodium-native/binding.js +2 -0
……@@ -0,0 +1,2 @@
1require.addon = require('require-addon')
2module.exports = require.addon('.', __filename)
node_modules/sodium-secretstream/node_modules/sodium-native/extensions/pbkdf2/pbkdf2.c +90 -0
……@@ -0,0 +1,90 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
29 */
30
31#include <string.h>
32#include <sodium.h>
33
34#include "pbkdf2.h"
35
36/**
37 * pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
38 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
39 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
40 */
41int
42sn__extension_pbkdf2_sha512(const unsigned char *passwd, size_t passwdlen,
43 const unsigned char *salt, size_t saltlen, uint64_t c,
44 unsigned char *buf, size_t dkLen)
45{
46 crypto_auth_hmacsha512_state PShctx, hctx;
47 size_t i;
48 unsigned char ivec[4];
49 unsigned char U[64];
50 unsigned char T[64];
51 uint64_t j;
52 unsigned int k;
53 size_t clen;
54
55 if (dkLen > sn__extension_pbkdf2_sha512_BYTES_MAX) {
56 return -1;
57 }
58
59 crypto_auth_hmacsha512_init(&PShctx, passwd, passwdlen);
60 crypto_auth_hmacsha512_update(&PShctx, salt, saltlen);
61
62 for (i = 0; i * crypto_auth_hmacsha512_BYTES < dkLen; i++) {
63 SN_PBKDF2_STORE32_BE(ivec, (uint32_t)(i + 1));
64 memcpy(&hctx, &PShctx, sizeof(crypto_auth_hmacsha512_state));
65 crypto_auth_hmacsha512_update(&hctx, ivec, 4);
66 crypto_auth_hmacsha512_final(&hctx, U);
67
68 memcpy(T, U, crypto_auth_hmacsha512_BYTES);
69 /* LCOV_EXCL_START */
70 for (j = 2; j <= c; j++) {
71 crypto_auth_hmacsha512_init(&hctx, passwd, passwdlen);
72 crypto_auth_hmacsha512_update(&hctx, U, crypto_auth_hmacsha512_BYTES);
73 crypto_auth_hmacsha512_final(&hctx, U);
74
75 for (k = 0; k < crypto_auth_hmacsha512_BYTES; k++) {
76 T[k] ^= U[k];
77 }
78 }
79 /* LCOV_EXCL_STOP */
80
81 clen = dkLen - i * crypto_auth_hmacsha512_BYTES;
82 if (clen > crypto_auth_hmacsha512_BYTES) {
83 clen = crypto_auth_hmacsha512_BYTES;
84 }
85 memcpy(&buf[i * crypto_auth_hmacsha512_BYTES], T, clen);
86 }
87 sodium_memzero((void *) &PShctx, sizeof PShctx);
88
89 return 0;
90}
node_modules/sodium-secretstream/node_modules/sodium-native/extensions/pbkdf2/pbkdf2.h +60 -0
……@@ -0,0 +1,60 @@
1/*-
2 * Copyright 2005,2007,2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28/*
29 * Adapted from libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf-sha256.c
30 */
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35#include <sodium.h>
36
37#define SN_PBKDF2_STORE32_BE(buf, n32) \
38 buf[0] = n32 >> 24 & 0xff; \
39 buf[1] = n32 >> 16 & 0xff; \
40 buf[2] = n32 >> 8 & 0xff; \
41 buf[3] = n32 >> 0 & 0xff;
42
43#define sn__extension_pbkdf2_sha512_SALTBYTES 16U
44
45#define sn__extension_pbkdf2_sha512_HASHBYTES crypto_hash_sha512_BYTES
46
47#define sn__extension_pbkdf2_sha512_ITERATIONS_MIN 1U
48
49#define sn__extension_pbkdf2_sha512_BYTES_MAX 0x3fffffffc0ULL
50
51/**
52 * extension_pbkdf2_sha512(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
53 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
54 * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
55 */
56int sn__extension_pbkdf2_sha512(const unsigned char *, size_t, const unsigned char *, size_t,
57 uint64_t, unsigned char *, size_t);
58#ifdef __cplusplus
59};
60#endif
node_modules/sodium-secretstream/node_modules/sodium-native/extensions/tweak/tweak.c +206 -0
……@@ -0,0 +1,206 @@
1#include "tweak.h"
2
3/*
4 *EXPERIMENTAL API*
5
6 This module is an experimental implementation of a key tweaking protocol
7 over ed25519 keys. The signature algorithm has been reimplemented from
8 libsodium, but the nonce generation algorithm is *non-standard*.
9
10 Use at your own risk
11*/
12
13static void _extension_tweak_nonce (unsigned char *nonce, const unsigned char *n,
14 const unsigned char *m, unsigned long long mlen)
15{
16 // dom2(x, y) with x = 0 (not prehashed) and y = "crypto_tweak_ed25519"
17 static const unsigned char TWEAK_PREFIX[32 + 2 + 20] = {
18 'S', 'i', 'g', 'E', 'd', '2', '5', '5', '1', '9', ' ',
19 'n', 'o', ' ', 'E', 'd', '2', '5', '5', '1', '9', ' ',
20 'c', 'o', 'l', 'l', 'i', 's', 'i', 'o', 'n', 's', 0,
21 20, 'c', 'r', 'y', 'p', 't', 'o', '_', 't', 'w', 'e',
22 'a', 'k', '_', 'e', 'd', '2', '5', '5', '1', '9'
23 };
24
25 crypto_hash_sha512_state hs;
26
27 crypto_hash_sha512_init(&hs);
28 crypto_hash_sha512_update(&hs, TWEAK_PREFIX, sizeof TWEAK_PREFIX);
29 crypto_hash_sha512_update(&hs, n, 32);
30 crypto_hash_sha512_update(&hs, m, mlen);
31 crypto_hash_sha512_final(&hs, nonce);
32}
33
34static inline void
35_crypto_sign_ed25519_clamp(unsigned char k[32])
36{
37 k[0] &= 248;
38 k[31] &= 127;
39 k[31] |= 64;
40}
41
42static void _extension_tweak_ed25519(unsigned char *q, unsigned char *n,
43 const unsigned char *ns, unsigned long long nslen)
44{
45 sodium_memzero(q, sizeof q);
46
47 crypto_hash(n, ns, nslen);
48 n[31] &= 127; // clear highest bit
49
50 crypto_scalarmult_ed25519_base_noclamp(q, n);
51
52 // hash tweak until we get a valid tweaked q
53 while (crypto_core_ed25519_is_valid_point(q) != 1) {
54 crypto_hash(n, n, 32);
55 n[31] &= 127; // clear highest bit
56
57 crypto_scalarmult_ed25519_base_noclamp(q, n);
58 }
59}
60
61void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
62 const unsigned char *ns, unsigned long long nslen)
63{
64 unsigned char n64[64];
65
66 _extension_tweak_ed25519(pk, n64, ns, nslen);
67
68 SN_TWEAK_COPY_32(scalar, n64)
69}
70
71int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
72 const unsigned char *m, unsigned long long mlen,
73 const unsigned char *n, unsigned char *pk)
74{
75 crypto_hash_sha512_state hs;
76
77 unsigned char nonce[64];
78 unsigned char R[32];
79 unsigned char hram[64];
80 unsigned char _pk[32];
81
82 // check if pk was passed
83 if (pk == NULL) {
84 pk = _pk;
85
86 // derive pk from scalar
87 if (crypto_scalarmult_ed25519_base_noclamp(pk, n) != 0) {
88 return -1;
89 }
90 }
91
92 _extension_tweak_nonce(nonce, n, m, mlen);
93 crypto_core_ed25519_scalar_reduce(nonce, nonce);
94
95 // R = G ^ nonce : curve point from nonce
96 if (crypto_scalarmult_ed25519_base_noclamp(R, nonce) != 0) {
97 return -1;
98 }
99
100 // generate challenge as h(ram) = hash(R, pk, message)
101 crypto_hash_sha512_init(&hs);
102 crypto_hash_sha512_update(&hs, R, 32);
103 crypto_hash_sha512_update(&hs, pk, 32);
104 crypto_hash_sha512_update(&hs, m, mlen);
105
106 crypto_hash_sha512_final(&hs, hram);
107
108 crypto_core_ed25519_scalar_reduce(hram, hram);
109
110 // sig = nonce + n * h(ram)
111 crypto_core_ed25519_scalar_mul(sig, hram, n);
112 crypto_core_ed25519_scalar_add(sig + 32, nonce, sig);
113
114 SN_TWEAK_COPY_32(sig, R)
115
116 if (siglen_p != NULL) {
117 *siglen_p = 64U;
118 }
119
120 return 0;
121}
122
123// tweak a secret key
124void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *n, const unsigned char *sk)
125{
126 unsigned char n64[64];
127
128 // get sk scalar from seed, cf. crypto_sign_keypair_seed
129 crypto_hash(n64, sk, 32);
130 _crypto_sign_ed25519_clamp(n64);
131
132 SN_TWEAK_COPY_32(n, n64)
133}
134
135// tweak a secret key
136void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
137 const unsigned char *scalar,
138 const unsigned char *ns,
139 unsigned long long nslen)
140{
141 unsigned char n[64];
142 unsigned char q[32];
143
144 _extension_tweak_ed25519(q, n, ns, nslen);
145 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
146}
147
148// tweak a public key
149int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
150 const unsigned char *pk,
151 const unsigned char *ns,
152 unsigned long long nslen)
153{
154 unsigned char n[64];
155 unsigned char q[32];
156
157 _extension_tweak_ed25519(q, n, ns, nslen);
158 return crypto_core_ed25519_add(tpk, q, pk);
159}
160
161
162void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
163 unsigned char *scalar, const unsigned char *ns,
164 unsigned long long nslen)
165{
166 unsigned char n64[64];
167
168 crypto_hash(n64, ns, nslen);
169 n64[31] &= 127; // clear highest bit
170
171 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
172 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
173
174 // hash tweak until we get a valid tweaked point
175 while (crypto_core_ed25519_is_valid_point(pk) != 1) {
176 crypto_hash(n64, n64, 32);
177 n64[31] &= 127; // clear highest bit
178
179 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, n64);
180 crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
181 }
182}
183
184// add tweak to scalar
185void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
186 const unsigned char *scalar,
187 const unsigned char *n)
188{
189 crypto_core_ed25519_scalar_add(scalar_out, scalar, n);
190}
191
192// add tweak point to public key
193int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
194 const unsigned char *pk,
195 const unsigned char *q)
196{
197 return crypto_core_ed25519_add(tpk, pk, q);
198}
199
200
201int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
202 unsigned char *scalar, const unsigned char *tweak)
203{
204 sn__extension_tweak_ed25519_scalar_add(scalar_out, scalar, tweak);
205 return crypto_scalarmult_ed25519_base_noclamp(pk, scalar_out);
206}
node_modules/sodium-secretstream/node_modules/sodium-native/extensions/tweak/tweak.h +62 -0
……@@ -0,0 +1,62 @@
1#ifdef __cplusplus
2extern "C" {
3#endif
4
5#include <sodium.h>
6
7// copy 32 bytes using int64_t pointers
8#define SN_TWEAK_COPY_32(a, b) \
9 { \
10 long long *dst = (long long *) a; \
11 long long *src = (long long *) b; \
12 dst[0] = src[0]; \
13 dst[1] = src[1]; \
14 dst[2] = src[2]; \
15 dst[3] = src[3]; \
16 }
17
18#define sn__extension_tweak_ed25519_BYTES crypto_sign_ed25519_PUBLICKEYBYTES
19
20#define sn__extension_tweak_ed25519_SCALARBYTES crypto_scalarmult_ed25519_SCALARBYTES
21
22int sn__extension_tweak_ed25519_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
23 const unsigned char *m, unsigned long long mlen,
24 const unsigned char *n, unsigned char *pk);
25
26void sn__extension_tweak_ed25519_base(unsigned char *pk, unsigned char *scalar,
27 const unsigned char *ns, unsigned long long nslen);
28
29void sn__extension_tweak_ed25519_sk_to_scalar(unsigned char *scalar, const unsigned char *sk);
30
31// tweak a secret key
32void sn__extension_tweak_ed25519_scalar(unsigned char *scalar_out,
33 const unsigned char *scalar,
34 const unsigned char *ns,
35 unsigned long long nslen);
36
37// tweak a public key
38int sn__extension_tweak_ed25519_pk(unsigned char *tpk,
39 const unsigned char *pk,
40 const unsigned char *ns,
41 unsigned long long nslen);
42
43void sn__extension_tweak_ed25519_keypair(unsigned char *pk, unsigned char *scalar_out,
44 unsigned char *scalar, const unsigned char *ns,
45 unsigned long long nslen);
46
47// add tweak scalar to private key
48void sn__extension_tweak_ed25519_scalar_add(unsigned char *scalar_out,
49 const unsigned char *scalar,
50 const unsigned char *n);
51
52// add tweak point to public key
53int sn__extension_tweak_ed25519_pk_add(unsigned char *tpk,
54 const unsigned char *pk,
55 const unsigned char *q);
56
57int sn__extension_tweak_ed25519_keypair_add(unsigned char *pk, unsigned char *scalar_out,
58 unsigned char *scalar, const unsigned char *tweak);
59
60#ifdef __cplusplus
61};
62#endif
node_modules/sodium-secretstream/node_modules/sodium-native/index.js +3231 -0
……@@ -0,0 +1,3231 @@
1const assert = require('assert')
2const binding = require('./binding')
3const { isNode } = require('which-runtime')
4
5const OPTIONAL = Buffer.from(new ArrayBuffer(0))
6
7module.exports = exports = { ...binding }
8
9// memory
10
11exports.sodium_memzero = function (buf) {
12 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
13
14 binding.sodium_memzero(buf)
15}
16
17exports.sodium_mlock = function (buf) {
18 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
19
20 const res = binding.sodium_mlock(buf)
21
22 if (res !== 0) throw new Error('memory lock failed')
23}
24
25exports.sodium_munlock = function (buf) {
26 assert(ArrayBuffer.isView(buf), 'buf must be a typed array')
27
28 const res = binding.sodium_munlock(buf)
29
30 if (res !== 0) throw new Error('memory unlock failed')
31}
32
33exports.sodium_malloc = function (size) {
34 assert(size >= 0, 'invalid size')
35
36 const buf = Buffer.from(binding.sodium_malloc(size))
37 buf.secure = true
38 return buf
39}
40
41exports.sodium_free = function (buf) {
42 if (!buf || !buf.secure) return
43
44 binding.sodium_free(buf.buffer)
45}
46
47exports.sodium_mprotect_noaccess = function (buf) {
48 const res = binding.sodium_mprotect_noaccess(buf.buffer)
49
50 if (res !== 0) throw new Error('failed to lock buffer')
51}
52
53exports.sodium_mprotect_readonly = function (buf) {
54 const res = binding.sodium_mprotect_readonly(buf.buffer)
55
56 if (res !== 0) throw new Error('failed to unlock buffer')
57}
58
59exports.sodium_mprotect_readwrite = function (buf) {
60 const res = binding.sodium_mprotect_readwrite(buf.buffer)
61
62 if (res !== 0) throw new Error('failed to unlock buffer')
63}
64
65// crypto_randombytes
66
67exports.randombytes_buf = function (buffer) {
68 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
69
70 binding.randombytes_buf(buffer.buffer, buffer.byteOffset, buffer.byteLength)
71}
72
73exports.randombytes_buf_deterministic = function (buffer, seed) {
74 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
75 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
76 assert(
77 seed.byteLength === binding.randombytes_SEEDBYTES,
78 "seed must be 'randombytes_SEEDBYTES' bytes"
79 )
80
81 binding.randombytes_buf_deterministic(
82 buffer.buffer,
83 buffer.byteOffset,
84 buffer.byteLength,
85
86 seed.buffer,
87 seed.byteOffset,
88 seed.byteLength
89 )
90}
91
92// sodium_helpers
93
94exports.sodium_memcmp = function (a, b) {
95 assert(ArrayBuffer.isView(a), 'a must be a typed array')
96 assert(ArrayBuffer.isView(b), 'b must be a typed array')
97 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
98
99 return binding.sodium_memcmp(a, b)
100}
101
102exports.sodium_add = function (a, b) {
103 assert(ArrayBuffer.isView(a), 'a must be a typed array')
104 assert(ArrayBuffer.isView(b), 'b must be a typed array')
105 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
106
107 binding.sodium_add(a, b)
108}
109
110exports.sodium_sub = function (a, b) {
111 assert(ArrayBuffer.isView(a), 'a must be a typed array')
112 assert(ArrayBuffer.isView(b), 'b must be a typed array')
113 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
114
115 binding.sodium_sub(a, b)
116}
117
118exports.sodium_compare = function (a, b) {
119 assert(ArrayBuffer.isView(a), 'a must be a typed array')
120 assert(ArrayBuffer.isView(b), 'b must be a typed array')
121 assert(a.byteLength === b.byteLength, 'buffers must be of same length')
122
123 return binding.sodium_compare(a, b)
124}
125
126exports.sodium_is_zero = function (buffer, length) {
127 if (length === undefined) length = buffer.byteLength
128
129 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
130 assert(length >= 0 && length <= buffer.byteLength, 'invalid length')
131
132 return binding.sodium_is_zero(buffer, length)
133}
134
135exports.sodium_pad = function (buffer, unpaddedBuflen, blockSize) {
136 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
137 assert(unpaddedBuflen <= buffer.byteLength, 'unpadded length cannot exceed buffer length')
138 assert(blockSize <= buffer.byteLength, 'block size cannot exceed buffer length')
139 assert(blockSize >= 1, 'block size must be at least 1 byte')
140 assert(
141 buffer.byteLength >= unpaddedBuflen + (blockSize - (unpaddedBuflen % blockSize)),
142 'buf not long enough'
143 )
144
145 return binding.sodium_pad(buffer, unpaddedBuflen, blockSize)
146}
147
148exports.sodium_unpad = function (buffer, paddedBuflen, blockSize) {
149 assert(ArrayBuffer.isView(buffer), 'buffer must be a typed array')
150 assert(paddedBuflen <= buffer.byteLength, 'unpadded length cannot exceed buffer length')
151 assert(blockSize <= buffer.byteLength, 'block size cannot exceed buffer length')
152 assert(blockSize >= 1, 'block size must be at least 1 byte')
153
154 return binding.sodium_unpad(buffer, paddedBuflen, blockSize)
155}
156
157// crypto_sign
158
159exports.crypto_sign_keypair = function (pk, sk) {
160 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
161 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
162 assert(
163 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
164 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
165 )
166 assert(
167 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
168 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
169 )
170
171 const res = binding.crypto_sign_keypair(pk, sk)
172
173 if (res !== 0) throw new Error('status: ' + res)
174}
175
176exports.crypto_sign_seed_keypair = function (pk, sk, seed) {
177 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
178 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
179 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
180 assert(
181 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
182 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
183 )
184 assert(
185 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
186 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
187 )
188 assert(
189 seed.byteLength === binding.crypto_sign_SEEDBYTES,
190 "seed must be 'crypto_sign_SEEDBYTES' bytes"
191 )
192
193 const res = binding.crypto_sign_seed_keypair(pk, sk, seed)
194
195 if (res !== 0) throw new Error('status: ' + res)
196}
197
198exports.crypto_sign = function (sm, m, sk) {
199 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
200 assert(ArrayBuffer.isView(m), 'm must be a typed array')
201 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
202 assert(
203 sm.byteLength === binding.crypto_sign_BYTES + m.byteLength,
204 "sm must be 'm.byteLength + crypto_sign_BYTES' bytes"
205 )
206 assert(
207 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
208 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
209 )
210
211 const res = binding.crypto_sign(sm, m, sk)
212
213 if (res !== 0) throw new Error('status: ' + res)
214}
215
216exports.crypto_sign_open = function (m, sm, pk) {
217 assert(ArrayBuffer.isView(m), 'm must be a typed array')
218 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
219 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
220 assert(
221 sm.byteLength >= binding.crypto_sign_BYTES,
222 "sm must be at least 'crypto_sign_BYTES' bytes"
223 )
224 assert(
225 m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
226 "m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
227 )
228 assert(
229 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
230 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
231 )
232
233 const res = binding.crypto_sign_open(m, sm, pk)
234
235 if (res !== 0) throw new Error('status: ' + res)
236}
237
238exports.crypto_sign_open = function (m, sm, pk) {
239 assert(ArrayBuffer.isView(m), 'm must be a typed array')
240 assert(ArrayBuffer.isView(sm), 'sm must be a typed array')
241 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
242 assert(
243 sm.byteLength >= binding.crypto_sign_BYTES,
244 "sm must be at least 'crypto_sign_BYTES' bytes"
245 )
246 assert(
247 m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
248 "m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
249 )
250 assert(
251 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
252 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
253 )
254
255 return binding.crypto_sign_open(m, sm, pk)
256}
257
258exports.crypto_sign_detached = function (sig, m, sk) {
259 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
260 assert(ArrayBuffer.isView(m), 'm must be a typed array')
261 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
262 assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes")
263 assert(
264 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
265 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
266 )
267
268 const res = binding.crypto_sign_detached(sig, m, sk)
269
270 if (res !== 0) throw new Error('status: ' + res)
271}
272
273exports.crypto_sign_verify_detached = function (sig, m, pk) {
274 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
275 assert(ArrayBuffer.isView(m), 'm must be a typed array')
276 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
277 assert(
278 sig.byteLength >= binding.crypto_sign_BYTES,
279 "sig must be at least 'crypto_sign_BYTES' bytes"
280 )
281 assert(
282 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
283 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
284 )
285
286 return binding.crypto_sign_verify_detached(
287 sig.buffer,
288 sig.byteOffset,
289 sig.byteLength,
290
291 m.buffer,
292 m.byteOffset,
293 m.byteLength,
294
295 pk.buffer,
296 pk.byteOffset,
297 pk.byteLength
298 )
299}
300
301exports.crypto_sign_ed25519_sk_to_pk = function (pk, sk) {
302 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
303 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
304 assert(
305 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
306 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
307 )
308 assert(
309 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
310 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
311 )
312
313 const res = binding.crypto_sign_ed25519_sk_to_pk(pk, sk)
314
315 if (res !== 0) throw new Error('status: ' + res)
316}
317
318exports.crypto_sign_ed25519_pk_to_curve25519 = function (x25519pk, ed25519pk) {
319 assert(ArrayBuffer.isView(x25519pk), 'x25519pk must be a typed array')
320 assert(ArrayBuffer.isView(ed25519pk), 'ed25519pk must be a typed array')
321 assert(
322 x25519pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
323 "x25519pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
324 )
325 assert(
326 ed25519pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
327 "ed25519pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
328 )
329
330 const res = binding.crypto_sign_ed25519_pk_to_curve25519(x25519pk, ed25519pk)
331
332 if (res !== 0) throw new Error('status: ' + res)
333}
334
335exports.crypto_sign_ed25519_sk_to_curve25519 = function (x25519sk, ed25519sk) {
336 assert(ArrayBuffer.isView(x25519sk), 'x25519sk must be a typed array')
337 assert(ArrayBuffer.isView(ed25519sk), 'ed25519sk must be a typed array')
338 assert(
339 x25519sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
340 "x25519sk must be 'crypto_box_SECRETKEYBYTES' bytes"
341 )
342
343 const edLen = ed25519sk.byteLength
344
345 assert(
346 edLen === binding.crypto_sign_SECRETKEYBYTES || edLen === binding.crypto_box_SECRETKEYBYTES,
347 "ed25519sk must be 'crypto_sign_SECRETKEYBYTES' or 'crypto_sign_SECRETKEYBYTES - crypto_sign_PUBLICKEYBYTES' bytes"
348 )
349
350 const res = binding.crypto_sign_ed25519_sk_to_curve25519(x25519sk, ed25519sk)
351
352 if (res !== 0) throw new Error('status: ' + res)
353}
354
355// crypto_box
356
357exports.crypto_box_keypair = function (pk, sk) {
358 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
359 assert(
360 pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
361 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
362 )
363 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
364 assert(
365 sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
366 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
367 )
368
369 const res = binding.crypto_box_keypair(pk, sk)
370
371 if (res !== 0) throw new Error('status: ' + res)
372}
373
374exports.crypto_box_seed_keypair = function (pk, sk, seed) {
375 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
376 assert(
377 pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
378 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
379 )
380 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
381 assert(
382 sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
383 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
384 )
385 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
386 assert(
387 seed.byteLength === binding.crypto_box_SEEDBYTES,
388 "seed must be 'crypto_box_SEEDBYTES' bytes"
389 )
390
391 const res = binding.crypto_box_seed_keypair(pk, sk, seed)
392
393 if (res !== 0) throw new Error('status: ' + res)
394}
395
396exports.crypto_box_easy = function (c, m, n, pk, sk) {
397 assert(ArrayBuffer.isView(c), 'c must be a typed array')
398 assert(ArrayBuffer.isView(m), 'm must be a typed array')
399 assert(ArrayBuffer.isView(n), 'n must be a typed array')
400 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
401 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
402 assert(
403 c.byteLength === m.byteLength + exports.crypto_box_MACBYTES,
404 "c must be 'm.byteLength + crypto_box_MACBYTES' bytes"
405 )
406 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
407 assert(
408 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
409 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
410 )
411 assert(
412 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
413 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
414 )
415
416 const res = binding.crypto_box_easy(c, m, n, pk, sk)
417
418 if (res !== 0) throw new Error('status: ' + res)
419}
420
421exports.crypto_box_detached = function (c, mac, m, n, pk, sk) {
422 assert(ArrayBuffer.isView(c), 'c must be a typed array')
423 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
424 assert(ArrayBuffer.isView(m), 'm must be a typed array')
425 assert(ArrayBuffer.isView(n), 'n must be a typed array')
426 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
427 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
428 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
429 assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes")
430 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
431 assert(
432 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
433 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
434 )
435 assert(
436 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
437 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
438 )
439
440 const res = binding.crypto_box_detached(c, mac, m, n, pk, sk)
441
442 if (res !== 0) throw new Error('status: ' + res)
443}
444
445exports.crypto_box_open_easy = function (m, c, n, pk, sk) {
446 assert(ArrayBuffer.isView(m), 'm must be a typed array')
447 assert(ArrayBuffer.isView(c), 'c must be a typed array')
448 assert(ArrayBuffer.isView(n), 'n must be a typed array')
449 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
450 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
451 assert(
452 c.byteLength >= exports.crypto_box_MACBYTES,
453 "c must be at least 'crypto_box_MACBYTES' bytes"
454 )
455 assert(
456 m.byteLength === c.byteLength - exports.crypto_box_MACBYTES,
457 "m must be 'c.byteLength - crypto_box_MACBYTES' bytes"
458 )
459 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
460 assert(
461 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
462 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
463 )
464 assert(
465 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
466 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
467 )
468
469 return binding.crypto_box_open_easy(m, c, n, pk, sk)
470}
471
472exports.crypto_box_open_detached = function (m, c, mac, n, pk, sk) {
473 assert(ArrayBuffer.isView(m), 'm must be a typed array')
474 assert(ArrayBuffer.isView(c), 'c must be a typed array')
475 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
476 assert(ArrayBuffer.isView(n), 'n must be a typed array')
477 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
478 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
479 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
480 assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes")
481 assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes")
482 assert(
483 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
484 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
485 )
486 assert(
487 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
488 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
489 )
490
491 return binding.crypto_box_open_detached(m, c, mac, n, pk, sk)
492}
493
494exports.crypto_box_seal = function (c, m, pk) {
495 assert(ArrayBuffer.isView(c), 'c must be a typed array')
496 assert(ArrayBuffer.isView(m), 'm must be a typed array')
497 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
498 assert(
499 c.byteLength === m.byteLength + exports.crypto_box_SEALBYTES,
500 "c must be 'm.byteLength + crypto_box_SEALBYTES' bytes"
501 )
502 assert(
503 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
504 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
505 )
506
507 const res = binding.crypto_box_seal(c, m, pk)
508
509 if (res !== 0) throw new Error('status: ' + res)
510}
511
512exports.crypto_box_seal_open = function (m, c, pk, sk) {
513 assert(ArrayBuffer.isView(m), 'm must be a typed array')
514 assert(ArrayBuffer.isView(c), 'c must be a typed array')
515 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
516 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
517 assert(
518 c.byteLength >= exports.crypto_box_SEALBYTES,
519 "c must be at least 'crypto_box_SEALBYTES' bytes"
520 )
521 assert(
522 m.byteLength === c.byteLength - exports.crypto_box_SEALBYTES,
523 "m must be 'c.byteLength - crypto_box_SEALBYTES' bytes"
524 )
525 assert(
526 pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
527 "pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
528 )
529 assert(
530 sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
531 "sk must be 'crypto_box_SECRETKEYBYTES' bytes"
532 )
533
534 return binding.crypto_box_seal_open(
535 m.buffer,
536 m.byteOffset,
537 m.byteLength,
538
539 c.buffer,
540 c.byteOffset,
541 c.byteLength,
542
543 pk.buffer,
544 pk.byteOffset,
545 pk.byteLength,
546
547 sk.buffer,
548 sk.byteOffset,
549 sk.byteLength
550 )
551}
552
553// crypto_secretbox
554
555exports.crypto_secretbox_easy = function (c, m, n, k) {
556 assert(ArrayBuffer.isView(c), 'c must be a typed array')
557 assert(ArrayBuffer.isView(m), 'm must be a typed array')
558 assert(ArrayBuffer.isView(n), 'n must be a typed array')
559 assert(ArrayBuffer.isView(k), 'k must be a typed array')
560 assert(
561 c.byteLength === m.byteLength + binding.crypto_secretbox_MACBYTES,
562 "c must be 'm.byteLength + crypto_secretbox_MACBYTES' bytes"
563 )
564 assert(
565 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
566 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
567 )
568 assert(
569 k.byteLength === binding.crypto_secretbox_KEYBYTES,
570 "k must be 'crypto_secretbox_KEYBYTES' bytes"
571 )
572
573 const res = binding.crypto_secretbox_easy(c, m, n, k)
574
575 if (res !== 0) throw new Error('status: ' + res)
576}
577
578exports.crypto_secretbox_open_easy = function (m, c, n, k) {
579 assert(ArrayBuffer.isView(m), 'm must be a typed array')
580 assert(ArrayBuffer.isView(c), 'c must be a typed array')
581 assert(ArrayBuffer.isView(n), 'n must be a typed array')
582 assert(ArrayBuffer.isView(k), 'k must be a typed array')
583 assert(
584 c.byteLength >= binding.crypto_secretbox_MACBYTES,
585 "c must be at least 'crypto_secretbox_MACBYTES' bytes"
586 )
587 assert(
588 m.byteLength === c.byteLength - binding.crypto_secretbox_MACBYTES,
589 "m must be 'c.byteLength - crypto_secretbox_MACBYTES' bytes"
590 )
591 assert(
592 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
593 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
594 )
595 assert(
596 k.byteLength === binding.crypto_secretbox_KEYBYTES,
597 "k must be 'crypto_secretbox_KEYBYTES' bytes"
598 )
599
600 return binding.crypto_secretbox_open_easy(m, c, n, k)
601}
602
603exports.crypto_secretbox_detached = function (c, mac, m, n, k) {
604 assert(ArrayBuffer.isView(c), 'c must be a typed array')
605 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
606 assert(ArrayBuffer.isView(m), 'm must be a typed array')
607 assert(ArrayBuffer.isView(n), 'n must be a typed array')
608 assert(ArrayBuffer.isView(k), 'k must be a typed array')
609 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
610 assert(
611 mac.byteLength === binding.crypto_secretbox_MACBYTES,
612 "mac must be 'crypto_secretbox_MACBYTES' bytes"
613 )
614 assert(
615 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
616 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
617 )
618 assert(
619 k.byteLength === binding.crypto_secretbox_KEYBYTES,
620 "k must be 'crypto_secretbox_KEYBYTES' bytes"
621 )
622
623 const res = binding.crypto_secretbox_detached(c, mac, m, n, k)
624
625 if (res !== 0) throw new Error('status: ' + res)
626}
627
628exports.crypto_secretbox_open_detached = function (m, c, mac, n, k) {
629 assert(ArrayBuffer.isView(m), 'm must be a typed array')
630 assert(ArrayBuffer.isView(c), 'c must be a typed array')
631 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
632 assert(ArrayBuffer.isView(n), 'n must be a typed array')
633 assert(ArrayBuffer.isView(k), 'k must be a typed array')
634 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
635 assert(
636 mac.byteLength === binding.crypto_secretbox_MACBYTES,
637 "mac must be 'crypto_secretbox_MACBYTES' bytes"
638 )
639 assert(
640 n.byteLength === binding.crypto_secretbox_NONCEBYTES,
641 "n must be 'crypto_secretbox_NONCEBYTES' bytes"
642 )
643 assert(
644 k.byteLength === binding.crypto_secretbox_KEYBYTES,
645 "k must be 'crypto_secretbox_KEYBYTES' bytes"
646 )
647
648 return binding.crypto_secretbox_open_detached(m, c, mac, n, k)
649}
650
651// crypto_generichash
652
653exports.crypto_generichash = function (output, input, key) {
654 if (!key) key = OPTIONAL
655
656 assert(ArrayBuffer.isView(output), 'output must be a typed array')
657 assert(ArrayBuffer.isView(input), 'input must be a typed array')
658 assert(
659 output.byteLength >= binding.crypto_generichash_BYTES_MIN &&
660 output.byteLength <= binding.crypto_generichash_BYTES_MAX,
661 'output must be between crypto_generichash_BYTES_MIN and crypto_generichash_BYTES_MAX bytes'
662 )
663
664 if (key !== OPTIONAL) {
665 assert(ArrayBuffer.isView(key), 'key must be a typed array')
666 assert(
667 key.byteLength >= binding.crypto_generichash_KEYBYTES_MIN &&
668 key.byteLength <= binding.crypto_generichash_KEYBYTES_MAX,
669 'key must be between crypto_generichash_KEYBYTES_MIN and crypto_generichash_KEYBYTES_MAX bytes'
670 )
671 }
672
673 const res = binding.crypto_generichash(
674 output.buffer,
675 output.byteOffset,
676 output.byteLength,
677
678 input.buffer,
679 input.byteOffset,
680 input.byteLength,
681
682 key.buffer,
683 key.byteOffset,
684 key.byteLength
685 )
686
687 if (res !== 0) throw new Error('status: ' + res)
688}
689
690exports.crypto_generichash_batch = function (output, batch, key) {
691 assert(ArrayBuffer.isView(output), 'output must be a typed array')
692
693 if (isNode || batch.length < 4) {
694 const res = binding.crypto_generichash_batch(output, batch, !!key, key || OPTIONAL)
695 if (res !== 0) throw new Error('status: ' + res)
696 } else {
697 const state = Buffer.alloc(binding.crypto_generichash_STATEBYTES)
698
699 exports.crypto_generichash_init(state, key, output.byteLength)
700
701 for (const buf of batch) {
702 exports.crypto_generichash_update(state, buf)
703 }
704
705 exports.crypto_generichash_final(state, output)
706 }
707}
708
709exports.crypto_generichash_keygen = function (key) {
710 assert(ArrayBuffer.isView(key), 'key must be a typed array')
711 assert(
712 key.byteLength === binding.crypto_generichash_KEYBYTES,
713 "key must be 'crypto_generichash_KEYBYTES' bytes"
714 )
715
716 const res = binding.crypto_generichash_keygen(key.buffer, key.byteOffset, key.byteLength)
717
718 if (res !== 0) throw new Error('status: ' + res)
719}
720
721exports.crypto_generichash_init = function (state, key, outputLength) {
722 if (!key) key = OPTIONAL
723
724 assert(ArrayBuffer.isView(state), 'state must be a typed array')
725 assert(
726 state.byteLength === binding.crypto_generichash_STATEBYTES,
727 "state must be 'crypto_generichash_STATEBYTES' bytes"
728 )
729
730 const res = binding.crypto_generichash_init(
731 state.buffer,
732 state.byteOffset,
733 state.byteLength,
734
735 key.buffer,
736 key.byteOffset,
737 key.byteLength,
738
739 outputLength
740 )
741
742 if (res !== 0) throw new Error('status: ' + res)
743}
744
745exports.crypto_generichash_update = function (state, input) {
746 assert(ArrayBuffer.isView(state), 'state must be a typed array')
747 assert(ArrayBuffer.isView(input), 'input must be a typed array')
748 assert(
749 state.byteLength === binding.crypto_generichash_STATEBYTES,
750 "state must be 'crypto_generichash_STATEBYTES' bytes"
751 )
752
753 const res = binding.crypto_generichash_update(
754 state.buffer,
755 state.byteOffset,
756 state.byteLength,
757
758 input.buffer,
759 input.byteOffset,
760 input.byteLength
761 )
762
763 if (res !== 0) throw new Error('status: ' + res)
764}
765
766exports.crypto_generichash_final = function (state, output) {
767 assert(ArrayBuffer.isView(state), 'state must be a typed array')
768 assert(ArrayBuffer.isView(output), 'output must be a typed array')
769 assert(
770 state.byteLength === binding.crypto_generichash_STATEBYTES,
771 "state must be 'crypto_generichash_STATEBYTES' bytes"
772 )
773
774 const res = binding.crypto_generichash_final(
775 state.buffer,
776 state.byteOffset,
777 state.byteLength,
778
779 output.buffer,
780 output.byteOffset,
781 output.byteLength
782 )
783
784 if (res !== 0) throw new Error('status: ' + res)
785}
786
787// secretstream
788
789exports.crypto_secretstream_xchacha20poly1305_keygen = function (k) {
790 assert(ArrayBuffer.isView(k), 'k must be a typed array')
791 assert(
792 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
793 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
794 )
795
796 binding.crypto_secretstream_xchacha20poly1305_keygen(k.buffer, k.byteOffset, k.byteLength)
797}
798
799exports.crypto_secretstream_xchacha20poly1305_init_push = function (state, header, k) {
800 assert(ArrayBuffer.isView(state), 'state must be a typed array')
801 assert(ArrayBuffer.isView(header), 'header must be a typed array')
802 assert(ArrayBuffer.isView(k), 'k must be a typed array')
803 assert(
804 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
805 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
806 )
807 assert(
808 header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
809 "header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
810 )
811 assert(
812 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
813 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
814 )
815
816 const res = binding.crypto_secretstream_xchacha20poly1305_init_push(
817 state.buffer,
818 state.byteOffset,
819 state.byteLength,
820
821 header.buffer,
822 header.byteOffset,
823 header.byteLength,
824
825 k.buffer,
826 k.byteOffset,
827 k.byteLength
828 )
829
830 if (res !== 0) throw new Error('status: ' + res)
831}
832
833exports.crypto_secretstream_xchacha20poly1305_init_pull = function (state, header, k) {
834 assert(ArrayBuffer.isView(state), 'state must be a typed array')
835 assert(ArrayBuffer.isView(header), 'header must be a typed array')
836 assert(ArrayBuffer.isView(k), 'k must be a typed array')
837 assert(
838 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
839 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
840 )
841 assert(
842 header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
843 "header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
844 )
845 assert(
846 k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
847 "k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
848 )
849
850 const res = binding.crypto_secretstream_xchacha20poly1305_init_pull(
851 state.buffer,
852 state.byteOffset,
853 state.byteLength,
854
855 header.buffer,
856 header.byteOffset,
857 header.byteLength,
858
859 k.buffer,
860 k.byteOffset,
861 k.byteLength
862 )
863
864 if (res !== 0) throw new Error('status: ' + res)
865}
866
867exports.crypto_secretstream_xchacha20poly1305_push = function (state, c, m, ad, tag) {
868 if (!ad) ad = OPTIONAL
869
870 assert(ArrayBuffer.isView(state), 'state must be a typed array')
871 assert(ArrayBuffer.isView(c), 'c must be a typed array')
872 assert(ArrayBuffer.isView(m), 'm must be a typed array')
873 assert(
874 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
875 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
876 )
877 assert(
878 c.byteLength === m.byteLength + binding.crypto_secretstream_xchacha20poly1305_ABYTES,
879 "c must be 'm.byteLength + crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
880 )
881
882 const res = binding.crypto_secretstream_xchacha20poly1305_push(
883 state.buffer,
884 state.byteOffset,
885 state.byteLength,
886
887 c.buffer,
888 c.byteOffset,
889 c.byteLength,
890
891 m.buffer,
892 m.byteOffset,
893 m.byteLength,
894
895 ad.buffer,
896 ad.byteOffset,
897 ad.byteLength,
898
899 tag
900 )
901
902 if (res < 0) throw new Error('push failed')
903
904 return res
905}
906
907exports.crypto_secretstream_xchacha20poly1305_pull = function (state, m, tag, c, ad) {
908 if (!ad) ad = OPTIONAL
909
910 assert(ArrayBuffer.isView(state), 'state must be a typed array')
911 assert(
912 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
913 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
914 )
915 assert(ArrayBuffer.isView(tag), 'tag must be a typed array')
916 assert(tag.byteLength === 1, 'tag must be 1 byte')
917
918 assert(ArrayBuffer.isView(c), 'c must be a typed array')
919 assert(
920 c.byteLength >= binding.crypto_secretstream_xchacha20poly1305_ABYTES,
921 "c must be at least 'crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
922 )
923 assert(ArrayBuffer.isView(m), 'm must be a typed array')
924 assert(
925 m.byteLength === c.byteLength - binding.crypto_secretstream_xchacha20poly1305_ABYTES,
926 "m must be 'c.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
927 )
928
929 const res = binding.crypto_secretstream_xchacha20poly1305_pull(
930 state.buffer,
931 state.byteOffset,
932 state.byteLength,
933
934 m.buffer,
935 m.byteOffset,
936 m.byteLength,
937
938 tag.buffer,
939 tag.byteOffset,
940 tag.byteLength,
941
942 c.buffer,
943 c.byteOffset,
944 c.byteLength,
945
946 ad.buffer,
947 ad.byteOffset,
948 ad.byteLength
949 )
950
951 if (res < 0) throw new Error('pull failed')
952
953 return res
954}
955
956exports.crypto_secretstream_xchacha20poly1305_rekey = function (state) {
957 assert(ArrayBuffer.isView(state), 'state must be a typed array')
958 assert(
959 state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
960 "state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
961 )
962
963 binding.crypto_secretstream_xchacha20poly1305_rekey(
964 state.buffer,
965 state.byteOffset,
966 state.byteLength
967 )
968}
969
970// crypto_stream
971
972exports.crypto_stream = function (c, n, k) {
973 assert(ArrayBuffer.isView(c), 'c must be a typed array')
974 assert(ArrayBuffer.isView(n), 'n must be a typed array')
975 assert(ArrayBuffer.isView(k), 'k must be a typed array')
976 assert(
977 n.byteLength === binding.crypto_stream_NONCEBYTES,
978 "n must be 'crypto_stream_NONCEBYTES' bytes"
979 )
980 assert(
981 k.byteLength === binding.crypto_stream_KEYBYTES,
982 "k must be 'crypto_stream_KEYBYTES' bytes"
983 )
984
985 const res = binding.crypto_stream(c, n, k)
986
987 if (res !== 0) throw new Error('status: ' + res)
988}
989
990exports.crypto_stream_xor = function (c, m, n, k) {
991 assert(ArrayBuffer.isView(c), 'c must be a typed array')
992 assert(ArrayBuffer.isView(m), 'm must be a typed array')
993 assert(ArrayBuffer.isView(n), 'n must be a typed array')
994 assert(ArrayBuffer.isView(k), 'k must be a typed array')
995 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
996 assert(
997 n.byteLength === binding.crypto_stream_NONCEBYTES,
998 "n must be 'crypto_stream_NONCEBYTES' bytes"
999 )
1000 assert(
1001 k.byteLength === binding.crypto_stream_KEYBYTES,
1002 "k must be 'crypto_stream_KEYBYTES' bytes"
1003 )
1004
1005 const res = binding.crypto_stream_xor(
1006 c.buffer,
1007 c.byteOffset,
1008 c.byteLength,
1009
1010 m.buffer,
1011 m.byteOffset,
1012 m.byteLength,
1013
1014 n.buffer,
1015 n.byteOffset,
1016 n.byteLength,
1017
1018 k.buffer,
1019 k.byteOffset,
1020 k.byteLength
1021 )
1022
1023 if (res !== 0) throw new Error('status: ' + res)
1024}
1025
1026exports.crypto_stream_chacha20 = function (c, n, k) {
1027 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1028 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1029 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1030 assert(
1031 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1032 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1033 )
1034 assert(
1035 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1036 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1037 )
1038
1039 const res = binding.crypto_stream_chacha20(c, n, k)
1040
1041 if (res !== 0) throw new Error('status: ' + res)
1042}
1043
1044exports.crypto_stream_chacha20_xor = function (c, m, n, k) {
1045 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1046 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1047 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1048 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1049 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1050 assert(
1051 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1052 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1053 )
1054 assert(
1055 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1056 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1057 )
1058
1059 const res = binding.crypto_stream_chacha20_xor(c, m, n, k)
1060
1061 if (res !== 0) throw new Error('status: ' + res)
1062}
1063
1064exports.crypto_stream_chacha20_xor_ic = function (c, m, n, ic, k) {
1065 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1066 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1067 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1068 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1069 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1070 assert(
1071 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
1072 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
1073 )
1074 assert(
1075 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
1076 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
1077 )
1078
1079 const res = binding.crypto_stream_chacha20_xor_ic(c, m, n, ic, k)
1080
1081 if (res !== 0) throw new Error('status: ' + res)
1082}
1083
1084exports.crypto_stream_chacha20_ietf = function (c, n, k) {
1085 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1086 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1087 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1088 assert(
1089 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1090 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1091 )
1092 assert(
1093 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1094 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1095 )
1096
1097 const res = binding.crypto_stream_chacha20_ietf(c, n, k)
1098
1099 if (res !== 0) throw new Error('status: ' + res)
1100}
1101
1102exports.crypto_stream_chacha20_ietf_xor = function (c, m, n, k) {
1103 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1104 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1105 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1106 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1107 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1108 assert(
1109 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1110 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1111 )
1112 assert(
1113 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1114 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1115 )
1116
1117 const res = binding.crypto_stream_chacha20_ietf_xor(c, m, n, k)
1118
1119 if (res !== 0) throw new Error('status: ' + res)
1120}
1121
1122exports.crypto_stream_chacha20_ietf_xor_ic = function (c, m, n, ic, k) {
1123 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1124 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1125 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1126 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1127 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1128 assert(
1129 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
1130 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
1131 )
1132 assert(
1133 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
1134 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
1135 )
1136
1137 const res = binding.crypto_stream_chacha20_ietf_xor_ic(c, m, n, ic, k)
1138
1139 if (res !== 0) throw new Error('status: ' + res)
1140}
1141
1142exports.crypto_stream_xchacha20 = function (c, n, k) {
1143 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1144 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1145 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1146 assert(
1147 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1148 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1149 )
1150 assert(
1151 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1152 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1153 )
1154
1155 const res = binding.crypto_stream_xchacha20(c, n, k)
1156
1157 if (res !== 0) throw new Error('status: ' + res)
1158}
1159
1160exports.crypto_stream_xchacha20_xor = function (c, m, n, k) {
1161 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1162 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1163 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1164 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1165 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1166 assert(
1167 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1168 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1169 )
1170 assert(
1171 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1172 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1173 )
1174
1175 const res = binding.crypto_stream_xchacha20_xor(c, m, n, k)
1176
1177 if (res !== 0) throw new Error('status: ' + res)
1178}
1179
1180exports.crypto_stream_xchacha20_xor_ic = function (c, m, n, ic, k) {
1181 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1182 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1183 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1184 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1185 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1186 assert(
1187 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
1188 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
1189 )
1190 assert(
1191 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
1192 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
1193 )
1194
1195 const res = binding.crypto_stream_xchacha20_xor_ic(c, m, n, ic, k)
1196
1197 if (res !== 0) throw new Error('status: ' + res)
1198}
1199
1200exports.crypto_stream_salsa20 = function (c, n, k) {
1201 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1202 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1203 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1204 assert(
1205 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1206 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1207 )
1208 assert(
1209 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1210 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1211 )
1212
1213 const res = binding.crypto_stream_salsa20(c, n, k)
1214
1215 if (res !== 0) throw new Error('status: ' + res)
1216}
1217
1218exports.crypto_stream_salsa20_xor = function (c, m, n, k) {
1219 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1220 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1221 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1222 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1223 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1224 assert(
1225 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1226 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1227 )
1228 assert(
1229 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1230 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1231 )
1232
1233 const res = binding.crypto_stream_salsa20_xor(c, m, n, k)
1234
1235 if (res !== 0) throw new Error('status: ' + res)
1236}
1237
1238exports.crypto_stream_salsa20_xor_ic = function (c, m, n, ic, k) {
1239 assert(ArrayBuffer.isView(c), 'c must be a typed array')
1240 assert(ArrayBuffer.isView(m), 'm must be a typed array')
1241 assert(ArrayBuffer.isView(n), 'n must be a typed array')
1242 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1243 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
1244 assert(
1245 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
1246 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
1247 )
1248 assert(
1249 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
1250 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
1251 )
1252
1253 const res = binding.crypto_stream_salsa20_xor_ic(c, m, n, ic, k)
1254
1255 if (res !== 0) throw new Error('status: ' + res)
1256}
1257
1258// crypto_auth
1259
1260exports.crypto_auth = function (out, input, k) {
1261 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1262 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1263 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1264 assert(out.byteLength === binding.crypto_auth_BYTES, "out must be 'crypto_auth_BYTES' bytes")
1265 assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes")
1266
1267 const res = binding.crypto_auth(out, input, k)
1268
1269 if (res !== 0) throw new Error('status: ' + res)
1270}
1271
1272exports.crypto_auth_verify = function (h, input, k) {
1273 assert(ArrayBuffer.isView(h), 'h must be a typed array')
1274 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1275 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1276 assert(h.byteLength === binding.crypto_auth_BYTES, "h must be 'crypto_auth_BYTES' bytes")
1277 assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes")
1278
1279 return binding.crypto_auth_verify(h, input, k)
1280}
1281
1282// crypto_onetimeauth
1283
1284exports.crypto_onetimeauth = function (out, input, k) {
1285 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1286 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1287 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1288 assert(
1289 out.byteLength === binding.crypto_onetimeauth_BYTES,
1290 "out must be 'crypto_onetimeauth_BYTES' bytes"
1291 )
1292 assert(
1293 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1294 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1295 )
1296
1297 const res = binding.crypto_onetimeauth(out, input, k)
1298
1299 if (res !== 0) throw new Error('status: ' + res)
1300}
1301
1302exports.crypto_onetimeauth_init = function (state, k) {
1303 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1304 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1305 assert(
1306 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1307 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1308 )
1309 assert(
1310 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1311 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1312 )
1313
1314 const res = binding.crypto_onetimeauth_init(state, k)
1315
1316 if (res !== 0) throw new Error('status: ' + res)
1317}
1318
1319exports.crypto_onetimeauth_update = function (state, input) {
1320 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1321 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1322 assert(
1323 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1324 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1325 )
1326
1327 const res = binding.crypto_onetimeauth_update(state, input)
1328
1329 if (res !== 0) throw new Error('status: ' + res)
1330}
1331
1332exports.crypto_onetimeauth_final = function (state, out) {
1333 assert(ArrayBuffer.isView(state), 'state must be a typed array')
1334 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1335 assert(
1336 state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
1337 "state must be 'crypto_onetimeauth_STATEBYTES' bytes"
1338 )
1339 assert(
1340 out.byteLength === binding.crypto_onetimeauth_BYTES,
1341 "out must be 'crypto_onetimeauth_BYTES' bytes"
1342 )
1343
1344 const res = binding.crypto_onetimeauth_final(state, out)
1345
1346 if (res !== 0) throw new Error('status: ' + res)
1347}
1348
1349exports.crypto_onetimeauth_verify = function (h, input, k) {
1350 assert(ArrayBuffer.isView(h), 'h must be a typed array')
1351 assert(ArrayBuffer.isView(input), 'input must be a typed array')
1352 assert(ArrayBuffer.isView(k), 'k must be a typed array')
1353 assert(
1354 h.byteLength === binding.crypto_onetimeauth_BYTES,
1355 "h must be 'crypto_onetimeauth_BYTES' bytes"
1356 )
1357 assert(
1358 k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
1359 "k must be 'crypto_onetimeauth_KEYBYTES' bytes"
1360 )
1361
1362 return binding.crypto_onetimeauth_verify(h, input, k)
1363}
1364
1365// crypto_pwhash
1366
1367exports.crypto_pwhash = function (out, passwd, salt, opslimit, memlimit, alg) {
1368 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1369 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1370 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1371 assert(
1372 out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
1373 "out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
1374 )
1375 assert(
1376 out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
1377 "out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
1378 )
1379 assert(
1380 salt.byteLength === binding.crypto_pwhash_SALTBYTES,
1381 "salt must be 'crypto_pwhash_SALTBYTES' bytes"
1382 )
1383 assert(
1384 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1385 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1386 )
1387 assert(
1388 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1389 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1390 )
1391 assert(
1392 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1393 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1394 )
1395 assert(
1396 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1397 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1398 )
1399 assert(alg >= 1 && alg <= 2, 'alg must be either Argon2i 1.3 or Argon2id 1.3')
1400
1401 const res = binding.crypto_pwhash(out, passwd, salt, opslimit, memlimit, alg)
1402
1403 if (res !== 0) throw new Error('status: ' + res)
1404}
1405
1406exports.crypto_pwhash_async = function (
1407 out,
1408 passwd,
1409 salt,
1410 opslimit,
1411 memlimit,
1412 alg,
1413 callback = undefined
1414) {
1415 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1416 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1417 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1418 assert(
1419 out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
1420 "out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
1421 )
1422 assert(
1423 out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
1424 "out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
1425 )
1426 assert(
1427 salt.byteLength === binding.crypto_pwhash_SALTBYTES,
1428 "salt must be 'crypto_pwhash_SALTBYTES' bytes"
1429 )
1430 assert(
1431 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1432 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1433 )
1434 assert(
1435 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1436 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1437 )
1438 assert(
1439 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1440 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1441 )
1442 assert(
1443 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1444 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1445 )
1446 assert(alg >= 1 && alg <= 2, 'alg must be either Argon2i 1.3 or Argon2id 1.3')
1447
1448 const [done, promise] = checkStatus(callback)
1449
1450 binding.crypto_pwhash_async(
1451 out.buffer,
1452 out.byteOffset,
1453 out.byteLength,
1454
1455 passwd.buffer,
1456 passwd.byteOffset,
1457 passwd.byteLength,
1458
1459 salt.buffer,
1460 salt.byteOffset,
1461 salt.byteLength,
1462
1463 opslimit,
1464 memlimit,
1465 alg,
1466
1467 done
1468 )
1469
1470 return promise
1471}
1472
1473exports.crypto_pwhash_str = function (out, passwd, opslimit, memlimit) {
1474 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1475 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1476 assert(
1477 out.byteLength === binding.crypto_pwhash_STRBYTES,
1478 "out must be 'crypto_pwhash_STRBYTES' bytes"
1479 )
1480 assert(typeof opslimit === 'number', 'opslimit must be a number')
1481 assert(
1482 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1483 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1484 )
1485 assert(
1486 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1487 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1488 )
1489 assert(typeof memlimit === 'number', 'memlimit must be a number')
1490 assert(
1491 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1492 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1493 )
1494 assert(
1495 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1496 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1497 )
1498
1499 const res = binding.crypto_pwhash_str(out, passwd, opslimit, memlimit)
1500
1501 if (res !== 0) throw new Error('status: ' + res)
1502}
1503
1504exports.crypto_pwhash_str_async = function (out, passwd, opslimit, memlimit, callback = undefined) {
1505 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1506 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1507 assert(
1508 out.byteLength === binding.crypto_pwhash_STRBYTES,
1509 "out must be 'crypto_pwhash_STRBYTES' bytes"
1510 )
1511 assert(passwd.byteLength > 0, 'passwd must not be empty')
1512 assert(typeof opslimit === 'number', 'opslimit must be a number')
1513 assert(
1514 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1515 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1516 )
1517 assert(
1518 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1519 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1520 )
1521 assert(typeof memlimit === 'number', 'memlimit must be a number')
1522 assert(
1523 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1524 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1525 )
1526 assert(
1527 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1528 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1529 )
1530
1531 const [done, promise] = checkStatus(callback)
1532
1533 binding.crypto_pwhash_str_async(
1534 out.buffer,
1535 out.byteOffset,
1536 out.byteLength,
1537
1538 passwd.buffer,
1539 passwd.byteOffset,
1540 passwd.byteLength,
1541
1542 opslimit,
1543 memlimit,
1544
1545 done
1546 )
1547
1548 return promise
1549}
1550
1551exports.crypto_pwhash_str_verify = function (str, passwd) {
1552 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1553 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1554 assert(
1555 str.byteLength === binding.crypto_pwhash_STRBYTES,
1556 "str must be 'crypto_pwhash_STRBYTES' bytes"
1557 )
1558
1559 return binding.crypto_pwhash_str_verify(str, passwd)
1560}
1561
1562exports.crypto_pwhash_str_verify_async = function (str, passwd, callback = undefined) {
1563 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1564 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1565 assert(
1566 str.byteLength === binding.crypto_pwhash_STRBYTES,
1567 "str must be 'crypto_pwhash_STRBYTES' bytes"
1568 )
1569 assert(passwd.byteLength > 0, 'passwd must not be empty')
1570
1571 const [done, promise] = checkStatus(callback, true)
1572
1573 binding.crypto_pwhash_str_verify_async(
1574 str.buffer,
1575 str.byteOffset,
1576 str.byteLength,
1577
1578 passwd.buffer,
1579 passwd.byteOffset,
1580 passwd.byteLength,
1581
1582 done
1583 )
1584
1585 return promise
1586}
1587
1588exports.crypto_pwhash_str_needs_rehash = function (str, opslimit, memlimit) {
1589 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1590 assert(
1591 str.byteLength === binding.crypto_pwhash_STRBYTES,
1592 "str must be 'crypto_pwhash_STRBYTES' bytes"
1593 )
1594 assert(
1595 opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
1596 "opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
1597 )
1598 assert(
1599 opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
1600 "opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
1601 )
1602 assert(
1603 memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
1604 "memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
1605 )
1606 assert(
1607 memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
1608 "memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
1609 )
1610
1611 return binding.crypto_pwhash_str_needs_rehash(str, opslimit, memlimit)
1612}
1613
1614exports.crypto_pwhash_scryptsalsa208sha256 = function (out, passwd, salt, opslimit, memlimit) {
1615 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1616 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1617 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1618 assert(
1619 out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
1620 "out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
1621 )
1622 assert(
1623 out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
1624 "out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
1625 )
1626 assert(
1627 salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
1628 "salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
1629 )
1630 assert(
1631 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1632 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1633 )
1634 assert(
1635 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1636 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1637 )
1638 assert(
1639 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1640 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1641 )
1642 assert(
1643 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1644 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1645 )
1646
1647 const res = binding.crypto_pwhash_scryptsalsa208sha256(out, passwd, salt, opslimit, memlimit)
1648
1649 if (res !== 0) throw new Error('status: ' + res)
1650}
1651
1652exports.crypto_pwhash_scryptsalsa208sha256_async = function (
1653 out,
1654 passwd,
1655 salt,
1656 opslimit,
1657 memlimit,
1658 callback = undefined
1659) {
1660 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1661 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1662 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
1663 assert(
1664 out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
1665 "out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
1666 )
1667 assert(
1668 out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
1669 "out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
1670 )
1671 assert(passwd.byteLength > 0, 'passwd must not be empty')
1672 assert(
1673 salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
1674 "salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
1675 )
1676 assert(
1677 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1678 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1679 )
1680 assert(
1681 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1682 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1683 )
1684 assert(
1685 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1686 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1687 )
1688 assert(
1689 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1690 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1691 )
1692
1693 const [done, promise] = checkStatus(callback)
1694
1695 binding.crypto_pwhash_scryptsalsa208sha256_async(
1696 out.buffer,
1697 out.byteOffset,
1698 out.byteLength,
1699
1700 passwd.buffer,
1701 passwd.byteOffset,
1702 passwd.byteLength,
1703
1704 salt.buffer,
1705 salt.byteOffset,
1706 salt.byteLength,
1707
1708 opslimit,
1709 memlimit,
1710
1711 done
1712 )
1713
1714 return promise
1715}
1716
1717exports.crypto_pwhash_scryptsalsa208sha256_str_async = function (
1718 out,
1719 passwd,
1720 opslimit,
1721 memlimit,
1722 callback = undefined
1723) {
1724 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1725 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1726 assert(
1727 out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1728 "out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1729 )
1730 assert(passwd.byteLength > 0, 'passwd must not be empty')
1731 assert(
1732 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1733 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1734 )
1735 assert(
1736 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1737 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1738 )
1739 assert(
1740 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1741 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1742 )
1743 assert(
1744 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1745 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1746 )
1747
1748 const [done, promise] = checkStatus(callback)
1749
1750 binding.crypto_pwhash_scryptsalsa208sha256_str_async(
1751 out.buffer,
1752 out.byteOffset,
1753 out.byteLength,
1754
1755 passwd.buffer,
1756 passwd.byteOffset,
1757 passwd.byteLength,
1758
1759 opslimit,
1760 memlimit,
1761
1762 done
1763 )
1764
1765 return promise
1766}
1767
1768exports.crypto_pwhash_scryptsalsa208sha256_str = function (out, passwd, opslimit, memlimit) {
1769 assert(ArrayBuffer.isView(out), 'out must be a typed array')
1770 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1771 assert(
1772 out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1773 "out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1774 )
1775 assert(passwd.byteLength > 0, 'passwd must not be empty')
1776 assert(
1777 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1778 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1779 )
1780 assert(
1781 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1782 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1783 )
1784 assert(
1785 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1786 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1787 )
1788 assert(
1789 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1790 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1791 )
1792
1793 const res = binding.crypto_pwhash_scryptsalsa208sha256_str(out, passwd, opslimit, memlimit)
1794
1795 if (res !== 0) throw new Error('status: ' + res)
1796}
1797
1798exports.crypto_pwhash_scryptsalsa208sha256_str_verify_async = function (
1799 str,
1800 passwd,
1801 callback = undefined
1802) {
1803 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1804 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1805 assert(
1806 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1807 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1808 )
1809 assert(passwd.byteLength > 0, 'passwd must not be empty')
1810
1811 const [done, promise] = checkStatus(callback, true)
1812
1813 binding.crypto_pwhash_scryptsalsa208sha256_str_verify_async(
1814 str.buffer,
1815 str.byteOffset,
1816 str.byteLength,
1817
1818 passwd.buffer,
1819 passwd.byteOffset,
1820 passwd.byteLength,
1821
1822 done
1823 )
1824
1825 return promise
1826}
1827
1828exports.crypto_pwhash_scryptsalsa208sha256_str_verify = function (str, passwd) {
1829 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1830 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
1831 assert(
1832 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1833 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1834 )
1835 assert(passwd.byteLength > 0, 'passwd must not be empty')
1836
1837 return binding.crypto_pwhash_scryptsalsa208sha256_str_verify(str, passwd)
1838}
1839
1840exports.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash = function (str, opslimit, memlimit) {
1841 assert(ArrayBuffer.isView(str), 'str must be a typed array')
1842 assert(
1843 str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
1844 "str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
1845 )
1846 assert(
1847 opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
1848 "opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
1849 )
1850 assert(
1851 opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
1852 "opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
1853 )
1854 assert(
1855 memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
1856 "memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
1857 )
1858 assert(
1859 memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
1860 "memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
1861 )
1862
1863 return binding.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str, opslimit, memlimit)
1864}
1865
1866// crypto_kx
1867
1868exports.crypto_kx_keypair = function (pk, sk) {
1869 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
1870 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
1871 assert(
1872 pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1873 "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1874 )
1875 assert(
1876 sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1877 "sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1878 )
1879
1880 const res = binding.crypto_kx_keypair(pk, sk)
1881
1882 if (res !== 0) throw new Error('status: ' + res)
1883}
1884
1885exports.crypto_kx_seed_keypair = function (pk, sk, seed) {
1886 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
1887 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
1888 assert(ArrayBuffer.isView(seed), 'seed must be a typed array')
1889 assert(
1890 pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1891 "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1892 )
1893 assert(
1894 sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1895 "sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1896 )
1897 assert(
1898 seed.byteLength === binding.crypto_kx_SEEDBYTES,
1899 "seed must be 'crypto_kx_SEEDBYTES' bytes"
1900 )
1901
1902 const res = binding.crypto_kx_seed_keypair(pk, sk, seed)
1903
1904 if (res !== 0) throw new Error('status: ' + res)
1905}
1906
1907exports.crypto_kx_client_session_keys = function (rx, tx, clientPk, clientSk, serverPk) {
1908 if (!rx) rx = undefined
1909 if (!tx) tx = undefined
1910
1911 assert(rx || tx, 'at least one session key must be specified')
1912
1913 if (rx) {
1914 assert(ArrayBuffer.isView(rx), 'rx must be a typed array')
1915 assert(
1916 rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1917 "rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1918 )
1919 }
1920
1921 if (tx) {
1922 assert(ArrayBuffer.isView(tx), 'tx must be a typed array')
1923 assert(
1924 tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1925 "tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1926 )
1927 }
1928
1929 assert(ArrayBuffer.isView(clientPk), 'clientPk must be a typed array')
1930 assert(ArrayBuffer.isView(clientSk), 'clientSk must be a typed array')
1931 assert(ArrayBuffer.isView(serverPk), 'serverPk must be a typed array')
1932 assert(
1933 clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1934 "clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1935 )
1936 assert(
1937 clientSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1938 "clientSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1939 )
1940 assert(
1941 serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1942 "serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1943 )
1944
1945 const res = binding.crypto_kx_client_session_keys(rx, tx, clientPk, clientSk, serverPk)
1946
1947 if (res !== 0) throw new Error('status: ' + res)
1948}
1949
1950exports.crypto_kx_server_session_keys = function (rx, tx, serverPk, serverSk, clientPk) {
1951 if (!rx) rx = undefined
1952 if (!tx) tx = undefined
1953
1954 assert(rx || tx, 'at least one session key must be specified')
1955
1956 if (rx) {
1957 assert(ArrayBuffer.isView(rx), 'rx must be a typed array')
1958 assert(
1959 rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1960 "rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1961 )
1962 }
1963
1964 if (tx) {
1965 assert(ArrayBuffer.isView(tx), 'tx must be a typed array')
1966 assert(
1967 tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
1968 "tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
1969 )
1970 }
1971
1972 assert(ArrayBuffer.isView(serverPk), 'serverPk must be a typed array')
1973 assert(ArrayBuffer.isView(serverSk), 'serverSk must be a typed array')
1974 assert(ArrayBuffer.isView(clientPk), 'clientPk must be a typed array')
1975 assert(
1976 serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1977 "serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1978 )
1979 assert(
1980 serverSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
1981 "serverSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
1982 )
1983 assert(
1984 clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
1985 "clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
1986 )
1987
1988 const res = binding.crypto_kx_server_session_keys(rx, tx, serverPk, serverSk, clientPk)
1989
1990 if (res !== 0) throw new Error('status: ' + res)
1991}
1992
1993// crypto_scalarmult
1994
1995exports.crypto_scalarmult_base = function (q, n) {
1996 assert(ArrayBuffer.isView(q), 'q must be a typed array')
1997 assert(
1998 q.byteLength === binding.crypto_scalarmult_BYTES,
1999 "q must be 'crypto_scalarmult_BYTES' bytes"
2000 )
2001 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2002 assert(
2003 n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
2004 "n must be 'crypto_scalarmult_SCALARBYTES' bytes"
2005 )
2006
2007 const res = binding.crypto_scalarmult_base(q, n)
2008
2009 if (res !== 0) throw new Error('status: ' + res)
2010}
2011
2012exports.crypto_scalarmult = function (q, n, p) {
2013 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2014 assert(
2015 q.byteLength === binding.crypto_scalarmult_BYTES,
2016 "q must be 'crypto_scalarmult_BYTES' bytes"
2017 )
2018 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2019 assert(
2020 n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
2021 "n must be 'crypto_scalarmult_SCALARBYTES' bytes"
2022 )
2023 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2024 assert(
2025 p.byteLength === binding.crypto_scalarmult_BYTES,
2026 "p must be 'crypto_scalarmult_BYTES' bytes"
2027 )
2028
2029 const res = binding.crypto_scalarmult(q, n, p)
2030
2031 if (res !== 0) throw new Error('status: ' + res)
2032}
2033
2034exports.crypto_scalarmult_ed25519_base = function (q, n) {
2035 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2036 assert(
2037 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2038 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2039 )
2040 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2041 assert(
2042 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2043 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2044 )
2045
2046 const res = binding.crypto_scalarmult_ed25519_base(q, n)
2047
2048 if (res !== 0) throw new Error('status: ' + res)
2049}
2050
2051exports.crypto_scalarmult_ed25519 = function (q, n, p) {
2052 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2053 assert(
2054 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2055 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2056 )
2057 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2058 assert(
2059 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2060 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2061 )
2062 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2063 assert(
2064 p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2065 "p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2066 )
2067
2068 const res = binding.crypto_scalarmult_ed25519(q, n, p)
2069
2070 if (res !== 0) throw new Error('status: ' + res)
2071}
2072
2073exports.crypto_core_ed25519_is_valid_point = function (p) {
2074 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2075 assert(
2076 p.byteLength === binding.crypto_core_ed25519_BYTES,
2077 "p must be 'crypto_core_ed25519_BYTES' bytes"
2078 )
2079
2080 return binding.crypto_core_ed25519_is_valid_point(p)
2081}
2082
2083exports.crypto_core_ed25519_from_uniform = function (p, r) {
2084 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2085 assert(
2086 p.byteLength === binding.crypto_core_ed25519_BYTES,
2087 "p must be 'crypto_core_ed25519_BYTES' bytes"
2088 )
2089 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2090 assert(
2091 r.byteLength === binding.crypto_core_ed25519_UNIFORMBYTES,
2092 "r must be 'crypto_core_ed25519_UNIFORMBYTES' bytes"
2093 )
2094
2095 const res = binding.crypto_core_ed25519_from_uniform(p, r)
2096
2097 if (res !== 0) throw new Error('status: ' + res)
2098}
2099
2100exports.crypto_scalarmult_ed25519_base_noclamp = function (q, n) {
2101 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2102 assert(
2103 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2104 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2105 )
2106 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2107 assert(
2108 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2109 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2110 )
2111
2112 const res = binding.crypto_scalarmult_ed25519_base_noclamp(q, n)
2113
2114 if (res !== 0) throw new Error('status: ' + res)
2115}
2116
2117exports.crypto_scalarmult_ed25519_noclamp = function (q, n, p) {
2118 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2119 assert(
2120 q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2121 "q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2122 )
2123 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2124 assert(
2125 n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
2126 "n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
2127 )
2128 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2129 assert(
2130 p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
2131 "p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
2132 )
2133
2134 const res = binding.crypto_scalarmult_ed25519_noclamp(q, n, p)
2135
2136 if (res !== 0) throw new Error('status: ' + res)
2137}
2138
2139// crypto_core
2140
2141exports.crypto_core_ed25519_add = function (r, p, q) {
2142 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2143 assert(
2144 r.byteLength === binding.crypto_core_ed25519_BYTES,
2145 "r must be 'crypto_core_ed25519_BYTES' bytes"
2146 )
2147 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2148 assert(
2149 p.byteLength === binding.crypto_core_ed25519_BYTES,
2150 "p must be 'crypto_core_ed25519_BYTES' bytes"
2151 )
2152 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2153 assert(
2154 q.byteLength === binding.crypto_core_ed25519_BYTES,
2155 "q must be 'crypto_core_ed25519_BYTES' bytes"
2156 )
2157
2158 const res = binding.crypto_core_ed25519_add(r, p, q)
2159
2160 if (res !== 0) throw new Error('status: ' + res)
2161}
2162
2163exports.crypto_core_ed25519_sub = function (r, p, q) {
2164 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2165 assert(
2166 r.byteLength === binding.crypto_core_ed25519_BYTES,
2167 "r must be 'crypto_core_ed25519_BYTES' bytes"
2168 )
2169 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2170 assert(
2171 p.byteLength === binding.crypto_core_ed25519_BYTES,
2172 "p must be 'crypto_core_ed25519_BYTES' bytes"
2173 )
2174 assert(ArrayBuffer.isView(q), 'q must be a typed array')
2175 assert(
2176 q.byteLength === binding.crypto_core_ed25519_BYTES,
2177 "q must be 'crypto_core_ed25519_BYTES' bytes"
2178 )
2179
2180 const res = binding.crypto_core_ed25519_sub(r, p, q)
2181
2182 if (res !== 0) throw new Error('status: ' + res)
2183}
2184
2185exports.crypto_core_ed25519_scalar_random = function (r) {
2186 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2187 assert(
2188 r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2189 "r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2190 )
2191
2192 binding.crypto_core_ed25519_scalar_random(r)
2193}
2194
2195exports.crypto_core_ed25519_scalar_reduce = function (r, s) {
2196 assert(ArrayBuffer.isView(r), 'r must be a typed array')
2197 assert(
2198 r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2199 "r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2200 )
2201 assert(ArrayBuffer.isView(s), 's must be a typed array')
2202 assert(
2203 s.byteLength === binding.crypto_core_ed25519_NONREDUCEDSCALARBYTES,
2204 "s must be 'crypto_core_ed25519_NONREDUCEDSCALARBYTES' bytes"
2205 )
2206
2207 binding.crypto_core_ed25519_scalar_reduce(r, s)
2208}
2209
2210exports.crypto_core_ed25519_scalar_invert = function (recip, s) {
2211 assert(ArrayBuffer.isView(recip), 'recip must be a typed array')
2212 assert(
2213 recip.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2214 "recip must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2215 )
2216 assert(ArrayBuffer.isView(s), 's must be a typed array')
2217 assert(
2218 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2219 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2220 )
2221
2222 binding.crypto_core_ed25519_scalar_invert(recip, s)
2223}
2224
2225exports.crypto_core_ed25519_scalar_negate = function (neg, s) {
2226 assert(ArrayBuffer.isView(neg), 'neg must be a typed array')
2227 assert(
2228 neg.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2229 "neg must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2230 )
2231 assert(ArrayBuffer.isView(s), 's must be a typed array')
2232 assert(
2233 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2234 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2235 )
2236
2237 binding.crypto_core_ed25519_scalar_negate(neg, s)
2238}
2239
2240exports.crypto_core_ed25519_scalar_complement = function (comp, s) {
2241 assert(ArrayBuffer.isView(comp), 'comp must be a typed array')
2242 assert(
2243 comp.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2244 "comp must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2245 )
2246 assert(ArrayBuffer.isView(s), 's must be a typed array')
2247 assert(
2248 s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2249 "s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2250 )
2251
2252 binding.crypto_core_ed25519_scalar_complement(comp, s)
2253}
2254
2255exports.crypto_core_ed25519_scalar_add = function (z, x, y) {
2256 assert(ArrayBuffer.isView(z), 'z must be a typed array')
2257 assert(
2258 z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2259 "z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2260 )
2261 assert(ArrayBuffer.isView(x), 'x must be a typed array')
2262 assert(
2263 x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2264 "x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2265 )
2266 assert(ArrayBuffer.isView(y), 'y must be a typed array')
2267 assert(
2268 y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2269 "y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2270 )
2271
2272 binding.crypto_core_ed25519_scalar_add(z, x, y)
2273}
2274
2275exports.crypto_core_ed25519_scalar_sub = function (z, x, y) {
2276 assert(ArrayBuffer.isView(z), 'z must be a typed array')
2277 assert(
2278 z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2279 "z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2280 )
2281 assert(ArrayBuffer.isView(x), 'x must be a typed array')
2282 assert(
2283 x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2284 "x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2285 )
2286 assert(ArrayBuffer.isView(y), 'y must be a typed array')
2287 assert(
2288 y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
2289 "y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
2290 )
2291
2292 binding.crypto_core_ed25519_scalar_sub(z, x, y)
2293}
2294
2295// crypto_shorthash
2296
2297exports.crypto_shorthash = function (out, input, k) {
2298 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2299 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2300 assert(
2301 out.byteLength === binding.crypto_shorthash_BYTES,
2302 "out must be 'crypto_shorthash_BYTES' bytes"
2303 )
2304 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2305 assert(
2306 k.byteLength === binding.crypto_shorthash_KEYBYTES,
2307 "k must be 'crypto_shorthash_KEYBYTES' bytes"
2308 )
2309
2310 const res = binding.crypto_shorthash(out, input, k)
2311
2312 if (res !== 0) throw new Error('status: ' + res)
2313}
2314
2315// crypto_kdf
2316
2317exports.crypto_kdf_keygen = function (key) {
2318 assert(ArrayBuffer.isView(key), 'key must be a typed array')
2319 assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes")
2320
2321 binding.crypto_kdf_keygen(key)
2322}
2323
2324exports.crypto_kdf_derive_from_key = function (subkey, subkeyId, ctx, key) {
2325 assert(ArrayBuffer.isView(subkey), 'subkey must be a typed array')
2326 assert(
2327 subkey.byteLength >= binding.crypto_kdf_BYTES_MIN,
2328 "subkey must be at least 'crypto_kdf_BYTES_MIN' bytes"
2329 )
2330 assert(
2331 subkey.byteLength <= binding.crypto_kdf_BYTES_MAX,
2332 "subkey must be at most 'crypto_kdf_BYTES_MAX' bytes"
2333 )
2334 assert(ArrayBuffer.isView(ctx), 'ctx must be a typed array')
2335 assert(
2336 ctx.byteLength === binding.crypto_kdf_CONTEXTBYTES,
2337 "ctx must be 'crypto_kdf_CONTEXTBYTES' bytes"
2338 )
2339 assert(ArrayBuffer.isView(key), 'key must be a typed array')
2340 assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes")
2341
2342 const res = binding.crypto_kdf_derive_from_key(subkey, subkeyId, ctx, key)
2343
2344 if (res !== 0) throw new Error('status: ' + res)
2345}
2346
2347// crypto_hash
2348
2349exports.crypto_hash = function (out, input) {
2350 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2351 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2352 assert(out.byteLength === binding.crypto_hash_BYTES, "out must be 'crypto_hash_BYTES' bytes")
2353
2354 const res = binding.crypto_hash(out, input)
2355
2356 if (res !== 0) throw new Error('status: ' + res)
2357}
2358
2359exports.crypto_hash_sha256 = function (out, input) {
2360 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2361 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2362 assert(
2363 out.byteLength === binding.crypto_hash_sha256_BYTES,
2364 "out must be 'crypto_hash_sha256_BYTES' bytes"
2365 )
2366
2367 const res = binding.crypto_hash_sha256(out, input)
2368
2369 if (res !== 0) throw new Error('status: ' + res)
2370}
2371
2372exports.crypto_hash_sha256_init = function (state) {
2373 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2374 assert(
2375 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2376 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2377 )
2378
2379 const res = binding.crypto_hash_sha256_init(state)
2380
2381 if (res !== 0) throw new Error('status: ' + res)
2382}
2383
2384exports.crypto_hash_sha256_update = function (state, input) {
2385 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2386 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2387 assert(
2388 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2389 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2390 )
2391
2392 const res = binding.crypto_hash_sha256_update(state, input)
2393
2394 if (res !== 0) throw new Error('status: ' + res)
2395}
2396
2397exports.crypto_hash_sha256_final = function (state, out) {
2398 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2399 assert(
2400 state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
2401 "state must be 'crypto_hash_sha256_STATEBYTES' bytes"
2402 )
2403 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2404 assert(
2405 out.byteLength === binding.crypto_hash_sha256_BYTES,
2406 "out must be 'crypto_hash_sha256_BYTES' bytes"
2407 )
2408
2409 const res = binding.crypto_hash_sha256_final(state, out)
2410
2411 if (res !== 0) throw new Error('status: ' + res)
2412}
2413
2414exports.crypto_hash_sha512 = function (out, input) {
2415 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2416 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2417 assert(
2418 out.byteLength === binding.crypto_hash_sha512_BYTES,
2419 "out must be 'crypto_hash_sha512_BYTES' bytes"
2420 )
2421
2422 const res = binding.crypto_hash_sha512(out, input)
2423
2424 if (res !== 0) throw new Error('status: ' + res)
2425}
2426
2427exports.crypto_hash_sha512_init = function (state) {
2428 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2429 assert(
2430 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2431 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2432 )
2433
2434 const res = binding.crypto_hash_sha512_init(state)
2435
2436 if (res !== 0) throw new Error('status: ' + res)
2437}
2438
2439exports.crypto_hash_sha512_update = function (state, input) {
2440 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2441 assert(ArrayBuffer.isView(input), 'input must be a typed array')
2442 assert(
2443 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2444 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2445 )
2446
2447 const res = binding.crypto_hash_sha512_update(state, input)
2448
2449 if (res !== 0) throw new Error('status: ' + res)
2450}
2451
2452exports.crypto_hash_sha512_final = function (state, out) {
2453 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2454 assert(
2455 state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
2456 "state must be 'crypto_hash_sha512_STATEBYTES' bytes"
2457 )
2458 assert(ArrayBuffer.isView(out), 'out must be a typed array')
2459 assert(
2460 out.byteLength === binding.crypto_hash_sha512_BYTES,
2461 "out must be 'crypto_hash_sha512_BYTES' bytes"
2462 )
2463
2464 const res = binding.crypto_hash_sha512_final(state, out)
2465
2466 if (res !== 0) throw new Error('status: ' + res)
2467}
2468
2469// crypto_aead
2470
2471exports.crypto_aead_xchacha20poly1305_ietf_keygen = function (k) {
2472 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2473 assert(
2474 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2475 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2476 )
2477
2478 binding.crypto_aead_xchacha20poly1305_ietf_keygen(k)
2479}
2480
2481exports.crypto_aead_xchacha20poly1305_ietf_encrypt = function (c, m, ad, nsec, npub, k) {
2482 if (!ad) ad = undefined
2483
2484 assert(nsec === null, 'nsec must always be set to null')
2485 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2486 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2487 assert(
2488 c.byteLength === m.byteLength + binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2489 "c must be 'm.byteLength + crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2490 )
2491 assert(c.byteLength <= 0xffffffff, 'c.byteLength must be a 32bit integer')
2492 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2493 assert(
2494 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2495 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2496 )
2497 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2498 assert(
2499 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2500 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2501 )
2502
2503 const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt(c, m, ad, npub, k)
2504
2505 if (res < 0) throw new Error('could not encrypt data')
2506
2507 return res
2508}
2509
2510exports.crypto_aead_xchacha20poly1305_ietf_decrypt = function (m, nsec, c, ad, npub, k) {
2511 if (!ad) ad = undefined
2512
2513 assert(nsec === null, 'nsec must always be set to null')
2514 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2515 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2516 assert(
2517 m.byteLength === c.byteLength - binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2518 "m must be 'c.byteLength - crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2519 )
2520 assert(m.byteLength <= 0xffffffff, 'm.byteLength must be a 32bit integer')
2521 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2522 assert(
2523 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2524 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2525 )
2526 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2527 assert(
2528 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2529 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2530 )
2531
2532 const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt(m, c, ad, npub, k)
2533
2534 if (res < 0) throw new Error('could not verify data')
2535
2536 return res
2537}
2538
2539exports.crypto_aead_xchacha20poly1305_ietf_encrypt_detached = function (
2540 c,
2541 mac,
2542 m,
2543 ad,
2544 nsec,
2545 npub,
2546 k
2547) {
2548 if (!ad) ad = undefined
2549
2550 assert(nsec === null, 'nsec must always be set to null')
2551 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2552 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2553 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2554 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2555 assert(
2556 mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2557 "mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2558 )
2559 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2560 assert(
2561 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2562 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2563 )
2564 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2565 assert(
2566 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2567 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2568 )
2569
2570 const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k)
2571
2572 if (res < 0) throw new Error('could not encrypt data')
2573
2574 return res
2575}
2576
2577exports.crypto_aead_xchacha20poly1305_ietf_decrypt_detached = function (
2578 m,
2579 nsec,
2580 c,
2581 mac,
2582 ad,
2583 npub,
2584 k
2585) {
2586 if (!ad) ad = undefined
2587
2588 assert(nsec === null, 'nsec must always be set to null')
2589 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2590 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2591 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
2592 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2593 assert(
2594 mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
2595 "mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
2596 )
2597 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2598 assert(
2599 npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
2600 "npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
2601 )
2602 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2603 assert(
2604 k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
2605 "k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
2606 )
2607
2608 const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k)
2609
2610 if (res !== 0) throw new Error('could not verify data')
2611}
2612
2613exports.crypto_aead_chacha20poly1305_ietf_keygen = function (k) {
2614 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2615 assert(
2616 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2617 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2618 )
2619
2620 binding.crypto_aead_chacha20poly1305_ietf_keygen(k)
2621}
2622
2623exports.crypto_aead_chacha20poly1305_ietf_encrypt = function (c, m, ad, nsec, npub, k) {
2624 if (!ad) ad = undefined
2625
2626 assert(nsec === null, 'nsec must always be set to null')
2627 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2628 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2629 assert(
2630 c.byteLength === m.byteLength + binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2631 "c must be 'm.byteLength + crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2632 )
2633 assert(c.byteLength <= 0xffffffff, 'c.byteLength must be a 32bit integer')
2634 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2635 assert(
2636 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2637 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2638 )
2639 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2640 assert(
2641 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2642 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2643 )
2644
2645 const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, ad, npub, k)
2646
2647 if (res < 0) throw new Error('could not encrypt data')
2648
2649 return res
2650}
2651
2652exports.crypto_aead_chacha20poly1305_ietf_decrypt = function (m, nsec, c, ad, npub, k) {
2653 if (!ad) ad = undefined
2654
2655 assert(nsec === null, 'nsec must always be set to null')
2656 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2657 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2658 assert(
2659 m.byteLength === c.byteLength - binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2660 "m must be 'c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2661 )
2662 assert(m.byteLength <= 0xffffffff, 'm.byteLength must be a 32bit integer')
2663 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2664 assert(
2665 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2666 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2667 )
2668 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2669 assert(
2670 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2671 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2672 )
2673
2674 const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt(m, c, ad, npub, k)
2675
2676 if (res < 0) throw new Error('could not verify data')
2677
2678 return res
2679}
2680
2681exports.crypto_aead_chacha20poly1305_ietf_encrypt_detached = function (
2682 c,
2683 mac,
2684 m,
2685 ad,
2686 nsec,
2687 npub,
2688 k
2689) {
2690 if (!ad) ad = undefined
2691
2692 assert(nsec === null, 'nsec must always be set to null')
2693 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2694 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2695 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2696 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2697 assert(
2698 mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2699 "mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2700 )
2701 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2702 assert(
2703 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2704 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2705 )
2706 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2707 assert(
2708 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2709 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2710 )
2711
2712 const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k)
2713
2714 if (res < 0) throw new Error('could not encrypt data')
2715
2716 return res
2717}
2718
2719exports.crypto_aead_chacha20poly1305_ietf_decrypt_detached = function (
2720 m,
2721 nsec,
2722 c,
2723 mac,
2724 ad,
2725 npub,
2726 k
2727) {
2728 if (!ad) ad = undefined
2729
2730 assert(nsec === null, 'nsec must always be set to null')
2731 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2732 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2733 assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes")
2734 assert(ArrayBuffer.isView(mac), 'mac must be a typed array')
2735 assert(
2736 mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
2737 "mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
2738 )
2739 assert(ArrayBuffer.isView(npub), 'npub must be a typed array')
2740 assert(
2741 npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
2742 "npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
2743 )
2744 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2745 assert(
2746 k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
2747 "k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
2748 )
2749
2750 const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k)
2751
2752 if (res !== 0) throw new Error('could not verify data')
2753}
2754
2755// crypto_stream
2756
2757exports.crypto_stream_xor_wrap_init = function (state, n, k) {
2758 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2759 assert(
2760 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2761 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2762 )
2763 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2764 assert(
2765 n.byteLength === binding.crypto_stream_NONCEBYTES,
2766 "n must be 'crypto_stream_NONCEBYTES' bytes"
2767 )
2768 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2769 assert(
2770 k.byteLength === binding.crypto_stream_KEYBYTES,
2771 "k must be 'crypto_stream_KEYBYTES' bytes"
2772 )
2773
2774 binding.crypto_stream_xor_wrap_init(state, n, k)
2775}
2776
2777exports.crypto_stream_xor_wrap_update = function (state, c, m) {
2778 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2779 assert(
2780 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2781 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2782 )
2783 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2784 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2785 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2786
2787 binding.crypto_stream_xor_wrap_update(state, c, m)
2788}
2789
2790exports.crypto_stream_xor_wrap_final = function (state) {
2791 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2792 assert(
2793 state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
2794 "state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
2795 )
2796
2797 binding.crypto_stream_xor_wrap_final(state)
2798}
2799
2800exports.crypto_stream_chacha20_xor_wrap_init = function (state, n, k) {
2801 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2802 assert(
2803 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2804 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2805 )
2806 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2807 assert(
2808 n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
2809 "n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
2810 )
2811 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2812 assert(
2813 k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
2814 "k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
2815 )
2816
2817 binding.crypto_stream_chacha20_xor_wrap_init(state, n, k)
2818}
2819
2820exports.crypto_stream_chacha20_xor_wrap_update = function (state, c, m) {
2821 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2822 assert(
2823 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2824 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2825 )
2826 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2827 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2828 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2829
2830 binding.crypto_stream_chacha20_xor_wrap_update(state, c, m)
2831}
2832
2833exports.crypto_stream_chacha20_xor_wrap_final = function (state) {
2834 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2835 assert(
2836 state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
2837 "state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
2838 )
2839
2840 binding.crypto_stream_chacha20_xor_wrap_final(state)
2841}
2842
2843exports.crypto_stream_chacha20_ietf_xor_wrap_init = function (state, n, k) {
2844 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2845 assert(
2846 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2847 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2848 )
2849 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2850 assert(
2851 n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
2852 "n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
2853 )
2854 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2855 assert(
2856 k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
2857 "k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
2858 )
2859
2860 binding.crypto_stream_chacha20_ietf_xor_wrap_init(state, n, k)
2861}
2862
2863exports.crypto_stream_chacha20_ietf_xor_wrap_update = function (state, c, m) {
2864 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2865 assert(
2866 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2867 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2868 )
2869 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2870 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2871 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2872
2873 binding.crypto_stream_chacha20_ietf_xor_wrap_update(state, c, m)
2874}
2875
2876exports.crypto_stream_chacha20_ietf_xor_wrap_final = function (state) {
2877 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2878 assert(
2879 state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
2880 "state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
2881 )
2882
2883 binding.crypto_stream_chacha20_ietf_xor_wrap_final(state)
2884}
2885
2886exports.crypto_stream_xchacha20_xor_wrap_init = function (state, n, k) {
2887 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2888 assert(
2889 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2890 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2891 )
2892 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2893 assert(
2894 n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
2895 "n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
2896 )
2897 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2898 assert(
2899 k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
2900 "k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
2901 )
2902
2903 binding.crypto_stream_xchacha20_xor_wrap_init(state, n, k)
2904}
2905
2906exports.crypto_stream_xchacha20_xor_wrap_update = function (state, c, m) {
2907 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2908 assert(
2909 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2910 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2911 )
2912 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2913 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2914 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2915
2916 binding.crypto_stream_xchacha20_xor_wrap_update(state, c, m)
2917}
2918
2919exports.crypto_stream_xchacha20_xor_wrap_final = function (state) {
2920 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2921 assert(
2922 state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
2923 "state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
2924 )
2925
2926 binding.crypto_stream_xchacha20_xor_wrap_final(state)
2927}
2928
2929exports.crypto_stream_salsa20_xor_wrap_init = function (state, n, k) {
2930 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2931 assert(
2932 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2933 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2934 )
2935 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2936 assert(
2937 n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
2938 "n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
2939 )
2940 assert(ArrayBuffer.isView(k), 'k must be a typed array')
2941 assert(
2942 k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
2943 "k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
2944 )
2945
2946 binding.crypto_stream_salsa20_xor_wrap_init(state, n, k)
2947}
2948
2949exports.crypto_stream_salsa20_xor_wrap_update = function (state, c, m) {
2950 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2951 assert(
2952 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2953 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2954 )
2955 assert(ArrayBuffer.isView(c), 'c must be a typed array')
2956 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2957 assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
2958
2959 binding.crypto_stream_salsa20_xor_wrap_update(state, c, m)
2960}
2961
2962exports.crypto_stream_salsa20_xor_wrap_final = function (state) {
2963 assert(ArrayBuffer.isView(state), 'state must be a typed array')
2964 assert(
2965 state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
2966 "state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
2967 )
2968
2969 binding.crypto_stream_salsa20_xor_wrap_final(state)
2970}
2971
2972// experimental
2973
2974exports.extension_tweak_ed25519_base = function (n, p, ns) {
2975 assert(ArrayBuffer.isView(n), 'n must be a typed array')
2976 assert(
2977 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
2978 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
2979 )
2980 assert(ArrayBuffer.isView(p), 'p must be a typed array')
2981 assert(
2982 p.byteLength === binding.extension_tweak_ed25519_BYTES,
2983 "p must be 'extension_tweak_ed25519_BYTES' bytes"
2984 )
2985
2986 binding.extension_tweak_ed25519_base(n, p, ns)
2987}
2988
2989exports.extension_tweak_ed25519_sign_detached = function (sig, m, scalar, pk) {
2990 assert(ArrayBuffer.isView(sig), 'sig must be a typed array')
2991 assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes")
2992 assert(ArrayBuffer.isView(m), 'm must be a typed array')
2993 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
2994 assert(
2995 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
2996 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
2997 )
2998
2999 if (pk) {
3000 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3001 assert(
3002 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3003 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3004 )
3005 }
3006
3007 const res = binding.extension_tweak_ed25519_sign_detached(sig, m, scalar, pk)
3008
3009 if (res !== 0) throw new Error('failed to compute signature')
3010}
3011
3012exports.extension_tweak_ed25519_sk_to_scalar = function (n, sk) {
3013 assert(ArrayBuffer.isView(n), 'n must be a typed array')
3014 assert(
3015 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3016 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3017 )
3018 assert(ArrayBuffer.isView(sk), 'sk must be a typed array')
3019 assert(
3020 sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
3021 "sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
3022 )
3023
3024 binding.extension_tweak_ed25519_sk_to_scalar(n, sk)
3025}
3026
3027exports.extension_tweak_ed25519_scalar = function (scalarOut, scalar, ns) {
3028 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3029 assert(
3030 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3031 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3032 )
3033 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
3034 assert(
3035 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3036 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3037 )
3038
3039 binding.extension_tweak_ed25519_scalar(scalarOut, scalar, ns)
3040}
3041
3042exports.extension_tweak_ed25519_pk = function (tpk, pk, ns) {
3043 assert(ArrayBuffer.isView(tpk), 'tpk must be a typed array')
3044 assert(
3045 tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3046 "tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3047 )
3048 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3049 assert(
3050 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3051 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3052 )
3053
3054 const res = binding.extension_tweak_ed25519_pk(tpk, pk, ns)
3055
3056 if (res !== 0) throw new Error('failed to tweak public key')
3057}
3058
3059exports.extension_tweak_ed25519_keypair = function (pk, scalarOut, scalarIn, ns) {
3060 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3061 assert(
3062 pk.byteLength === binding.extension_tweak_ed25519_BYTES,
3063 "pk must be 'extension_tweak_ed25519_BYTES' bytes"
3064 )
3065 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3066 assert(
3067 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3068 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3069 )
3070 assert(ArrayBuffer.isView(scalarIn), 'scalarIn must be a typed array')
3071 assert(
3072 scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3073 "scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3074 )
3075
3076 binding.extension_tweak_ed25519_keypair(pk, scalarOut, scalarIn, ns)
3077}
3078
3079exports.extension_tweak_ed25519_scalar_add = function (scalarOut, scalar, n) {
3080 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3081 assert(
3082 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3083 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3084 )
3085 assert(ArrayBuffer.isView(scalar), 'scalar must be a typed array')
3086 assert(
3087 scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3088 "scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3089 )
3090 assert(ArrayBuffer.isView(n), 'n must be a typed array')
3091 assert(
3092 n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3093 "n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3094 )
3095
3096 binding.extension_tweak_ed25519_scalar_add(scalarOut, scalar, n)
3097}
3098
3099exports.extension_tweak_ed25519_pk_add = function (tpk, pk, p) {
3100 assert(ArrayBuffer.isView(tpk), 'tpk must be a typed array')
3101 assert(
3102 tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3103 "tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3104 )
3105 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3106 assert(
3107 pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3108 "pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3109 )
3110 assert(ArrayBuffer.isView(p), 'p must be a typed array')
3111 assert(
3112 p.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
3113 "p must be 'crypto_sign_PUBLICKEYBYTES' bytes"
3114 )
3115
3116 const res = binding.extension_tweak_ed25519_pk_add(tpk, pk, p)
3117
3118 if (res !== 0) throw new Error('failed to add tweak to public key')
3119}
3120
3121exports.extension_tweak_ed25519_keypair_add = function (pk, scalarOut, scalarIn, tweak) {
3122 assert(ArrayBuffer.isView(pk), 'pk must be a typed array')
3123 assert(
3124 pk.byteLength === binding.extension_tweak_ed25519_BYTES,
3125 "pk must be 'extension_tweak_ed25519_BYTES' bytes"
3126 )
3127 assert(ArrayBuffer.isView(scalarOut), 'scalarOut must be a typed array')
3128 assert(
3129 scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3130 "scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3131 )
3132 assert(ArrayBuffer.isView(scalarIn), 'scalarIn must be a typed array')
3133 assert(
3134 scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3135 "scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3136 )
3137 assert(ArrayBuffer.isView(tweak), 'tweak must be a typed array')
3138 assert(
3139 tweak.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
3140 "tweak must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
3141 )
3142
3143 const res = binding.extension_tweak_ed25519_keypair_add(pk, scalarOut, scalarIn, tweak)
3144
3145 if (res !== 0) throw new Error('failed to add tweak to keypair')
3146}
3147
3148exports.extension_pbkdf2_sha512_async = function (out, passwd, salt, iter, outlen, callback) {
3149 assert(
3150 iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
3151 "iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
3152 )
3153 assert(
3154 outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
3155 "outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
3156 )
3157 assert(ArrayBuffer.isView(out), 'out must be a typed array')
3158 assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes")
3159 assert(out.byteLength > 0, 'out must not be empty')
3160 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
3161 assert(passwd.byteLength > 0, 'passwd must not be empty')
3162 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
3163 assert(salt.byteLength > 0, 'salt must not be empty')
3164
3165 const [done, promise] = checkStatus(callback)
3166
3167 binding.extension_pbkdf2_sha512_async(
3168 out.buffer,
3169 out.byteOffset,
3170 out.byteLength,
3171
3172 passwd.buffer,
3173 passwd.byteOffset,
3174 passwd.byteLength,
3175
3176 salt.buffer,
3177 salt.byteOffset,
3178 salt.byteLength,
3179
3180 iter,
3181 outlen,
3182
3183 done
3184 )
3185
3186 return promise
3187}
3188
3189exports.extension_pbkdf2_sha512 = function (out, passwd, salt, iter, outlen) {
3190 assert(
3191 iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
3192 "iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
3193 )
3194 assert(
3195 outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
3196 "outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
3197 )
3198 assert(ArrayBuffer.isView(out), 'out must be a typed array')
3199 assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes")
3200 assert(out.byteLength > 0, 'out must not be empty')
3201 assert(ArrayBuffer.isView(passwd), 'passwd must be a typed array')
3202 assert(passwd.byteLength > 0, 'passwd must not be empty')
3203 assert(ArrayBuffer.isView(salt), 'salt must be a typed array')
3204 assert(salt.byteLength > 0, 'salt must not be empty')
3205
3206 const res = binding.extension_pbkdf2_sha512(out, passwd, salt, iter, outlen)
3207
3208 if (res !== 0) throw new Error('failed to add tweak to public key')
3209}
3210
3211function checkStatus(callback, booleanResult = false) {
3212 let done, promise
3213
3214 if (typeof callback === 'function') {
3215 done = function (status) {
3216 if (booleanResult) callback(null, status === 0)
3217 else if (status === 0) callback(null)
3218 else callback(new Error('status: ' + status))
3219 }
3220 } else {
3221 promise = new Promise(function (resolve, reject) {
3222 done = function (status) {
3223 if (booleanResult) resolve(status === 0)
3224 else if (status === 0) resolve()
3225 else reject(new Error('status: ' + status))
3226 }
3227 })
3228 }
3229
3230 return [done, promise]
3231}
node_modules/sodium-secretstream/node_modules/sodium-native/package.json +62 -0
……@@ -0,0 +1,62 @@
1{
2 "name": "sodium-native",
3 "version": "5.1.0",
4 "description": "Low level bindings for libsodium",
5 "main": "index.js",
6 "files": [
7 "index.js",
8 "binding.cc",
9 "binding.js",
10 "extensions",
11 "prebuilds",
12 "CMakeLists.txt"
13 ],
14 "imports": {
15 "assert": {
16 "bare": "bare-assert",
17 "node": "assert"
18 }
19 },
20 "addon": true,
21 "dependencies": {
22 "bare-assert": "^1.2.0",
23 "require-addon": "^1.1.0",
24 "which-runtime": "^1.2.1"
25 },
26 "devDependencies": {
27 "bare-compat-napi": "^1.3.5",
28 "brittle": "^3.16.2",
29 "cmake-bare": "^1.6.1",
30 "cmake-fetch": "^1.4.3",
31 "cmake-napi": "^1.2.1",
32 "prettier": "^3.6.2",
33 "prettier-config-holepunch": "^2.0.0"
34 },
35 "scripts": {
36 "test": "prettier . --check && npm run test:node && npm run test:bare",
37 "test:node": "node test/all.js",
38 "test:bare": "bare test/all.js"
39 },
40 "standard": {
41 "ignore": [
42 "/test/fixtures/*.js"
43 ]
44 },
45 "engines": {
46 "bare": ">=1.16.0"
47 },
48 "repository": {
49 "type": "git",
50 "url": "git+https://github.com/holepunchto/sodium-native.git"
51 },
52 "contributors": [
53 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
54 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
55 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
56 ],
57 "license": "MIT",
58 "bugs": {
59 "url": "https://github.com/holepunchto/sodium-native/issues"
60 },
61 "homepage": "https://github.com/holepunchto/sodium-native"
62}
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/android-arm/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/android-arm/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/android-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/android-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/android-ia32/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/android-ia32/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/android-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/android-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/darwin-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/darwin-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/ios-arm64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/ios-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/ios-x64-simulator/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/linux-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/win32-arm64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/win32-x64/sodium-native.bare +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-native/prebuilds/win32-x64/sodium-native.node +0 -0
(no content changes — binary or rename)
node_modules/sodium-secretstream/node_modules/sodium-universal/LICENSE.md +7 -0
……@@ -0,0 +1,7 @@
1Copyright 2017 Mathias Buus & Emil Bay
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
node_modules/sodium-secretstream/node_modules/sodium-universal/README.md +288 -0
……@@ -0,0 +1,288 @@
1# sodium-universal
2
3Universal wrapper for `sodium-javascript` and `sodium-native` working in Node.js and the Browser
4
5```sh
6npm install sodium-universal
7```
8
9`sodium-native` ships with prebuilds for macOS, Windows, and Linux.
10
11Note that the module itself is generated on a prepublish hook.
12
13## Usage
14
15```js
16var sodium = require('sodium-universal')
17
18var rnd = Buffer.allocUnsafe(12) // Cryptographically random data
19sodium.randombytes_buf(rnd)
20
21console.log(rnd.toString('hex'))
22
23```
24
25Works seamlessly with Node.js:
26
27```sh
28$ node example.js
29c7dbd46a6cc84ff2e0d1285c
30```
31
32And the browser:
33
34First install the peer dep, `sodium-javascript`.
35
36```sh
37npm install --save sodium-javascript
38```
39
40And then browserify
41
42```sh
43browserify example.js > bundle.js
44```
45
46## Introduction
47
48[`libsodium`](https://download.libsodium.org/doc/) is a collection of cryptographic primitives, providing a low-level foundation to build higher-level cryptographic applications and protocols. It is often put in contrast to RSA based cryptography and OpenSSL, even though they all share overlapping algorithms and target slightly different audiences. Sodium is a collection of modern collection of primitives, fulfilling the same cryptographic tasks, but based on simpler and more efficient algorithms.
49
50This library provides seamless bindings to [`sodium-native`](https://github.com/sodium-friends/sodium-native), which is the original C implementation of `libsodium` exposed as a Node native module. For the browser we expose [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript), using the `package.json` [`browser`](https://github.com/defunctzombie/package-browser-field-spec) field, which is supported by most bundlers.
51
52## API
53
54Please refer to [`sodium-native`](https://github.com/sodium-friends/sodium-native#api) and [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript#api). Note that the two modules do not yet have feature parity, where `sodium-native` is the more featureful of the two.
55
56## Compatibilty
57
58<!-- Generated by build-scripts/symbols.js with
59 sodium-native@3.2.0
60 sodium-javascript@0.6.0 -->
61| C Library Symbol | `sodium-native` | `sodium-javascript` |
62|:--------------------------------------------------------:|:--------------------:|:--------------------:|
63| `crypto_aead_chacha20poly1305_ietf_ABYTES` | :white_check_mark: | :white_check_mark: |
64| `crypto_aead_chacha20poly1305_ietf_decrypt` | :white_check_mark: | :white_check_mark: |
65| `crypto_aead_chacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :white_check_mark: |
66| `crypto_aead_chacha20poly1305_ietf_encrypt` | :white_check_mark: | :white_check_mark: |
67| `crypto_aead_chacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :white_check_mark: |
68| `crypto_aead_chacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
69| `crypto_aead_chacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
70| `crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
71| `crypto_aead_chacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :white_check_mark: |
72| `crypto_aead_chacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :white_check_mark: |
73| `crypto_aead_xchacha20poly1305_ietf_ABYTES` | :white_check_mark: | :small_red_triangle: |
74| `crypto_aead_xchacha20poly1305_ietf_decrypt` | :white_check_mark: | :small_red_triangle: |
75| `crypto_aead_xchacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :small_red_triangle: |
76| `crypto_aead_xchacha20poly1305_ietf_encrypt` | :white_check_mark: | :small_red_triangle: |
77| `crypto_aead_xchacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :small_red_triangle: |
78| `crypto_aead_xchacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
79| `crypto_aead_xchacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
80| `crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
81| `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :small_red_triangle: |
82| `crypto_aead_xchacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :small_red_triangle: |
83| `crypto_auth` | :white_check_mark: | :small_red_triangle: |
84| `crypto_auth_BYTES` | :white_check_mark: | :small_red_triangle: |
85| `crypto_auth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
86| `crypto_auth_verify` | :white_check_mark: | :small_red_triangle: |
87| `crypto_box_BEFORENMBYTES` | :small_red_triangle: | :white_check_mark: |
88| `crypto_box_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
89| `crypto_box_detached` | :white_check_mark: | :small_red_triangle: |
90| `crypto_box_easy` | :white_check_mark: | :small_red_triangle: |
91| `crypto_box_keypair` | :white_check_mark: | :white_check_mark: |
92| `crypto_box_MACBYTES` | :white_check_mark: | :small_red_triangle: |
93| `crypto_box_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
94| `crypto_box_open_detached` | :white_check_mark: | :small_red_triangle: |
95| `crypto_box_open_easy` | :white_check_mark: | :small_red_triangle: |
96| `crypto_box_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
97| `crypto_box_seal` | :white_check_mark: | :white_check_mark: |
98| `crypto_box_seal_open` | :white_check_mark: | :white_check_mark: |
99| `crypto_box_SEALBYTES` | :white_check_mark: | :white_check_mark: |
100| `crypto_box_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
101| `crypto_box_seed_keypair` | :white_check_mark: | :white_check_mark: |
102| `crypto_box_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
103| `crypto_box_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
104| `crypto_core_ed25519_add` | :white_check_mark: | :small_red_triangle: |
105| `crypto_core_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
106| `crypto_core_ed25519_from_uniform` | :white_check_mark: | :small_red_triangle: |
107| `crypto_core_ed25519_is_valid_point` | :white_check_mark: | :small_red_triangle: |
108| `crypto_core_ed25519_NONREDUCEDSCALARBYTES` | :white_check_mark: | :small_red_triangle: |
109| `crypto_core_ed25519_scalar_add` | :white_check_mark: | :small_red_triangle: |
110| `crypto_core_ed25519_scalar_complement` | :white_check_mark: | :small_red_triangle: |
111| `crypto_core_ed25519_scalar_invert` | :white_check_mark: | :small_red_triangle: |
112| `crypto_core_ed25519_scalar_negate` | :white_check_mark: | :small_red_triangle: |
113| `crypto_core_ed25519_scalar_random` | :white_check_mark: | :small_red_triangle: |
114| `crypto_core_ed25519_scalar_reduce` | :white_check_mark: | :small_red_triangle: |
115| `crypto_core_ed25519_scalar_sub` | :white_check_mark: | :small_red_triangle: |
116| `crypto_core_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
117| `crypto_core_ed25519_sub` | :white_check_mark: | :small_red_triangle: |
118| `crypto_core_ed25519_UNIFORMBYTES` | :white_check_mark: | :small_red_triangle: |
119| `crypto_generichash` | :white_check_mark: | :white_check_mark: |
120| `crypto_generichash_BYTES` | :white_check_mark: | :white_check_mark: |
121| `crypto_generichash_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
122| `crypto_generichash_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
123| `crypto_generichash_final` | :white_check_mark: | :small_red_triangle: |
124| `crypto_generichash_init` | :white_check_mark: | :small_red_triangle: |
125| `crypto_generichash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
126| `crypto_generichash_KEYBYTES_MAX` | :white_check_mark: | :white_check_mark: |
127| `crypto_generichash_KEYBYTES_MIN` | :white_check_mark: | :white_check_mark: |
128| `crypto_generichash_keygen` | :white_check_mark: | :small_red_triangle: |
129| `crypto_generichash_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
130| `crypto_generichash_update` | :white_check_mark: | :small_red_triangle: |
131| `crypto_hash` | :white_check_mark: | :white_check_mark: |
132| `crypto_hash_BYTES` | :white_check_mark: | :white_check_mark: |
133| `crypto_hash_sha256` | :white_check_mark: | :white_check_mark: |
134| `crypto_hash_sha256_BYTES` | :white_check_mark: | :white_check_mark: |
135| `crypto_hash_sha256_final` | :white_check_mark: | :small_red_triangle: |
136| `crypto_hash_sha256_init` | :white_check_mark: | :small_red_triangle: |
137| `crypto_hash_sha256_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
138| `crypto_hash_sha256_update` | :white_check_mark: | :small_red_triangle: |
139| `crypto_hash_sha512` | :white_check_mark: | :white_check_mark: |
140| `crypto_hash_sha512_BYTES` | :white_check_mark: | :white_check_mark: |
141| `crypto_hash_sha512_final` | :white_check_mark: | :small_red_triangle: |
142| `crypto_hash_sha512_init` | :white_check_mark: | :small_red_triangle: |
143| `crypto_hash_sha512_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
144| `crypto_hash_sha512_update` | :white_check_mark: | :small_red_triangle: |
145| `crypto_kdf_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
146| `crypto_kdf_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
147| `crypto_kdf_CONTEXTBYTES` | :white_check_mark: | :white_check_mark: |
148| `crypto_kdf_derive_from_key` | :white_check_mark: | :white_check_mark: |
149| `crypto_kdf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
150| `crypto_kdf_keygen` | :white_check_mark: | :white_check_mark: |
151| `crypto_kx_client_session_keys` | :white_check_mark: | :small_red_triangle: |
152| `crypto_kx_keypair` | :white_check_mark: | :white_check_mark: |
153| `crypto_kx_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
154| `crypto_kx_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
155| `crypto_kx_seed_keypair` | :white_check_mark: | :white_check_mark: |
156| `crypto_kx_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
157| `crypto_kx_server_session_keys` | :white_check_mark: | :small_red_triangle: |
158| `crypto_kx_SESSIONKEYBYTES` | :white_check_mark: | :small_red_triangle: |
159| `crypto_onetimeauth` | :white_check_mark: | :white_check_mark: |
160| `crypto_onetimeauth_BYTES` | :white_check_mark: | :small_red_triangle: |
161| `crypto_onetimeauth_final` | :white_check_mark: | :small_red_triangle: |
162| `crypto_onetimeauth_init` | :white_check_mark: | :small_red_triangle: |
163| `crypto_onetimeauth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
164| `crypto_onetimeauth_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
165| `crypto_onetimeauth_update` | :white_check_mark: | :small_red_triangle: |
166| `crypto_onetimeauth_verify` | :white_check_mark: | :white_check_mark: |
167| `crypto_pwhash` | :white_check_mark: | :small_red_triangle: |
168| `crypto_pwhash_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
169| `crypto_pwhash_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
170| `crypto_pwhash_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
171| `crypto_pwhash_scryptsalsa208sha256` | :white_check_mark: | :small_red_triangle: |
172| `crypto_pwhash_scryptsalsa208sha256_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
173| `crypto_pwhash_scryptsalsa208sha256_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
174| `crypto_pwhash_scryptsalsa208sha256_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
175| `crypto_pwhash_scryptsalsa208sha256_str` | :white_check_mark: | :small_red_triangle: |
176| `crypto_pwhash_scryptsalsa208sha256_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
177| `crypto_pwhash_scryptsalsa208sha256_str_verify` | :white_check_mark: | :small_red_triangle: |
178| `crypto_pwhash_scryptsalsa208sha256_STRBYTES` | :white_check_mark: | :small_red_triangle: |
179| `crypto_pwhash_str` | :white_check_mark: | :small_red_triangle: |
180| `crypto_pwhash_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
181| `crypto_pwhash_str_verify` | :white_check_mark: | :small_red_triangle: |
182| `crypto_pwhash_STRBYTES` | :white_check_mark: | :small_red_triangle: |
183| `crypto_scalarmult` | :white_check_mark: | :white_check_mark: |
184| `crypto_scalarmult_base` | :white_check_mark: | :white_check_mark: |
185| `crypto_scalarmult_BYTES` | :white_check_mark: | :white_check_mark: |
186| `crypto_scalarmult_ed25519` | :white_check_mark: | :small_red_triangle: |
187| `crypto_scalarmult_ed25519_base` | :white_check_mark: | :small_red_triangle: |
188| `crypto_scalarmult_ed25519_base_noclamp` | :white_check_mark: | :small_red_triangle: |
189| `crypto_scalarmult_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
190| `crypto_scalarmult_ed25519_noclamp` | :white_check_mark: | :small_red_triangle: |
191| `crypto_scalarmult_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
192| `crypto_scalarmult_SCALARBYTES` | :white_check_mark: | :white_check_mark: |
193| `crypto_secretbox` | :small_red_triangle: | :white_check_mark: |
194| `crypto_secretbox_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
195| `crypto_secretbox_detached` | :white_check_mark: | :white_check_mark: |
196| `crypto_secretbox_easy` | :white_check_mark: | :white_check_mark: |
197| `crypto_secretbox_KEYBYTES` | :white_check_mark: | :white_check_mark: |
198| `crypto_secretbox_MACBYTES` | :white_check_mark: | :white_check_mark: |
199| `crypto_secretbox_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
200| `crypto_secretbox_open` | :small_red_triangle: | :white_check_mark: |
201| `crypto_secretbox_open_detached` | :white_check_mark: | :white_check_mark: |
202| `crypto_secretbox_open_easy` | :white_check_mark: | :white_check_mark: |
203| `crypto_secretbox_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
204| `crypto_secretstream_xchacha20poly1305_ABYTES` | :white_check_mark: | :small_red_triangle: |
205| `crypto_secretstream_xchacha20poly1305_HEADERBYTES` | :white_check_mark: | :small_red_triangle: |
206| `crypto_secretstream_xchacha20poly1305_init_pull` | :white_check_mark: | :small_red_triangle: |
207| `crypto_secretstream_xchacha20poly1305_init_push` | :white_check_mark: | :small_red_triangle: |
208| `crypto_secretstream_xchacha20poly1305_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
209| `crypto_secretstream_xchacha20poly1305_keygen` | :white_check_mark: | :small_red_triangle: |
210| `crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
211| `crypto_secretstream_xchacha20poly1305_pull` | :white_check_mark: | :small_red_triangle: |
212| `crypto_secretstream_xchacha20poly1305_push` | :white_check_mark: | :small_red_triangle: |
213| `crypto_secretstream_xchacha20poly1305_rekey` | :white_check_mark: | :small_red_triangle: |
214| `crypto_secretstream_xchacha20poly1305_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
215| `crypto_shorthash` | :white_check_mark: | :white_check_mark: |
216| `crypto_shorthash_BYTES` | :white_check_mark: | :white_check_mark: |
217| `crypto_shorthash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
218| `crypto_sign` | :white_check_mark: | :white_check_mark: |
219| `crypto_sign_BYTES` | :white_check_mark: | :white_check_mark: |
220| `crypto_sign_detached` | :white_check_mark: | :white_check_mark: |
221| `crypto_sign_ed25519_pk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
222| `crypto_sign_ed25519_sk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
223| `crypto_sign_ed25519_sk_to_pk` | :white_check_mark: | :small_red_triangle: |
224| `crypto_sign_keypair` | :white_check_mark: | :white_check_mark: |
225| `crypto_sign_open` | :white_check_mark: | :white_check_mark: |
226| `crypto_sign_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
227| `crypto_sign_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
228| `crypto_sign_seed_keypair` | :white_check_mark: | :white_check_mark: |
229| `crypto_sign_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
230| `crypto_sign_verify_detached` | :white_check_mark: | :white_check_mark: |
231| `crypto_stream` | :white_check_mark: | :white_check_mark: |
232| `crypto_stream_chacha20` | :white_check_mark: | :white_check_mark: |
233| `crypto_stream_chacha20_ietf` | :white_check_mark: | :white_check_mark: |
234| `crypto_stream_chacha20_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
235| `crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
236| `crypto_stream_chacha20_ietf_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
237| `crypto_stream_chacha20_ietf_xor` | :white_check_mark: | :white_check_mark: |
238| `crypto_stream_chacha20_ietf_xor_ic` | :white_check_mark: | :white_check_mark: |
239| `crypto_stream_chacha20_KEYBYTES` | :white_check_mark: | :white_check_mark: |
240| `crypto_stream_chacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
241| `crypto_stream_chacha20_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
242| `crypto_stream_chacha20_xor` | :white_check_mark: | :white_check_mark: |
243| `crypto_stream_chacha20_xor_ic` | :white_check_mark: | :white_check_mark: |
244| `crypto_stream_KEYBYTES` | :white_check_mark: | :white_check_mark: |
245| `crypto_stream_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
246| `crypto_stream_salsa20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
247| `crypto_stream_salsa20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
248| `crypto_stream_salsa20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
249| `crypto_stream_salsa20_xor` | :white_check_mark: | :small_red_triangle: |
250| `crypto_stream_salsa20_xor_ic` | :white_check_mark: | :small_red_triangle: |
251| `crypto_stream_xchacha20` | :white_check_mark: | :small_red_triangle: |
252| `crypto_stream_xchacha20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
253| `crypto_stream_xchacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
254| `crypto_stream_xchacha20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
255| `crypto_stream_xchacha20_xor` | :white_check_mark: | :small_red_triangle: |
256| `crypto_stream_xchacha20_xor_ic` | :white_check_mark: | :small_red_triangle: |
257| `crypto_stream_xor` | :white_check_mark: | :white_check_mark: |
258| `crypto_verify_16` | :small_red_triangle: | :white_check_mark: |
259| `crypto_verify_32` | :small_red_triangle: | :white_check_mark: |
260| `randombytes_buf` | :white_check_mark: | :white_check_mark: |
261| `randombytes_buf_deterministic` | :white_check_mark: | :small_red_triangle: |
262| `randombytes_random` | :white_check_mark: | :small_red_triangle: |
263| `randombytes_SEEDBYTES` | :white_check_mark: | :small_red_triangle: |
264| `randombytes_uniform` | :white_check_mark: | :small_red_triangle: |
265| `sodium_add` | :white_check_mark: | :small_red_triangle: |
266| `sodium_compare` | :white_check_mark: | :small_red_triangle: |
267| `sodium_free` | :white_check_mark: | :small_red_triangle: |
268| `sodium_increment` | :white_check_mark: | :small_red_triangle: |
269| `sodium_is_zero` | :white_check_mark: | :white_check_mark: |
270| `sodium_malloc` | :white_check_mark: | :white_check_mark: |
271| `sodium_memcmp` | :white_check_mark: | :white_check_mark: |
272| `sodium_memzero` | :white_check_mark: | :white_check_mark: |
273| `sodium_mlock` | :white_check_mark: | :small_red_triangle: |
274| `sodium_mprotect_noaccess` | :white_check_mark: | :small_red_triangle: |
275| `sodium_mprotect_readonly` | :white_check_mark: | :small_red_triangle: |
276| `sodium_mprotect_readwrite` | :white_check_mark: | :small_red_triangle: |
277| `sodium_munlock` | :white_check_mark: | :small_red_triangle: |
278| `sodium_pad` | :white_check_mark: | :small_red_triangle: |
279| `sodium_sub` | :white_check_mark: | :small_red_triangle: |
280| `sodium_unpad` | :white_check_mark: | :small_red_triangle: |
281
282### Missing altogether (Ctrl + F friendly)
283
284`crypto_aead_aes256gcm_ABYTES`, `crypto_aead_aes256gcm_beforenm`, `crypto_aead_aes256gcm_decrypt`, `crypto_aead_aes256gcm_decrypt_afternm`, `crypto_aead_aes256gcm_decrypt_detached`, `crypto_aead_aes256gcm_decrypt_detached_afternm`, `crypto_aead_aes256gcm_encrypt`, `crypto_aead_aes256gcm_encrypt_afternm`, `crypto_aead_aes256gcm_encrypt_detached`, `crypto_aead_aes256gcm_encrypt_detached_afternm`, `crypto_aead_aes256gcm_is_available`, `crypto_aead_aes256gcm_KEYBYTES`, `crypto_aead_aes256gcm_keygen`, `crypto_aead_aes256gcm_MESSAGEBYTES_MAX`, `crypto_aead_aes256gcm_NPUBBYTES`, `crypto_aead_aes256gcm_NSECBYTES`, `crypto_aead_aes256gcm_STATEBYTES`, `crypto_aead_chacha20poly1305_ABYTES`, `crypto_aead_chacha20poly1305_decrypt`, `crypto_aead_chacha20poly1305_decrypt_detached`, `crypto_aead_chacha20poly1305_encrypt`, `crypto_aead_chacha20poly1305_encrypt_detached`, `crypto_aead_chacha20poly1305_KEYBYTES`, `crypto_aead_chacha20poly1305_keygen`, `crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX`, `crypto_aead_chacha20poly1305_NPUBBYTES`, `crypto_aead_chacha20poly1305_NSECBYTES`, `crypto_auth_hmacsha256`, `crypto_auth_hmacsha256_BYTES`, `crypto_auth_hmacsha256_final`, `crypto_auth_hmacsha256_init`, `crypto_auth_hmacsha256_KEYBYTES`, `crypto_auth_hmacsha256_keygen`, `crypto_auth_hmacsha256_STATEBYTES`, `crypto_auth_hmacsha256_update`, `crypto_auth_hmacsha256_verify`, `crypto_auth_hmacsha512`, `crypto_auth_hmacsha512256`, `crypto_auth_hmacsha512256_BYTES`, `crypto_auth_hmacsha512256_final`, `crypto_auth_hmacsha512256_init`, `crypto_auth_hmacsha512256_KEYBYTES`, `crypto_auth_hmacsha512256_keygen`, `crypto_auth_hmacsha512256_STATEBYTES`, `crypto_auth_hmacsha512256_update`, `crypto_auth_hmacsha512256_verify`, `crypto_auth_hmacsha512_BYTES`, `crypto_auth_hmacsha512_final`, `crypto_auth_hmacsha512_init`, `crypto_auth_hmacsha512_KEYBYTES`, `crypto_auth_hmacsha512_keygen`, `crypto_auth_hmacsha512_STATEBYTES`, `crypto_auth_hmacsha512_update`, `crypto_auth_hmacsha512_verify`, `crypto_auth_keygen`, `crypto_auth_primitive`, `crypto_box`, `crypto_box_afternm`, `crypto_box_beforenm`, `crypto_box_curve25519xchacha20poly1305_beforenm`, `crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xchacha20poly1305_detached`, `crypto_box_curve25519xchacha20poly1305_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_easy`, `crypto_box_curve25519xchacha20poly1305_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_keypair`, `crypto_box_curve25519xchacha20poly1305_MACBYTES`, `crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xchacha20poly1305_NONCEBYTES`, `crypto_box_curve25519xchacha20poly1305_open_detached`, `crypto_box_curve25519xchacha20poly1305_open_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_open_easy`, `crypto_box_curve25519xchacha20poly1305_open_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seal`, `crypto_box_curve25519xchacha20poly1305_seal_open`, `crypto_box_curve25519xchacha20poly1305_SEALBYTES`, `crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seed_keypair`, `crypto_box_curve25519xchacha20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305`, `crypto_box_curve25519xsalsa20poly1305_afternm`, `crypto_box_curve25519xsalsa20poly1305_beforenm`, `crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES`, `crypto_box_curve25519xsalsa20poly1305_keypair`, `crypto_box_curve25519xsalsa20poly1305_MACBYTES`, `crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xsalsa20poly1305_NONCEBYTES`, `crypto_box_curve25519xsalsa20poly1305_open`, `crypto_box_curve25519xsalsa20poly1305_open_afternm`, `crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_seed_keypair`, `crypto_box_curve25519xsalsa20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305_ZEROBYTES`, `crypto_box_detached_afternm`, `crypto_box_easy_afternm`, `crypto_box_MESSAGEBYTES_MAX`, `crypto_box_open`, `crypto_box_open_afternm`, `crypto_box_open_detached_afternm`, `crypto_box_open_easy_afternm`, `crypto_box_primitive`, `crypto_core_ed25519_from_hash`, `crypto_core_ed25519_HASHBYTES`, `crypto_core_ed25519_random`, `crypto_core_ed25519_scalar_mul`, `crypto_core_hchacha20`, `crypto_core_hchacha20_CONSTBYTES`, `crypto_core_hchacha20_INPUTBYTES`, `crypto_core_hchacha20_KEYBYTES`, `crypto_core_hchacha20_OUTPUTBYTES`, `crypto_core_hsalsa20`, `crypto_core_hsalsa20_CONSTBYTES`, `crypto_core_hsalsa20_INPUTBYTES`, `crypto_core_hsalsa20_KEYBYTES`, `crypto_core_hsalsa20_OUTPUTBYTES`, `crypto_core_ristretto255_add`, `crypto_core_ristretto255_BYTES`, `crypto_core_ristretto255_from_hash`, `crypto_core_ristretto255_HASHBYTES`, `crypto_core_ristretto255_is_valid_point`, `crypto_core_ristretto255_NONREDUCEDSCALARBYTES`, `crypto_core_ristretto255_random`, `crypto_core_ristretto255_scalar_add`, `crypto_core_ristretto255_scalar_complement`, `crypto_core_ristretto255_scalar_invert`, `crypto_core_ristretto255_scalar_mul`, `crypto_core_ristretto255_scalar_negate`, `crypto_core_ristretto255_scalar_random`, `crypto_core_ristretto255_scalar_reduce`, `crypto_core_ristretto255_scalar_sub`, `crypto_core_ristretto255_SCALARBYTES`, `crypto_core_ristretto255_sub`, `crypto_core_salsa20`, `crypto_core_salsa2012`, `crypto_core_salsa2012_CONSTBYTES`, `crypto_core_salsa2012_INPUTBYTES`, `crypto_core_salsa2012_KEYBYTES`, `crypto_core_salsa2012_OUTPUTBYTES`, `crypto_core_salsa208`, `crypto_core_salsa208_CONSTBYTES`, `crypto_core_salsa208_INPUTBYTES`, `crypto_core_salsa208_KEYBYTES`, `crypto_core_salsa208_OUTPUTBYTES`, `crypto_core_salsa20_CONSTBYTES`, `crypto_core_salsa20_INPUTBYTES`, `crypto_core_salsa20_KEYBYTES`, `crypto_core_salsa20_OUTPUTBYTES`, `crypto_generichash_blake2b`, `crypto_generichash_blake2b_BYTES`, `crypto_generichash_blake2b_BYTES_MAX`, `crypto_generichash_blake2b_BYTES_MIN`, `crypto_generichash_blake2b_final`, `crypto_generichash_blake2b_init`, `crypto_generichash_blake2b_init_salt_personal`, `crypto_generichash_blake2b_KEYBYTES`, `crypto_generichash_blake2b_KEYBYTES_MAX`, `crypto_generichash_blake2b_KEYBYTES_MIN`, `crypto_generichash_blake2b_keygen`, `crypto_generichash_blake2b_PERSONALBYTES`, `crypto_generichash_blake2b_salt_personal`, `crypto_generichash_blake2b_SALTBYTES`, `crypto_generichash_blake2b_STATEBYTES`, `crypto_generichash_blake2b_update`, `crypto_generichash_primitive`, `crypto_hash_primitive`, `crypto_kdf_blake2b_BYTES_MAX`, `crypto_kdf_blake2b_BYTES_MIN`, `crypto_kdf_blake2b_CONTEXTBYTES`, `crypto_kdf_blake2b_derive_from_key`, `crypto_kdf_blake2b_KEYBYTES`, `crypto_kdf_primitive`, `crypto_kx_primitive`, `crypto_onetimeauth_keygen`, `crypto_onetimeauth_poly1305`, `crypto_onetimeauth_poly1305_BYTES`, `crypto_onetimeauth_poly1305_final`, `crypto_onetimeauth_poly1305_init`, `crypto_onetimeauth_poly1305_KEYBYTES`, `crypto_onetimeauth_poly1305_keygen`, `crypto_onetimeauth_poly1305_STATEBYTES`, `crypto_onetimeauth_poly1305_update`, `crypto_onetimeauth_poly1305_verify`, `crypto_onetimeauth_primitive`, `crypto_pwhash_alg_argon2i13`, `crypto_pwhash_alg_argon2id13`, `crypto_pwhash_alg_default`, `crypto_pwhash_argon2i`, `crypto_pwhash_argon2i_alg_argon2i13`, `crypto_pwhash_argon2i_BYTES_MAX`, `crypto_pwhash_argon2i_BYTES_MIN`, `crypto_pwhash_argon2i_memlimit_interactive`, `crypto_pwhash_argon2i_memlimit_max`, `crypto_pwhash_argon2i_memlimit_min`, `crypto_pwhash_argon2i_memlimit_moderate`, `crypto_pwhash_argon2i_memlimit_sensitive`, `crypto_pwhash_argon2i_opslimit_interactive`, `crypto_pwhash_argon2i_opslimit_max`, `crypto_pwhash_argon2i_opslimit_min`, `crypto_pwhash_argon2i_opslimit_moderate`, `crypto_pwhash_argon2i_opslimit_sensitive`, `crypto_pwhash_argon2i_passwd_max`, `crypto_pwhash_argon2i_passwd_min`, `crypto_pwhash_argon2i_SALTBYTES`, `crypto_pwhash_argon2i_str`, `crypto_pwhash_argon2i_str_needs_rehash`, `crypto_pwhash_argon2i_str_verify`, `crypto_pwhash_argon2i_STRBYTES`, `crypto_pwhash_argon2i_strprefix`, `crypto_pwhash_argon2id`, `crypto_pwhash_argon2id_alg_argon2id13`, `crypto_pwhash_argon2id_BYTES_MAX`, `crypto_pwhash_argon2id_BYTES_MIN`, `crypto_pwhash_argon2id_memlimit_interactive`, `crypto_pwhash_argon2id_memlimit_max`, `crypto_pwhash_argon2id_memlimit_min`, `crypto_pwhash_argon2id_memlimit_moderate`, `crypto_pwhash_argon2id_memlimit_sensitive`, `crypto_pwhash_argon2id_opslimit_interactive`, `crypto_pwhash_argon2id_opslimit_max`, `crypto_pwhash_argon2id_opslimit_min`, `crypto_pwhash_argon2id_opslimit_moderate`, `crypto_pwhash_argon2id_opslimit_sensitive`, `crypto_pwhash_argon2id_passwd_max`, `crypto_pwhash_argon2id_passwd_min`, `crypto_pwhash_argon2id_SALTBYTES`, `crypto_pwhash_argon2id_str`, `crypto_pwhash_argon2id_str_needs_rehash`, `crypto_pwhash_argon2id_str_verify`, `crypto_pwhash_argon2id_STRBYTES`, `crypto_pwhash_argon2id_strprefix`, `crypto_pwhash_memlimit_interactive`, `crypto_pwhash_memlimit_max`, `crypto_pwhash_memlimit_min`, `crypto_pwhash_memlimit_moderate`, `crypto_pwhash_memlimit_sensitive`, `crypto_pwhash_opslimit_interactive`, `crypto_pwhash_opslimit_max`, `crypto_pwhash_opslimit_min`, `crypto_pwhash_opslimit_moderate`, `crypto_pwhash_opslimit_sensitive`, `crypto_pwhash_passwd_max`, `crypto_pwhash_passwd_min`, `crypto_pwhash_primitive`, `crypto_pwhash_scryptsalsa208sha256_ll`, `crypto_pwhash_scryptsalsa208sha256_memlimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_memlimit_max`, `crypto_pwhash_scryptsalsa208sha256_memlimit_min`, `crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_max`, `crypto_pwhash_scryptsalsa208sha256_opslimit_min`, `crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_passwd_max`, `crypto_pwhash_scryptsalsa208sha256_passwd_min`, `crypto_pwhash_scryptsalsa208sha256_strprefix`, `crypto_pwhash_str_alg`, `crypto_pwhash_strprefix`, `crypto_scalarmult_curve25519`, `crypto_scalarmult_curve25519_base`, `crypto_scalarmult_curve25519_BYTES`, `crypto_scalarmult_curve25519_SCALARBYTES`, `crypto_scalarmult_primitive`, `crypto_scalarmult_ristretto255`, `crypto_scalarmult_ristretto255_base`, `crypto_scalarmult_ristretto255_BYTES`, `crypto_scalarmult_ristretto255_SCALARBYTES`, `crypto_secretbox_keygen`, `crypto_secretbox_MESSAGEBYTES_MAX`, `crypto_secretbox_primitive`, `crypto_secretbox_xchacha20poly1305_detached`, `crypto_secretbox_xchacha20poly1305_easy`, `crypto_secretbox_xchacha20poly1305_KEYBYTES`, `crypto_secretbox_xchacha20poly1305_MACBYTES`, `crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xchacha20poly1305_NONCEBYTES`, `crypto_secretbox_xchacha20poly1305_open_detached`, `crypto_secretbox_xchacha20poly1305_open_easy`, `crypto_secretbox_xsalsa20poly1305`, `crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES`, `crypto_secretbox_xsalsa20poly1305_KEYBYTES`, `crypto_secretbox_xsalsa20poly1305_keygen`, `crypto_secretbox_xsalsa20poly1305_MACBYTES`, `crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xsalsa20poly1305_NONCEBYTES`, `crypto_secretbox_xsalsa20poly1305_open`, `crypto_secretbox_xsalsa20poly1305_ZEROBYTES`, `crypto_secretstream_xchacha20poly1305_tag_final`, `crypto_secretstream_xchacha20poly1305_tag_message`, `crypto_secretstream_xchacha20poly1305_tag_push`, `crypto_secretstream_xchacha20poly1305_tag_rekey`, `crypto_shorthash_keygen`, `crypto_shorthash_primitive`, `crypto_shorthash_siphash24`, `crypto_shorthash_siphash24_BYTES`, `crypto_shorthash_siphash24_KEYBYTES`, `crypto_shorthash_siphashx24`, `crypto_shorthash_siphashx24_BYTES`, `crypto_shorthash_siphashx24_KEYBYTES`, `crypto_sign_ed25519`, `crypto_sign_ed25519_BYTES`, `crypto_sign_ed25519_detached`, `crypto_sign_ed25519_keypair`, `crypto_sign_ed25519_MESSAGEBYTES_MAX`, `crypto_sign_ed25519_open`, `crypto_sign_ed25519_PUBLICKEYBYTES`, `crypto_sign_ed25519_SECRETKEYBYTES`, `crypto_sign_ed25519_seed_keypair`, `crypto_sign_ed25519_SEEDBYTES`, `crypto_sign_ed25519_sk_to_seed`, `crypto_sign_ed25519_verify_detached`, `crypto_sign_ed25519ph_final_create`, `crypto_sign_ed25519ph_final_verify`, `crypto_sign_ed25519ph_init`, `crypto_sign_ed25519ph_STATEBYTES`, `crypto_sign_ed25519ph_update`, `crypto_sign_edwards25519sha512batch`, `crypto_sign_edwards25519sha512batch_keypair`, `crypto_sign_edwards25519sha512batch_open`, `crypto_sign_final_create`, `crypto_sign_final_verify`, `crypto_sign_init`, `crypto_sign_MESSAGEBYTES_MAX`, `crypto_sign_primitive`, `crypto_sign_STATEBYTES`, `crypto_sign_update`, `crypto_stream_chacha20_ietf_keygen`, `crypto_stream_chacha20_keygen`, `crypto_stream_keygen`, `crypto_stream_MESSAGEBYTES_MAX`, `crypto_stream_primitive`, `crypto_stream_salsa20`, `crypto_stream_salsa2012`, `crypto_stream_salsa2012_KEYBYTES`, `crypto_stream_salsa2012_keygen`, `crypto_stream_salsa2012_MESSAGEBYTES_MAX`, `crypto_stream_salsa2012_NONCEBYTES`, `crypto_stream_salsa2012_xor`, `crypto_stream_salsa208`, `crypto_stream_salsa208_KEYBYTES`, `crypto_stream_salsa208_keygen`, `crypto_stream_salsa208_MESSAGEBYTES_MAX`, `crypto_stream_salsa208_NONCEBYTES`, `crypto_stream_salsa208_xor`, `crypto_stream_salsa20_keygen`, `crypto_stream_xchacha20_keygen`, `crypto_stream_xsalsa20`, `crypto_stream_xsalsa20_KEYBYTES`, `crypto_stream_xsalsa20_keygen`, `crypto_stream_xsalsa20_MESSAGEBYTES_MAX`, `crypto_stream_xsalsa20_NONCEBYTES`, `crypto_stream_xsalsa20_xor`, `crypto_stream_xsalsa20_xor_ic`, `crypto_verify_16_BYTES`, `crypto_verify_32_BYTES`, `crypto_verify_64`, `crypto_verify_64_BYTES`, `randombytes`, `randombytes_close`, `randombytes_implementation_name`, `randombytes_internal_implementation`, `randombytes_set_implementation`, `randombytes_stir`, `randombytes_sysrandom_implementation`, `sodium_allocarray`, `sodium_base642bin`, `sodium_base64_encoded_len`, `sodium_bin2base64`, `sodium_bin2hex`, `sodium_hex2bin`, `sodium_init`, `sodium_library_minimal`, `sodium_library_version_major`, `sodium_library_version_minor`, `sodium_misuse`, `sodium_runtime_has_aesni`, `sodium_runtime_has_avx`, `sodium_runtime_has_avx2`, `sodium_runtime_has_avx512f`, `sodium_runtime_has_neon`, `sodium_runtime_has_pclmul`, `sodium_runtime_has_rdrand`, `sodium_runtime_has_sse2`, `sodium_runtime_has_sse3`, `sodium_runtime_has_sse41`, `sodium_runtime_has_ssse3`, `sodium_set_misuse_handler`, `sodium_stackzero`, `sodium_version_string`
285
286## License
287
288[MIT](LICENSE.md)
node_modules/sodium-secretstream/node_modules/sodium-universal/build-scripts/generate.js +33 -0
……@@ -0,0 +1,33 @@
1#!/usr/bin/env node
2
3const fs = require('fs')
4const path = require('path')
5const root = path.dirname(require.resolve('sodium-javascript/package.json'))
6
7const tmp = "module.exports = require('sodium-native')\n"
8
9function recurse (dir) {
10 const ls = fs.readdirSync(dir)
11 const subdir = path.relative(root, dir)
12 if (subdir) fs.mkdirSync(subdir, { recursive: true })
13
14 for (const file of ls) {
15 if (file === 'internal') recurse(path.join(dir, file))
16 if (!/\.js$/i.test(file)) continue
17 if (file === 'example.js') continue
18 if (file === 'test.js') continue
19
20 fs.writeFileSync(path.join(__dirname, '..', subdir, file), tmp)
21 }
22}
23
24recurse(root)
25
26const pkg = require('sodium-javascript/package.json')
27const myPkg = require('../package.json')
28
29for (const key of Object.keys(pkg.dependencies)) {
30 myPkg.dependencies[key] = pkg.dependencies[key]
31}
32
33fs.writeFileSync(path.join(__dirname, '../package.json'), JSON.stringify(myPkg, null, 2) + '\n')
node_modules/sodium-secretstream/node_modules/sodium-universal/build-scripts/symbols.js +32 -0
……@@ -0,0 +1,32 @@
1var exec = require('child_process').execSync
2var path = require('path')
3
4var symbols = exec(`nm -gU "${path.join(require.resolve('sodium-native'), '../prebuilds/darwin-x64/libsodium.dylib')}"`).toString().trim().split('\n')
5var native = new Set(Object.keys(require('sodium-native')).sort())
6var js = new Set(Object.keys(require('sodium-javascript')).sort())
7
8symbols = symbols.map(l => l.split(' ').pop().replace(/^_/, '').replace(/_[^_]*bytes.*/, (s) => s.toUpperCase()))
9
10var missing = []
11
12console.log(`
13<!-- Generated by build-scripts/symbols.js with
14 sodium-native@${require('sodium-native/package.json').version}
15 sodium-javascript@${require('sodium-javascript/package.json').version} -->\
16`)
17
18const max = symbols.filter(s => native.has(s) || js.has(s)).map(s => s.length).reduce((a, b) => Math.max(a, b))
19const lines = ':-' + ''.padEnd(max, '--') + '-:'
20const center = s => s.padStart(Math.floor((max + s.length) / 2), ' ').padEnd(max, ' ')
21
22console.log(`| ${center('C Library Symbol')} | \`sodium-native\` | \`sodium-javascript\` |`)
23console.log(`|${lines}|:--------------------:|:--------------------:|`)
24
25for (var i = 0; i < symbols.length; i++) {
26 var s = symbols[i]
27 if (!(native.has(s) || js.has(s))) missing.push(s)
28 else console.log(`| \`${(s + '`').padEnd(max + 1, ' ')} | ${native.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} | ${js.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} |`)
29}
30
31console.log('\n### Missing altogether (Ctrl + F friendly)\n')
32console.log(missing.map(s => '`' + s + '`').join(', '))
node_modules/sodium-secretstream/node_modules/sodium-universal/build-scripts/transform.js +26 -0
……@@ -0,0 +1,26 @@
1const fs = require('fs')
2const path = require('path')
3const { Transform, PassThrough } = require('stream')
4
5module.exports = function (file, opts) {
6 const basedir = path.resolve(__dirname, '..')
7 const relname = path.relative(basedir, file)
8
9 if (opts._flags.browserField === false) {
10 return new PassThrough()
11 }
12
13 return new Transform({
14 transform (data, enc, cb) {
15 cb()
16 },
17 flush (cb) {
18 const filename = require.resolve('sodium-javascript/' + relname)
19 fs.readFile(filename, (err, buf) => {
20 if (err) return cb(err)
21 this.push(buf)
22 cb(null)
23 })
24 }
25 })
26}
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_aead.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_auth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_box.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_generichash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_hash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_hash_sha256.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_kdf.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_kx.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_onetimeauth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_scalarmult.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_secretbox.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_secretstream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_shorthash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_sign.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_stream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_stream_chacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/crypto_verify.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/helpers.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/index.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/internal/ed25519.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/internal/hchacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/internal/poly1305.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/memory.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/node_modules/sodium-universal/package.json +49 -0
……@@ -0,0 +1,49 @@
1{
2 "name": "sodium-universal",
3 "version": "5.0.1",
4 "description": "Universal wrapper for sodium-javascript and sodium-native working in Node.js and the Browser",
5 "main": "index.js",
6 "dependencies": {
7 "sodium-native": "^5.0.1"
8 },
9 "peerDependencies": {
10 "sodium-javascript": "~0.8.0"
11 },
12 "peerDependenciesMeta": {
13 "sodium-javascript": {
14 "optional": true
15 }
16 },
17 "scripts": {
18 "prepublish": "./build-scripts/generate.js"
19 },
20 "browser": {
21 "sodium-native": "sodium-javascript"
22 },
23 "browserify": {
24 "transform": [
25 "./build-scripts/transform.js"
26 ]
27 },
28 "repository": {
29 "type": "git",
30 "url": "git+https://github.com/holepunchto/sodium-universal.git"
31 },
32 "keywords": [
33 "libsodium",
34 "sodium",
35 "sodium-native",
36 "sodium-javascript",
37 "browserify"
38 ],
39 "contributors": [
40 "Emil Bay <github@tixz.dk> (http://bayes.dk)",
41 "Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)",
42 "Christophe Diederichs <chm-diederichs@hyperdivision.dk>"
43 ],
44 "license": "MIT",
45 "bugs": {
46 "url": "https://github.com/holepunchto/sodium-universal/issues"
47 },
48 "homepage": "https://github.com/holepunchto/sodium-universal#readme"
49}
node_modules/sodium-secretstream/node_modules/sodium-universal/randombytes.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-secretstream/package.json +26 -0
……@@ -0,0 +1,26 @@
1{
2 "name": "sodium-secretstream",
3 "version": "1.2.0",
4 "description": "Wraps libsodiums secretstream in a higher level abstraction",
5 "main": "index.js",
6 "dependencies": {
7 "b4a": "^1.1.1",
8 "sodium-universal": "^5.0.0"
9 },
10 "devDependencies": {
11 "standard": "^17.0.0"
12 },
13 "scripts": {
14 "test": "standard"
15 },
16 "repository": {
17 "type": "git",
18 "url": "https://github.com/mafintosh/sodium-secretstream.git"
19 },
20 "author": "Mathias Buus (@mafintosh)",
21 "license": "MIT",
22 "bugs": {
23 "url": "https://github.com/mafintosh/sodium-secretstream/issues"
24 },
25 "homepage": "https://github.com/mafintosh/sodium-secretstream"
26}
node_modules/sodium-universal/LICENSE.md +7 -0
……@@ -0,0 +1,7 @@
1Copyright 2017 Mathias Buus & Emil Bay
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
node_modules/sodium-universal/README.md +288 -0
……@@ -0,0 +1,288 @@
1# sodium-universal
2
3Universal wrapper for `sodium-javascript` and `sodium-native` working in Node.js and the Browser
4
5```sh
6npm install sodium-universal
7```
8
9`sodium-native` ships with prebuilds for macOS, Windows, and Linux.
10
11Note that the module itself is generated on a prepublish hook.
12
13## Usage
14
15```js
16var sodium = require('sodium-universal')
17
18var rnd = Buffer.allocUnsafe(12) // Cryptographically random data
19sodium.randombytes_buf(rnd)
20
21console.log(rnd.toString('hex'))
22
23```
24
25Works seamlessly with Node.js:
26
27```sh
28$ node example.js
29c7dbd46a6cc84ff2e0d1285c
30```
31
32And the browser:
33
34First install the peer dep, `sodium-javascript`.
35
36```sh
37npm install --save sodium-javascript
38```
39
40And then browserify
41
42```sh
43browserify example.js > bundle.js
44```
45
46## Introduction
47
48[`libsodium`](https://download.libsodium.org/doc/) is a collection of cryptographic primitives, providing a low-level foundation to build higher-level cryptographic applications and protocols. It is often put in contrast to RSA based cryptography and OpenSSL, even though they all share overlapping algorithms and target slightly different audiences. Sodium is a collection of modern collection of primitives, fulfilling the same cryptographic tasks, but based on simpler and more efficient algorithms.
49
50This library provides seamless bindings to [`sodium-native`](https://github.com/sodium-friends/sodium-native), which is the original C implementation of `libsodium` exposed as a Node native module. For the browser we expose [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript), using the `package.json` [`browser`](https://github.com/defunctzombie/package-browser-field-spec) field, which is supported by most bundlers.
51
52## API
53
54Please refer to [`sodium-native`](https://github.com/sodium-friends/sodium-native#api) and [`sodium-javascript`](https://github.com/sodium-friends/sodium-javascript#api). Note that the two modules do not yet have feature parity, where `sodium-native` is the more featureful of the two.
55
56## Compatibilty
57
58<!-- Generated by build-scripts/symbols.js with
59 sodium-native@3.2.0
60 sodium-javascript@0.6.0 -->
61| C Library Symbol | `sodium-native` | `sodium-javascript` |
62|:--------------------------------------------------------:|:--------------------:|:--------------------:|
63| `crypto_aead_chacha20poly1305_ietf_ABYTES` | :white_check_mark: | :white_check_mark: |
64| `crypto_aead_chacha20poly1305_ietf_decrypt` | :white_check_mark: | :white_check_mark: |
65| `crypto_aead_chacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :white_check_mark: |
66| `crypto_aead_chacha20poly1305_ietf_encrypt` | :white_check_mark: | :white_check_mark: |
67| `crypto_aead_chacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :white_check_mark: |
68| `crypto_aead_chacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
69| `crypto_aead_chacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
70| `crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
71| `crypto_aead_chacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :white_check_mark: |
72| `crypto_aead_chacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :white_check_mark: |
73| `crypto_aead_xchacha20poly1305_ietf_ABYTES` | :white_check_mark: | :small_red_triangle: |
74| `crypto_aead_xchacha20poly1305_ietf_decrypt` | :white_check_mark: | :small_red_triangle: |
75| `crypto_aead_xchacha20poly1305_ietf_decrypt_detached` | :white_check_mark: | :small_red_triangle: |
76| `crypto_aead_xchacha20poly1305_ietf_encrypt` | :white_check_mark: | :small_red_triangle: |
77| `crypto_aead_xchacha20poly1305_ietf_encrypt_detached` | :white_check_mark: | :small_red_triangle: |
78| `crypto_aead_xchacha20poly1305_ietf_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
79| `crypto_aead_xchacha20poly1305_ietf_keygen` | :white_check_mark: | :small_red_triangle: |
80| `crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
81| `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES` | :white_check_mark: | :small_red_triangle: |
82| `crypto_aead_xchacha20poly1305_ietf_NSECBYTES` | :white_check_mark: | :small_red_triangle: |
83| `crypto_auth` | :white_check_mark: | :small_red_triangle: |
84| `crypto_auth_BYTES` | :white_check_mark: | :small_red_triangle: |
85| `crypto_auth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
86| `crypto_auth_verify` | :white_check_mark: | :small_red_triangle: |
87| `crypto_box_BEFORENMBYTES` | :small_red_triangle: | :white_check_mark: |
88| `crypto_box_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
89| `crypto_box_detached` | :white_check_mark: | :small_red_triangle: |
90| `crypto_box_easy` | :white_check_mark: | :small_red_triangle: |
91| `crypto_box_keypair` | :white_check_mark: | :white_check_mark: |
92| `crypto_box_MACBYTES` | :white_check_mark: | :small_red_triangle: |
93| `crypto_box_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
94| `crypto_box_open_detached` | :white_check_mark: | :small_red_triangle: |
95| `crypto_box_open_easy` | :white_check_mark: | :small_red_triangle: |
96| `crypto_box_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
97| `crypto_box_seal` | :white_check_mark: | :white_check_mark: |
98| `crypto_box_seal_open` | :white_check_mark: | :white_check_mark: |
99| `crypto_box_SEALBYTES` | :white_check_mark: | :white_check_mark: |
100| `crypto_box_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
101| `crypto_box_seed_keypair` | :white_check_mark: | :white_check_mark: |
102| `crypto_box_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
103| `crypto_box_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
104| `crypto_core_ed25519_add` | :white_check_mark: | :small_red_triangle: |
105| `crypto_core_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
106| `crypto_core_ed25519_from_uniform` | :white_check_mark: | :small_red_triangle: |
107| `crypto_core_ed25519_is_valid_point` | :white_check_mark: | :small_red_triangle: |
108| `crypto_core_ed25519_NONREDUCEDSCALARBYTES` | :white_check_mark: | :small_red_triangle: |
109| `crypto_core_ed25519_scalar_add` | :white_check_mark: | :small_red_triangle: |
110| `crypto_core_ed25519_scalar_complement` | :white_check_mark: | :small_red_triangle: |
111| `crypto_core_ed25519_scalar_invert` | :white_check_mark: | :small_red_triangle: |
112| `crypto_core_ed25519_scalar_negate` | :white_check_mark: | :small_red_triangle: |
113| `crypto_core_ed25519_scalar_random` | :white_check_mark: | :small_red_triangle: |
114| `crypto_core_ed25519_scalar_reduce` | :white_check_mark: | :small_red_triangle: |
115| `crypto_core_ed25519_scalar_sub` | :white_check_mark: | :small_red_triangle: |
116| `crypto_core_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
117| `crypto_core_ed25519_sub` | :white_check_mark: | :small_red_triangle: |
118| `crypto_core_ed25519_UNIFORMBYTES` | :white_check_mark: | :small_red_triangle: |
119| `crypto_generichash` | :white_check_mark: | :white_check_mark: |
120| `crypto_generichash_BYTES` | :white_check_mark: | :white_check_mark: |
121| `crypto_generichash_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
122| `crypto_generichash_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
123| `crypto_generichash_final` | :white_check_mark: | :small_red_triangle: |
124| `crypto_generichash_init` | :white_check_mark: | :small_red_triangle: |
125| `crypto_generichash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
126| `crypto_generichash_KEYBYTES_MAX` | :white_check_mark: | :white_check_mark: |
127| `crypto_generichash_KEYBYTES_MIN` | :white_check_mark: | :white_check_mark: |
128| `crypto_generichash_keygen` | :white_check_mark: | :small_red_triangle: |
129| `crypto_generichash_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
130| `crypto_generichash_update` | :white_check_mark: | :small_red_triangle: |
131| `crypto_hash` | :white_check_mark: | :white_check_mark: |
132| `crypto_hash_BYTES` | :white_check_mark: | :white_check_mark: |
133| `crypto_hash_sha256` | :white_check_mark: | :white_check_mark: |
134| `crypto_hash_sha256_BYTES` | :white_check_mark: | :white_check_mark: |
135| `crypto_hash_sha256_final` | :white_check_mark: | :small_red_triangle: |
136| `crypto_hash_sha256_init` | :white_check_mark: | :small_red_triangle: |
137| `crypto_hash_sha256_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
138| `crypto_hash_sha256_update` | :white_check_mark: | :small_red_triangle: |
139| `crypto_hash_sha512` | :white_check_mark: | :white_check_mark: |
140| `crypto_hash_sha512_BYTES` | :white_check_mark: | :white_check_mark: |
141| `crypto_hash_sha512_final` | :white_check_mark: | :small_red_triangle: |
142| `crypto_hash_sha512_init` | :white_check_mark: | :small_red_triangle: |
143| `crypto_hash_sha512_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
144| `crypto_hash_sha512_update` | :white_check_mark: | :small_red_triangle: |
145| `crypto_kdf_BYTES_MAX` | :white_check_mark: | :white_check_mark: |
146| `crypto_kdf_BYTES_MIN` | :white_check_mark: | :white_check_mark: |
147| `crypto_kdf_CONTEXTBYTES` | :white_check_mark: | :white_check_mark: |
148| `crypto_kdf_derive_from_key` | :white_check_mark: | :white_check_mark: |
149| `crypto_kdf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
150| `crypto_kdf_keygen` | :white_check_mark: | :white_check_mark: |
151| `crypto_kx_client_session_keys` | :white_check_mark: | :small_red_triangle: |
152| `crypto_kx_keypair` | :white_check_mark: | :white_check_mark: |
153| `crypto_kx_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
154| `crypto_kx_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
155| `crypto_kx_seed_keypair` | :white_check_mark: | :white_check_mark: |
156| `crypto_kx_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
157| `crypto_kx_server_session_keys` | :white_check_mark: | :small_red_triangle: |
158| `crypto_kx_SESSIONKEYBYTES` | :white_check_mark: | :small_red_triangle: |
159| `crypto_onetimeauth` | :white_check_mark: | :white_check_mark: |
160| `crypto_onetimeauth_BYTES` | :white_check_mark: | :small_red_triangle: |
161| `crypto_onetimeauth_final` | :white_check_mark: | :small_red_triangle: |
162| `crypto_onetimeauth_init` | :white_check_mark: | :small_red_triangle: |
163| `crypto_onetimeauth_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
164| `crypto_onetimeauth_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
165| `crypto_onetimeauth_update` | :white_check_mark: | :small_red_triangle: |
166| `crypto_onetimeauth_verify` | :white_check_mark: | :white_check_mark: |
167| `crypto_pwhash` | :white_check_mark: | :small_red_triangle: |
168| `crypto_pwhash_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
169| `crypto_pwhash_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
170| `crypto_pwhash_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
171| `crypto_pwhash_scryptsalsa208sha256` | :white_check_mark: | :small_red_triangle: |
172| `crypto_pwhash_scryptsalsa208sha256_BYTES_MAX` | :white_check_mark: | :small_red_triangle: |
173| `crypto_pwhash_scryptsalsa208sha256_BYTES_MIN` | :white_check_mark: | :small_red_triangle: |
174| `crypto_pwhash_scryptsalsa208sha256_SALTBYTES` | :white_check_mark: | :small_red_triangle: |
175| `crypto_pwhash_scryptsalsa208sha256_str` | :white_check_mark: | :small_red_triangle: |
176| `crypto_pwhash_scryptsalsa208sha256_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
177| `crypto_pwhash_scryptsalsa208sha256_str_verify` | :white_check_mark: | :small_red_triangle: |
178| `crypto_pwhash_scryptsalsa208sha256_STRBYTES` | :white_check_mark: | :small_red_triangle: |
179| `crypto_pwhash_str` | :white_check_mark: | :small_red_triangle: |
180| `crypto_pwhash_str_needs_rehash` | :white_check_mark: | :small_red_triangle: |
181| `crypto_pwhash_str_verify` | :white_check_mark: | :small_red_triangle: |
182| `crypto_pwhash_STRBYTES` | :white_check_mark: | :small_red_triangle: |
183| `crypto_scalarmult` | :white_check_mark: | :white_check_mark: |
184| `crypto_scalarmult_base` | :white_check_mark: | :white_check_mark: |
185| `crypto_scalarmult_BYTES` | :white_check_mark: | :white_check_mark: |
186| `crypto_scalarmult_ed25519` | :white_check_mark: | :small_red_triangle: |
187| `crypto_scalarmult_ed25519_base` | :white_check_mark: | :small_red_triangle: |
188| `crypto_scalarmult_ed25519_base_noclamp` | :white_check_mark: | :small_red_triangle: |
189| `crypto_scalarmult_ed25519_BYTES` | :white_check_mark: | :small_red_triangle: |
190| `crypto_scalarmult_ed25519_noclamp` | :white_check_mark: | :small_red_triangle: |
191| `crypto_scalarmult_ed25519_SCALARBYTES` | :white_check_mark: | :small_red_triangle: |
192| `crypto_scalarmult_SCALARBYTES` | :white_check_mark: | :white_check_mark: |
193| `crypto_secretbox` | :small_red_triangle: | :white_check_mark: |
194| `crypto_secretbox_BOXZEROBYTES` | :small_red_triangle: | :white_check_mark: |
195| `crypto_secretbox_detached` | :white_check_mark: | :white_check_mark: |
196| `crypto_secretbox_easy` | :white_check_mark: | :white_check_mark: |
197| `crypto_secretbox_KEYBYTES` | :white_check_mark: | :white_check_mark: |
198| `crypto_secretbox_MACBYTES` | :white_check_mark: | :white_check_mark: |
199| `crypto_secretbox_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
200| `crypto_secretbox_open` | :small_red_triangle: | :white_check_mark: |
201| `crypto_secretbox_open_detached` | :white_check_mark: | :white_check_mark: |
202| `crypto_secretbox_open_easy` | :white_check_mark: | :white_check_mark: |
203| `crypto_secretbox_ZEROBYTES` | :small_red_triangle: | :white_check_mark: |
204| `crypto_secretstream_xchacha20poly1305_ABYTES` | :white_check_mark: | :small_red_triangle: |
205| `crypto_secretstream_xchacha20poly1305_HEADERBYTES` | :white_check_mark: | :small_red_triangle: |
206| `crypto_secretstream_xchacha20poly1305_init_pull` | :white_check_mark: | :small_red_triangle: |
207| `crypto_secretstream_xchacha20poly1305_init_push` | :white_check_mark: | :small_red_triangle: |
208| `crypto_secretstream_xchacha20poly1305_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
209| `crypto_secretstream_xchacha20poly1305_keygen` | :white_check_mark: | :small_red_triangle: |
210| `crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
211| `crypto_secretstream_xchacha20poly1305_pull` | :white_check_mark: | :small_red_triangle: |
212| `crypto_secretstream_xchacha20poly1305_push` | :white_check_mark: | :small_red_triangle: |
213| `crypto_secretstream_xchacha20poly1305_rekey` | :white_check_mark: | :small_red_triangle: |
214| `crypto_secretstream_xchacha20poly1305_STATEBYTES` | :white_check_mark: | :small_red_triangle: |
215| `crypto_shorthash` | :white_check_mark: | :white_check_mark: |
216| `crypto_shorthash_BYTES` | :white_check_mark: | :white_check_mark: |
217| `crypto_shorthash_KEYBYTES` | :white_check_mark: | :white_check_mark: |
218| `crypto_sign` | :white_check_mark: | :white_check_mark: |
219| `crypto_sign_BYTES` | :white_check_mark: | :white_check_mark: |
220| `crypto_sign_detached` | :white_check_mark: | :white_check_mark: |
221| `crypto_sign_ed25519_pk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
222| `crypto_sign_ed25519_sk_to_curve25519` | :white_check_mark: | :small_red_triangle: |
223| `crypto_sign_ed25519_sk_to_pk` | :white_check_mark: | :small_red_triangle: |
224| `crypto_sign_keypair` | :white_check_mark: | :white_check_mark: |
225| `crypto_sign_open` | :white_check_mark: | :white_check_mark: |
226| `crypto_sign_PUBLICKEYBYTES` | :white_check_mark: | :white_check_mark: |
227| `crypto_sign_SECRETKEYBYTES` | :white_check_mark: | :white_check_mark: |
228| `crypto_sign_seed_keypair` | :white_check_mark: | :white_check_mark: |
229| `crypto_sign_SEEDBYTES` | :white_check_mark: | :white_check_mark: |
230| `crypto_sign_verify_detached` | :white_check_mark: | :white_check_mark: |
231| `crypto_stream` | :white_check_mark: | :white_check_mark: |
232| `crypto_stream_chacha20` | :white_check_mark: | :white_check_mark: |
233| `crypto_stream_chacha20_ietf` | :white_check_mark: | :white_check_mark: |
234| `crypto_stream_chacha20_ietf_KEYBYTES` | :white_check_mark: | :white_check_mark: |
235| `crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
236| `crypto_stream_chacha20_ietf_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
237| `crypto_stream_chacha20_ietf_xor` | :white_check_mark: | :white_check_mark: |
238| `crypto_stream_chacha20_ietf_xor_ic` | :white_check_mark: | :white_check_mark: |
239| `crypto_stream_chacha20_KEYBYTES` | :white_check_mark: | :white_check_mark: |
240| `crypto_stream_chacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :white_check_mark: |
241| `crypto_stream_chacha20_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
242| `crypto_stream_chacha20_xor` | :white_check_mark: | :white_check_mark: |
243| `crypto_stream_chacha20_xor_ic` | :white_check_mark: | :white_check_mark: |
244| `crypto_stream_KEYBYTES` | :white_check_mark: | :white_check_mark: |
245| `crypto_stream_NONCEBYTES` | :white_check_mark: | :white_check_mark: |
246| `crypto_stream_salsa20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
247| `crypto_stream_salsa20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
248| `crypto_stream_salsa20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
249| `crypto_stream_salsa20_xor` | :white_check_mark: | :small_red_triangle: |
250| `crypto_stream_salsa20_xor_ic` | :white_check_mark: | :small_red_triangle: |
251| `crypto_stream_xchacha20` | :white_check_mark: | :small_red_triangle: |
252| `crypto_stream_xchacha20_KEYBYTES` | :white_check_mark: | :small_red_triangle: |
253| `crypto_stream_xchacha20_MESSAGEBYTES_MAX` | :white_check_mark: | :small_red_triangle: |
254| `crypto_stream_xchacha20_NONCEBYTES` | :white_check_mark: | :small_red_triangle: |
255| `crypto_stream_xchacha20_xor` | :white_check_mark: | :small_red_triangle: |
256| `crypto_stream_xchacha20_xor_ic` | :white_check_mark: | :small_red_triangle: |
257| `crypto_stream_xor` | :white_check_mark: | :white_check_mark: |
258| `crypto_verify_16` | :small_red_triangle: | :white_check_mark: |
259| `crypto_verify_32` | :small_red_triangle: | :white_check_mark: |
260| `randombytes_buf` | :white_check_mark: | :white_check_mark: |
261| `randombytes_buf_deterministic` | :white_check_mark: | :small_red_triangle: |
262| `randombytes_random` | :white_check_mark: | :small_red_triangle: |
263| `randombytes_SEEDBYTES` | :white_check_mark: | :small_red_triangle: |
264| `randombytes_uniform` | :white_check_mark: | :small_red_triangle: |
265| `sodium_add` | :white_check_mark: | :small_red_triangle: |
266| `sodium_compare` | :white_check_mark: | :small_red_triangle: |
267| `sodium_free` | :white_check_mark: | :small_red_triangle: |
268| `sodium_increment` | :white_check_mark: | :small_red_triangle: |
269| `sodium_is_zero` | :white_check_mark: | :white_check_mark: |
270| `sodium_malloc` | :white_check_mark: | :white_check_mark: |
271| `sodium_memcmp` | :white_check_mark: | :white_check_mark: |
272| `sodium_memzero` | :white_check_mark: | :white_check_mark: |
273| `sodium_mlock` | :white_check_mark: | :small_red_triangle: |
274| `sodium_mprotect_noaccess` | :white_check_mark: | :small_red_triangle: |
275| `sodium_mprotect_readonly` | :white_check_mark: | :small_red_triangle: |
276| `sodium_mprotect_readwrite` | :white_check_mark: | :small_red_triangle: |
277| `sodium_munlock` | :white_check_mark: | :small_red_triangle: |
278| `sodium_pad` | :white_check_mark: | :small_red_triangle: |
279| `sodium_sub` | :white_check_mark: | :small_red_triangle: |
280| `sodium_unpad` | :white_check_mark: | :small_red_triangle: |
281
282### Missing altogether (Ctrl + F friendly)
283
284`crypto_aead_aes256gcm_ABYTES`, `crypto_aead_aes256gcm_beforenm`, `crypto_aead_aes256gcm_decrypt`, `crypto_aead_aes256gcm_decrypt_afternm`, `crypto_aead_aes256gcm_decrypt_detached`, `crypto_aead_aes256gcm_decrypt_detached_afternm`, `crypto_aead_aes256gcm_encrypt`, `crypto_aead_aes256gcm_encrypt_afternm`, `crypto_aead_aes256gcm_encrypt_detached`, `crypto_aead_aes256gcm_encrypt_detached_afternm`, `crypto_aead_aes256gcm_is_available`, `crypto_aead_aes256gcm_KEYBYTES`, `crypto_aead_aes256gcm_keygen`, `crypto_aead_aes256gcm_MESSAGEBYTES_MAX`, `crypto_aead_aes256gcm_NPUBBYTES`, `crypto_aead_aes256gcm_NSECBYTES`, `crypto_aead_aes256gcm_STATEBYTES`, `crypto_aead_chacha20poly1305_ABYTES`, `crypto_aead_chacha20poly1305_decrypt`, `crypto_aead_chacha20poly1305_decrypt_detached`, `crypto_aead_chacha20poly1305_encrypt`, `crypto_aead_chacha20poly1305_encrypt_detached`, `crypto_aead_chacha20poly1305_KEYBYTES`, `crypto_aead_chacha20poly1305_keygen`, `crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX`, `crypto_aead_chacha20poly1305_NPUBBYTES`, `crypto_aead_chacha20poly1305_NSECBYTES`, `crypto_auth_hmacsha256`, `crypto_auth_hmacsha256_BYTES`, `crypto_auth_hmacsha256_final`, `crypto_auth_hmacsha256_init`, `crypto_auth_hmacsha256_KEYBYTES`, `crypto_auth_hmacsha256_keygen`, `crypto_auth_hmacsha256_STATEBYTES`, `crypto_auth_hmacsha256_update`, `crypto_auth_hmacsha256_verify`, `crypto_auth_hmacsha512`, `crypto_auth_hmacsha512256`, `crypto_auth_hmacsha512256_BYTES`, `crypto_auth_hmacsha512256_final`, `crypto_auth_hmacsha512256_init`, `crypto_auth_hmacsha512256_KEYBYTES`, `crypto_auth_hmacsha512256_keygen`, `crypto_auth_hmacsha512256_STATEBYTES`, `crypto_auth_hmacsha512256_update`, `crypto_auth_hmacsha512256_verify`, `crypto_auth_hmacsha512_BYTES`, `crypto_auth_hmacsha512_final`, `crypto_auth_hmacsha512_init`, `crypto_auth_hmacsha512_KEYBYTES`, `crypto_auth_hmacsha512_keygen`, `crypto_auth_hmacsha512_STATEBYTES`, `crypto_auth_hmacsha512_update`, `crypto_auth_hmacsha512_verify`, `crypto_auth_keygen`, `crypto_auth_primitive`, `crypto_box`, `crypto_box_afternm`, `crypto_box_beforenm`, `crypto_box_curve25519xchacha20poly1305_beforenm`, `crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xchacha20poly1305_detached`, `crypto_box_curve25519xchacha20poly1305_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_easy`, `crypto_box_curve25519xchacha20poly1305_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_keypair`, `crypto_box_curve25519xchacha20poly1305_MACBYTES`, `crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xchacha20poly1305_NONCEBYTES`, `crypto_box_curve25519xchacha20poly1305_open_detached`, `crypto_box_curve25519xchacha20poly1305_open_detached_afternm`, `crypto_box_curve25519xchacha20poly1305_open_easy`, `crypto_box_curve25519xchacha20poly1305_open_easy_afternm`, `crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seal`, `crypto_box_curve25519xchacha20poly1305_seal_open`, `crypto_box_curve25519xchacha20poly1305_SEALBYTES`, `crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xchacha20poly1305_seed_keypair`, `crypto_box_curve25519xchacha20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305`, `crypto_box_curve25519xsalsa20poly1305_afternm`, `crypto_box_curve25519xsalsa20poly1305_beforenm`, `crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES`, `crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES`, `crypto_box_curve25519xsalsa20poly1305_keypair`, `crypto_box_curve25519xsalsa20poly1305_MACBYTES`, `crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_box_curve25519xsalsa20poly1305_NONCEBYTES`, `crypto_box_curve25519xsalsa20poly1305_open`, `crypto_box_curve25519xsalsa20poly1305_open_afternm`, `crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES`, `crypto_box_curve25519xsalsa20poly1305_seed_keypair`, `crypto_box_curve25519xsalsa20poly1305_SEEDBYTES`, `crypto_box_curve25519xsalsa20poly1305_ZEROBYTES`, `crypto_box_detached_afternm`, `crypto_box_easy_afternm`, `crypto_box_MESSAGEBYTES_MAX`, `crypto_box_open`, `crypto_box_open_afternm`, `crypto_box_open_detached_afternm`, `crypto_box_open_easy_afternm`, `crypto_box_primitive`, `crypto_core_ed25519_from_hash`, `crypto_core_ed25519_HASHBYTES`, `crypto_core_ed25519_random`, `crypto_core_ed25519_scalar_mul`, `crypto_core_hchacha20`, `crypto_core_hchacha20_CONSTBYTES`, `crypto_core_hchacha20_INPUTBYTES`, `crypto_core_hchacha20_KEYBYTES`, `crypto_core_hchacha20_OUTPUTBYTES`, `crypto_core_hsalsa20`, `crypto_core_hsalsa20_CONSTBYTES`, `crypto_core_hsalsa20_INPUTBYTES`, `crypto_core_hsalsa20_KEYBYTES`, `crypto_core_hsalsa20_OUTPUTBYTES`, `crypto_core_ristretto255_add`, `crypto_core_ristretto255_BYTES`, `crypto_core_ristretto255_from_hash`, `crypto_core_ristretto255_HASHBYTES`, `crypto_core_ristretto255_is_valid_point`, `crypto_core_ristretto255_NONREDUCEDSCALARBYTES`, `crypto_core_ristretto255_random`, `crypto_core_ristretto255_scalar_add`, `crypto_core_ristretto255_scalar_complement`, `crypto_core_ristretto255_scalar_invert`, `crypto_core_ristretto255_scalar_mul`, `crypto_core_ristretto255_scalar_negate`, `crypto_core_ristretto255_scalar_random`, `crypto_core_ristretto255_scalar_reduce`, `crypto_core_ristretto255_scalar_sub`, `crypto_core_ristretto255_SCALARBYTES`, `crypto_core_ristretto255_sub`, `crypto_core_salsa20`, `crypto_core_salsa2012`, `crypto_core_salsa2012_CONSTBYTES`, `crypto_core_salsa2012_INPUTBYTES`, `crypto_core_salsa2012_KEYBYTES`, `crypto_core_salsa2012_OUTPUTBYTES`, `crypto_core_salsa208`, `crypto_core_salsa208_CONSTBYTES`, `crypto_core_salsa208_INPUTBYTES`, `crypto_core_salsa208_KEYBYTES`, `crypto_core_salsa208_OUTPUTBYTES`, `crypto_core_salsa20_CONSTBYTES`, `crypto_core_salsa20_INPUTBYTES`, `crypto_core_salsa20_KEYBYTES`, `crypto_core_salsa20_OUTPUTBYTES`, `crypto_generichash_blake2b`, `crypto_generichash_blake2b_BYTES`, `crypto_generichash_blake2b_BYTES_MAX`, `crypto_generichash_blake2b_BYTES_MIN`, `crypto_generichash_blake2b_final`, `crypto_generichash_blake2b_init`, `crypto_generichash_blake2b_init_salt_personal`, `crypto_generichash_blake2b_KEYBYTES`, `crypto_generichash_blake2b_KEYBYTES_MAX`, `crypto_generichash_blake2b_KEYBYTES_MIN`, `crypto_generichash_blake2b_keygen`, `crypto_generichash_blake2b_PERSONALBYTES`, `crypto_generichash_blake2b_salt_personal`, `crypto_generichash_blake2b_SALTBYTES`, `crypto_generichash_blake2b_STATEBYTES`, `crypto_generichash_blake2b_update`, `crypto_generichash_primitive`, `crypto_hash_primitive`, `crypto_kdf_blake2b_BYTES_MAX`, `crypto_kdf_blake2b_BYTES_MIN`, `crypto_kdf_blake2b_CONTEXTBYTES`, `crypto_kdf_blake2b_derive_from_key`, `crypto_kdf_blake2b_KEYBYTES`, `crypto_kdf_primitive`, `crypto_kx_primitive`, `crypto_onetimeauth_keygen`, `crypto_onetimeauth_poly1305`, `crypto_onetimeauth_poly1305_BYTES`, `crypto_onetimeauth_poly1305_final`, `crypto_onetimeauth_poly1305_init`, `crypto_onetimeauth_poly1305_KEYBYTES`, `crypto_onetimeauth_poly1305_keygen`, `crypto_onetimeauth_poly1305_STATEBYTES`, `crypto_onetimeauth_poly1305_update`, `crypto_onetimeauth_poly1305_verify`, `crypto_onetimeauth_primitive`, `crypto_pwhash_alg_argon2i13`, `crypto_pwhash_alg_argon2id13`, `crypto_pwhash_alg_default`, `crypto_pwhash_argon2i`, `crypto_pwhash_argon2i_alg_argon2i13`, `crypto_pwhash_argon2i_BYTES_MAX`, `crypto_pwhash_argon2i_BYTES_MIN`, `crypto_pwhash_argon2i_memlimit_interactive`, `crypto_pwhash_argon2i_memlimit_max`, `crypto_pwhash_argon2i_memlimit_min`, `crypto_pwhash_argon2i_memlimit_moderate`, `crypto_pwhash_argon2i_memlimit_sensitive`, `crypto_pwhash_argon2i_opslimit_interactive`, `crypto_pwhash_argon2i_opslimit_max`, `crypto_pwhash_argon2i_opslimit_min`, `crypto_pwhash_argon2i_opslimit_moderate`, `crypto_pwhash_argon2i_opslimit_sensitive`, `crypto_pwhash_argon2i_passwd_max`, `crypto_pwhash_argon2i_passwd_min`, `crypto_pwhash_argon2i_SALTBYTES`, `crypto_pwhash_argon2i_str`, `crypto_pwhash_argon2i_str_needs_rehash`, `crypto_pwhash_argon2i_str_verify`, `crypto_pwhash_argon2i_STRBYTES`, `crypto_pwhash_argon2i_strprefix`, `crypto_pwhash_argon2id`, `crypto_pwhash_argon2id_alg_argon2id13`, `crypto_pwhash_argon2id_BYTES_MAX`, `crypto_pwhash_argon2id_BYTES_MIN`, `crypto_pwhash_argon2id_memlimit_interactive`, `crypto_pwhash_argon2id_memlimit_max`, `crypto_pwhash_argon2id_memlimit_min`, `crypto_pwhash_argon2id_memlimit_moderate`, `crypto_pwhash_argon2id_memlimit_sensitive`, `crypto_pwhash_argon2id_opslimit_interactive`, `crypto_pwhash_argon2id_opslimit_max`, `crypto_pwhash_argon2id_opslimit_min`, `crypto_pwhash_argon2id_opslimit_moderate`, `crypto_pwhash_argon2id_opslimit_sensitive`, `crypto_pwhash_argon2id_passwd_max`, `crypto_pwhash_argon2id_passwd_min`, `crypto_pwhash_argon2id_SALTBYTES`, `crypto_pwhash_argon2id_str`, `crypto_pwhash_argon2id_str_needs_rehash`, `crypto_pwhash_argon2id_str_verify`, `crypto_pwhash_argon2id_STRBYTES`, `crypto_pwhash_argon2id_strprefix`, `crypto_pwhash_memlimit_interactive`, `crypto_pwhash_memlimit_max`, `crypto_pwhash_memlimit_min`, `crypto_pwhash_memlimit_moderate`, `crypto_pwhash_memlimit_sensitive`, `crypto_pwhash_opslimit_interactive`, `crypto_pwhash_opslimit_max`, `crypto_pwhash_opslimit_min`, `crypto_pwhash_opslimit_moderate`, `crypto_pwhash_opslimit_sensitive`, `crypto_pwhash_passwd_max`, `crypto_pwhash_passwd_min`, `crypto_pwhash_primitive`, `crypto_pwhash_scryptsalsa208sha256_ll`, `crypto_pwhash_scryptsalsa208sha256_memlimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_memlimit_max`, `crypto_pwhash_scryptsalsa208sha256_memlimit_min`, `crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_interactive`, `crypto_pwhash_scryptsalsa208sha256_opslimit_max`, `crypto_pwhash_scryptsalsa208sha256_opslimit_min`, `crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive`, `crypto_pwhash_scryptsalsa208sha256_passwd_max`, `crypto_pwhash_scryptsalsa208sha256_passwd_min`, `crypto_pwhash_scryptsalsa208sha256_strprefix`, `crypto_pwhash_str_alg`, `crypto_pwhash_strprefix`, `crypto_scalarmult_curve25519`, `crypto_scalarmult_curve25519_base`, `crypto_scalarmult_curve25519_BYTES`, `crypto_scalarmult_curve25519_SCALARBYTES`, `crypto_scalarmult_primitive`, `crypto_scalarmult_ristretto255`, `crypto_scalarmult_ristretto255_base`, `crypto_scalarmult_ristretto255_BYTES`, `crypto_scalarmult_ristretto255_SCALARBYTES`, `crypto_secretbox_keygen`, `crypto_secretbox_MESSAGEBYTES_MAX`, `crypto_secretbox_primitive`, `crypto_secretbox_xchacha20poly1305_detached`, `crypto_secretbox_xchacha20poly1305_easy`, `crypto_secretbox_xchacha20poly1305_KEYBYTES`, `crypto_secretbox_xchacha20poly1305_MACBYTES`, `crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xchacha20poly1305_NONCEBYTES`, `crypto_secretbox_xchacha20poly1305_open_detached`, `crypto_secretbox_xchacha20poly1305_open_easy`, `crypto_secretbox_xsalsa20poly1305`, `crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES`, `crypto_secretbox_xsalsa20poly1305_KEYBYTES`, `crypto_secretbox_xsalsa20poly1305_keygen`, `crypto_secretbox_xsalsa20poly1305_MACBYTES`, `crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX`, `crypto_secretbox_xsalsa20poly1305_NONCEBYTES`, `crypto_secretbox_xsalsa20poly1305_open`, `crypto_secretbox_xsalsa20poly1305_ZEROBYTES`, `crypto_secretstream_xchacha20poly1305_tag_final`, `crypto_secretstream_xchacha20poly1305_tag_message`, `crypto_secretstream_xchacha20poly1305_tag_push`, `crypto_secretstream_xchacha20poly1305_tag_rekey`, `crypto_shorthash_keygen`, `crypto_shorthash_primitive`, `crypto_shorthash_siphash24`, `crypto_shorthash_siphash24_BYTES`, `crypto_shorthash_siphash24_KEYBYTES`, `crypto_shorthash_siphashx24`, `crypto_shorthash_siphashx24_BYTES`, `crypto_shorthash_siphashx24_KEYBYTES`, `crypto_sign_ed25519`, `crypto_sign_ed25519_BYTES`, `crypto_sign_ed25519_detached`, `crypto_sign_ed25519_keypair`, `crypto_sign_ed25519_MESSAGEBYTES_MAX`, `crypto_sign_ed25519_open`, `crypto_sign_ed25519_PUBLICKEYBYTES`, `crypto_sign_ed25519_SECRETKEYBYTES`, `crypto_sign_ed25519_seed_keypair`, `crypto_sign_ed25519_SEEDBYTES`, `crypto_sign_ed25519_sk_to_seed`, `crypto_sign_ed25519_verify_detached`, `crypto_sign_ed25519ph_final_create`, `crypto_sign_ed25519ph_final_verify`, `crypto_sign_ed25519ph_init`, `crypto_sign_ed25519ph_STATEBYTES`, `crypto_sign_ed25519ph_update`, `crypto_sign_edwards25519sha512batch`, `crypto_sign_edwards25519sha512batch_keypair`, `crypto_sign_edwards25519sha512batch_open`, `crypto_sign_final_create`, `crypto_sign_final_verify`, `crypto_sign_init`, `crypto_sign_MESSAGEBYTES_MAX`, `crypto_sign_primitive`, `crypto_sign_STATEBYTES`, `crypto_sign_update`, `crypto_stream_chacha20_ietf_keygen`, `crypto_stream_chacha20_keygen`, `crypto_stream_keygen`, `crypto_stream_MESSAGEBYTES_MAX`, `crypto_stream_primitive`, `crypto_stream_salsa20`, `crypto_stream_salsa2012`, `crypto_stream_salsa2012_KEYBYTES`, `crypto_stream_salsa2012_keygen`, `crypto_stream_salsa2012_MESSAGEBYTES_MAX`, `crypto_stream_salsa2012_NONCEBYTES`, `crypto_stream_salsa2012_xor`, `crypto_stream_salsa208`, `crypto_stream_salsa208_KEYBYTES`, `crypto_stream_salsa208_keygen`, `crypto_stream_salsa208_MESSAGEBYTES_MAX`, `crypto_stream_salsa208_NONCEBYTES`, `crypto_stream_salsa208_xor`, `crypto_stream_salsa20_keygen`, `crypto_stream_xchacha20_keygen`, `crypto_stream_xsalsa20`, `crypto_stream_xsalsa20_KEYBYTES`, `crypto_stream_xsalsa20_keygen`, `crypto_stream_xsalsa20_MESSAGEBYTES_MAX`, `crypto_stream_xsalsa20_NONCEBYTES`, `crypto_stream_xsalsa20_xor`, `crypto_stream_xsalsa20_xor_ic`, `crypto_verify_16_BYTES`, `crypto_verify_32_BYTES`, `crypto_verify_64`, `crypto_verify_64_BYTES`, `randombytes`, `randombytes_close`, `randombytes_implementation_name`, `randombytes_internal_implementation`, `randombytes_set_implementation`, `randombytes_stir`, `randombytes_sysrandom_implementation`, `sodium_allocarray`, `sodium_base642bin`, `sodium_base64_encoded_len`, `sodium_bin2base64`, `sodium_bin2hex`, `sodium_hex2bin`, `sodium_init`, `sodium_library_minimal`, `sodium_library_version_major`, `sodium_library_version_minor`, `sodium_misuse`, `sodium_runtime_has_aesni`, `sodium_runtime_has_avx`, `sodium_runtime_has_avx2`, `sodium_runtime_has_avx512f`, `sodium_runtime_has_neon`, `sodium_runtime_has_pclmul`, `sodium_runtime_has_rdrand`, `sodium_runtime_has_sse2`, `sodium_runtime_has_sse3`, `sodium_runtime_has_sse41`, `sodium_runtime_has_ssse3`, `sodium_set_misuse_handler`, `sodium_stackzero`, `sodium_version_string`
285
286## License
287
288[MIT](LICENSE.md)
node_modules/sodium-universal/build-scripts/generate.js +33 -0
……@@ -0,0 +1,33 @@
1#!/usr/bin/env node
2
3const fs = require('fs')
4const path = require('path')
5const root = path.dirname(require.resolve('sodium-javascript/package.json'))
6
7const tmp = "module.exports = require('sodium-native')\n"
8
9function recurse (dir) {
10 const ls = fs.readdirSync(dir)
11 const subdir = path.relative(root, dir)
12 if (subdir) fs.mkdirSync(subdir, { recursive: true })
13
14 for (const file of ls) {
15 if (file === 'internal') recurse(path.join(dir, file))
16 if (!/\.js$/i.test(file)) continue
17 if (file === 'example.js') continue
18 if (file === 'test.js') continue
19
20 fs.writeFileSync(path.join(__dirname, '..', subdir, file), tmp)
21 }
22}
23
24recurse(root)
25
26const pkg = require('sodium-javascript/package.json')
27const myPkg = require('../package.json')
28
29for (const key of Object.keys(pkg.dependencies)) {
30 myPkg.dependencies[key] = pkg.dependencies[key]
31}
32
33fs.writeFileSync(path.join(__dirname, '../package.json'), JSON.stringify(myPkg, null, 2) + '\n')
node_modules/sodium-universal/build-scripts/symbols.js +32 -0
……@@ -0,0 +1,32 @@
1var exec = require('child_process').execSync
2var path = require('path')
3
4var symbols = exec(`nm -gU "${path.join(require.resolve('sodium-native'), '../prebuilds/darwin-x64/libsodium.dylib')}"`).toString().trim().split('\n')
5var native = new Set(Object.keys(require('sodium-native')).sort())
6var js = new Set(Object.keys(require('sodium-javascript')).sort())
7
8symbols = symbols.map(l => l.split(' ').pop().replace(/^_/, '').replace(/_[^_]*bytes.*/, (s) => s.toUpperCase()))
9
10var missing = []
11
12console.log(`
13<!-- Generated by build-scripts/symbols.js with
14 sodium-native@${require('sodium-native/package.json').version}
15 sodium-javascript@${require('sodium-javascript/package.json').version} -->\
16`)
17
18const max = symbols.filter(s => native.has(s) || js.has(s)).map(s => s.length).reduce((a, b) => Math.max(a, b))
19const lines = ':-' + ''.padEnd(max, '--') + '-:'
20const center = s => s.padStart(Math.floor((max + s.length) / 2), ' ').padEnd(max, ' ')
21
22console.log(`| ${center('C Library Symbol')} | \`sodium-native\` | \`sodium-javascript\` |`)
23console.log(`|${lines}|:--------------------:|:--------------------:|`)
24
25for (var i = 0; i < symbols.length; i++) {
26 var s = symbols[i]
27 if (!(native.has(s) || js.has(s))) missing.push(s)
28 else console.log(`| \`${(s + '`').padEnd(max + 1, ' ')} | ${native.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} | ${js.has(s) ? ' :white_check_mark: ' : ':small_red_triangle:'} |`)
29}
30
31console.log('\n### Missing altogether (Ctrl + F friendly)\n')
32console.log(missing.map(s => '`' + s + '`').join(', '))
node_modules/sodium-universal/build-scripts/transform.js +26 -0
……@@ -0,0 +1,26 @@
1const fs = require('fs')
2const path = require('path')
3const { Transform, PassThrough } = require('stream')
4
5module.exports = function (file, opts) {
6 const basedir = path.resolve(__dirname, '..')
7 const relname = path.relative(basedir, file)
8
9 if (opts._flags.browserField === false) {
10 return new PassThrough()
11 }
12
13 return new Transform({
14 transform (data, enc, cb) {
15 cb()
16 },
17 flush (cb) {
18 const filename = require.resolve('sodium-javascript/' + relname)
19 fs.readFile(filename, (err, buf) => {
20 if (err) return cb(err)
21 this.push(buf)
22 cb(null)
23 })
24 }
25 })
26}
node_modules/sodium-universal/crypto_aead.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_auth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_box.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_generichash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_hash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_hash_sha256.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_kdf.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_kx.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_onetimeauth.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_scalarmult.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_secretbox.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_secretstream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_shorthash.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_sign.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_stream.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_stream_chacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/crypto_verify.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/helpers.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/index.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/internal/ed25519.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/internal/hchacha20.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/internal/poly1305.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/memory.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/sodium-universal/package.json +45 -0
……@@ -0,0 +1,45 @@
1{
2 "name": "sodium-universal",
3 "version": "4.0.1",
4 "description": "Universal wrapper for sodium-javascript and sodium-native working in Node.js and the Browser",
5 "main": "index.js",
6 "dependencies": {
7 "sodium-native": "^4.0.0"
8 },
9 "peerDependencies": {
10 "sodium-javascript": "~0.8.0"
11 },
12 "peerDependenciesMeta": {
13 "sodium-javascript": {
14 "optional": true
15 }
16 },
17 "scripts": {
18 "prepublish": "./build-scripts/generate.js"
19 },
20 "browser": {
21 "sodium-native": "sodium-javascript"
22 },
23 "browserify": {
24 "transform": [
25 "./build-scripts/transform.js"
26 ]
27 },
28 "repository": {
29 "type": "git",
30 "url": "git+https://github.com/sodium-friends/sodium-universal.git"
31 },
32 "keywords": [
33 "libsodium",
34 "sodium",
35 "sodium-native",
36 "sodium-javascript",
37 "browserify"
38 ],
39 "author": "Emil Bay <github@tixz.dk>",
40 "license": "MIT",
41 "bugs": {
42 "url": "https://github.com/sodium-friends/sodium-universal/issues"
43 },
44 "homepage": "https://github.com/sodium-friends/sodium-universal#readme"
45}
node_modules/sodium-universal/randombytes.js +1 -0
……@@ -0,0 +1 @@
1module.exports = require('sodium-native')
node_modules/speedometer/LICENSE +20 -0
……@@ -0,0 +1,20 @@
1Copyright 2013 Mathias Buus
2
3Permission is hereby granted, free of charge, to any person obtaining
4a copy of this software and associated documentation files (the
5"Software"), to deal in the Software without restriction, including
6without limitation the rights to use, copy, modify, merge, publish,
7distribute, sublicense, and/or sell copies of the Software, and to
8permit persons to whom the Software is furnished to do so, subject to
9the following conditions:
10
11The above copyright notice and this permission notice shall be
12included in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
node_modules/speedometer/README.md +38 -0
……@@ -0,0 +1,38 @@
1# speedometer
2
3Speed measurement in Javascript
4
5```
6npm install speedometer
7```
8
9## Usage
10
11``` js
12var speedometer = require('speedometer')
13var fs = require('fs')
14
15// Let's measure how fast we can read from /dev/urandom
16var speed = speedometer()
17var stream = fs.createReadStream('/dev/urandom')
18
19stream.on('data', function(data) {
20 // Simply call speed with the amount of bytes transferred
21 var bytesPerSecond = speed(data.length)
22
23 console.log(bytesPerSecond+' bytes/second')
24})
25```
26
27You can always get the current speed by calling `speed()`.
28
29Per default `speedometer` uses a 5 second buffer.
30To change this simply pass another value to the constructor
31
32``` js
33var speed = speedometer(20) // uses a 20s buffer instead
34```
35
36## License
37
38MIT
node_modules/speedometer/index.js +39 -0
……@@ -0,0 +1,39 @@
1var tick = 1
2var maxTick = 65535
3var resolution = 4
4var timer
5var inc = function () {
6 tick = (tick + 1) & maxTick
7}
8
9
10module.exports = function (seconds) {
11 if (!timer) {
12 timer = setInterval(inc, (1000 / resolution) | 0)
13 if (timer.unref) timer.unref()
14 }
15
16 var size = resolution * (seconds || 5)
17 var buffer = [0]
18 var pointer = 1
19 var last = (tick - 1) & maxTick
20
21 return function (delta) {
22 var dist = (tick - last) & maxTick
23 if (dist > size) dist = size
24 last = tick
25
26 while (dist--) {
27 if (pointer === size) pointer = 0
28 buffer[pointer] = buffer[pointer === 0 ? size - 1 : pointer - 1]
29 pointer++
30 }
31
32 if (delta) buffer[pointer - 1] += delta
33
34 var top = buffer[pointer - 1]
35 var btm = buffer.length < size ? 0 : buffer[pointer === size ? 0 : pointer]
36
37 return buffer.length < resolution ? top : (top - btm) * resolution / buffer.length
38 }
39}
node_modules/speedometer/package.json +15 -0
……@@ -0,0 +1,15 @@
1{
2 "name": "speedometer",
3 "version": "1.1.0",
4 "repository": "git://github.com/mafintosh/speedometer",
5 "description": "simple speed measurement in javascript",
6 "license": "MIT",
7 "keywords": [
8 "speed",
9 "bytes",
10 "per",
11 "second",
12 "transfer"
13 ],
14 "author": "Mathias Buus Madsen <mathiasbuus@gmail.com>"
15}
node_modules/streamx/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2019 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/streamx/README.md +490 -0
……@@ -0,0 +1,490 @@
1# streamx
2
3An iteration of the Node.js core streams with a series of improvements.
4
5```
6npm install streamx
7```
8
9[![Build Status](https://github.com/streamxorg/streamx/workflows/Build%20Status/badge.svg)](https://github.com/streamxorg/streamx/actions?query=workflow%3A%22Build+Status%22)
10
11## Main improvements from Node.js core stream
12
13#### Proper lifecycle support.
14
15Streams have an `_open` function that is called before any read/write operation and a `_destroy`
16function that is always run as the last part of the stream.
17
18This makes it easy to maintain state.
19
20#### Easy error handling
21
22Fully integrates a `.destroy()` function. When called the stream will wait for any
23pending operation to finish and call the stream destroy logic.
24
25Close is _always_ the last event emitted and `destroy` is always run.
26
27#### `pipe()` error handles
28
29`pipe` accepts a callback that is called when the pipeline is fully drained.
30It also error handles the streams provided and destroys both streams if either
31of them fail.
32
33#### All streams are both binary and object mode streams
34
35A `map` function can be provided to map your input data into buffers
36or other formats. To indicate how much buffer space each data item takes
37an `byteLength` function can be provided as well.
38
39This removes the need for two modes of streams.
40
41#### Simplicity
42
43This is a full rewrite, all contained in one file.
44
45Lots of stream methods are simplified based on how I and devs I work with actually use streams in the wild.
46
47#### Backwards compat
48
49streamx aims to be compatible with Node.js streams whenever it is reasonable to do so.
50
51This means that streamx streams behave a lot like Node.js streams from the outside but still provides the
52improvements above.
53
54#### Smaller browser footprint
55
56streamx has a much smaller footprint when compiled for the browser:
57
58```
59$ for x in stream{,x}; do echo $x: $(browserify -r $x | wc -c) bytes; done
60stream: 173844 bytes
61streamx: 46943 bytes
62```
63
64With optimizations turned on, the difference is even more stark:
65
66```
67$ for x in stream{,x}; do echo $x: $(browserify -r $x -p tinyify | wc -c) bytes; done
68stream: 62649 bytes
69streamx: 8460 bytes
70$ for x in stream{,x}; do echo $x: $(browserify -r $x -p tinyify | gzip | wc -c) "bytes (gzipped)"; done
71stream: 18053 bytes (gzipped)
72streamx: 2806 bytes (gzipped)
73```
74
75#### AbortSignal support
76
77To make it easier to integrate streams in a `async/await` flow, all streams support a `signal` option
78that accepts a [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to as an
79alternative means to `.destroy` streams.
80
81## Usage
82
83```js
84const { Readable } = require('streamx')
85
86const rs = new Readable({
87 read(cb) {
88 this.push('Cool data')
89 cb(null)
90 }
91})
92
93rs.on('data', (data) => console.log('data:', data))
94```
95
96## API
97
98This streamx package contains 4 streams similar to Node.js core.
99
100## Readable Stream
101
102#### `rs = new stream.Readable([options])`
103
104Create a new readable stream.
105
106Options include:
107
108```
109{
110 highWaterMark: 16384, // max buffer size in bytes
111 map: (data) => data, // optional function to map input data
112 byteLength: (data) => size, // optional function that calculates the byte size of input data
113 signal: abortController.signal, // optional AbortSignal that triggers `.destroy` when on `abort`
114 eagerOpen: false // eagerly open the stream
115}
116```
117
118In addition you can pass the `open`, `read`, and `destroy` functions as shorthands in
119the constructor instead of overwrite the methods below.
120
121The default byteLength function returns the byte length of buffers and `1024`
122for any other object. This means the buffer will contain around 16 non buffers
123or buffers worth 16kb when full if the defaults are used.
124
125If you set highWaterMark to `0` then all read ahead buffering on the stream
126is disabled and it will only call `_read` when a user reads rather than ahead of time.
127
128#### `rs._read(cb)`
129
130This function is called when the stream wants you to push new data.
131Overwrite this and add your own read logic.
132You should call the callback when you are fully done with the read.
133
134Can also be set using `options.read` in the constructor.
135
136Note that this function differs from Node.js streams in that it takes
137the "read finished" callback.
138
139#### `drained = rs.push(data)`
140
141Push new data to the stream. Returns true if the buffer is not full
142and you should push more data if you can.
143
144If you call `rs.push(null)` you signal to the stream that no more
145data will be pushed and that you want to end the stream.
146
147#### `data = rs.read()`
148
149Read a piece of data from the stream buffer. If the buffer is currently empty
150`null` will be returned and you should wait for `readable` to be emitted before
151trying again. If the stream has been ended it will also return `null`.
152
153Note that this method differs from Node.js streams in that it does not accept
154an optional amounts of bytes to consume.
155
156#### `rs.unshift(data)`
157
158Add a piece of data to the front of the buffer. Use this if you read too much
159data using the `rs.read()` function.
160
161#### `rs._open(cb)`
162
163This function is called once before the first read is issued. Use this function
164to implement your own open logic.
165
166Can also be set using `options.open` in the constructor.
167
168#### `rs._destroy(cb)`
169
170This function is called just before the stream is fully destroyed. You should
171use this to implement whatever teardown logic you need. The final part of the
172stream life cycle is always to call destroy itself so this function will always
173be called wheather or not the stream ends gracefully or forcefully.
174
175Can also be set using `options.destroy` in the constructor.
176
177Note that the `_destroy` might be called without the open function being called
178in case no read was ever performed on the stream.
179
180#### `rs._predestroy()`
181
182A simple hook that is called as soon as the first `stream.destroy()` call is invoked.
183
184Use this in case you need to cancel pending reads (if possible) instead of waiting for them to finish.
185
186Can also be set using `options.predestroy` in the constructor.
187
188#### `rs.destroy([error])`
189
190Forcefully destroy the stream. Will call `_destroy` as soon as all pending reads have finished.
191Once the stream is fully destroyed `close` will be emitted.
192
193If you pass an error this error will be emitted just before `close` is, signifying a reason
194as to why this stream was destroyed.
195
196#### `rs.pause()`
197
198Pauses the stream. You will only need to call this if you want to pause a resumed stream.
199
200Returns this stream instance.
201
202#### `rs.resume()`
203
204Will start reading data from the stream as fast as possible.
205
206If you do not call this, you need to use the `read()` method to read data or the `pipe()` method to
207pipe the stream somewhere else or the `data` handler.
208
209If none of these option are used the stream will stay paused.
210
211Returns this stream instance.
212
213#### `bool = Readable.isPaused(rs)`
214
215Returns `true` if the stream is paused, else `false`.
216
217#### `writableStream = rs.pipe(writableStream, [callback])`
218
219Efficently pipe the readable stream to a writable stream (can be Node.js core stream or a stream from this package).
220If you provide a callback the callback is called when the pipeline has fully finished with an optional error in case
221it failed.
222
223To cancel the pipeline destroy either of the streams.
224
225#### `rs.on('readable')`
226
227Emitted when data is pushed to the stream if the buffer was previously empty.
228
229#### `rs.on('data', data)`
230
231Emitted when data is being read from the stream. If you attach a data handler you are implicitly resuming the stream.
232
233#### `rs.on('end')`
234
235Emitted when the readable stream has ended and no data is left in it's buffer.
236
237#### `rs.on('close')`
238
239Emitted when the readable stream has fully closed (i.e. it's destroy function has completed)
240
241#### `rs.on('error', err)`
242
243Emitted if any of the stream operations fail with an error. `close` is always emitted right after this.
244
245#### `rs.on('piping', dest)`
246
247Emitted when the readable stream is pipeing to a destination.
248
249#### `rs.destroyed`
250
251Boolean property indicating wheather or not this stream has been destroyed.
252
253#### `bool = Readable.isBackpressured(rs)`
254
255Static method to check if a readable stream is currently under backpressure.
256
257#### `stream = Readable.from(arrayOrBufferOrStringOrAsyncIterator)`
258
259Static method to turn an array or buffer or string or AsyncIterator into a readable stream.
260
261## Writable Stream
262
263#### `ws = new stream.Writable([options])`
264
265Create a new writable stream.
266
267Options include:
268
269```
270{
271 highWaterMark: 16384, // max buffer size in bytes
272 map: (data) => data, // optional function to map input data
273 byteLength: (data) => size, // optional function that calculates the byte size of input data
274 signal: abortController.signal // optional AbortSignal that triggers `.destroy` when on `abort`
275}
276```
277
278In addition you can pass the `open`, `write`, `final`, and `destroy` functions as shorthands in
279the constructor instead of overwrite the methods below.
280
281The default byteLength function returns the byte length of buffers and `1024`
282for any other object. This means the buffer will contain around 16 non buffers
283or buffers worth 16kb when full if the defaults are used.
284
285#### `ws._open(cb)`
286
287This function is called once before the first write is issued. Use this function
288to implement your own open logic.
289
290Can also be set using `options.open` in the constructor.
291
292#### `ws._destroy(cb)`
293
294This function is called just before the stream is fully destroyed. You should
295use this to implement whatever teardown logic you need. The final part of the
296stream life cycle is always to call destroy itself so this function will always
297be called wheather or not the stream ends gracefully or forcefully.
298
299Can also be set using `options.destroy` in the constructor.
300
301Note that the `_destroy` might be called without the open function being called
302in case no write was ever performed on the stream.
303
304#### `ws._predestroy()`
305
306A simple hook that is called as soon as the first `stream.destroy()` call is invoked.
307
308Use this in case you need to cancel pending writes (if possible) instead of waiting for them to finish.
309
310Can also be set using `options.predestroy` in the constructor.
311
312#### `ws.destroy([error])`
313
314Forcefully destroy the stream. Will call `_destroy` as soon as all pending reads have finished.
315Once the stream is fully destroyed `close` will be emitted.
316
317If you pass an error this error will be emitted just before `close` is, signifying a reason
318as to why this stream was destroyed.
319
320#### `drained = ws.write(data)`
321
322Write a piece of data to the stream. Returns `true` if the stream buffer is not full and you
323should keep writing to it if you can. If `false` is returned the stream will emit `drain`
324once it's buffer is fully drained.
325
326#### `ws._write(data, callback)`
327
328This function is called when the stream want to write some data. Use this to implement your own
329write logic. When done call the callback and the stream will call it again if more data exists in the buffer.
330
331Can also be set using `options.write` in the constructor.
332
333#### `ws._writev(batch, callback)`
334
335Similar to `_write` but passes an array of all data in the current write buffer instead of the oldest one.
336Useful if the destination you are writing the data to supports batching.
337
338Can also be set using `options.writev` in the constructor.
339
340#### `ws.end()`
341
342Gracefully end the writable stream. Call this when you no longer want to write to the stream.
343
344Once all writes have been fully drained `finish` will be emitted.
345
346Returns this stream instance.
347
348#### `ws._final(callback)`
349
350This function is called just before `finish` is emitted, i.e. when all writes have flushed but `ws.end()`
351have been called. Use this to implement any logic that should happen after all writes but before finish.
352
353Can also be set using `options.final` in the constructor.
354
355#### `ws.on('finish')`
356
357Emitted when the stream has been ended and all writes have been drained.
358
359#### `ws.on('close')`
360
361Emitted when the readable stream has fully closed (i.e. it's destroy function has completed)
362
363#### `ws.on('error', err)`
364
365Emitted if any of the stream operations fail with an error. `close` is always emitted right after this.
366
367#### `ws.on('pipe', src)`
368
369Emitted when a readable stream is being piped to the writable one.
370
371#### `ws.destroyed`
372
373Boolean property indicating wheather or not this stream has been destroyed.
374
375#### `bool = Writable.isBackpressured(ws)`
376
377Static method to check if a writable stream is currently under backpressure.
378
379#### `bool = await Writable.drained(ws)`
380
381Static helper to wait for a stream to drain the currently queued writes.
382Returns true if they were drained and false otherwise if the stream was destroyed.
383
384## Duplex Stream
385
386#### `s = new stream.Duplex([options])`
387
388A duplex stream is a stream that is both readable and writable.
389
390Since JS does not support multiple inheritance it inherits directly from Readable
391but implements the Writable API as well.
392
393If you want to provide only a map function for the readable side use `mapReadable` instead.
394If you want to provide only a byteLength function for the readable side use `byteLengthReadable` instead.
395
396Same goes for the writable side but using `mapWritable` and `byteLengthWritable` instead.
397
398## Transform Stream
399
400A Transform stream is a duplex stream with an `._transform` template method that allows to
401asynchronously map the input to a different output.
402
403The transform stream overrides the `_write` and `_read` operations of `Readable` and `Writable` but
404still allows the setting of these options in the constructor. Usually it is unnecessary to pass
405in `read` or `write`/`writev` or to override the corresponding `._read`, `._write` or `._writev` operation.
406
407#### `ts = new stream.Transform([options])`
408
409A transform stream is a duplex stream that maps the data written to it and emits that as readable data.
410
411Has the same options as a duplex stream except you can provide a `transform` function also.
412
413#### `ts._transform(data, callback)`
414
415Transform the incoming data. Call `callback(null, mappedData)` or use `ts.push(mappedData)` to
416return data to the readable side of the stream.
417
418Per default the transform function just remits the incoming data making it act as a pass-through stream.
419
420## Pipeline
421
422`pipeline` allows to stream form a readable through a set of duplex streams to a writable entry.
423
424```js
425const { pipeline, Readable, Transform, Writable } = require('streamx')
426const lastStream = pipeline(
427 Readable.from([1, 2, 3]),
428 new Transform({
429 transform (from, cb) {
430 this.push(from.toString())
431 cb()
432 }
433 }),
434 new Writable({
435 write (data, cb) {
436 console.log(data)
437 cb()
438 }
439 })
440 error => {
441 // Callback once write has finished
442 }
443)
444```
445
446#### `lastStream = stream.pipeline(...streams, [done])`
447
448Pipe all streams together and return the last stream piped to.
449When the last stream finishes the pipeline ended succesfully.
450
451If any of the streams error, whether they are Node.js core streams
452or streamx streams, all streams in the pipeline are shutdown.
453
454Optionally you can pass a done callback to know when the pipeline is done.
455
456#### `promise = stream.pipelinePromise(...streams)`
457
458Same as normal pipeline except instead of returning the last stream it returns
459a promise representing the done callback. Note you should error handle this
460promise if you use this version.
461
462## Helpers
463
464#### `bool = isStream(stream)`
465
466#### `bool = isStreamx(stream)`
467
468#### `err = getStreamError(stream, [options])`
469
470Returns `null` if the stream has no errors.
471
472## Utilities
473
474Streamx aims to be minimal and stable. It therefore only contains a minimal set of utilities.
475To help discover of other modules that help you build streamx apps, we link some useful utilities here
476
477- [stream-composer](https://github.com/mafintosh/stream-composer) - Compose streams like Node's `stream.compose` and the `duplexify` and `pumpify` modules.
478- [teex](https://github.com/mafintosh/teex) - Clone a readable stream into multiple new readable instances.
479- [merge-readable](https://github.com/holepunchto/merge-readable) - Merge multiple readers into a new readable with optional mapping of data
480
481## Contributing
482
483If you want to help contribute to streamx a good way to start is to help writing more test
484cases, compatibility tests, documentation, or performance benchmarks.
485
486If in doubt open an issue :)
487
488## License
489
490MIT
node_modules/streamx/index.js +1232 -0
……@@ -0,0 +1,1232 @@
1const { EventEmitter } = require('events-universal')
2const STREAM_DESTROYED = new Error('Stream was destroyed')
3const PREMATURE_CLOSE = new Error('Premature close')
4
5const FIFO = require('fast-fifo')
6const TextDecoder = require('text-decoder')
7
8// if we do a future major, expect queue microtask to be there always, for now a bit defensive
9const qmt =
10 typeof queueMicrotask === 'undefined' ? (fn) => global.process.nextTick(fn) : queueMicrotask
11
12// 29 bits used total (4 from shared, 14 from read, and 11 from write)
13const MAX = (1 << 29) - 1
14
15// Shared state
16const OPENING = 0b0001
17const PREDESTROYING = 0b0010
18const DESTROYING = 0b0100
19const DESTROYED = 0b1000
20
21const NOT_OPENING = MAX ^ OPENING
22const NOT_PREDESTROYING = MAX ^ PREDESTROYING
23
24// Read state (4 bit offset from shared state)
25const READ_ACTIVE = 0b00000000000001 << 4
26const READ_UPDATING = 0b00000000000010 << 4
27const READ_PRIMARY = 0b00000000000100 << 4
28const READ_QUEUED = 0b00000000001000 << 4
29const READ_RESUMED = 0b00000000010000 << 4
30const READ_PIPE_DRAINED = 0b00000000100000 << 4
31const READ_ENDING = 0b00000001000000 << 4
32const READ_EMIT_DATA = 0b00000010000000 << 4
33const READ_EMIT_READABLE = 0b00000100000000 << 4
34const READ_EMITTED_READABLE = 0b00001000000000 << 4
35const READ_DONE = 0b00010000000000 << 4
36const READ_NEXT_TICK = 0b00100000000000 << 4
37const READ_NEEDS_PUSH = 0b01000000000000 << 4
38const READ_READ_AHEAD = 0b10000000000000 << 4
39
40// Combined read state
41const READ_FLOWING = READ_RESUMED | READ_PIPE_DRAINED
42const READ_ACTIVE_AND_NEEDS_PUSH = READ_ACTIVE | READ_NEEDS_PUSH
43const READ_PRIMARY_AND_ACTIVE = READ_PRIMARY | READ_ACTIVE
44const READ_EMIT_READABLE_AND_QUEUED = READ_EMIT_READABLE | READ_QUEUED
45const READ_RESUMED_READ_AHEAD = READ_RESUMED | READ_READ_AHEAD
46
47const READ_NOT_ACTIVE = MAX ^ READ_ACTIVE
48const READ_NON_PRIMARY = MAX ^ READ_PRIMARY
49const READ_NON_PRIMARY_AND_PUSHED = MAX ^ (READ_PRIMARY | READ_NEEDS_PUSH)
50const READ_PUSHED = MAX ^ READ_NEEDS_PUSH
51const READ_PAUSED = MAX ^ READ_RESUMED
52const READ_NOT_QUEUED = MAX ^ (READ_QUEUED | READ_EMITTED_READABLE)
53const READ_NOT_ENDING = MAX ^ READ_ENDING
54const READ_PIPE_NOT_DRAINED = MAX ^ READ_FLOWING
55const READ_NOT_NEXT_TICK = MAX ^ READ_NEXT_TICK
56const READ_NOT_UPDATING = MAX ^ READ_UPDATING
57const READ_NO_READ_AHEAD = MAX ^ READ_READ_AHEAD
58const READ_PAUSED_NO_READ_AHEAD = MAX ^ READ_RESUMED_READ_AHEAD
59
60// Write state (18 bit offset, 4 bit offset from shared state and 14 from read state)
61const WRITE_ACTIVE = 0b00000000001 << 18
62const WRITE_UPDATING = 0b00000000010 << 18
63const WRITE_PRIMARY = 0b00000000100 << 18
64const WRITE_QUEUED = 0b00000001000 << 18
65const WRITE_UNDRAINED = 0b00000010000 << 18
66const WRITE_DONE = 0b00000100000 << 18
67const WRITE_EMIT_DRAIN = 0b00001000000 << 18
68const WRITE_NEXT_TICK = 0b00010000000 << 18
69const WRITE_WRITING = 0b00100000000 << 18
70const WRITE_FINISHING = 0b01000000000 << 18
71const WRITE_CORKED = 0b10000000000 << 18
72
73const WRITE_NOT_ACTIVE = MAX ^ (WRITE_ACTIVE | WRITE_WRITING)
74const WRITE_NON_PRIMARY = MAX ^ WRITE_PRIMARY
75const WRITE_NOT_FINISHING = MAX ^ (WRITE_ACTIVE | WRITE_FINISHING)
76const WRITE_DRAINED = MAX ^ WRITE_UNDRAINED
77const WRITE_NOT_QUEUED = MAX ^ WRITE_QUEUED
78const WRITE_NOT_NEXT_TICK = MAX ^ WRITE_NEXT_TICK
79const WRITE_NOT_UPDATING = MAX ^ WRITE_UPDATING
80const WRITE_NOT_CORKED = MAX ^ WRITE_CORKED
81
82// Combined shared state
83const ACTIVE = READ_ACTIVE | WRITE_ACTIVE
84const NOT_ACTIVE = MAX ^ ACTIVE
85const DONE = READ_DONE | WRITE_DONE
86const DESTROY_STATUS = DESTROYING | DESTROYED | PREDESTROYING
87const OPEN_STATUS = DESTROY_STATUS | OPENING
88const AUTO_DESTROY = DESTROY_STATUS | DONE
89const NON_PRIMARY = WRITE_NON_PRIMARY & READ_NON_PRIMARY
90const ACTIVE_OR_TICKING = WRITE_NEXT_TICK | READ_NEXT_TICK
91const TICKING = ACTIVE_OR_TICKING & NOT_ACTIVE
92const IS_OPENING = OPEN_STATUS | TICKING
93
94// Combined shared state and read state
95const READ_PRIMARY_STATUS = OPEN_STATUS | READ_ENDING | READ_DONE
96const READ_STATUS = OPEN_STATUS | READ_DONE | READ_QUEUED
97const READ_ENDING_STATUS = OPEN_STATUS | READ_ENDING | READ_QUEUED
98const READ_READABLE_STATUS = OPEN_STATUS | READ_EMIT_READABLE | READ_QUEUED | READ_EMITTED_READABLE
99const SHOULD_NOT_READ =
100 OPEN_STATUS | READ_ACTIVE | READ_ENDING | READ_DONE | READ_NEEDS_PUSH | READ_READ_AHEAD
101const READ_BACKPRESSURE_STATUS = DESTROY_STATUS | READ_ENDING | READ_DONE
102const READ_UPDATE_SYNC_STATUS = READ_UPDATING | OPEN_STATUS | READ_NEXT_TICK | READ_PRIMARY
103const READ_NEXT_TICK_OR_OPENING = READ_NEXT_TICK | OPENING
104
105// Combined write state
106const WRITE_PRIMARY_STATUS = OPEN_STATUS | WRITE_FINISHING | WRITE_DONE
107const WRITE_QUEUED_AND_UNDRAINED = WRITE_QUEUED | WRITE_UNDRAINED
108const WRITE_QUEUED_AND_ACTIVE = WRITE_QUEUED | WRITE_ACTIVE
109const WRITE_DRAIN_STATUS = WRITE_QUEUED | WRITE_UNDRAINED | OPEN_STATUS | WRITE_ACTIVE
110const WRITE_STATUS = OPEN_STATUS | WRITE_ACTIVE | WRITE_QUEUED | WRITE_CORKED
111const WRITE_PRIMARY_AND_ACTIVE = WRITE_PRIMARY | WRITE_ACTIVE
112const WRITE_ACTIVE_AND_WRITING = WRITE_ACTIVE | WRITE_WRITING
113const WRITE_FINISHING_STATUS = OPEN_STATUS | WRITE_FINISHING | WRITE_QUEUED_AND_ACTIVE | WRITE_DONE
114const WRITE_BACKPRESSURE_STATUS = WRITE_UNDRAINED | DESTROY_STATUS | WRITE_FINISHING | WRITE_DONE
115const WRITE_UPDATE_SYNC_STATUS = WRITE_UPDATING | OPEN_STATUS | WRITE_NEXT_TICK | WRITE_PRIMARY
116const WRITE_DROP_DATA = WRITE_FINISHING | WRITE_DONE | DESTROY_STATUS
117
118const asyncIterator = Symbol.asyncIterator || Symbol('asyncIterator')
119
120class WritableState {
121 constructor(
122 stream,
123 { highWaterMark = 16384, map = null, mapWritable, byteLength, byteLengthWritable } = {}
124 ) {
125 this.stream = stream
126 this.queue = new FIFO()
127 this.highWaterMark = highWaterMark
128 this.buffered = 0
129 this.error = null
130 this.pipeline = null
131 this.drains = null // if we add more seldomly used helpers we might them into a subobject so its a single ptr
132 this.byteLength = byteLengthWritable || byteLength || defaultByteLength
133 this.map = mapWritable || map
134 this.afterWrite = afterWrite.bind(this)
135 this.afterUpdateNextTick = updateWriteNT.bind(this)
136 }
137
138 get ending() {
139 return (this.stream._duplexState & WRITE_FINISHING) !== 0
140 }
141
142 get ended() {
143 return (this.stream._duplexState & WRITE_DONE) !== 0
144 }
145
146 push(data) {
147 if ((this.stream._duplexState & WRITE_DROP_DATA) !== 0) return false
148 if (this.map !== null) data = this.map(data)
149
150 this.buffered += this.byteLength(data)
151 this.queue.push(data)
152
153 if (this.buffered < this.highWaterMark) {
154 this.stream._duplexState |= WRITE_QUEUED
155 return true
156 }
157
158 this.stream._duplexState |= WRITE_QUEUED_AND_UNDRAINED
159 return false
160 }
161
162 shift() {
163 const data = this.queue.shift()
164
165 this.buffered -= this.byteLength(data)
166 if (this.buffered === 0) this.stream._duplexState &= WRITE_NOT_QUEUED
167
168 return data
169 }
170
171 end(data) {
172 if (typeof data === 'function') this.stream.once('finish', data)
173 else if (data !== undefined && data !== null) this.push(data)
174 this.stream._duplexState = (this.stream._duplexState | WRITE_FINISHING) & WRITE_NON_PRIMARY
175 }
176
177 autoBatch(data, cb) {
178 const buffer = []
179 const stream = this.stream
180
181 buffer.push(data)
182 while ((stream._duplexState & WRITE_STATUS) === WRITE_QUEUED_AND_ACTIVE) {
183 buffer.push(stream._writableState.shift())
184 }
185
186 if ((stream._duplexState & OPEN_STATUS) !== 0) return cb(null)
187 stream._writev(buffer, cb)
188 }
189
190 update() {
191 const stream = this.stream
192
193 stream._duplexState |= WRITE_UPDATING
194
195 do {
196 while ((stream._duplexState & WRITE_STATUS) === WRITE_QUEUED) {
197 const data = this.shift()
198 stream._duplexState |= WRITE_ACTIVE_AND_WRITING
199 stream._write(data, this.afterWrite)
200 }
201
202 if ((stream._duplexState & WRITE_PRIMARY_AND_ACTIVE) === 0) this.updateNonPrimary()
203 } while (this.continueUpdate() === true)
204
205 stream._duplexState &= WRITE_NOT_UPDATING
206 }
207
208 updateNonPrimary() {
209 const stream = this.stream
210
211 if ((stream._duplexState & WRITE_FINISHING_STATUS) === WRITE_FINISHING) {
212 stream._duplexState = stream._duplexState | WRITE_ACTIVE
213 stream._final(afterFinal.bind(this))
214 return
215 }
216
217 if ((stream._duplexState & DESTROY_STATUS) === DESTROYING) {
218 if ((stream._duplexState & ACTIVE_OR_TICKING) === 0) {
219 stream._duplexState |= ACTIVE
220 stream._destroy(afterDestroy.bind(this))
221 }
222 return
223 }
224
225 if ((stream._duplexState & IS_OPENING) === OPENING) {
226 stream._duplexState = (stream._duplexState | ACTIVE) & NOT_OPENING
227 stream._open(afterOpen.bind(this))
228 }
229 }
230
231 continueUpdate() {
232 if ((this.stream._duplexState & WRITE_NEXT_TICK) === 0) return false
233 this.stream._duplexState &= WRITE_NOT_NEXT_TICK
234 return true
235 }
236
237 updateCallback() {
238 if ((this.stream._duplexState & WRITE_UPDATE_SYNC_STATUS) === WRITE_PRIMARY) this.update()
239 else this.updateNextTick()
240 }
241
242 updateNextTick() {
243 if ((this.stream._duplexState & WRITE_NEXT_TICK) !== 0) return
244 this.stream._duplexState |= WRITE_NEXT_TICK
245 if ((this.stream._duplexState & WRITE_UPDATING) === 0) qmt(this.afterUpdateNextTick)
246 }
247}
248
249class ReadableState {
250 constructor(
251 stream,
252 { highWaterMark = 16384, map = null, mapReadable, byteLength, byteLengthReadable } = {}
253 ) {
254 this.stream = stream
255 this.queue = new FIFO()
256 this.highWaterMark = highWaterMark === 0 ? 1 : highWaterMark
257 this.buffered = 0
258 this.readAhead = highWaterMark > 0
259 this.error = null
260 this.pipeline = null
261 this.byteLength = byteLengthReadable || byteLength || defaultByteLength
262 this.map = mapReadable || map
263 this.pipeTo = null
264 this.afterRead = afterRead.bind(this)
265 this.afterUpdateNextTick = updateReadNT.bind(this)
266 }
267
268 get ending() {
269 return (this.stream._duplexState & READ_ENDING) !== 0
270 }
271
272 get ended() {
273 return (this.stream._duplexState & READ_DONE) !== 0
274 }
275
276 pipe(pipeTo, cb) {
277 if (this.pipeTo !== null) throw new Error('Can only pipe to one destination')
278 if (typeof cb !== 'function') cb = null
279
280 this.stream._duplexState |= READ_PIPE_DRAINED
281 this.pipeTo = pipeTo
282 this.pipeline = new Pipeline(this.stream, pipeTo, cb)
283
284 if (cb) this.stream.on('error', noop) // We already error handle this so supress crashes
285
286 if (isStreamx(pipeTo)) {
287 pipeTo._writableState.pipeline = this.pipeline
288 if (cb) pipeTo.on('error', noop) // We already error handle this so supress crashes
289 pipeTo.on('finish', this.pipeline.finished.bind(this.pipeline)) // TODO: just call finished from pipeTo itself
290 } else {
291 const onerror = this.pipeline.done.bind(this.pipeline, pipeTo)
292 const onclose = this.pipeline.done.bind(this.pipeline, pipeTo, null) // onclose has a weird bool arg
293 pipeTo.on('error', onerror)
294 pipeTo.on('close', onclose)
295 pipeTo.on('finish', this.pipeline.finished.bind(this.pipeline))
296 }
297
298 pipeTo.on('drain', afterDrain.bind(this))
299 this.stream.emit('piping', pipeTo)
300 pipeTo.emit('pipe', this.stream)
301 }
302
303 push(data) {
304 const stream = this.stream
305
306 if (data === null) {
307 this.highWaterMark = 0
308 stream._duplexState = (stream._duplexState | READ_ENDING) & READ_NON_PRIMARY_AND_PUSHED
309 return false
310 }
311
312 if (this.map !== null) {
313 data = this.map(data)
314 if (data === null) {
315 stream._duplexState &= READ_PUSHED
316 return this.buffered < this.highWaterMark
317 }
318 }
319
320 this.buffered += this.byteLength(data)
321 this.queue.push(data)
322
323 stream._duplexState = (stream._duplexState | READ_QUEUED) & READ_PUSHED
324
325 return this.buffered < this.highWaterMark
326 }
327
328 shift() {
329 const data = this.queue.shift()
330
331 this.buffered -= this.byteLength(data)
332 if (this.buffered === 0) this.stream._duplexState &= READ_NOT_QUEUED
333 return data
334 }
335
336 unshift(data) {
337 const pending = [this.map !== null ? this.map(data) : data]
338 while (this.buffered > 0) pending.push(this.shift())
339
340 for (let i = 0; i < pending.length - 1; i++) {
341 const data = pending[i]
342 this.buffered += this.byteLength(data)
343 this.queue.push(data)
344 }
345
346 this.push(pending[pending.length - 1])
347 }
348
349 read() {
350 const stream = this.stream
351
352 if ((stream._duplexState & READ_STATUS) === READ_QUEUED) {
353 const data = this.shift()
354 if (this.pipeTo !== null && this.pipeTo.write(data) === false)
355 stream._duplexState &= READ_PIPE_NOT_DRAINED
356 if ((stream._duplexState & READ_EMIT_DATA) !== 0) stream.emit('data', data)
357 return data
358 }
359
360 if (this.readAhead === false) {
361 stream._duplexState |= READ_READ_AHEAD
362 this.updateNextTick()
363 }
364
365 return null
366 }
367
368 drain() {
369 const stream = this.stream
370
371 while (
372 (stream._duplexState & READ_STATUS) === READ_QUEUED &&
373 (stream._duplexState & READ_FLOWING) !== 0
374 ) {
375 const data = this.shift()
376 if (this.pipeTo !== null && this.pipeTo.write(data) === false)
377 stream._duplexState &= READ_PIPE_NOT_DRAINED
378 if ((stream._duplexState & READ_EMIT_DATA) !== 0) stream.emit('data', data)
379 }
380 }
381
382 update() {
383 const stream = this.stream
384
385 stream._duplexState |= READ_UPDATING
386
387 do {
388 this.drain()
389
390 while (
391 this.buffered < this.highWaterMark &&
392 (stream._duplexState & SHOULD_NOT_READ) === READ_READ_AHEAD
393 ) {
394 stream._duplexState |= READ_ACTIVE_AND_NEEDS_PUSH
395 stream._read(this.afterRead)
396 this.drain()
397 }
398
399 if ((stream._duplexState & READ_READABLE_STATUS) === READ_EMIT_READABLE_AND_QUEUED) {
400 stream._duplexState |= READ_EMITTED_READABLE
401 stream.emit('readable')
402 }
403
404 if ((stream._duplexState & READ_PRIMARY_AND_ACTIVE) === 0) this.updateNonPrimary()
405 } while (this.continueUpdate() === true)
406
407 stream._duplexState &= READ_NOT_UPDATING
408 }
409
410 updateNonPrimary() {
411 const stream = this.stream
412
413 if ((stream._duplexState & READ_ENDING_STATUS) === READ_ENDING) {
414 stream._duplexState = (stream._duplexState | READ_DONE) & READ_NOT_ENDING
415 stream.emit('end')
416 if ((stream._duplexState & AUTO_DESTROY) === DONE) stream._duplexState |= DESTROYING
417 if (this.pipeTo !== null) this.pipeTo.end()
418 }
419
420 if ((stream._duplexState & DESTROY_STATUS) === DESTROYING) {
421 if ((stream._duplexState & ACTIVE_OR_TICKING) === 0) {
422 stream._duplexState |= ACTIVE
423 stream._destroy(afterDestroy.bind(this))
424 }
425 return
426 }
427
428 if ((stream._duplexState & IS_OPENING) === OPENING) {
429 stream._duplexState = (stream._duplexState | ACTIVE) & NOT_OPENING
430 stream._open(afterOpen.bind(this))
431 }
432 }
433
434 continueUpdate() {
435 if ((this.stream._duplexState & READ_NEXT_TICK) === 0) return false
436 this.stream._duplexState &= READ_NOT_NEXT_TICK
437 return true
438 }
439
440 updateCallback() {
441 if ((this.stream._duplexState & READ_UPDATE_SYNC_STATUS) === READ_PRIMARY) this.update()
442 else this.updateNextTick()
443 }
444
445 updateNextTickIfOpen() {
446 if ((this.stream._duplexState & READ_NEXT_TICK_OR_OPENING) !== 0) return
447 this.stream._duplexState |= READ_NEXT_TICK
448 if ((this.stream._duplexState & READ_UPDATING) === 0) qmt(this.afterUpdateNextTick)
449 }
450
451 updateNextTick() {
452 if ((this.stream._duplexState & READ_NEXT_TICK) !== 0) return
453 this.stream._duplexState |= READ_NEXT_TICK
454 if ((this.stream._duplexState & READ_UPDATING) === 0) qmt(this.afterUpdateNextTick)
455 }
456}
457
458class TransformState {
459 constructor(stream) {
460 this.data = null
461 this.afterTransform = afterTransform.bind(stream)
462 this.afterFinal = null
463 }
464}
465
466class Pipeline {
467 constructor(src, dst, cb) {
468 this.from = src
469 this.to = dst
470 this.afterPipe = cb
471 this.error = null
472 this.pipeToFinished = false
473 }
474
475 finished() {
476 this.pipeToFinished = true
477 }
478
479 done(stream, err) {
480 if (err) this.error = err
481
482 if (stream === this.to) {
483 this.to = null
484
485 if (this.from !== null) {
486 if ((this.from._duplexState & READ_DONE) === 0 || !this.pipeToFinished) {
487 this.from.destroy(this.error || new Error('Writable stream closed prematurely'))
488 }
489 return
490 }
491 }
492
493 if (stream === this.from) {
494 this.from = null
495
496 if (this.to !== null) {
497 if ((stream._duplexState & READ_DONE) === 0) {
498 this.to.destroy(this.error || new Error('Readable stream closed before ending'))
499 }
500 return
501 }
502 }
503
504 if (this.afterPipe !== null) this.afterPipe(this.error)
505 this.to = this.from = this.afterPipe = null
506 }
507}
508
509function afterDrain() {
510 this.stream._duplexState |= READ_PIPE_DRAINED
511 this.updateCallback()
512}
513
514function afterFinal(err) {
515 const stream = this.stream
516 if (err) stream.destroy(err)
517 if ((stream._duplexState & DESTROY_STATUS) === 0) {
518 stream._duplexState |= WRITE_DONE
519 stream.emit('finish')
520 }
521 if ((stream._duplexState & AUTO_DESTROY) === DONE) {
522 stream._duplexState |= DESTROYING
523 }
524
525 stream._duplexState &= WRITE_NOT_FINISHING
526
527 // no need to wait the extra tick here, so we short circuit that
528 if ((stream._duplexState & WRITE_UPDATING) === 0) this.update()
529 else this.updateNextTick()
530}
531
532function afterDestroy(err) {
533 const stream = this.stream
534
535 if (!err && this.error !== STREAM_DESTROYED) err = this.error
536 if (err) stream.emit('error', err)
537 stream._duplexState |= DESTROYED
538 stream.emit('close')
539
540 const rs = stream._readableState
541 const ws = stream._writableState
542
543 if (rs !== null && rs.pipeline !== null) rs.pipeline.done(stream, err)
544
545 if (ws !== null) {
546 while (ws.drains !== null && ws.drains.length > 0) ws.drains.shift().resolve(false)
547 if (ws.pipeline !== null) ws.pipeline.done(stream, err)
548 }
549}
550
551function afterWrite(err) {
552 const stream = this.stream
553
554 if (err) stream.destroy(err)
555 stream._duplexState &= WRITE_NOT_ACTIVE
556
557 if (this.drains !== null) tickDrains(this.drains)
558
559 if ((stream._duplexState & WRITE_DRAIN_STATUS) === WRITE_UNDRAINED) {
560 stream._duplexState &= WRITE_DRAINED
561 if ((stream._duplexState & WRITE_EMIT_DRAIN) === WRITE_EMIT_DRAIN) {
562 stream.emit('drain')
563 }
564 }
565
566 this.updateCallback()
567}
568
569function afterRead(err) {
570 if (err) this.stream.destroy(err)
571 this.stream._duplexState &= READ_NOT_ACTIVE
572 if (this.readAhead === false && (this.stream._duplexState & READ_RESUMED) === 0)
573 this.stream._duplexState &= READ_NO_READ_AHEAD
574 this.updateCallback()
575}
576
577function updateReadNT() {
578 if ((this.stream._duplexState & READ_UPDATING) === 0) {
579 this.stream._duplexState &= READ_NOT_NEXT_TICK
580 this.update()
581 }
582}
583
584function updateWriteNT() {
585 if ((this.stream._duplexState & WRITE_UPDATING) === 0) {
586 this.stream._duplexState &= WRITE_NOT_NEXT_TICK
587 this.update()
588 }
589}
590
591function tickDrains(drains) {
592 for (let i = 0; i < drains.length; i++) {
593 // drains.writes are monotonic, so if one is 0 its always the first one
594 if (--drains[i].writes === 0) {
595 drains.shift().resolve(true)
596 i--
597 }
598 }
599}
600
601function afterOpen(err) {
602 const stream = this.stream
603
604 if (err) stream.destroy(err)
605
606 if ((stream._duplexState & DESTROYING) === 0) {
607 if ((stream._duplexState & READ_PRIMARY_STATUS) === 0) stream._duplexState |= READ_PRIMARY
608 if ((stream._duplexState & WRITE_PRIMARY_STATUS) === 0) stream._duplexState |= WRITE_PRIMARY
609 stream.emit('open')
610 }
611
612 stream._duplexState &= NOT_ACTIVE
613
614 if (stream._writableState !== null) {
615 stream._writableState.updateCallback()
616 }
617
618 if (stream._readableState !== null) {
619 stream._readableState.updateCallback()
620 }
621}
622
623function afterTransform(err, data) {
624 if (data !== undefined && data !== null) this.push(data)
625 this._writableState.afterWrite(err)
626}
627
628function newListener(name) {
629 if (this._readableState !== null) {
630 if (name === 'data') {
631 this._duplexState |= READ_EMIT_DATA | READ_RESUMED_READ_AHEAD
632 this._readableState.updateNextTick()
633 }
634 if (name === 'readable') {
635 this._duplexState |= READ_EMIT_READABLE
636 this._readableState.updateNextTick()
637 }
638 }
639
640 if (this._writableState !== null) {
641 if (name === 'drain') {
642 this._duplexState |= WRITE_EMIT_DRAIN
643 this._writableState.updateNextTick()
644 }
645 }
646}
647
648class Stream extends EventEmitter {
649 constructor(opts) {
650 super()
651
652 this._duplexState = 0
653 this._readableState = null
654 this._writableState = null
655
656 if (opts) {
657 if (opts.open) this._open = opts.open
658 if (opts.destroy) this._destroy = opts.destroy
659 if (opts.predestroy) this._predestroy = opts.predestroy
660 if (opts.signal) {
661 opts.signal.addEventListener('abort', abort.bind(this))
662 }
663 }
664
665 this.on('newListener', newListener)
666 }
667
668 _open(cb) {
669 cb(null)
670 }
671
672 _destroy(cb) {
673 cb(null)
674 }
675
676 _predestroy() {
677 // does nothing
678 }
679
680 get readable() {
681 return this._readableState !== null ? true : undefined
682 }
683
684 get writable() {
685 return this._writableState !== null ? true : undefined
686 }
687
688 get destroyed() {
689 return (this._duplexState & DESTROYED) !== 0
690 }
691
692 get destroying() {
693 return (this._duplexState & DESTROY_STATUS) !== 0
694 }
695
696 destroy(err) {
697 if ((this._duplexState & DESTROY_STATUS) === 0) {
698 if (!err) err = STREAM_DESTROYED
699 this._duplexState = (this._duplexState | DESTROYING) & NON_PRIMARY
700
701 if (this._readableState !== null) {
702 this._readableState.highWaterMark = 0
703 this._readableState.error = err
704 }
705 if (this._writableState !== null) {
706 this._writableState.highWaterMark = 0
707 this._writableState.error = err
708 }
709
710 this._duplexState |= PREDESTROYING
711 this._predestroy()
712 this._duplexState &= NOT_PREDESTROYING
713
714 if (this._readableState !== null) this._readableState.updateNextTick()
715 if (this._writableState !== null) this._writableState.updateNextTick()
716 }
717 }
718}
719
720class Readable extends Stream {
721 constructor(opts) {
722 super(opts)
723
724 this._duplexState |= OPENING | WRITE_DONE | READ_READ_AHEAD
725 this._readableState = new ReadableState(this, opts)
726
727 if (opts) {
728 if (this._readableState.readAhead === false) this._duplexState &= READ_NO_READ_AHEAD
729 if (opts.read) this._read = opts.read
730 if (opts.eagerOpen) this._readableState.updateNextTick()
731 if (opts.encoding) this.setEncoding(opts.encoding)
732 }
733 }
734
735 setEncoding(encoding) {
736 const dec = new TextDecoder(encoding)
737 const map = this._readableState.map || echo
738 this._readableState.map = mapOrSkip
739 return this
740
741 function mapOrSkip(data) {
742 const next = dec.push(data)
743 return next === '' && (data.byteLength !== 0 || dec.remaining > 0) ? null : map(next)
744 }
745 }
746
747 _read(cb) {
748 cb(null)
749 }
750
751 pipe(dest, cb) {
752 this._readableState.updateNextTick()
753 this._readableState.pipe(dest, cb)
754 return dest
755 }
756
757 read() {
758 this._readableState.updateNextTick()
759 return this._readableState.read()
760 }
761
762 push(data) {
763 this._readableState.updateNextTickIfOpen()
764 return this._readableState.push(data)
765 }
766
767 unshift(data) {
768 this._readableState.updateNextTickIfOpen()
769 return this._readableState.unshift(data)
770 }
771
772 resume() {
773 this._duplexState |= READ_RESUMED_READ_AHEAD
774 this._readableState.updateNextTick()
775 return this
776 }
777
778 pause() {
779 this._duplexState &=
780 this._readableState.readAhead === false ? READ_PAUSED_NO_READ_AHEAD : READ_PAUSED
781 return this
782 }
783
784 static _fromAsyncIterator(ite, opts) {
785 let destroy
786
787 const rs = new Readable({
788 ...opts,
789 read(cb) {
790 ite.next().then(push).then(cb.bind(null, null)).catch(cb)
791 },
792 predestroy() {
793 destroy = ite.return()
794 },
795 destroy(cb) {
796 if (!destroy) return cb(null)
797 destroy.then(cb.bind(null, null)).catch(cb)
798 }
799 })
800
801 return rs
802
803 function push(data) {
804 if (data.done) rs.push(null)
805 else rs.push(data.value)
806 }
807 }
808
809 static from(data, opts) {
810 if (isReadStreamx(data)) return data
811 if (data[asyncIterator]) return this._fromAsyncIterator(data[asyncIterator](), opts)
812 if (!Array.isArray(data)) data = data === undefined ? [] : [data]
813
814 let i = 0
815 return new Readable({
816 ...opts,
817 read(cb) {
818 this.push(i === data.length ? null : data[i++])
819 cb(null)
820 }
821 })
822 }
823
824 static isBackpressured(rs) {
825 return (
826 (rs._duplexState & READ_BACKPRESSURE_STATUS) !== 0 ||
827 rs._readableState.buffered >= rs._readableState.highWaterMark
828 )
829 }
830
831 static isPaused(rs) {
832 return (rs._duplexState & READ_RESUMED) === 0
833 }
834
835 [asyncIterator]() {
836 const stream = this
837
838 let error = null
839 let promiseResolve = null
840 let promiseReject = null
841
842 this.on('error', (err) => {
843 error = err
844 })
845 this.on('readable', onreadable)
846 this.on('close', onclose)
847
848 return {
849 [asyncIterator]() {
850 return this
851 },
852 next() {
853 return new Promise(function (resolve, reject) {
854 promiseResolve = resolve
855 promiseReject = reject
856 const data = stream.read()
857 if (data !== null) ondata(data)
858 else if ((stream._duplexState & DESTROYED) !== 0) ondata(null)
859 })
860 },
861 return() {
862 return destroy(null)
863 },
864 throw(err) {
865 return destroy(err)
866 }
867 }
868
869 function onreadable() {
870 if (promiseResolve !== null) ondata(stream.read())
871 }
872
873 function onclose() {
874 if (promiseResolve !== null) ondata(null)
875 }
876
877 function ondata(data) {
878 if (promiseReject === null) return
879 if (error) promiseReject(error)
880 else if (data === null && (stream._duplexState & READ_DONE) === 0)
881 promiseReject(STREAM_DESTROYED)
882 else promiseResolve({ value: data, done: data === null })
883 promiseReject = promiseResolve = null
884 }
885
886 function destroy(err) {
887 stream.destroy(err)
888 return new Promise((resolve, reject) => {
889 if (stream._duplexState & DESTROYED) return resolve({ value: undefined, done: true })
890 stream.once('close', function () {
891 if (err) reject(err)
892 else resolve({ value: undefined, done: true })
893 })
894 })
895 }
896 }
897}
898
899class Writable extends Stream {
900 constructor(opts) {
901 super(opts)
902
903 this._duplexState |= OPENING | READ_DONE
904 this._writableState = new WritableState(this, opts)
905
906 if (opts) {
907 if (opts.writev) this._writev = opts.writev
908 if (opts.write) this._write = opts.write
909 if (opts.final) this._final = opts.final
910 if (opts.eagerOpen) this._writableState.updateNextTick()
911 }
912 }
913
914 cork() {
915 this._duplexState |= WRITE_CORKED
916 }
917
918 uncork() {
919 this._duplexState &= WRITE_NOT_CORKED
920 this._writableState.updateNextTick()
921 }
922
923 _writev(batch, cb) {
924 cb(null)
925 }
926
927 _write(data, cb) {
928 this._writableState.autoBatch(data, cb)
929 }
930
931 _final(cb) {
932 cb(null)
933 }
934
935 static isBackpressured(ws) {
936 return (ws._duplexState & WRITE_BACKPRESSURE_STATUS) !== 0
937 }
938
939 static drained(ws) {
940 if (ws.destroyed) return Promise.resolve(false)
941 const state = ws._writableState
942 const pending = isWritev(ws) ? Math.min(1, state.queue.length) : state.queue.length
943 const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0)
944 if (writes === 0) return Promise.resolve(true)
945 if (state.drains === null) state.drains = []
946 return new Promise((resolve) => {
947 state.drains.push({ writes, resolve })
948 })
949 }
950
951 write(data) {
952 this._writableState.updateNextTick()
953 return this._writableState.push(data)
954 }
955
956 end(data) {
957 this._writableState.updateNextTick()
958 this._writableState.end(data)
959 return this
960 }
961}
962
963class Duplex extends Readable {
964 // and Writable
965 constructor(opts) {
966 super(opts)
967
968 this._duplexState = OPENING | (this._duplexState & READ_READ_AHEAD)
969 this._writableState = new WritableState(this, opts)
970
971 if (opts) {
972 if (opts.writev) this._writev = opts.writev
973 if (opts.write) this._write = opts.write
974 if (opts.final) this._final = opts.final
975 }
976 }
977
978 cork() {
979 this._duplexState |= WRITE_CORKED
980 }
981
982 uncork() {
983 this._duplexState &= WRITE_NOT_CORKED
984 this._writableState.updateNextTick()
985 }
986
987 _writev(batch, cb) {
988 cb(null)
989 }
990
991 _write(data, cb) {
992 this._writableState.autoBatch(data, cb)
993 }
994
995 _final(cb) {
996 cb(null)
997 }
998
999 write(data) {
1000 this._writableState.updateNextTick()
1001 return this._writableState.push(data)
1002 }
1003
1004 end(data) {
1005 this._writableState.updateNextTick()
1006 this._writableState.end(data)
1007 return this
1008 }
1009}
1010
1011class Transform extends Duplex {
1012 constructor(opts) {
1013 super(opts)
1014 this._transformState = new TransformState(this)
1015
1016 if (opts) {
1017 if (opts.transform) this._transform = opts.transform
1018 if (opts.flush) this._flush = opts.flush
1019 }
1020 }
1021
1022 _write(data, cb) {
1023 if (this._readableState.buffered >= this._readableState.highWaterMark) {
1024 this._transformState.data = data
1025 } else {
1026 this._transform(data, this._transformState.afterTransform)
1027 }
1028 }
1029
1030 _read(cb) {
1031 if (this._transformState.data !== null) {
1032 const data = this._transformState.data
1033 this._transformState.data = null
1034 cb(null)
1035 this._transform(data, this._transformState.afterTransform)
1036 } else {
1037 cb(null)
1038 }
1039 }
1040
1041 destroy(err) {
1042 super.destroy(err)
1043 if (this._transformState.data !== null) {
1044 this._transformState.data = null
1045 this._transformState.afterTransform()
1046 }
1047 }
1048
1049 _transform(data, cb) {
1050 cb(null, data)
1051 }
1052
1053 _flush(cb) {
1054 cb(null)
1055 }
1056
1057 _final(cb) {
1058 this._transformState.afterFinal = cb
1059 this._flush(transformAfterFlush.bind(this))
1060 }
1061}
1062
1063class PassThrough extends Transform {}
1064
1065function transformAfterFlush(err, data) {
1066 const cb = this._transformState.afterFinal
1067 if (err) return cb(err)
1068 if (data !== null && data !== undefined) this.push(data)
1069 this.push(null)
1070 cb(null)
1071}
1072
1073function pipelinePromise(...streams) {
1074 return new Promise((resolve, reject) => {
1075 return pipeline(...streams, (err) => {
1076 if (err) return reject(err)
1077 resolve()
1078 })
1079 })
1080}
1081
1082function pipeline(stream, ...streams) {
1083 const all = Array.isArray(stream) ? [...stream, ...streams] : [stream, ...streams]
1084 const done = all.length && typeof all[all.length - 1] === 'function' ? all.pop() : null
1085
1086 if (all.length < 2) throw new Error('Pipeline requires at least 2 streams')
1087
1088 let src = all[0]
1089 let dest = null
1090 let error = null
1091
1092 for (let i = 1; i < all.length; i++) {
1093 dest = all[i]
1094
1095 if (isStreamx(src)) {
1096 src.pipe(dest, onerror)
1097 } else {
1098 errorHandle(src, true, i > 1, onerror)
1099 src.pipe(dest)
1100 }
1101
1102 src = dest
1103 }
1104
1105 if (done) {
1106 let fin = false
1107
1108 const autoDestroy =
1109 isStreamx(dest) || !!(dest._writableState && dest._writableState.autoDestroy)
1110
1111 dest.on('error', (err) => {
1112 if (error === null) error = err
1113 })
1114
1115 dest.on('finish', () => {
1116 fin = true
1117 if (!autoDestroy) done(error)
1118 })
1119
1120 if (autoDestroy) {
1121 dest.on('close', () => done(error || (fin ? null : PREMATURE_CLOSE)))
1122 }
1123 }
1124
1125 return dest
1126
1127 function errorHandle(s, rd, wr, onerror) {
1128 s.on('error', onerror)
1129 s.on('close', onclose)
1130
1131 function onclose() {
1132 if (rd && s._readableState && !s._readableState.ended) return onerror(PREMATURE_CLOSE)
1133 if (wr && s._writableState && !s._writableState.ended) return onerror(PREMATURE_CLOSE)
1134 }
1135 }
1136
1137 function onerror(err) {
1138 if (!err || error) return
1139 error = err
1140
1141 for (const s of all) {
1142 s.destroy(err)
1143 }
1144 }
1145}
1146
1147function echo(s) {
1148 return s
1149}
1150
1151function isStream(stream) {
1152 return !!stream._readableState || !!stream._writableState
1153}
1154
1155function isStreamx(stream) {
1156 return typeof stream._duplexState === 'number' && isStream(stream)
1157}
1158
1159function isEnding(stream) {
1160 return !!stream._readableState && stream._readableState.ending
1161}
1162
1163function isEnded(stream) {
1164 return !!stream._readableState && stream._readableState.ended
1165}
1166
1167function isFinishing(stream) {
1168 return !!stream._writableState && stream._writableState.ending
1169}
1170
1171function isFinished(stream) {
1172 return !!stream._writableState && stream._writableState.ended
1173}
1174
1175function getStreamError(stream, opts = {}) {
1176 const err =
1177 (stream._readableState && stream._readableState.error) ||
1178 (stream._writableState && stream._writableState.error)
1179
1180 // avoid implicit errors by default
1181 return !opts.all && err === STREAM_DESTROYED ? null : err
1182}
1183
1184function isReadStreamx(stream) {
1185 return isStreamx(stream) && stream.readable
1186}
1187
1188function isDisturbed(stream) {
1189 return (
1190 (stream._duplexState & OPENING) !== OPENING ||
1191 (stream._duplexState & DESTROYING) === DESTROYING ||
1192 (stream._duplexState & ACTIVE_OR_TICKING) !== 0
1193 )
1194}
1195
1196function isTypedArray(data) {
1197 return typeof data === 'object' && data !== null && typeof data.byteLength === 'number'
1198}
1199
1200function defaultByteLength(data) {
1201 return isTypedArray(data) ? data.byteLength : 1024
1202}
1203
1204function noop() {}
1205
1206function abort() {
1207 this.destroy(new Error('Stream aborted.'))
1208}
1209
1210function isWritev(s) {
1211 return s._writev !== Writable.prototype._writev && s._writev !== Duplex.prototype._writev
1212}
1213
1214module.exports = {
1215 pipeline,
1216 pipelinePromise,
1217 isStream,
1218 isStreamx,
1219 isEnding,
1220 isEnded,
1221 isFinishing,
1222 isFinished,
1223 isDisturbed,
1224 getStreamError,
1225 Stream,
1226 Writable,
1227 Readable,
1228 Duplex,
1229 Transform,
1230 // Export PassThrough for compatibility with Node.js core's stream module
1231 PassThrough
1232}
node_modules/streamx/package.json +36 -0
……@@ -0,0 +1,36 @@
1{
2 "name": "streamx",
3 "version": "2.25.0",
4 "description": "An iteration of the Node.js core streams with a series of improvements",
5 "main": "index.js",
6 "dependencies": {
7 "events-universal": "^1.0.0",
8 "fast-fifo": "^1.3.2",
9 "text-decoder": "^1.1.0"
10 },
11 "devDependencies": {
12 "b4a": "^1.6.6",
13 "brittle": "^3.1.1",
14 "end-of-stream": "^1.4.4",
15 "prettier": "^3.6.2",
16 "prettier-config-holepunch": "^2.0.0"
17 },
18 "files": [
19 "index.js"
20 ],
21 "scripts": {
22 "format": "prettier --write .",
23 "test": "prettier --check . && node test/all.js",
24 "test:bare": "bare test/all.js"
25 },
26 "repository": {
27 "type": "git",
28 "url": "https://github.com/mafintosh/streamx.git"
29 },
30 "author": "Mathias Buus (@mafintosh)",
31 "license": "MIT",
32 "bugs": {
33 "url": "https://github.com/mafintosh/streamx/issues"
34 },
35 "homepage": "https://github.com/mafintosh/streamx"
36}
node_modules/sub-encoder/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - main
6 pull_request:
7 branches:
8 - main
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v2
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v2
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/sub-encoder/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/sub-encoder/NOTICE +13 -0
……@@ -0,0 +1,13 @@
1Copyright 2022 Holepunch Inc
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
node_modules/sub-encoder/README.md +56 -0
……@@ -0,0 +1,56 @@
1# sub-encoder
2Generate sub encodings for key/value stores
3
4### Usage
5```js
6const enc = new SubEncoder()
7const subA = enc.sub('sub-a')
8const subB = enc.sub('sub-b', 'binary') // subs support custom key encodings
9
10await bee.put('k1', 'b')
11await bee.put('a1', 'a1', { keyEncoding: subA })
12await bee.put('b1', 'b1', { keyEncoding: subB })
13
14// k1 as normal
15await bee.get('k1')
16// a1 from the sub
17await bee.get('a1', { keyEncoding: subA })
18
19// also supports read streams
20for await (const node of bee.createReadStream({ keyEncoding: subA })) {
21 // Iterates everything in the A sub
22}
23
24// The range options will be encoded properly too
25for await (const node of bee.createReadStream({ lt: 'b2' }, { keyEncoding: subB })) {
26}
27```
28
29### API
30
31#### `const enc = new SubEncoder([prefix, encoding])`
32
33Create a new SubEncoder. Optionally set the initial prefix and encoding.
34
35`prefix` can be string or Buffer. If set, acts as an initial sub instead of starting at the Hyperbee's base level.
36
37#### `subEnc = enc.sub(prefix, [encoding])`
38
39Make a new sub. Returns a SubEncoder, so subs can easily be nested.
40
41`prefix` can be string or Buffer.
42
43#### `buf = enc.encode(key)`
44
45Encode a key.
46
47#### `key = enc.decode(buf)`
48
49Decode a key.
50
51#### `encodedRange = enc.encodeRange(range)`
52
53Encode a range.
54
55### License
56Apache-2.0
node_modules/sub-encoder/index.js +70 -0
……@@ -0,0 +1,70 @@
1const codecs = require('codecs')
2const b = require('b4a')
3
4const SEP = b.alloc(1)
5const SEP_BUMPED = b.from([0x1])
6const EMPTY = b.alloc(0)
7
8module.exports = class SubEncoder {
9 constructor (prefix, encoding, parent = null) {
10 this.userEncoding = codecs(encoding)
11 this.prefix = prefix != null ? createPrefix(prefix, parent) : null
12 this.lt = this.prefix && b.concat([this.prefix.subarray(0, this.prefix.byteLength - 1), SEP_BUMPED])
13 }
14
15 _encodeRangeUser (r) {
16 if (this.userEncoding.encodeRange) return this.userEncoding.encodeRange(r)
17
18 const res = {}
19 if (r.gt != null) res.gt = this.userEncoding.encode(r.gt)
20 if (r.gte != null) res.gte = this.userEncoding.encode(r.gte)
21 if (r.lte != null) res.lte = this.userEncoding.encode(r.lte)
22 if (r.lt != null) res.lt = this.userEncoding.encode(r.lt)
23
24 return res
25 }
26
27 _addPrefix (key) {
28 return this.prefix ? b.concat([this.prefix, key]) : key
29 }
30
31 encode (key) {
32 return this._addPrefix(this.userEncoding.encode(key))
33 }
34
35 encodeRange (range) {
36 const r = this._encodeRangeUser(range)
37
38 if (r.gt) r.gt = this._addPrefix(r.gt)
39 else if (r.gte) r.gte = this._addPrefix(r.gte)
40 else if (this.prefix) r.gte = this.prefix
41
42 if (r.lt) r.lt = this._addPrefix(r.lt)
43 else if (r.lte) r.lte = this._addPrefix(r.lte)
44 else if (this.prefix) r.lt = this.lt
45
46 return r
47 }
48
49 decode (key) {
50 return this.userEncoding.decode(this.prefix ? key.subarray(this.prefix.byteLength) : key)
51 }
52
53 sub (prefix, encoding) {
54 return new SubEncoder(prefix || EMPTY, compat(encoding), this.prefix)
55 }
56}
57
58function createPrefix (prefix, parent) {
59 prefix = typeof prefix === 'string' ? b.from(prefix) : prefix
60
61 if (prefix && parent) return b.concat([parent, prefix, SEP])
62 if (prefix) return b.concat([prefix, SEP])
63 if (parent) return b.concat([parent, SEP])
64 return SEP
65}
66
67function compat (enc) {
68 if (enc && enc.keyEncoding) return enc.keyEncoding
69 return enc
70}
node_modules/sub-encoder/package.json +37 -0
……@@ -0,0 +1,37 @@
1{
2 "name": "sub-encoder",
3 "version": "2.1.3",
4 "description": "Generate sub encodings for key/value stores",
5 "main": "index.js",
6 "scripts": {
7 "test": "standard && brittle test/*.js"
8 },
9 "repository": {
10 "type": "git",
11 "url": "git+https://github.com/holepunchto/sub-encoder.git"
12 },
13 "keywords": [
14 "kv-store",
15 "encoding",
16 "hyperbee"
17 ],
18 "author": "Andrew Osheroff <andrewosh@gmail.com>",
19 "license": "Apache-2.0",
20 "bugs": {
21 "url": "https://github.com/holepunchto/sub-encoder/issues"
22 },
23 "homepage": "https://github.com/holepunchto/sub-encoder#readme",
24 "devDependencies": {
25 "brittle": "^3.1.1",
26 "compact-encoding": "^2.12.0",
27 "hyperbee": "^2.11.0",
28 "hypercore": "^10.3.2",
29 "index-encoder": "^3.0.0",
30 "random-access-memory": "^6.0.0",
31 "standard": "^17.0.0"
32 },
33 "dependencies": {
34 "b4a": "^1.6.0",
35 "codecs": "^3.1.0"
36 }
37}
node_modules/sub-encoder/test/all.js +281 -0
……@@ -0,0 +1,281 @@
1const test = require('brittle')
2
3const Hypercore = require('hypercore')
4const Hyperbee = require('hyperbee')
5const IndexEncoder = require('index-encoder')
6const ram = require('random-access-memory')
7const b = require('b4a')
8const cenc = require('compact-encoding')
9
10const SEP = b.alloc(1)
11
12const SubEncoder = require('..')
13
14test('simple sub key encoding', t => {
15 const enc = new SubEncoder()
16 const sub1 = enc.sub('a')
17 const sub2 = sub1.sub('b')
18
19 const key = b.alloc(1).fill(1)
20 const k1 = enc.encode(key)
21 const k2 = sub1.encode(key)
22 const k3 = sub2.encode(key)
23
24 t.alike(k1, key)
25 t.alike(k2, b.concat([b.from('a'), SEP, key]))
26 t.alike(k3, b.concat([b.from('a'), SEP, b.from('b'), SEP, key]))
27
28 t.alike(key, enc.decode(k1))
29 t.alike(key, sub1.decode(k2))
30 t.alike(key, sub2.decode(k3))
31})
32
33test('sub key encoding with hyperbee', async t => {
34 const bee = new Hyperbee(new Hypercore(ram))
35 const enc = new SubEncoder()
36
37 const sub1 = enc.sub('hello', { keyEncoding: 'utf-8' })
38 const sub2 = enc.sub('world')
39
40 await bee.put('a', b.from('a'), { keyEncoding: sub1 })
41 await bee.put('b', b.from('b'), { keyEncoding: sub2 })
42
43 const n1 = await bee.get('a', { keyEncoding: sub1 })
44 const n2 = await bee.get('b', { keyEncoding: sub2 })
45
46 t.is(n1.key, 'a')
47 t.alike(n1.value, b.from('a'))
48 t.alike(n2.key, b.from('b'))
49 t.alike(n2.value, b.from('b'))
50})
51
52test('sub range encoding with hyperbee', async t => {
53 const bee = new Hyperbee(new Hypercore(ram), { valueEncoding: 'utf-8' })
54
55 const enc = new SubEncoder(null, 'utf-8')
56 const subA = enc.sub('sub-a', 'utf-8')
57 const subB = enc.sub('sub-b', 'utf-8')
58 const subC = enc.sub('sub-c', 'utf-8')
59
60 await bee.put(enc.encode('d1'), 'd2')
61 await bee.put(subA.encode('a1'), 'a1')
62 await bee.put(subB.encode('b1'), 'b1')
63 await bee.put(subB.encode('b2'), 'b2')
64 await bee.put(subB.encode('b3'), 'b3')
65 await bee.put(subC.encode('c1'), 'c1')
66
67 {
68 const range = { lt: 'sub' }
69 const nodes = await collect(bee.createReadStream(range, { keyEncoding: enc }))
70 t.is(nodes.length, 1)
71 t.is(nodes[0].key, 'd1')
72 }
73
74 {
75 const range = {}
76 const nodes = await collect(bee.createReadStream(range, { keyEncoding: subA }))
77 t.is(nodes.length, 1)
78 t.is(nodes[0].key, 'a1')
79 }
80
81 {
82 const range = { gt: 'b1', lt: 'b3' }
83 const nodes = await collect(bee.createReadStream(range, { keyEncoding: subB }))
84 t.is(nodes.length, 1)
85 t.is(nodes[0].key, 'b2')
86 }
87})
88
89test('sub range encoding encodes non-undefined falsy values', async t => {
90 const bee = new Hyperbee(new Hypercore(ram), { valueEncoding: 'utf-8' })
91
92 const enc = new SubEncoder()
93
94 const preSub = enc.sub('sub-a')
95 const keyEncoding = enc.sub('sub-b', cenc.lexint)
96 const postSub = enc.sub('sub-c')
97
98 await bee.put('what', 'ever', { keyEncoding: preSub })
99 await bee.put('what', 'ever', { keyEncoding: postSub })
100
101 await bee.put(0, 'entry0', { keyEncoding })
102 await bee.put(1, 'entry1', { keyEncoding })
103
104 {
105 const range = { gt: 0 }
106 const nodes = await collect(bee.createReadStream(range, { keyEncoding }))
107 t.is(nodes.length, 1, 'gt works')
108 t.is(nodes[0].key, 1)
109 }
110
111 {
112 const range = { lt: 0 }
113 const nodes = await collect(bee.createReadStream(range, { keyEncoding }))
114 t.is(nodes.length, 0, 'lt works')
115 }
116
117 {
118 const range = { lte: 0 }
119 const nodes = await collect(bee.createReadStream(range, { keyEncoding }))
120 t.is(nodes.length, 1, 'lte works')
121 t.is(nodes[0].key, 0)
122 }
123
124 {
125 // Note: also passes when processed as falsy value
126 // would ideally have a value below 0 in the bee, but lexint does not support that
127 const range = { gte: 0 }
128 const nodes = await collect(bee.createReadStream(range, { keyEncoding }))
129 t.is(nodes.length, 2, 'gte works')
130 t.is(nodes[0].key, 0)
131 }
132})
133
134test('sub range diff encoding with hyperbee', async t => {
135 const bee = new Hyperbee(new Hypercore(ram), { valueEncoding: 'utf-8' })
136
137 const enc = new SubEncoder(null, 'utf-8')
138 const subA = enc.sub('sub-a', 'utf-8')
139 const subB = enc.sub('sub-b', 'utf-8')
140 const subC = enc.sub('sub-c', 'utf-8')
141
142 await bee.put(enc.encode('d1'), 'd2')
143 await bee.put(subA.encode('a1'), 'a1')
144 await bee.put(subB.encode('b1'), 'b1')
145 await bee.put(subB.encode('b2'), 'b2')
146 await bee.put(subB.encode('b3'), 'b3')
147 await bee.put(subC.encode('c1'), 'c1')
148
149 {
150 const range = { lt: 'sub' }
151 const nodes = await collect(bee.createDiffStream(0, range, { keyEncoding: enc }))
152 t.is(nodes.length, 1)
153 t.is(nodes[0].left.key, 'd1')
154 }
155
156 {
157 const range = {}
158 const nodes = await collect(bee.createDiffStream(0, range, { keyEncoding: subA }))
159 t.is(nodes.length, 1)
160 t.is(nodes[0].left.key, 'a1')
161 }
162
163 {
164 const range = { gt: 'b1', lt: 'b3' }
165 const nodes = await collect(bee.createDiffStream(0, range, { keyEncoding: subB }))
166 t.is(nodes.length, 1)
167 t.is(nodes[0].left.key, 'b2')
168 }
169})
170
171test('supports the empty sub', async t => {
172 const bee = new Hyperbee(new Hypercore(ram))
173 const enc = new SubEncoder()
174
175 const sub1 = enc.sub('1', 'utf-8')
176 const sub2 = enc.sub('2', 'utf-8')
177 const sub3 = enc.sub()
178
179 await bee.put('', b.from('a'), { keyEncoding: sub1 })
180 await bee.put('', b.from('b'), { keyEncoding: sub2 })
181 await bee.put(b.alloc(1), b.from('c'), { keyEncoding: sub3 })
182
183 const n3 = await collect(bee.createReadStream({ keyEncoding: sub3 }))
184
185 t.is(n3.length, 1)
186 t.alike(n3[0].key, b.alloc(1))
187})
188
189test('supports the empty sub on top of another sub', async t => {
190 const bee = new Hyperbee(new Hypercore(ram))
191 const enc = new SubEncoder()
192
193 const sub1 = enc.sub('1', 'utf-8')
194 const subSubEmpty = sub1.sub()
195 const subSub1 = sub1.sub('not empty', 'utf-8')
196
197 await bee.put('', 'sub1 Entry', { keyEncoding: sub1 })
198 await bee.put('', 'subSub1 Entry', { keyEncoding: subSub1 })
199 await bee.put(b.alloc(1), 'EmptySubsub entry', { keyEncoding: subSubEmpty })
200
201 const n3 = await collect(bee.createReadStream({ keyEncoding: subSubEmpty }))
202
203 t.is(n3.length, 1)
204 t.alike(n3[0].key, b.alloc(1))
205})
206
207test('empty str is a valid prefix, causing no overlap', async t => {
208 const bee = new Hyperbee(new Hypercore(ram))
209 const enc = new SubEncoder()
210
211 const sub1 = enc.sub('', 'utf-8')
212 const sub2 = enc.sub('other', 'utf-8')
213
214 await bee.put('hey', 'ho', { keyEncoding: sub1 })
215 await bee.put('not', 'a part', { keyEncoding: sub2 })
216 const res = await collect(bee.createReadStream({ keyEncoding: sub1 }))
217 t.is(res.length, 1)
218 t.alike(res[0].key, 'hey')
219})
220
221test('can read out the empty key in subs', async t => {
222 const bee = new Hyperbee(new Hypercore(ram))
223 const enc = new SubEncoder()
224
225 const sub1 = enc.sub('1', 'utf-8')
226 const sub2 = enc.sub('2', 'utf-8')
227 const sub3 = enc.sub('3', 'binary')
228
229 await bee.put('', b.from('a'), { keyEncoding: sub1 })
230 await bee.put('', b.from('b'), { keyEncoding: sub2 })
231 await bee.put(b.alloc(1), b.from('c'), { keyEncoding: sub3 })
232
233 const n1 = await collect(bee.createReadStream({ keyEncoding: sub1 }))
234 const n2 = await collect(bee.createReadStream({ keyEncoding: sub2 }))
235 const n3 = await collect(bee.createReadStream({ keyEncoding: sub3 }))
236
237 t.is(n1[0].key, '')
238 t.is(n2[0].key, '')
239 t.alike(n3[0].key, b.alloc(1))
240})
241
242test('sub + index + hyperbee combo', async t => {
243 const root = new SubEncoder()
244 const enc = {
245 keyEncoding: root.sub(b.from([1]), {
246 keyEncoding: new IndexEncoder([
247 IndexEncoder.UINT,
248 IndexEncoder.STRING
249 ])
250 }),
251 valueEncoding: 'utf-8'
252 }
253 const bee = new Hyperbee(new Hypercore(ram))
254
255 await bee.put([1, 'a'], 'a', enc)
256 await bee.put([1, 'b'], 'b', enc)
257 await bee.put([2, 'aa'], 'aa', enc)
258 await bee.put([2, 'bb'], 'bb', enc)
259 await bee.put([3, 'aaa'], 'aaa', enc)
260 await bee.put([3, 'bbb'], 'bbb', enc)
261
262 const expectedKeys = [[2, 'aa'], [2, 'bb']]
263 for await (const node of bee.createReadStream({ gt: [1], lt: [3] }, enc)) {
264 t.alike(node.key, expectedKeys.shift())
265 }
266 t.is(expectedKeys.length, 0)
267})
268
269test('constructor-specified sub equivalent to calling .sub()', async t => {
270 const directSub = new SubEncoder('mysub', 'utf-8')
271 const roundaboutSub = (new SubEncoder()).sub('mysub', 'utf-8')
272 t.alike(directSub, roundaboutSub)
273})
274
275async function collect (ite) {
276 const res = []
277 for await (const node of ite) {
278 res.push(node)
279 }
280 return res
281}
node_modules/teex/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2020 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/teex/README.md +31 -0
……@@ -0,0 +1,31 @@
1# teex
2
3Turn a readable stream into multiple readable [streamx streams](https://github.com/mafintosh/streamx).
4
5```
6npm install teex
7```
8
9## Usage
10
11``` js
12const tee = require('teex')
13
14// a, b are readable streams that are "clones"
15// of someReadableStream. both streams need to
16// be flowing, for someReadableStream to flow
17
18const [a, b] = tee(someReadableStream)
19```
20
21## API
22
23#### `const streams = tee(s, [howMany])`
24
25Split a readable stream into multiple streams.
26The `howMany` argument indicates how many streams
27to split into and defaults to 2.
28
29## License
30
31MIT
node_modules/teex/example.js +16 -0
……@@ -0,0 +1,16 @@
1const tee = require('./')
2const { Readable } = require('streamx')
3
4const s = new Readable()
5
6for (let i = 0; i < 1000; i++) {
7 s.push(Buffer.alloc(1024))
8}
9
10const [a, b] = tee(s)
11
12a.on('data', console.log)
13
14setTimeout(function () {
15 b.read()
16}, 1000)
node_modules/teex/index.js +52 -0
……@@ -0,0 +1,52 @@
1const { Readable } = require('streamx')
2
3module.exports = function (s, forks = 2) {
4 const streams = new Array(forks)
5 const status = new Array(forks).fill(true)
6
7 let ended = false
8
9 for (let i = 0; i < forks; i++) {
10 streams[i] = new Readable({
11 read (cb) {
12 const check = !status[i]
13 status[i] = true
14 if (check && allReadable()) s.resume()
15 cb(null)
16 }
17 })
18 }
19
20 s.on('end', function () {
21 ended = true
22 for (const stream of streams) stream.push(null)
23 })
24
25 s.on('error', function (err) {
26 for (const stream of streams) stream.destroy(err)
27 })
28
29 s.on('close', function () {
30 if (ended) return
31 for (const stream of streams) stream.destroy()
32 })
33
34 s.on('data', function (data) {
35 let needsPause = false
36 for (let i = 0; i < streams.length; i++) {
37 if (!(status[i] = streams[i].push(data))) {
38 needsPause = true
39 }
40 }
41 if (needsPause) s.pause()
42 })
43
44 return streams
45
46 function allReadable () {
47 for (let j = 0; j < status.length; j++) {
48 if (!status[j]) return false
49 }
50 return true
51 }
52}
node_modules/teex/package.json +26 -0
……@@ -0,0 +1,26 @@
1{
2 "name": "teex",
3 "version": "1.0.1",
4 "description": "Turn a readable stream into multiple readable streamx streams",
5 "main": "index.js",
6 "dependencies": {
7 "streamx": "^2.12.5"
8 },
9 "devDependencies": {
10 "standard": "^14.3.4",
11 "tape": "^5.0.1"
12 },
13 "scripts": {
14 "test": "standard && tape test.js"
15 },
16 "repository": {
17 "type": "git",
18 "url": "https://github.com/mafintosh/teex.git"
19 },
20 "author": "Mathias Buus (@mafintosh)",
21 "license": "MIT",
22 "bugs": {
23 "url": "https://github.com/mafintosh/teex/issues"
24 },
25 "homepage": "https://github.com/mafintosh/teex"
26}
node_modules/teex/test.js +68 -0
……@@ -0,0 +1,68 @@
1const tape = require('tape')
2const tee = require('./')
3const { Readable } = require('streamx')
4
5tape('throttled by eachother', function (t) {
6 const r = new Readable()
7
8 for (let i = 0; i < 1000; i++) {
9 r.push(Buffer.alloc(1000))
10 }
11
12 const [a, b] = tee(r)
13
14 let aTicks = 0
15
16 a.on('data', function (data) {
17 aTicks++
18 })
19
20 setTimeout(() => b.read(), 100)
21
22 setTimeout(() => {
23 t.same(aTicks, 18)
24 t.end()
25 }, 200)
26})
27
28tape('does not premature destroy', function (t) {
29 const r = new Readable()
30
31 const [a, b] = tee(r)
32
33 r.push('a')
34 r.push('b')
35 r.push('c')
36 r.push(null)
37
38 setTimeout(() => {
39 const aSeen = []
40 const bSeen = []
41
42 a.on('data', function (data) {
43 aSeen.push(data)
44 })
45 a.on('end', function () {
46 aSeen.push(null)
47 })
48
49 b.on('data', function (data) {
50 bSeen.push(data)
51 })
52 b.on('end', function () {
53 bSeen.push(null)
54 })
55
56 let missing = 2
57 a.on('close', onclose)
58 b.on('close', onclose)
59
60 function onclose () {
61 if (--missing === 0) {
62 t.same(aSeen, ['a', 'b', 'c', null])
63 t.same(bSeen, ['a', 'b', 'c', null])
64 t.end()
65 }
66 }
67 }, 200)
68})
node_modules/text-decoder/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/text-decoder/README.md +36 -0
……@@ -0,0 +1,36 @@
1# text-decoder
2
3Streaming text decoder that preserves multibyte Unicode characters.
4
5```
6npm i text-decoder
7```
8
9## Usage
10
11```js
12const TextDecoder = require('text-decoder')
13
14const td = new TextDecoder()
15
16td.push(Buffer.of(0xf0, 0x9f, 0x92)) // returns ''
17td.push(Buffer.of(0xa9)) // returns '💩'
18```
19
20## API
21
22#### `const td = new TextDecoder([encoding])`
23
24Create a text decoder. `encoding` defaults to `utf8`.
25
26#### `const string = td.push(data)`
27
28Push either a `Buffer` or a `string` to the text decoder. Returns the decoded string, buffering any partial data.
29
30#### `const string = td.end([data])`
31
32End the decoder, optionally pushing a final piece of data. Returns the decoded string.
33
34## License
35
36Apache-2.0
node_modules/text-decoder/index.js +64 -0
……@@ -0,0 +1,64 @@
1const PassThroughDecoder = require('./lib/pass-through-decoder')
2const UTF8Decoder = require('./lib/utf8-decoder')
3
4module.exports = class TextDecoder {
5 constructor(encoding = 'utf8') {
6 this.encoding = normalizeEncoding(encoding)
7
8 switch (this.encoding) {
9 case 'utf8':
10 this.decoder = new UTF8Decoder()
11 break
12 case 'utf16le':
13 case 'base64':
14 throw new Error('Unsupported encoding: ' + this.encoding)
15 default:
16 this.decoder = new PassThroughDecoder(this.encoding)
17 }
18 }
19
20 get remaining() {
21 return this.decoder.remaining
22 }
23
24 push(data) {
25 if (typeof data === 'string') return data
26 return this.decoder.decode(data)
27 }
28
29 // For Node.js compatibility
30 write(data) {
31 return this.push(data)
32 }
33
34 end(data) {
35 let result = ''
36 if (data) result = this.push(data)
37 result += this.decoder.flush()
38 return result
39 }
40}
41
42function normalizeEncoding(encoding) {
43 encoding = encoding.toLowerCase()
44
45 switch (encoding) {
46 case 'utf8':
47 case 'utf-8':
48 return 'utf8'
49 case 'ucs2':
50 case 'ucs-2':
51 case 'utf16le':
52 case 'utf-16le':
53 return 'utf16le'
54 case 'latin1':
55 case 'binary':
56 return 'latin1'
57 case 'base64':
58 case 'ascii':
59 case 'hex':
60 return encoding
61 default:
62 throw new Error('Unknown encoding: ' + encoding)
63 }
64}
node_modules/text-decoder/lib/pass-through-decoder.js +19 -0
……@@ -0,0 +1,19 @@
1const b4a = require('b4a')
2
3module.exports = class PassThroughDecoder {
4 constructor(encoding) {
5 this.encoding = encoding
6 }
7
8 get remaining() {
9 return 0
10 }
11
12 decode(data) {
13 return b4a.toString(data, this.encoding)
14 }
15
16 flush() {
17 return ''
18 }
19}
node_modules/text-decoder/lib/utf8-decoder.js +185 -0
……@@ -0,0 +1,185 @@
1const b4a = require('b4a')
2
3/**
4 * https://encoding.spec.whatwg.org/#utf-8-decoder
5 */
6module.exports = class UTF8Decoder {
7 constructor() {
8 this._reset()
9 }
10
11 get remaining() {
12 return this.bytesSeen
13 }
14
15 decode(data) {
16 if (data.byteLength === 0) return ''
17
18 if (this.bytesNeeded === 0 && trailingIncomplete(data, 0) === 0) {
19 this.bytesSeen = trailingBytesSeen(data)
20 return b4a.toString(data, 'utf8')
21 }
22
23 let result = ''
24 let start = 0
25
26 if (this.bytesNeeded > 0) {
27 while (start < data.byteLength) {
28 const byte = data[start]
29
30 if (byte < this.lowerBoundary || byte > this.upperBoundary) {
31 result += '\ufffd'
32 this._reset()
33 break
34 }
35
36 this.lowerBoundary = 0x80
37 this.upperBoundary = 0xbf
38 this.codePoint = (this.codePoint << 6) | (byte & 0x3f)
39 this.bytesSeen++
40 start++
41
42 if (this.bytesSeen === this.bytesNeeded) {
43 result += String.fromCodePoint(this.codePoint)
44 this._reset()
45 break
46 }
47 }
48
49 if (this.bytesNeeded > 0) return result
50 }
51
52 const trailing = trailingIncomplete(data, start)
53 const end = data.byteLength - trailing
54
55 if (end > start) result += b4a.toString(data, 'utf8', start, end)
56
57 for (let i = end; i < data.byteLength; i++) {
58 const byte = data[i]
59
60 if (this.bytesNeeded === 0) {
61 if (byte <= 0x7f) {
62 this.bytesSeen = 0
63 result += String.fromCharCode(byte)
64 } else if (byte >= 0xc2 && byte <= 0xdf) {
65 this.bytesNeeded = 2
66 this.bytesSeen = 1
67 this.codePoint = byte & 0x1f
68 } else if (byte >= 0xe0 && byte <= 0xef) {
69 if (byte === 0xe0) this.lowerBoundary = 0xa0
70 else if (byte === 0xed) this.upperBoundary = 0x9f
71 this.bytesNeeded = 3
72 this.bytesSeen = 1
73 this.codePoint = byte & 0xf
74 } else if (byte >= 0xf0 && byte <= 0xf4) {
75 if (byte === 0xf0) this.lowerBoundary = 0x90
76 else if (byte === 0xf4) this.upperBoundary = 0x8f
77 this.bytesNeeded = 4
78 this.bytesSeen = 1
79 this.codePoint = byte & 0x7
80 } else {
81 this.bytesSeen = 1
82 result += '\ufffd'
83 }
84
85 continue
86 }
87
88 if (byte < this.lowerBoundary || byte > this.upperBoundary) {
89 result += '\ufffd'
90 i--
91 this._reset()
92
93 continue
94 }
95
96 this.lowerBoundary = 0x80
97 this.upperBoundary = 0xbf
98
99 this.codePoint = (this.codePoint << 6) | (byte & 0x3f)
100 this.bytesSeen++
101
102 if (this.bytesSeen === this.bytesNeeded) {
103 result += String.fromCodePoint(this.codePoint)
104 this._reset()
105 }
106 }
107
108 return result
109 }
110
111 flush() {
112 const result = this.bytesNeeded > 0 ? '\ufffd' : ''
113 this._reset()
114 return result
115 }
116
117 _reset() {
118 this.codePoint = 0
119 this.bytesNeeded = 0
120 this.bytesSeen = 0
121 this.lowerBoundary = 0x80
122 this.upperBoundary = 0xbf
123 }
124}
125
126function trailingIncomplete(data, start) {
127 const len = data.byteLength
128 if (len <= start) return 0
129
130 const limit = Math.max(start, len - 4)
131
132 let i = len - 1
133 while (i > limit && (data[i] & 0xc0) === 0x80) i--
134
135 if (i < start) return 0
136
137 const byte = data[i]
138
139 let needed
140 if (byte <= 0x7f) return 0
141 if (byte >= 0xc2 && byte <= 0xdf) needed = 2
142 else if (byte >= 0xe0 && byte <= 0xef) needed = 3
143 else if (byte >= 0xf0 && byte <= 0xf4) needed = 4
144 else return 0
145
146 const available = len - i
147 return available < needed ? available : 0
148}
149
150function trailingBytesSeen(data) {
151 const len = data.byteLength
152 if (len === 0) return 0
153
154 const last = data[len - 1]
155
156 if (last <= 0x7f) return 0
157 if ((last & 0xc0) !== 0x80) return 1
158
159 const limit = Math.max(0, len - 4)
160
161 let i = len - 2
162 while (i >= limit && (data[i] & 0xc0) === 0x80) i--
163
164 if (i < 0) return 1
165
166 const first = data[i]
167
168 let needed
169 if (first >= 0xc2 && first <= 0xdf) needed = 2
170 else if (first >= 0xe0 && first <= 0xef) needed = 3
171 else if (first >= 0xf0 && first <= 0xf4) needed = 4
172 else return 1
173
174 if (len - i !== needed) return 1
175
176 if (needed >= 3) {
177 const second = data[i + 1]
178 if (first === 0xe0 && second < 0xa0) return 1
179 if (first === 0xed && second > 0x9f) return 1
180 if (first === 0xf0 && second < 0x90) return 1
181 if (first === 0xf4 && second > 0x8f) return 1
182 }
183
184 return 0
185}
node_modules/text-decoder/package.json +39 -0
……@@ -0,0 +1,39 @@
1{
2 "name": "text-decoder",
3 "version": "1.2.7",
4 "description": "Streaming text decoder that preserves multibyte Unicode characters",
5 "exports": {
6 "./package": "./package.json",
7 ".": "./index.js"
8 },
9 "files": [
10 "index.js",
11 "lib"
12 ],
13 "scripts": {
14 "format": "prettier --write .",
15 "lint": "prettier --check . && lunte",
16 "test": "npm run test:node && npm run test:bare",
17 "test:node": "brittle-node test.js",
18 "test:bare": "brittle-bare test.js"
19 },
20 "repository": {
21 "type": "git",
22 "url": "git+https://github.com/holepunchto/text-decoder.git"
23 },
24 "author": "Holepunch",
25 "license": "Apache-2.0",
26 "bugs": {
27 "url": "https://github.com/holepunchto/text-decoder/issues"
28 },
29 "homepage": "https://github.com/holepunchto/text-decoder#readme",
30 "dependencies": {
31 "b4a": "^1.6.4"
32 },
33 "devDependencies": {
34 "brittle": "^3.3.2",
35 "lunte": "^1.3.0",
36 "prettier": "^3.6.2",
37 "prettier-config-holepunch": "^1.0.0"
38 }
39}
node_modules/timeout-refresh/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - master
6 pull_request:
7 branches:
8 - master
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v2
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v2
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/timeout-refresh/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2018 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/timeout-refresh/README.md +67 -0
……@@ -0,0 +1,67 @@
1# timeout-refresh
2
3Efficiently refresh a timer
4
5```
6npm install timeout-refresh
7```
8
9Uses `timeout.refresh` in Node.
10In the browser a basic `clearTimeout + setTimeout` is used since no other method exists
11
12## Usage
13
14``` js
15const Timeout = require('timeout-refresh')
16
17const to = Timeout.once(100, function () {
18 console.log('Timed out!')
19})
20
21const i = setInterval(function () {
22 // refresh every 50ms
23 to.refresh()
24}, 50)
25
26setTimeout(function () {
27 // cancel the refresh after 500ms
28 clearInterval(i)
29 setTimeout(function () {
30 console.log('Should have timed out now')
31 }, 200)
32}, 500)
33```
34
35## API
36
37#### `to = Timeout.once(ms, ontimeout, [context])`
38
39Make a new refreshable timeout that fires once.
40
41If you pass `context`, it will be set as `this` when calling `ontimeout`.
42
43#### `to = Timeout.on(ms, ontimeout, [context])`
44
45Make a new refreshable timeout that fires every `ms`.
46
47If you pass `context`, it will be set as `this` when calling `ontimeout`.
48
49#### `to.unref()`
50
51Unref the timer.
52
53#### `to.ref()`
54
55Ref the timer.
56
57#### `to.refresh()`
58
59Refresh the timeout.
60
61#### `to.destroy()`
62
63Destroy the timeout.
64
65## License
66
67MIT
node_modules/timeout-refresh/browser.js +54 -0
……@@ -0,0 +1,54 @@
1module.exports = class TimerBrowser {
2 constructor (ms, fn, ctx = null, interval = false) {
3 this.ms = ms
4 this.ontimeout = fn
5 this.context = ctx || null
6 this.interval = interval
7 this.done = false
8
9 this._timer = interval
10 ? setInterval(callInterval, ms, this)
11 : setTimeout(callTimeout, ms, this)
12 }
13
14 unref () {}
15
16 ref () {}
17
18 refresh () {
19 if (this.done) return
20
21 if (this.interval) {
22 clearInterval(this._timer)
23 this._timer = setInterval(callInterval, this.ms, this)
24 } else {
25 clearTimeout(this._timer)
26 this._timer = setTimeout(callTimeout, this.ms, this)
27 }
28 }
29
30 destroy () {
31 this.done = true
32 this.ontimeout = null
33
34 if (this.interval) clearInterval(this._timer)
35 else clearTimeout(this._timer)
36 }
37
38 static once (ms, fn, ctx) {
39 return new this(ms, fn, ctx, false)
40 }
41
42 static on (ms, fn, ctx) {
43 return new this(ms, fn, ctx, true)
44 }
45}
46
47function callTimeout (self) {
48 self.done = true
49 self.ontimeout.call(self.context)
50}
51
52function callInterval (self) {
53 self.ontimeout.call(self.context)
54}
node_modules/timeout-refresh/example.js +19 -0
……@@ -0,0 +1,19 @@
1const Timeout = require('./')
2
3const to = Timeout.once(100, function () {
4 console.log('Timed out!')
5})
6
7const i = setInterval(function () {
8 // refresh every 50ms
9 to.refresh()
10}, 50)
11
12setTimeout(function () {
13 // cancel the refresh after 500ms
14 clearInterval(i)
15 console.log('Stopping refresh')
16 setTimeout(function () {
17 console.log('Should have timed out now')
18 }, 200)
19}, 500)
node_modules/timeout-refresh/index.js +9 -0
……@@ -0,0 +1,9 @@
1module.exports = isNode()
2 ? require('./node')
3 : require('./browser')
4
5function isNode () {
6 const to = setTimeout(function () {}, 1000)
7 clearTimeout(to)
8 return !!to.refresh
9}
node_modules/timeout-refresh/node.js +49 -0
……@@ -0,0 +1,49 @@
1module.exports = class Timer {
2 constructor (ms, fn, ctx = null, interval = false) {
3 this.ms = ms
4 this.ontimeout = fn
5 this.context = ctx
6 this.interval = interval
7 this.done = false
8
9 this._timer = interval
10 ? setInterval(callInterval, ms, this)
11 : setTimeout(callTimeout, ms, this)
12 }
13
14 unref () {
15 this._timer.unref()
16 }
17
18 ref () {
19 this._timer.ref()
20 }
21
22 refresh () {
23 if (this.done !== true) this._timer.refresh()
24 }
25
26 destroy () {
27 this.done = true
28 this.ontimeout = null
29 if (this.interval) clearInterval(this._timer)
30 else clearTimeout(this._timer)
31 }
32
33 static once (ms, fn, ctx) {
34 return new this(ms, fn, ctx, false)
35 }
36
37 static on (ms, fn, ctx) {
38 return new this(ms, fn, ctx, true)
39 }
40}
41
42function callTimeout (self) {
43 self.done = true
44 self.ontimeout.call(self.context)
45}
46
47function callInterval (self) {
48 self.ontimeout.call(self.context)
49}
node_modules/timeout-refresh/package.json +25 -0
……@@ -0,0 +1,25 @@
1{
2 "name": "timeout-refresh",
3 "version": "2.0.1",
4 "description": "Efficiently refresh a timer",
5 "main": "index.js",
6 "dependencies": {},
7 "devDependencies": {
8 "standard": "^16.0.4",
9 "tape": "^5.5.2"
10 },
11 "browser": "./browser.js",
12 "scripts": {
13 "test": "standard && tape test.js"
14 },
15 "repository": {
16 "type": "git",
17 "url": "https://github.com/mafintosh/timeout-refresh.git"
18 },
19 "author": "Mathias Buus (@mafintosh)",
20 "license": "MIT",
21 "bugs": {
22 "url": "https://github.com/mafintosh/timeout-refresh/issues"
23 },
24 "homepage": "https://github.com/mafintosh/timeout-refresh"
25}
node_modules/timeout-refresh/test.js +102 -0
……@@ -0,0 +1,102 @@
1const tape = require('tape')
2
3run('', require('./'))
4run('browser: ', require('./browser'))
5
6function run (prefix, Timeout) {
7 tape(prefix + 'refresh', function (t) {
8 let refreshing = true
9 let timedout = false
10
11 const ctx = {}
12 const to = Timeout.once(100, function () {
13 t.ok(ctx === this)
14 t.ok(!refreshing)
15 timedout = true
16 }, ctx)
17
18 const i = setInterval(function () {
19 to.refresh()
20 }, 50)
21
22 setTimeout(function () {
23 refreshing = false
24 clearInterval(i)
25 setTimeout(function () {
26 t.ok(timedout)
27 t.end()
28 }, 100)
29 }, 500)
30 })
31
32 tape(prefix + 'destroy', function (t) {
33 let timedout = false
34
35 const to = Timeout.once(100, function () {
36 t.fail('should be destroyed')
37 timedout = true
38 })
39
40 const i = setInterval(function () {
41 to.refresh()
42 }, 50)
43
44 setTimeout(function () {
45 clearInterval(i)
46 to.destroy()
47 setTimeout(function () {
48 t.ok(!timedout)
49 t.end()
50 }, 100)
51 }, 500)
52 })
53
54 tape(prefix + 'cannot be refreshed after call', function (t) {
55 t.plan(2)
56
57 let timedout = false
58
59 const to = Timeout.once(50, function () {
60 t.notOk(timedout, 'did not already timeout')
61 t.pass('should be destroyed')
62 to.refresh()
63 timedout = true
64 })
65
66 setTimeout(function () {
67 t.end()
68 }, 500)
69 })
70
71 tape(prefix + 'setInterval', function (t) {
72 t.plan(1)
73
74 const actual = []
75 let tick = 0
76
77 const i = setInterval(function () {
78 tick++
79 }, 100)
80
81 const to = Timeout.on(500, function () {
82 actual.push(tick)
83
84 if (actual.length === 2) {
85 setTimeout(() => {
86 to.refresh()
87 setTimeout(() => {
88 to.refresh()
89 }, 250)
90 }, 250)
91 }
92
93 if (actual.length === 4) {
94 to.destroy()
95 clearInterval(i)
96
97 t.same(actual.map(n => Math.round(n / 5)), [1, 2, 4, 5])
98 t.end()
99 }
100 })
101 })
102}
node_modules/unix-path-resolve/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - master
6 pull_request:
7 branches:
8 - master
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v2
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v2
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/unix-path-resolve/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2021 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/unix-path-resolve/README.md +27 -0
……@@ -0,0 +1,27 @@
1# unix-path-resolve
2
3Cross platform resolve that always returns a UNIX style `/` seperated path
4
5```
6npm install unix-path-resolve
7```
8
9Mostly useful for resolving modules cross platform
10
11## Usage
12
13``` js
14const resolve = require('unix-path-resolve')
15
16resolve('/foo/bar', '../baz') // /foo/baz
17resolve('/foo/bar', '/baz/foo') // /baz/foo
18resolve('/a/b/c', '../../../../d') // throws since its out of bounds
19resolve('a', 'b') // throws since none of them are absolute
20resolve('/a/b/c', '..\\d') // /a/b/d
21resolve('/a/b/c', 'c:\\foo\\bar') // /foo/bar
22resolve('file:///a/b', './c') // /a/b/c
23```
24
25## License
26
27MIT
node_modules/unix-path-resolve/index.js +68 -0
……@@ -0,0 +1,68 @@
1module.exports = resolve
2
3function parse (addr) {
4 const names = addr.split(/[/\\]/)
5
6 const r = {
7 isAbsolute: false,
8 names
9 }
10
11 // don't think this ever happens, but whatevs
12 if (names.length === 0) return r
13
14 if (names.length > 1 && names[0].endsWith(':')) {
15 r.isAbsolute = true
16
17 if (names[0].length === 2) { // windows
18 r.names = names.slice(1)
19 return r
20 }
21
22 if (names[0] === 'file:') {
23 r.names = names.slice(1)
24 return r
25 }
26
27 r.names = names.slice(3)
28 return r
29 }
30
31 r.isAbsolute = addr.startsWith('/') || addr.startsWith('\\')
32
33 return r
34}
35
36function resolve (a, b = '') {
37 const ap = parse(a)
38 const bp = parse(b)
39
40 if (bp.isAbsolute) {
41 return resolveNames([], bp.names)
42 }
43
44 if (!ap.isAbsolute) {
45 throw new Error('One of the two paths must be absolute')
46 }
47
48 return resolveNames(ap.names, bp.names)
49}
50
51function toString (p, names) {
52 for (let i = 0; i < names.length; i++) {
53 if (names[i] === '') continue
54 if (names[i] === '.') continue
55 if (names[i] === '..') {
56 if (p.length === 1) throw new Error('Path cannot be resolved, too many \'..\'')
57 p = p.slice(0, p.lastIndexOf('/')) || '/'
58 continue
59 }
60 p += (p.length === 1 ? names[i] : '/' + names[i])
61 }
62
63 return p
64}
65
66function resolveNames (a, b) {
67 return toString(toString('/', a), b)
68}
node_modules/unix-path-resolve/package.json +24 -0
……@@ -0,0 +1,24 @@
1{
2 "name": "unix-path-resolve",
3 "version": "1.0.2",
4 "description": "Cross platform resolve that always returns a UNIX style `/` seperated path",
5 "main": "index.js",
6 "dependencies": {},
7 "devDependencies": {
8 "brittle": "^2.0.1",
9 "standard": "^16.0.4"
10 },
11 "scripts": {
12 "test": "standard && brittle test.js"
13 },
14 "repository": {
15 "type": "git",
16 "url": "https://github.com/mafintosh/unix-path-resolve.git"
17 },
18 "author": "Mathias Buus (@mafintosh)",
19 "license": "MIT",
20 "bugs": {
21 "url": "https://github.com/mafintosh/unix-path-resolve/issues"
22 },
23 "homepage": "https://github.com/mafintosh/unix-path-resolve"
24}
node_modules/unix-path-resolve/test.js +25 -0
……@@ -0,0 +1,25 @@
1const test = require('brittle')
2const resolve = require('./')
3
4test('normalises', function (t) {
5 t.is(resolve('/a/b'), '/a/b')
6 t.is(resolve('/a/b/..'), '/a')
7 t.is(resolve('/a/b/../..'), '/')
8 t.is(resolve('/a/b/././////c'), '/a/b/c')
9 t.is(resolve('/a/b/.\\.\\//\\/c/..///d'), '/a/b/d')
10 t.is(resolve('file:/a/b/../../c'), '/c')
11 t.is(resolve('file:///a/b/../../c'), '/c')
12 t.is(resolve('file:///a/b/../../c'), '/c')
13 t.is(resolve('proto://host/a/b/../../c'), '/c')
14 t.is(resolve('c:\\dir\\file'), '/dir/file')
15 t.is(resolve('\\dir'), '/dir')
16 t.exception(() => resolve('/..'))
17})
18
19test('resolve two paths', function (t) {
20 t.is(resolve('/a/b', 'c/d'), '/a/b/c/d')
21 t.is(resolve('/a/b', '../c/d'), '/a/c/d')
22 t.is(resolve('/', '\\c\\d/e'), '/c/d/e')
23 t.is(resolve('/a', '/b'), '/b')
24 t.exception(() => resolve('a', 'b'))
25})
node_modules/unslab/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/unslab/README.md +23 -0
……@@ -0,0 +1,23 @@
1# unslab
2
3Unslab some slab'ed buffers
4
5```
6npm install unslab
7```
8
9## Usage
10
11``` js
12const unslab = require('unslab')
13
14// the buf returned unpools the buffer passed from the memory slab
15const buf = unslab(Buffer.from('hello world'))
16
17// can do multiple at the same time if you use them together. only does a single alloc in this case
18const [a, b] = unslab([Buffer.from('hello'), Buffer.from('world')])
19```
20
21## License
22
23Apache-2.0
node_modules/unslab/index.js +42 -0
……@@ -0,0 +1,42 @@
1const b4a = require('b4a')
2
3unslab.all = all
4unslab.is = is
5
6module.exports = unslab
7
8function unslab (buf) {
9 if (buf === null || buf.buffer.byteLength === buf.byteLength) return buf
10 const copy = b4a.allocUnsafeSlow(buf.byteLength)
11 copy.set(buf, 0)
12 return copy
13}
14
15function is (buf) {
16 return buf.buffer.byteLength !== buf.byteLength
17}
18
19function all (list) {
20 let size = 0
21 for (let i = 0; i < list.length; i++) {
22 const buf = list[i]
23 size += buf === null || buf.buffer.byteLength === buf.byteLength ? 0 : buf.byteLength
24 }
25
26 const copy = b4a.allocUnsafeSlow(size)
27 const result = new Array(list.length)
28
29 let offset = 0
30 for (let i = 0; i < list.length; i++) {
31 let buf = list[i]
32
33 if (buf !== null && buf.buffer.byteLength !== buf.byteLength) {
34 copy.set(buf, offset)
35 buf = copy.subarray(offset, offset += buf.byteLength)
36 }
37
38 result[i] = buf
39 }
40
41 return result
42}
node_modules/unslab/package.json +29 -0
……@@ -0,0 +1,29 @@
1{
2 "name": "unslab",
3 "version": "1.3.0",
4 "description": "Unslab some slab'ed buffers",
5 "main": "index.js",
6 "files": [
7 "index.js"
8 ],
9 "dependencies": {
10 "b4a": "^1.6.6"
11 },
12 "devDependencies": {
13 "brittle": "^3.5.2",
14 "standard": "^17.1.0"
15 },
16 "scripts": {
17 "test": "standard && brittle test.js"
18 },
19 "repository": {
20 "type": "git",
21 "url": "https://github.com/holepunchto/unslab.git"
22 },
23 "author": "Holepunch",
24 "license": "Apache-2.0",
25 "bugs": {
26 "url": "https://github.com/holepunchto/unslab/issues"
27 },
28 "homepage": "https://github.com/holepunchto/unslab"
29}
node_modules/varint/README.md +53 -0
……@@ -0,0 +1,53 @@
1# varint
2
3encode whole numbers to an array of [protobuf-style varint bytes](https://developers.google.com/protocol-buffers/docs/encoding#varints) and also decode them.
4
5```javascript
6var varint = require('varint')
7
8var bytes = varint.encode(300) // === [0xAC, 0x02]
9varint.decode(bytes) // 300
10varint.decode.bytes // 2 (the last decode() call required 2 bytes)
11```
12
13## api
14
15### varint = require('varint')
16
17### varint.encode(num[, buffer=[], offset=0]) -> buffer
18
19Encodes `num` into `buffer` starting at `offset`. returns `buffer`, with the encoded varint written into it. If `buffer` is not provided, it will default to a new array.
20
21`varint.encode.bytes` will now be set to the number of bytes
22modified.
23
24### varint.decode(data[, offset=0]) -> number
25
26decodes `data`, which can be either a buffer or array of integers, from position `offset` or default 0 and returns the decoded original integer.
27
28Throws a `RangeError` when `data` does not represent a valid encoding.
29
30### varint.decode.bytes
31
32if you also require the length (number of bytes) that were required to decode the integer you can access it via `varint.decode.bytes`. this is an integer property that will tell you the number of bytes that the last .decode() call had to use to decode.
33
34### varint.encode.bytes
35
36similar to `decode.bytes` when encoding a number it can be useful to know how many bytes where written (especially if you pass an output array). you can access this via `varint.encode.bytes` which holds the number of bytes written in the last encode.
37
38
39### varint.encodingLength(num)
40
41returns the number of bytes this number will be encoded as, up to a maximum of 8.
42
43## usage notes
44
45If varint is passed a buffer that does not contain a valid end
46byte, then `decode` will throw `RangeError`, and `decode.bytes`
47will be set to 0. If you are reading from a streaming source,
48it's okay to pass an incomplete buffer into `decode`, detect this
49case, and then concatenate the next buffer.
50
51# License
52
53MIT
node_modules/varint/bench.js +57 -0
……@@ -0,0 +1,57 @@
1var N = 1e7
2var M = 10
3/*
4 benchmark encoding and decoding N random integers.
5
6 A number is encoded into a buffer, (the buffer is reused so
7 that allocation does not affect the benchmark)
8
9 to test the effect on performance of invalid records
10 (i.e. too short, with the Most Significant Byte missing)
11 every M items, attempt to decode from a shorter slice of the buffer.
12 This will probably be produce an invalid result. We do not
13 need to write into that buffer - because it refurs to the same memory as
14 the full size buffer.
15
16 run with INVALID=1 to include N/M invalid decodes.
17
18 results:
19 with no invalid decodes, I get about 2428 decodes/ms
20 with invalid decodes:
21 old code that overruns buffer: 1122 decodes/ms
22 check length & return undefined: 2439 decodecs/ms
23 check length & return NaN: 2434 d/ms
24 check length & return -1: 2400 d/ms
25
26 conclusion, it doesn't make a significant difference whether
27 what is returned to show an invalid read,
28 but if you overrun the buffer the cost is considerable.
29
30 recomendation: return undefined
31*/
32
33var buffer = new Buffer(8)
34var _buffer = buffer.slice(0, 4)
35var varint = require('./')
36var l = N
37var invalid = 0
38
39includeInvalid = !!process.env.INVALID
40
41var start = Date.now()
42while (l--) {
43 var int = Math.floor(Math.random()*0x01fffffffffffff)
44 varint.encode(int, buffer, 0)
45 //console.log(int, varint.decode(buffer, 0))
46 //every 1000 varints, do one that will be too short,
47 //measure
48 if(includeInvalid && !(l%M)) {
49 if(undefined == varint.decode(_buffer, 0))
50 invalid ++
51 } else
52 if(int !== varint.decode(buffer, 0))
53 throw new Error('decode was incorrect')
54}
55
56console.log('decode&encode/ms, invalidDecodes')
57console.log(N/(Date.now() - start) + ',', invalid)
node_modules/varint/decode.js +29 -0
……@@ -0,0 +1,29 @@
1module.exports = read
2
3var MSB = 0x80
4 , REST = 0x7F
5
6function read(buf, offset) {
7 var res = 0
8 , offset = offset || 0
9 , shift = 0
10 , counter = offset
11 , b
12 , l = buf.length
13
14 do {
15 if (counter >= l) {
16 read.bytes = 0
17 throw new RangeError('Could not decode varint')
18 }
19 b = buf[counter++]
20 res += shift < 28
21 ? (b & REST) << shift
22 : (b & REST) * Math.pow(2, shift)
23 shift += 7
24 } while (b >= MSB)
25
26 read.bytes = counter - offset
27
28 return res
29}
node_modules/varint/encode.js +26 -0
……@@ -0,0 +1,26 @@
1module.exports = encode
2
3var MSB = 0x80
4 , REST = 0x7F
5 , MSBALL = ~REST
6 , INT = Math.pow(2, 31)
7
8function encode(num, out, offset) {
9 out = out || []
10 offset = offset || 0
11 var oldOffset = offset
12
13 while(num >= INT) {
14 out[offset++] = (num & 0xFF) | MSB
15 num /= 128
16 }
17 while(num & MSBALL) {
18 out[offset++] = (num & 0xFF) | MSB
19 num >>>= 7
20 }
21 out[offset] = num | 0
22
23 encode.bytes = offset - oldOffset + 1
24
25 return out
26}
node_modules/varint/index.js +5 -0
……@@ -0,0 +1,5 @@
1module.exports = {
2 encode: require('./encode.js')
3 , decode: require('./decode.js')
4 , encodingLength: require('./length.js')
5}
node_modules/varint/length.js +25 -0
……@@ -0,0 +1,25 @@
1
2var N1 = Math.pow(2, 7)
3var N2 = Math.pow(2, 14)
4var N3 = Math.pow(2, 21)
5var N4 = Math.pow(2, 28)
6var N5 = Math.pow(2, 35)
7var N6 = Math.pow(2, 42)
8var N7 = Math.pow(2, 49)
9var N8 = Math.pow(2, 56)
10var N9 = Math.pow(2, 63)
11
12module.exports = function (value) {
13 return (
14 value < N1 ? 1
15 : value < N2 ? 2
16 : value < N3 ? 3
17 : value < N4 ? 4
18 : value < N5 ? 5
19 : value < N6 ? 6
20 : value < N7 ? 7
21 : value < N8 ? 8
22 : value < N9 ? 9
23 : 10
24 )
25}
node_modules/varint/package.json +24 -0
……@@ -0,0 +1,24 @@
1{
2 "name": "varint",
3 "version": "5.0.0",
4 "description": "protobuf-style varint bytes - use msb to create integer values of varying sizes",
5 "main": "index.js",
6 "scripts": {
7 "test": "node test.js"
8 },
9 "repository": {
10 "type": "git",
11 "url": "git://github.com/chrisdickinson/varint.git"
12 },
13 "keywords": [
14 "varint",
15 "protobuf",
16 "encode",
17 "decode"
18 ],
19 "author": "Chris Dickinson <chris@neversaw.us>",
20 "license": "MIT",
21 "devDependencies": {
22 "tape": "~2.12.3"
23 }
24}
node_modules/varint/test.js +139 -0
……@@ -0,0 +1,139 @@
1var varint = require('./index')
2 , test = require('tape')
3 , decode = varint.decode
4 , encode = varint.encode
5 , encodingLength = varint.encodingLength
6
7test('fuzz test', function(assert) {
8 var expect
9 , encoded
10
11 for(var i = 0, len = 100; i < len; ++i) {
12 expect = randint(0x7FFFFFFF)
13 encoded = encode(expect)
14 var data = decode(encoded)
15 assert.equal(expect, data, 'fuzz test: ' + expect.toString())
16 assert.equal(decode.bytes, encoded.length)
17 }
18
19 assert.end()
20})
21
22test('test single byte works as expected', function(assert) {
23 var buf = new Uint8Array(2)
24 buf[0] = 172
25 buf[1] = 2
26 var data = decode(buf)
27 assert.equal(data, 300, 'should equal 300')
28 assert.equal(decode.bytes, 2)
29 assert.end()
30})
31
32test('test encode works as expected', function(assert) {
33 var out = []
34
35 assert.deepEqual(encode(300), [0xAC, 0x02])
36
37 assert.end()
38})
39
40test('test decode single bytes', function(assert) {
41 var expected = randint(parseInt('1111111', '2'))
42 var buf = new Uint8Array(1)
43 buf[0] = expected
44 var data = decode(buf)
45 assert.equal(data, expected)
46 assert.equal(decode.bytes, 1)
47 assert.end()
48})
49
50test('test decode multiple bytes with zero', function(assert) {
51 var expected = randint(parseInt('1111111', '2'))
52 var buf = new Uint8Array(2)
53 buf[0] = 128
54 buf[1] = expected
55 var data = decode(buf)
56 assert.equal(data, expected << 7)
57 assert.equal(decode.bytes, 2)
58 assert.end()
59})
60
61test('encode single byte', function(assert) {
62 var expected = randint(parseInt('1111111', '2'))
63 assert.deepEqual(encode(expected), [expected])
64 assert.equal(encode.bytes, 1)
65 assert.end()
66})
67
68test('encode multiple byte with zero first byte', function(assert) {
69 var expected = 0x0F00
70 assert.deepEqual(encode(expected), [0x80, 0x1E])
71 assert.equal(encode.bytes, 2)
72 assert.end()
73})
74
75test('big integers', function (assert) {
76
77 var bigs = []
78 for(var i = 32; i <= 53; i++) (function (i) {
79 bigs.push(Math.pow(2, i) - 1)
80 bigs.push(Math.pow(2, i))
81 })(i)
82
83 bigs.forEach(function (n) {
84 var data = encode(n)
85 console.error(n, '->', data)
86 assert.equal(decode(data), n)
87 assert.notEqual(decode(data), n - 1)
88 })
89 assert.end()
90})
91
92test('fuzz test - big', function(assert) {
93 var expect
94 , encoded
95
96 var MAX_INTD = Math.pow(2, 55)
97 var MAX_INT = Math.pow(2, 31)
98
99 for(var i = 0, len = 100; i < len; ++i) {
100 expect = randint(MAX_INTD - MAX_INT) + MAX_INT
101 encoded = encode(expect)
102 var data = decode(encoded)
103 assert.equal(expect, data, 'fuzz test: ' + expect.toString())
104 assert.equal(decode.bytes, encoded.length)
105 }
106
107 assert.end()
108})
109
110test('encodingLength', function (assert) {
111
112 for(var i = 0; i <= 53; i++) {
113 var n = Math.pow(2, i)
114 assert.equal(encode(n).length, encodingLength(n))
115 }
116
117 assert.end()
118})
119
120test('buffer too short', function (assert) {
121
122 var value = encode(9812938912312)
123 var buffer = encode(value)
124
125 var l = buffer.length
126 while(l--) {
127 try {
128 var val = decode(buffer.slice(0, l))
129 } catch (err) {
130 assert.equal(err.constructor, RangeError)
131 assert.equal(decode.bytes, 0)
132 }
133 }
134 assert.end()
135})
136
137function randint(range) {
138 return Math.floor(Math.random() * range)
139}
node_modules/which-runtime/LICENSE +201 -0
……@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
node_modules/which-runtime/README.md +29 -0
……@@ -0,0 +1,29 @@
1# which-runtime
2
3Detect if you are in Bare or Node and which os etc
4
5```
6npm install which-runtime
7```
8
9## Usage
10
11``` js
12import {
13 runtime, // bare, node, or browser
14 platform, // the platform string, ie darwin, win32, etc
15 arch, // which arch, arm64, ia32, x64 etc
16 isBrowser,
17 isBare,
18 isNode,
19 isLinux,
20 isWindows,
21 isMac,
22 isIOS,
23 isAndroid
24} from 'which-runtime'
25```
26
27## License
28
29Apache-2.0
node_modules/which-runtime/index.js +24 -0
……@@ -0,0 +1,24 @@
1const { runtime, platform, arch } = typeof Bare !== 'undefined'
2 ? { runtime: 'bare', platform: global.Bare.platform, arch: global.Bare.arch }
3 : typeof process !== 'undefined'
4 ? { runtime: 'node', platform: global.process.platform, arch: global.process.arch }
5 : typeof Window !== 'undefined'
6 ? { runtime: 'browser', platform: 'unknown', arch: 'unknown' }
7 : { runtime: 'unknown', platform: 'unknown', arch: 'unknown' }
8
9exports.runtime = runtime
10exports.platform = platform
11exports.arch = arch
12exports.isBare = runtime === 'bare'
13exports.isBareKit = exports.isBare && typeof BareKit !== 'undefined'
14exports.isPear = typeof Pear !== 'undefined'
15exports.isNode = runtime === 'node'
16exports.isBrowser = runtime === 'browser'
17exports.isWindows = platform === 'win32'
18exports.isLinux = platform === 'linux'
19exports.isMac = platform === 'darwin'
20exports.isIOS = platform === 'ios' || platform === 'ios-simulator'
21exports.isAndroid = platform === 'android'
22exports.isElectron = typeof process !== 'undefined' && !!global.process.versions?.electron
23exports.isElectronRenderer = exports.isElectron && global.process.type === 'renderer'
24exports.isElectronWorker = exports.isElectron && global.process.type === 'worker'
node_modules/which-runtime/package.json +26 -0
……@@ -0,0 +1,26 @@
1{
2 "name": "which-runtime",
3 "version": "1.3.2",
4 "description": "Detect if you are in Bare or Node and which os etc",
5 "main": "index.js",
6 "files": [
7 "index.js"
8 ],
9 "dependencies": {},
10 "devDependencies": {
11 "standard": "^17.0.0"
12 },
13 "scripts": {
14 "test": "standard"
15 },
16 "repository": {
17 "type": "git",
18 "url": "https://github.com/holepunchto/which-runtime.git"
19 },
20 "author": "Holepunch Inc.",
21 "license": "Apache-2.0",
22 "bugs": {
23 "url": "https://github.com/holepunchto/which-runtime/issues"
24 },
25 "homepage": "https://github.com/holepunchto/which-runtime"
26}
node_modules/xache/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2021 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/xache/README.md +35 -0
……@@ -0,0 +1,35 @@
1# xache
2
3Yet another auto expiring, max sizable cache
4
5```
6npm install xache
7```
8
9## Usage
10
11``` js
12const Xache = require('xache')
13
14const cache = new Xache({
15 maxSize: 10, // at max (ish) have 10 entries
16 maxAge: 100, // auto expire entries after (ish) 100ms
17 createMap () { // optional function to create backing storage
18 return new Map()
19 }
20})
21
22// When maxSize is hit, the oldest entries are removed
23// cache has the same api as a map
24
25cache.set('hello', 'world')
26console.log(cache.get('hello'))
27
28console.log(...cache) // iterable!
29```
30
31That's it, nice and simple.
32
33## License
34
35MIT
node_modules/xache/index.js +108 -0
……@@ -0,0 +1,108 @@
1module.exports = class MaxCache {
2 constructor ({ maxSize, maxAge, createMap, ongc }) {
3 this.maxSize = maxSize
4 this.maxAge = maxAge
5 this.ongc = ongc || null
6
7 this._createMap = createMap || defaultCreateMap
8 this._latest = this._createMap()
9 this._oldest = this._createMap()
10 this._retained = this._createMap()
11 this._gced = false
12 this._interval = null
13
14 if (this.maxAge > 0 && this.maxAge < Infinity) {
15 const tick = Math.ceil(2 / 3 * this.maxAge)
16 this._interval = setInterval(this._gcAuto.bind(this), tick)
17 if (this._interval.unref) this._interval.unref()
18 }
19 }
20
21 * [Symbol.iterator] () {
22 for (const it of [this._latest, this._oldest, this._retained]) {
23 yield * it
24 }
25 }
26
27 * keys () {
28 for (const it of [this._latest, this._oldest, this._retained]) {
29 yield * it.keys()
30 }
31 }
32
33 * values () {
34 for (const it of [this._latest, this._oldest, this._retained]) {
35 yield * it.values()
36 }
37 }
38
39 destroy () {
40 this.clear()
41 clearInterval(this._interval)
42 this._interval = null
43 }
44
45 clear () {
46 this._gced = true
47 this._latest.clear()
48 this._oldest.clear()
49 this._retained.clear()
50 }
51
52 set (k, v) {
53 if (this._retained.has(k)) return this
54 this._latest.set(k, v)
55 this._oldest.delete(k) || this._retained.delete(k)
56 if (this._latest.size >= this.maxSize) this._gc()
57 return this
58 }
59
60 retain (k, v) {
61 this._retained.set(k, v)
62 this._latest.delete(k) || this._oldest.delete(k)
63 return this
64 }
65
66 delete (k) {
67 return this._latest.delete(k) || this._oldest.delete(k) || this._retained.delete(k)
68 }
69
70 has (k) {
71 return this._latest.has(k) || this._oldest.has(k) || this._retained.has(k)
72 }
73
74 get (k) {
75 if (this._latest.has(k)) {
76 return this._latest.get(k)
77 }
78
79 if (this._oldest.has(k)) {
80 const v = this._oldest.get(k)
81 this._latest.set(k, v)
82 this._oldest.delete(k)
83 return v
84 }
85
86 if (this._retained.has(k)) {
87 return this._retained.get(k)
88 }
89
90 return null
91 }
92
93 _gcAuto () {
94 if (!this._gced) this._gc()
95 this._gced = false
96 }
97
98 _gc () {
99 this._gced = true
100 if (this.ongc !== null && this._oldest.size > 0) this.ongc(this._oldest)
101 this._oldest = this._latest
102 this._latest = this._createMap()
103 }
104}
105
106function defaultCreateMap () {
107 return new Map()
108}
node_modules/xache/package.json +26 -0
……@@ -0,0 +1,26 @@
1{
2 "name": "xache",
3 "version": "1.2.1",
4 "description": "Yet another auto expiring, max sizable cache",
5 "main": "index.js",
6 "files": [
7 "index.js"
8 ],
9 "devDependencies": {
10 "brittle": "^3.3.2",
11 "standard": "^17.1.0"
12 },
13 "scripts": {
14 "test": "standard && brittle test.js"
15 },
16 "repository": {
17 "type": "git",
18 "url": "https://github.com/mafintosh/xache.git"
19 },
20 "author": "Mathias Buus (@mafintosh)",
21 "license": "MIT",
22 "bugs": {
23 "url": "https://github.com/mafintosh/xache/issues"
24 },
25 "homepage": "https://github.com/mafintosh/xache"
26}
node_modules/z32/.github/workflows/test-node.yml +23 -0
……@@ -0,0 +1,23 @@
1name: Build Status
2on:
3 push:
4 branches:
5 - master
6 pull_request:
7 branches:
8 - master
9jobs:
10 build:
11 strategy:
12 matrix:
13 node-version: [lts/*]
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 runs-on: ${{ matrix.os }}
16 steps:
17 - uses: actions/checkout@v2
18 - name: Use Node.js ${{ matrix.node-version }}
19 uses: actions/setup-node@v2
20 with:
21 node-version: ${{ matrix.node-version }}
22 - run: npm install
23 - run: npm test
node_modules/z32/LICENSE +21 -0
……@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2022 Mathias Buus
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
node_modules/z32/README.md +35 -0
……@@ -0,0 +1,35 @@
1# z32
2
3z-base-32 encoder & decoder
4
5```
6npm install z32
7```
8
9## Usage
10
11``` js
12const z32 = require('z32')
13
14const s = z32.encode('Hello, World!')
15
16console.log(s) // jb1sa5dxfoofq551pt1nn
17
18const b = z32.decode(s)
19
20console.log(b) // Buffer('Hello, World!')
21```
22
23## API
24
25#### `const s = z32.encode(stringOrBuffer)`
26
27Encode a string or buffer to z-base-32.
28
29#### `const buf = z32.decode(s)`
30
31Returns a decoded buffer. Throws if the string is invalid.
32
33## License
34
35MIT
node_modules/z32/benchmark.js +133 -0
……@@ -0,0 +1,133 @@
1const bench = require('nanobench')
2const { randomBytes } = require('node:crypto')
3
4const buffers = Array(1e4)
5 .fill(null)
6 .map(() => {
7 return randomBytes(Math.round(Math.random() * 100))
8 })
9
10bench('z32 encode 100 times', function (b) {
11 const z32 = require('.')
12 b.start()
13 for (let i = 0; i < 100; i++) {
14 for (const buf of buffers) {
15 z32.encode(buf)
16 }
17 }
18
19 b.end()
20})
21
22bench('z32 decode 100 times', function (b) {
23 const z32 = require('.')
24 const encoded = buffers.map(buf => z32.encode(buf))
25 b.start()
26 for (let i = 0; i < 100; i++) {
27 for (const s of encoded) {
28 z32.decode(s)
29 }
30 }
31
32 b.end()
33})
34
35bench("buf.toString('hex') 100 times", function (b) {
36 b.start()
37 for (let i = 0; i < 100; i++) {
38 for (const buf of buffers) {
39 buf.toString('hex')
40 }
41 }
42
43 b.end()
44})
45
46bench("Buffer.from(s, 'hex') 100 times", function (b) {
47 const encoded = buffers.map(buf => buf.toString('hex'))
48 b.start()
49 for (let i = 0; i < 100; i++) {
50 for (const s of encoded) {
51 Buffer.from(s, 'hex')
52 }
53 }
54
55 b.end()
56})
57
58bench('base32 encode 100 times', function (b) {
59 const base32 = require('base32')
60 b.start()
61 for (let i = 0; i < 100; i++) {
62 for (const buf of buffers) {
63 base32.encode(buf)
64 }
65 }
66
67 b.end()
68})
69
70bench('base32 decode 100 times', function (b) {
71 const base32 = require('base32')
72 const encoded = buffers.map(buf => base32.encode(buf))
73 b.start()
74 for (let i = 0; i < 100; i++) {
75 for (const s of encoded) {
76 base32.decode(s)
77 }
78 }
79
80 b.end()
81})
82
83bench('rfc4648.base32 encode 100 times', function (b) {
84 const { base32 } = require('rfc4648')
85 b.start()
86 for (let i = 0; i < 100; i++) {
87 for (const buf of buffers) {
88 base32.stringify(buf)
89 }
90 }
91
92 b.end()
93})
94
95bench('rfc4648.base32 decode 100 times', function (b) {
96 const { base32 } = require('rfc4648')
97 const encoded = buffers.map(buf => base32.stringify(buf))
98 b.start()
99 for (let i = 0; i < 100; i++) {
100 for (const s of encoded) {
101 base32.parse(s, { out: Buffer.allocUnsafe })
102 }
103 }
104
105 b.end()
106})
107
108bench('base-x z-base-32 encode 100 times', function (b) {
109 const ZBASE32 = 'ybndrfg8ejkmcpqxot1uwisza345h769'
110 const base32 = require('base-x')(ZBASE32)
111 b.start()
112 for (let i = 0; i < 100; i++) {
113 for (const buf of buffers) {
114 base32.encode(buf)
115 }
116 }
117
118 b.end()
119})
120
121bench('base-x z-base-32 decode 100 times', function (b) {
122 const ZBASE32 = 'ybndrfg8ejkmcpqxot1uwisza345h769'
123 const base32 = require('base-x')(ZBASE32)
124 const encoded = buffers.map(buf => base32.encode(buf))
125 b.start()
126 for (let i = 0; i < 100; i++) {
127 for (const s of encoded) {
128 base32.decode(s)
129 }
130 }
131
132 b.end()
133})
node_modules/z32/index.js +126 -0
……@@ -0,0 +1,126 @@
1const b4a = require('b4a')
2
3const ALPHABET = 'ybndrfg8ejkmcpqxot1uwisza345h769'
4const MIN = 0x31 // 1
5const MAX = 0x7a // z
6const REVERSE = new Int8Array(1 + MAX - MIN)
7
8REVERSE.fill(-1)
9
10for (let i = 0; i < ALPHABET.length; i++) {
11 const v = ALPHABET.charCodeAt(i) - MIN
12 REVERSE[v] = i
13}
14
15exports.encode = encode
16exports.decode = decode
17exports.ALPHABET = ALPHABET
18
19function decode (s, out) {
20 let pb = 0
21 let ps = 0
22
23 const r = s.length & 7
24 const q = (s.length - r) / 8
25
26 if (!out) out = b4a.allocUnsafe(Math.ceil(s.length * 5 / 8))
27
28 // 0 5 2 7 4 1 6 3 (+5 mod 8)
29 for (let i = 0; i < q; i++) {
30 const a = quintet(s, ps++)
31 const b = quintet(s, ps++)
32 const c = quintet(s, ps++)
33 const d = quintet(s, ps++)
34 const e = quintet(s, ps++)
35 const f = quintet(s, ps++)
36 const g = quintet(s, ps++)
37 const h = quintet(s, ps++)
38
39 out[pb++] = (a << 3) | (b >>> 2)
40 out[pb++] = ((b & 0b11) << 6) | (c << 1) | (d >>> 4)
41 out[pb++] = ((d & 0b1111) << 4) | (e >>> 1)
42 out[pb++] = ((e & 0b1) << 7) | (f << 2) | (g >>> 3)
43 out[pb++] = ((g & 0b111) << 5) | h
44 }
45
46 if (r === 0) return out.subarray(0, pb)
47
48 const a = quintet(s, ps++)
49 const b = quintet(s, ps++)
50
51 out[pb++] = (a << 3) | (b >>> 2)
52
53 if (r <= 2) return out.subarray(0, pb)
54
55 const c = quintet(s, ps++)
56 const d = quintet(s, ps++)
57
58 out[pb++] = ((b & 0b11) << 6) | (c << 1) | (d >>> 4)
59
60 if (r <= 4) return out.subarray(0, pb)
61
62 const e = quintet(s, ps++)
63
64 out[pb++] = ((d & 0b1111) << 4) | (e >>> 1)
65
66 if (r <= 5) return out.subarray(0, pb)
67
68 const f = quintet(s, ps++)
69 const g = quintet(s, ps++)
70
71 out[pb++] = ((e & 0b1) << 7) | (f << 2) | (g >>> 3)
72
73 if (r <= 7) return out.subarray(0, pb)
74
75 const h = quintet(s, ps++)
76
77 out[pb++] = ((g & 0b111) << 5) | h
78
79 return out.subarray(0, pb)
80}
81
82function encode (buf) {
83 if (typeof buf === 'string') buf = b4a.from(buf)
84
85 const max = buf.byteLength * 8
86
87 let s = ''
88
89 for (let p = 0; p < max; p += 5) {
90 const i = p >>> 3
91 const j = p & 7
92
93 if (j <= 3) {
94 s += ALPHABET[(buf[i] >>> (3 - j)) & 0b11111]
95 continue
96 }
97
98 const of = j - 3
99 const h = (buf[i] << of) & 0b11111
100 const l = (i >= buf.byteLength ? 0 : buf[i + 1]) >>> (8 - of)
101
102 s += ALPHABET[h | l]
103 }
104
105 return s
106}
107
108function quintet (s, i) {
109 if (i > s.length) {
110 return 0
111 }
112
113 const v = s.charCodeAt(i)
114
115 if (v < MIN || v > MAX) {
116 throw Error('Invalid character in base32 input: "' + s[i] + '" at position ' + i)
117 }
118
119 const bits = REVERSE[v - MIN]
120
121 if (bits === -1) {
122 throw Error('Invalid character in base32 input: "' + s[i] + '" at position ' + i)
123 }
124
125 return bits
126}
node_modules/z32/package.json +31 -0
……@@ -0,0 +1,31 @@
1{
2 "name": "z32",
3 "version": "1.1.0",
4 "description": "Encode & decode z-base32",
5 "main": "index.js",
6 "dependencies": {
7 "b4a": "^1.5.3"
8 },
9 "devDependencies": {
10 "base-x": "^4.0.0",
11 "base32": "0.0.7",
12 "brittle": "^3.1.3",
13 "nanobench": "^3.0.0",
14 "rfc4648": "^1.5.2",
15 "standard": "^17.0.0"
16 },
17 "repository": {
18 "type": "git",
19 "url": "https://github.com/mafintosh/z32.git"
20 },
21 "scripts": {
22 "test": "standard && brittle test.js",
23 "bench": "node benchmark.js"
24 },
25 "author": "Mathias Buus (@mafintosh)",
26 "license": "MIT",
27 "bugs": {
28 "url": "https://github.com/mafintosh/z32/issues"
29 },
30 "homepage": "https://github.com/mafintosh/z32"
31}
node_modules/z32/test.js +49 -0
……@@ -0,0 +1,49 @@
1const z32 = require('./')
2const b4a = require('b4a')
3const test = require('brittle')
4const crypto = require('crypto')
5
6test('basic examples', function (t) {
7 {
8 const s = z32.encode('Example z-base-32')
9 const b = z32.decode(s)
10
11 t.is(s, 'eihgn5mopt11y6tpcjozg3jpgc3y')
12 t.is(b.toString(), 'Example z-base-32')
13 }
14
15 {
16 const s = z32.encode('The quick brown fox jumps over the lazy dog. 👀')
17 const b = z32.decode(s)
18
19 t.is(s, 'ktwgkedtqiwsg43ycj3g675qrbug66bypj4s4hdurbzzc3m1rb4go3jyptozw6jyctzsqmty6nx3dyy')
20 t.is(b.toString(), 'The quick brown fox jumps over the lazy dog. 👀')
21 }
22})
23
24test('random buffers', function (t) {
25 for (let i = 0; i < 1e5; i++) {
26 const b = crypto.randomBytes(Math.round(Math.random() * 100))
27 const s = z32.encode(b)
28 const o = z32.decode(s)
29
30 if (!b4a.equals(o, b)) {
31 t.alike(o, b)
32 return
33 }
34 }
35
36 t.pass('all random buffers passed')
37})
38
39test('bad inputs', function (t) {
40 t.exception(function () {
41 z32.decode('!!!')
42 })
43 t.exception(function () {
44 z32.decode('~~~')
45 })
46 t.exception(function () {
47 z32.decode('I1I1I1')
48 })
49})
package-lock.json +1019 -0
……@@ -0,0 +1,1019 @@
1{
2 "name": "hyper-inspector",
3 "version": "0.1.0",
4 "lockfileVersion": 3,
5 "requires": true,
6 "packages": {
7 "": {
8 "name": "hyper-inspector",
9 "version": "0.1.0",
10 "license": "MIT",
11 "dependencies": {
12 "b4a": "^1.6.7",
13 "corestore": "^6.18.0",
14 "hyperdrive": "^11.13.0",
15 "paparam": "^1.10.0",
16 "rocksdb-native": "^3.13.0"
17 },
18 "bin": {
19 "hyper-inspector": "bin/cli.js"
20 }
21 },
22 "node_modules/@hyperswarm/secret-stream": {
23 "version": "6.9.1",
24 "resolved": "https://registry.npmjs.org/@hyperswarm/secret-stream/-/secret-stream-6.9.1.tgz",
25 "integrity": "sha512-xb0S5y3YJwBakD77JOGBHlBxdp63mHClZoXBYoLv+9wH8e054ESKlmQptWqjJK5dv5VMUIVYOJB4MaOpB0JdGw==",
26 "license": "Apache-2.0",
27 "dependencies": {
28 "b4a": "^1.1.0",
29 "hypercore-crypto": "^3.3.1",
30 "noise-curve-ed": "^2.0.1",
31 "noise-handshake": "^4.0.0",
32 "sodium-secretstream": "^1.1.0",
33 "sodium-universal": "^5.0.0",
34 "streamx": "^2.14.0",
35 "timeout-refresh": "^2.0.0",
36 "unslab": "^1.3.0"
37 }
38 },
39 "node_modules/@hyperswarm/secret-stream/node_modules/sodium-native": {
40 "version": "5.1.0",
41 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-5.1.0.tgz",
42 "integrity": "sha512-3RxgyWyJlhTsABPnJVpCI5CoTDANZTqqFrEPqr+kjfnRaBihpVtMUE3yTF40ukdoB1APXeoBNKF3MzZAIHg39g==",
43 "license": "MIT",
44 "dependencies": {
45 "bare-assert": "^1.2.0",
46 "require-addon": "^1.1.0",
47 "which-runtime": "^1.2.1"
48 },
49 "engines": {
50 "bare": ">=1.16.0"
51 }
52 },
53 "node_modules/@hyperswarm/secret-stream/node_modules/sodium-universal": {
54 "version": "5.0.1",
55 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-5.0.1.tgz",
56 "integrity": "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q==",
57 "license": "MIT",
58 "dependencies": {
59 "sodium-native": "^5.0.1"
60 },
61 "peerDependencies": {
62 "sodium-javascript": "~0.8.0"
63 },
64 "peerDependenciesMeta": {
65 "sodium-javascript": {
66 "optional": true
67 }
68 }
69 },
70 "node_modules/b4a": {
71 "version": "1.8.0",
72 "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz",
73 "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==",
74 "license": "Apache-2.0",
75 "peerDependencies": {
76 "react-native-b4a": "*"
77 },
78 "peerDependenciesMeta": {
79 "react-native-b4a": {
80 "optional": true
81 }
82 }
83 },
84 "node_modules/bare-addon-resolve": {
85 "version": "1.10.0",
86 "resolved": "https://registry.npmjs.org/bare-addon-resolve/-/bare-addon-resolve-1.10.0.tgz",
87 "integrity": "sha512-sSd0jieRJlDaODOzj0oe0RjFVC1QI0ZIjGIdPkbrTXsdVVtENg14c+lHHAhHwmWCZ2nQlMhy8jA3Y5LYPc/isA==",
88 "license": "Apache-2.0",
89 "dependencies": {
90 "bare-module-resolve": "^1.10.0",
91 "bare-semver": "^1.0.0"
92 },
93 "peerDependencies": {
94 "bare-url": "*"
95 },
96 "peerDependenciesMeta": {
97 "bare-url": {
98 "optional": true
99 }
100 }
101 },
102 "node_modules/bare-ansi-escapes": {
103 "version": "2.2.3",
104 "resolved": "https://registry.npmjs.org/bare-ansi-escapes/-/bare-ansi-escapes-2.2.3.tgz",
105 "integrity": "sha512-02ES4/E2RbrtZSnHJ9LntBhYkLA6lPpSEeP8iqS3MccBIVhVBlEmruF1I7HZqx5Q8aiTeYfQVeqmrU9YO2yYoQ==",
106 "license": "Apache-2.0",
107 "dependencies": {
108 "bare-stream": "^2.6.5"
109 },
110 "peerDependencies": {
111 "bare-buffer": "*"
112 },
113 "peerDependenciesMeta": {
114 "bare-buffer": {
115 "optional": true
116 }
117 }
118 },
119 "node_modules/bare-assert": {
120 "version": "1.2.0",
121 "resolved": "https://registry.npmjs.org/bare-assert/-/bare-assert-1.2.0.tgz",
122 "integrity": "sha512-c6uvgvTJBspTDxtVnPgrBKmLgcpW3Fp72NVKDLg6oT4QjQbhGtvrkHMhGYMK1sh4vjBHOBmuUalyt9hSzV37fQ==",
123 "license": "Apache-2.0",
124 "dependencies": {
125 "bare-inspect": "^3.1.2"
126 }
127 },
128 "node_modules/bare-events": {
129 "version": "2.8.2",
130 "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz",
131 "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==",
132 "license": "Apache-2.0",
133 "peerDependencies": {
134 "bare-abort-controller": "*"
135 },
136 "peerDependenciesMeta": {
137 "bare-abort-controller": {
138 "optional": true
139 }
140 }
141 },
142 "node_modules/bare-fs": {
143 "version": "4.5.6",
144 "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.6.tgz",
145 "integrity": "sha512-1QovqDrR80Pmt5HPAsMsXTCFcDYr+NSUKW6nd6WO5v0JBmnItc/irNRzm2KOQ5oZ69P37y+AMujNyNtG+1Rggw==",
146 "license": "Apache-2.0",
147 "dependencies": {
148 "bare-events": "^2.5.4",
149 "bare-path": "^3.0.0",
150 "bare-stream": "^2.6.4",
151 "bare-url": "^2.2.2",
152 "fast-fifo": "^1.3.2"
153 },
154 "engines": {
155 "bare": ">=1.16.0"
156 },
157 "peerDependencies": {
158 "bare-buffer": "*"
159 },
160 "peerDependenciesMeta": {
161 "bare-buffer": {
162 "optional": true
163 }
164 }
165 },
166 "node_modules/bare-inspect": {
167 "version": "3.1.4",
168 "resolved": "https://registry.npmjs.org/bare-inspect/-/bare-inspect-3.1.4.tgz",
169 "integrity": "sha512-jfW5KRA84o3REpI6Vr4nbvMn+hqVAw8GU1mMdRwUsY5yJovQamxYeKGVKGqdzs+8ZbG4jRzGUXP/3Ji/DnqfPg==",
170 "license": "Apache-2.0",
171 "dependencies": {
172 "bare-ansi-escapes": "^2.1.0",
173 "bare-type": "^1.0.0"
174 },
175 "engines": {
176 "bare": ">=1.18.0"
177 }
178 },
179 "node_modules/bare-module-resolve": {
180 "version": "1.12.1",
181 "resolved": "https://registry.npmjs.org/bare-module-resolve/-/bare-module-resolve-1.12.1.tgz",
182 "integrity": "sha512-hbmAPyFpEq8FoZMd5sFO3u6MC5feluWoGE8YKlA8fCrl6mNtx68Wjg4DTiDJcqRJaovTvOYKfYngoBUnbaT7eg==",
183 "license": "Apache-2.0",
184 "dependencies": {
185 "bare-semver": "^1.0.0"
186 },
187 "peerDependencies": {
188 "bare-url": "*"
189 },
190 "peerDependenciesMeta": {
191 "bare-url": {
192 "optional": true
193 }
194 }
195 },
196 "node_modules/bare-os": {
197 "version": "3.8.0",
198 "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.8.0.tgz",
199 "integrity": "sha512-Dc9/SlwfxkXIGYhvMQNUtKaXCaGkZYGcd1vuNUUADVqzu4/vQfvnMkYYOUnt2VwQ2AqKr/8qAVFRtwETljgeFg==",
200 "license": "Apache-2.0",
201 "engines": {
202 "bare": ">=1.14.0"
203 }
204 },
205 "node_modules/bare-path": {
206 "version": "3.0.0",
207 "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz",
208 "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==",
209 "license": "Apache-2.0",
210 "dependencies": {
211 "bare-os": "^3.0.1"
212 }
213 },
214 "node_modules/bare-semver": {
215 "version": "1.0.2",
216 "resolved": "https://registry.npmjs.org/bare-semver/-/bare-semver-1.0.2.tgz",
217 "integrity": "sha512-ESVaN2nzWhcI5tf3Zzcq9aqCZ676VWzqw07eEZ0qxAcEOAFYBa0pWq8sK34OQeHLY3JsfKXZS9mDyzyxGjeLzA==",
218 "license": "Apache-2.0"
219 },
220 "node_modules/bare-stream": {
221 "version": "2.10.0",
222 "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.10.0.tgz",
223 "integrity": "sha512-DOPZF/DDcDruKDA43cOw6e9Quq5daua7ygcAwJE/pKJsRWhgSSemi7qVNGE5kyDIxIeN1533G/zfbvWX7Wcb9w==",
224 "license": "Apache-2.0",
225 "dependencies": {
226 "streamx": "^2.25.0",
227 "teex": "^1.0.1"
228 },
229 "peerDependencies": {
230 "bare-buffer": "*",
231 "bare-events": "*"
232 },
233 "peerDependenciesMeta": {
234 "bare-buffer": {
235 "optional": true
236 },
237 "bare-events": {
238 "optional": true
239 }
240 }
241 },
242 "node_modules/bare-type": {
243 "version": "1.1.0",
244 "resolved": "https://registry.npmjs.org/bare-type/-/bare-type-1.1.0.tgz",
245 "integrity": "sha512-LdtnnEEYldOc87Dr4GpsKnStStZk3zfgoEMXy8yvEZkXrcCv9RtYDrUYWFsBQHtaB0s1EUWmcvS6XmEZYIj3Bw==",
246 "license": "Apache-2.0",
247 "engines": {
248 "bare": ">=1.2.0"
249 }
250 },
251 "node_modules/bare-url": {
252 "version": "2.4.0",
253 "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.0.tgz",
254 "integrity": "sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA==",
255 "license": "Apache-2.0",
256 "dependencies": {
257 "bare-path": "^3.0.0"
258 }
259 },
260 "node_modules/big-sparse-array": {
261 "version": "1.0.3",
262 "resolved": "https://registry.npmjs.org/big-sparse-array/-/big-sparse-array-1.0.3.tgz",
263 "integrity": "sha512-6RjV/3mSZORlMdpUaQ6rUSpG637cZm0//E54YYGtQg1c1O+AbZP8UTdJ/TchsDZcTVLmyWZcseBfp2HBeXUXOQ==",
264 "license": "MIT"
265 },
266 "node_modules/binary-stream-equals": {
267 "version": "1.0.0",
268 "resolved": "https://registry.npmjs.org/binary-stream-equals/-/binary-stream-equals-1.0.0.tgz",
269 "integrity": "sha512-xiUT5LGfD8JiLhbXiG+ByOnbgb9f2ssRLfZDQMl3nZdf89EotQZGZuMkDN8J3n46emabE7RnJ1q0r7Hv3INExw==",
270 "license": "MIT",
271 "dependencies": {
272 "b4a": "^1.3.1"
273 }
274 },
275 "node_modules/codecs": {
276 "version": "3.1.0",
277 "resolved": "https://registry.npmjs.org/codecs/-/codecs-3.1.0.tgz",
278 "integrity": "sha512-Dqx8NwvBvnMeuPQdVKy/XEF71igjR5apxBvCGeV0pP1tXadOiaLvDTXt7xh+/5wI1ASB195mXQGJbw3Ml4YDWQ==",
279 "license": "MIT",
280 "dependencies": {
281 "b4a": "^1.6.3"
282 }
283 },
284 "node_modules/compact-encoding": {
285 "version": "2.19.1",
286 "resolved": "https://registry.npmjs.org/compact-encoding/-/compact-encoding-2.19.1.tgz",
287 "integrity": "sha512-4J4FHc5UugLv2YMss1tL8OBZdgR0vVkV4EuXoAqFS4NbK4gz0Qp+E+VGUnwvDqmMOw2ce/H8duXh3rreC0Qccg==",
288 "license": "Apache-2.0",
289 "dependencies": {
290 "b4a": "^1.3.0"
291 }
292 },
293 "node_modules/corestore": {
294 "version": "6.18.4",
295 "resolved": "https://registry.npmjs.org/corestore/-/corestore-6.18.4.tgz",
296 "integrity": "sha512-KL1cOUyj3DFRNzeVRekGPRiGN4sIfGo7BsncSJQQBT3Rh2y1nQ32MOR9X5DlOMlWIT4txwqBzhzam6+JXtwFVw==",
297 "license": "MIT",
298 "dependencies": {
299 "b4a": "^1.6.4",
300 "hypercore": "^10.37.10",
301 "hypercore-crypto": "^3.4.0",
302 "hypercore-id-encoding": "^1.2.0",
303 "read-write-mutexify": "^2.1.0",
304 "ready-resource": "^1.0.0",
305 "safety-catch": "^1.0.1",
306 "sodium-universal": "^4.0.0",
307 "xache": "^1.1.0"
308 }
309 },
310 "node_modules/crc-native": {
311 "version": "1.1.8",
312 "resolved": "https://registry.npmjs.org/crc-native/-/crc-native-1.1.8.tgz",
313 "integrity": "sha512-R/RYbD8lhG5M1k0iLX49tJdwHM0ipevJPpZw2Wk7b4EShyvx2P0uaq79xyRpcknjiVGiUfjFA8Gyy0mOlhABvw==",
314 "license": "Apache-2.0",
315 "optional": true,
316 "dependencies": {
317 "require-addon": "^1.1.0"
318 }
319 },
320 "node_modules/crc-universal": {
321 "version": "1.0.4",
322 "resolved": "https://registry.npmjs.org/crc-universal/-/crc-universal-1.0.4.tgz",
323 "integrity": "sha512-CE9xWEI6Gd5V0Bdmj5NoWH3d7+EIe4zUpy1sv6uvKYznzsDP1vhiWsTBmL6q9IrH2P6RRshp+8AkhR4CMtY5Hg==",
324 "license": "ISC",
325 "optionalDependencies": {
326 "crc-native": "^1.0.3"
327 }
328 },
329 "node_modules/debounceify": {
330 "version": "1.1.0",
331 "resolved": "https://registry.npmjs.org/debounceify/-/debounceify-1.1.0.tgz",
332 "integrity": "sha512-eKuHDVfJVg+u/0nPy8P+fhnLgbyuTgVxuCRrS/R7EpDSMMkBDgSes41MJtSAY1F1hcqfHz3Zy/qpqHHIp/EhdA==",
333 "license": "MIT"
334 },
335 "node_modules/events-universal": {
336 "version": "1.0.1",
337 "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz",
338 "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==",
339 "license": "Apache-2.0",
340 "dependencies": {
341 "bare-events": "^2.7.0"
342 }
343 },
344 "node_modules/fast-fifo": {
345 "version": "1.3.2",
346 "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
347 "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
348 "license": "MIT"
349 },
350 "node_modules/flat-tree": {
351 "version": "1.13.0",
352 "resolved": "https://registry.npmjs.org/flat-tree/-/flat-tree-1.13.0.tgz",
353 "integrity": "sha512-fT3HIuCPwHhFgJ20QYzDHgUG0zMmFg5cHvFiFo5h+QMSJ28TihsEVY0f8HGliuO+pOzmvjMx1odToeaEWkTnyQ==",
354 "license": "MIT"
355 },
356 "node_modules/fs-native-extensions": {
357 "version": "1.4.5",
358 "resolved": "https://registry.npmjs.org/fs-native-extensions/-/fs-native-extensions-1.4.5.tgz",
359 "integrity": "sha512-ekV0T//iDm4AvhOcuPaHpxub4DI7HvY5ucLJVDvi7T2J+NZkQ9S6MuvgP0yeQvoqNUaAGyLjVYb1905BF9bpmg==",
360 "license": "Apache-2.0",
361 "optional": true,
362 "dependencies": {
363 "require-addon": "^1.1.0",
364 "which-runtime": "^1.2.0"
365 }
366 },
367 "node_modules/hyperbee": {
368 "version": "2.27.3",
369 "resolved": "https://registry.npmjs.org/hyperbee/-/hyperbee-2.27.3.tgz",
370 "integrity": "sha512-PXURH2U4juUZyJRKHTrY5z1zX851pmI1Q0jfv5F/hCIErDt/ND8jOZuxc3hfOLM9f0W3qJEDTMlV5AJBkVPy8w==",
371 "license": "MIT",
372 "dependencies": {
373 "b4a": "^1.6.0",
374 "codecs": "^3.0.0",
375 "debounceify": "^1.0.0",
376 "hypercore-errors": "^1.0.0",
377 "mutexify": "^1.4.0",
378 "protocol-buffers-encodings": "^1.2.0",
379 "rache": "^1.0.0",
380 "ready-resource": "^1.0.0",
381 "resolve-reject-promise": "^1.1.0",
382 "safety-catch": "^1.0.2",
383 "streamx": "^2.12.4",
384 "unslab": "^1.2.0"
385 }
386 },
387 "node_modules/hyperblobs": {
388 "version": "2.9.0",
389 "resolved": "https://registry.npmjs.org/hyperblobs/-/hyperblobs-2.9.0.tgz",
390 "integrity": "sha512-kbJV2+QvXIcFejqOj2UgSjeeHMjWqP1n083vcI+j4E93MhV3oVV2L8/6X+K/id/KQrUmngPTzNTHHXKlkb1CEA==",
391 "license": "Apache-2.0",
392 "dependencies": {
393 "b4a": "^1.6.1",
394 "bare-events": "^2.5.0",
395 "compact-encoding": "^2.18.0",
396 "hypercore-crypto": "^3.6.1",
397 "hypercore-errors": "^1.1.1",
398 "mutexify": "^1.4.0",
399 "speedometer": "^1.1.0",
400 "streamx": "^2.13.2"
401 }
402 },
403 "node_modules/hypercore": {
404 "version": "10.38.2",
405 "resolved": "https://registry.npmjs.org/hypercore/-/hypercore-10.38.2.tgz",
406 "integrity": "sha512-2vx42g2RKdP/o2XzlxKfvgEaZ3+h/B855gCR8iscUDnxUoOZej7vXZ2buex0sweDUEW5aEfMxFR6o5hncio3Nw==",
407 "license": "MIT",
408 "dependencies": {
409 "@hyperswarm/secret-stream": "^6.0.0",
410 "b4a": "^1.1.0",
411 "bare-events": "^2.2.0",
412 "big-sparse-array": "^1.0.3",
413 "compact-encoding": "^2.11.0",
414 "crc-universal": "^1.0.2",
415 "fast-fifo": "^1.3.0",
416 "flat-tree": "^1.9.0",
417 "hypercore-crypto": "^3.2.1",
418 "hypercore-errors": "^1.2.0",
419 "hypercore-id-encoding": "^1.2.0",
420 "is-options": "^1.0.1",
421 "protomux": "^3.5.0",
422 "quickbit-universal": "^2.2.0",
423 "random-access-file": "^4.0.0",
424 "random-array-iterator": "^1.0.0",
425 "safety-catch": "^1.0.1",
426 "sodium-universal": "^4.0.0",
427 "streamx": "^2.12.4",
428 "unslab": "^1.3.0",
429 "xache": "^1.1.0",
430 "z32": "^1.0.0"
431 }
432 },
433 "node_modules/hypercore-crypto": {
434 "version": "3.6.1",
435 "resolved": "https://registry.npmjs.org/hypercore-crypto/-/hypercore-crypto-3.6.1.tgz",
436 "integrity": "sha512-ltIz2uDwy9pO/ZGTvqcjzyBkvt6O4cVm4r/nNxh0GFs/RbQtqP/i4wCvLEdmU7ptgtnw7fI67WYD1aHPuv4OVA==",
437 "license": "MIT",
438 "dependencies": {
439 "b4a": "^1.6.6",
440 "compact-encoding": "^2.15.0",
441 "sodium-universal": "^5.0.0"
442 }
443 },
444 "node_modules/hypercore-crypto/node_modules/sodium-native": {
445 "version": "5.1.0",
446 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-5.1.0.tgz",
447 "integrity": "sha512-3RxgyWyJlhTsABPnJVpCI5CoTDANZTqqFrEPqr+kjfnRaBihpVtMUE3yTF40ukdoB1APXeoBNKF3MzZAIHg39g==",
448 "license": "MIT",
449 "dependencies": {
450 "bare-assert": "^1.2.0",
451 "require-addon": "^1.1.0",
452 "which-runtime": "^1.2.1"
453 },
454 "engines": {
455 "bare": ">=1.16.0"
456 }
457 },
458 "node_modules/hypercore-crypto/node_modules/sodium-universal": {
459 "version": "5.0.1",
460 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-5.0.1.tgz",
461 "integrity": "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q==",
462 "license": "MIT",
463 "dependencies": {
464 "sodium-native": "^5.0.1"
465 },
466 "peerDependencies": {
467 "sodium-javascript": "~0.8.0"
468 },
469 "peerDependenciesMeta": {
470 "sodium-javascript": {
471 "optional": true
472 }
473 }
474 },
475 "node_modules/hypercore-errors": {
476 "version": "1.5.0",
477 "resolved": "https://registry.npmjs.org/hypercore-errors/-/hypercore-errors-1.5.0.tgz",
478 "integrity": "sha512-5KQ/SuDxsvet+7qWA35Ay6zdD9WyAHQoyWHGcPUTbmJBd300gvNIJoi3oma7kp4TTCSzii6qYumNZe/s0j/saQ==",
479 "license": "Apache-2.0",
480 "dependencies": {
481 "hypercore-id-encoding": "^1.3.0"
482 }
483 },
484 "node_modules/hypercore-id-encoding": {
485 "version": "1.3.0",
486 "resolved": "https://registry.npmjs.org/hypercore-id-encoding/-/hypercore-id-encoding-1.3.0.tgz",
487 "integrity": "sha512-W6sHdGo5h7LXEsoWfKf/KfuROZmZRQDlGqJF2EPHW+noCK66Vvr0+zE6cL0vqQi18s0kQPeN7Sq3QyR0Ytc2VQ==",
488 "license": "Apache-2.0",
489 "dependencies": {
490 "b4a": "^1.5.3",
491 "z32": "^1.0.0"
492 }
493 },
494 "node_modules/hyperdrive": {
495 "version": "11.13.4",
496 "resolved": "https://registry.npmjs.org/hyperdrive/-/hyperdrive-11.13.4.tgz",
497 "integrity": "sha512-PN0gClSRx+QBbsLGnGqo2ei9TavJN8d6D3jv2yNMlu7zgXSnqR6QcGo8mgyKnrzgR336oNfvQ2C2Y6cY5klScg==",
498 "license": "Apache-2.0",
499 "dependencies": {
500 "hyperbee": "^2.11.1",
501 "hyperblobs": "^2.3.0",
502 "hypercore": "^10.33.0",
503 "hypercore-errors": "^1.0.0",
504 "is-options": "^1.0.2",
505 "mirror-drive": "^1.2.0",
506 "ready-resource": "^1.0.0",
507 "safety-catch": "^1.0.2",
508 "speedometer": "^1.1.0",
509 "streamx": "^2.12.4",
510 "sub-encoder": "^2.1.1",
511 "unix-path-resolve": "^1.0.2"
512 }
513 },
514 "node_modules/is-options": {
515 "version": "1.0.2",
516 "resolved": "https://registry.npmjs.org/is-options/-/is-options-1.0.2.tgz",
517 "integrity": "sha512-u+Ai74c8Q74aS8BuHwPdI1jptGOT1FQXgCq8/zv0xRuE+wRgSMEJLj8lVO8Zp9BeGb29BXY6AsNPinfqjkr7Fg==",
518 "license": "MIT",
519 "dependencies": {
520 "b4a": "^1.1.1"
521 }
522 },
523 "node_modules/mirror-drive": {
524 "version": "1.13.0",
525 "resolved": "https://registry.npmjs.org/mirror-drive/-/mirror-drive-1.13.0.tgz",
526 "integrity": "sha512-dwf2eIaeFgzv03hfW4aCQ/smNIGuxbsnNRrdGAGIyS70Hp0lbOoHXce2V34hGCoxmzn7jeLA4bHJiWlfKOu2Sg==",
527 "license": "Apache-2.0",
528 "dependencies": {
529 "bare-events": "^2.8.2",
530 "binary-stream-equals": "^1.0.0",
531 "rabin-stream": "^2.0.0",
532 "same-data": "^1.0.0",
533 "speedometer": "^1.1.0",
534 "streamx": "^2.22.1",
535 "unix-path-resolve": "^1.0.2"
536 }
537 },
538 "node_modules/mutexify": {
539 "version": "1.4.0",
540 "resolved": "https://registry.npmjs.org/mutexify/-/mutexify-1.4.0.tgz",
541 "integrity": "sha512-pbYSsOrSB/AKN5h/WzzLRMFgZhClWccf2XIB4RSMC8JbquiB0e0/SH5AIfdQMdyHmYtv4seU7yV/TvAwPLJ1Yg==",
542 "license": "MIT",
543 "dependencies": {
544 "queue-tick": "^1.0.0"
545 }
546 },
547 "node_modules/nanoassert": {
548 "version": "2.0.0",
549 "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-2.0.0.tgz",
550 "integrity": "sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==",
551 "license": "ISC"
552 },
553 "node_modules/noise-curve-ed": {
554 "version": "2.1.0",
555 "resolved": "https://registry.npmjs.org/noise-curve-ed/-/noise-curve-ed-2.1.0.tgz",
556 "integrity": "sha512-zAzJx+VwZM3w6EA1hTmDhJfvAnCeBQn/1FAeZ0LtGxCcCtlAK/uJXQVF/eDVUOaAZ286lHlx77WJ+qj9SmsRRg==",
557 "license": "ISC",
558 "dependencies": {
559 "b4a": "^1.1.0",
560 "nanoassert": "^2.0.0",
561 "sodium-universal": "^5.0.0"
562 }
563 },
564 "node_modules/noise-curve-ed/node_modules/sodium-native": {
565 "version": "5.1.0",
566 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-5.1.0.tgz",
567 "integrity": "sha512-3RxgyWyJlhTsABPnJVpCI5CoTDANZTqqFrEPqr+kjfnRaBihpVtMUE3yTF40ukdoB1APXeoBNKF3MzZAIHg39g==",
568 "license": "MIT",
569 "dependencies": {
570 "bare-assert": "^1.2.0",
571 "require-addon": "^1.1.0",
572 "which-runtime": "^1.2.1"
573 },
574 "engines": {
575 "bare": ">=1.16.0"
576 }
577 },
578 "node_modules/noise-curve-ed/node_modules/sodium-universal": {
579 "version": "5.0.1",
580 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-5.0.1.tgz",
581 "integrity": "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q==",
582 "license": "MIT",
583 "dependencies": {
584 "sodium-native": "^5.0.1"
585 },
586 "peerDependencies": {
587 "sodium-javascript": "~0.8.0"
588 },
589 "peerDependenciesMeta": {
590 "sodium-javascript": {
591 "optional": true
592 }
593 }
594 },
595 "node_modules/noise-handshake": {
596 "version": "4.2.0",
597 "resolved": "https://registry.npmjs.org/noise-handshake/-/noise-handshake-4.2.0.tgz",
598 "integrity": "sha512-9O/VTNX/E2/AToyMTTDU0J/4WhaXMTdqc2DHs9vf+snoZ0cenSBq0dNYTVV1snYYEkmo6QeRrYMxtqtoYnY+LA==",
599 "license": "Apache-2.0",
600 "dependencies": {
601 "b4a": "^1.1.0",
602 "nanoassert": "^2.0.0",
603 "sodium-universal": "^5.0.0"
604 }
605 },
606 "node_modules/noise-handshake/node_modules/sodium-native": {
607 "version": "5.1.0",
608 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-5.1.0.tgz",
609 "integrity": "sha512-3RxgyWyJlhTsABPnJVpCI5CoTDANZTqqFrEPqr+kjfnRaBihpVtMUE3yTF40ukdoB1APXeoBNKF3MzZAIHg39g==",
610 "license": "MIT",
611 "dependencies": {
612 "bare-assert": "^1.2.0",
613 "require-addon": "^1.1.0",
614 "which-runtime": "^1.2.1"
615 },
616 "engines": {
617 "bare": ">=1.16.0"
618 }
619 },
620 "node_modules/noise-handshake/node_modules/sodium-universal": {
621 "version": "5.0.1",
622 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-5.0.1.tgz",
623 "integrity": "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q==",
624 "license": "MIT",
625 "dependencies": {
626 "sodium-native": "^5.0.1"
627 },
628 "peerDependencies": {
629 "sodium-javascript": "~0.8.0"
630 },
631 "peerDependenciesMeta": {
632 "sodium-javascript": {
633 "optional": true
634 }
635 }
636 },
637 "node_modules/paparam": {
638 "version": "1.10.1",
639 "resolved": "https://registry.npmjs.org/paparam/-/paparam-1.10.1.tgz",
640 "integrity": "sha512-viyQI64VIja0Za3njIzhoEP8ZVkgPowhZPuG0E96NwBfYJ6ZIyrrlhWGtFPkdN7eYLl2L8CTWL+wla0evm1KKQ==",
641 "license": "Apache-2.0"
642 },
643 "node_modules/protocol-buffers-encodings": {
644 "version": "1.2.0",
645 "resolved": "https://registry.npmjs.org/protocol-buffers-encodings/-/protocol-buffers-encodings-1.2.0.tgz",
646 "integrity": "sha512-daeNPuKh1NlLD1uDfbLpD+xyUTc07nEtfHwmBZmt/vH0B7VOM+JOCOpDcx9ZRpqHjAiIkGqyTDi+wfGSl17R9w==",
647 "license": "MIT",
648 "dependencies": {
649 "b4a": "^1.6.0",
650 "signed-varint": "^2.0.1",
651 "varint": "5.0.0"
652 }
653 },
654 "node_modules/protomux": {
655 "version": "3.10.1",
656 "resolved": "https://registry.npmjs.org/protomux/-/protomux-3.10.1.tgz",
657 "integrity": "sha512-jgBqx8ZyaBWea/DFG4eOu1scOaeBwcnagiRC1XFVrjeGt7oAb0Pk5udPpBUpJ4DJBRjra50jD6YcZiQQTRqaaA==",
658 "license": "MIT",
659 "dependencies": {
660 "b4a": "^1.3.1",
661 "compact-encoding": "^2.5.1",
662 "queue-tick": "^1.0.0",
663 "safety-catch": "^1.0.1",
664 "unslab": "^1.3.0"
665 }
666 },
667 "node_modules/queue-tick": {
668 "version": "1.0.1",
669 "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
670 "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==",
671 "license": "MIT"
672 },
673 "node_modules/quickbit-native": {
674 "version": "2.4.8",
675 "resolved": "https://registry.npmjs.org/quickbit-native/-/quickbit-native-2.4.8.tgz",
676 "integrity": "sha512-FcCcqI+nIAWGknqhtrYT5TSD7t/N+Xd8ctM+2PrIIBuwOi5hx0SxAvuPtzLIEMfT/2h9+fhBakUe2uALOHX6yw==",
677 "license": "Apache-2.0",
678 "optional": true,
679 "dependencies": {
680 "require-addon": "^1.1.0"
681 }
682 },
683 "node_modules/quickbit-universal": {
684 "version": "2.2.0",
685 "resolved": "https://registry.npmjs.org/quickbit-universal/-/quickbit-universal-2.2.0.tgz",
686 "integrity": "sha512-w02i1R8n7+6pEKTud8DfF8zbFY9o7RtPlUc3jWbtCkDKvhbx/AvV7oNnz4/TcmsPGpSJS+fq5Ud6RH6+YPvSGg==",
687 "license": "ISC",
688 "dependencies": {
689 "b4a": "^1.6.0",
690 "simdle-universal": "^1.1.0"
691 },
692 "optionalDependencies": {
693 "quickbit-native": "^2.2.0"
694 }
695 },
696 "node_modules/rabin-native": {
697 "version": "2.0.0",
698 "resolved": "https://registry.npmjs.org/rabin-native/-/rabin-native-2.0.0.tgz",
699 "integrity": "sha512-x1BlYdIWh+nk9G0scvxyscrYiDPJ7vQZepqqPlVUSInIko1Zxooi8cm6lzBghEGI9aN3DXiunC8FXLgy6kke3Q==",
700 "license": "Apache-2.0",
701 "dependencies": {
702 "require-addon": "^1.1.0"
703 }
704 },
705 "node_modules/rabin-stream": {
706 "version": "2.0.0",
707 "resolved": "https://registry.npmjs.org/rabin-stream/-/rabin-stream-2.0.0.tgz",
708 "integrity": "sha512-EzS2Ig/qsMBSk1PahC0O0IPdRZe3bspHHLWChhqW1feKz+J46tlVL3g4wWr4lrQdXGzABIMsOhvdT6bjXYMuUw==",
709 "license": "Apache-2.0",
710 "dependencies": {
711 "rabin-native": "^2.0.0",
712 "streamx": "^2.23.0"
713 }
714 },
715 "node_modules/rache": {
716 "version": "1.0.0",
717 "resolved": "https://registry.npmjs.org/rache/-/rache-1.0.0.tgz",
718 "integrity": "sha512-e0k0g0w/8jOCB+7YqCIlOa+OJ38k0wrYS4x18pMSmqOvLKoyhmMhmQyCcvfY6VaP8D75cqkEnlakXs+RYYLqNg==",
719 "license": "Apache-2.0"
720 },
721 "node_modules/random-access-file": {
722 "version": "4.1.2",
723 "resolved": "https://registry.npmjs.org/random-access-file/-/random-access-file-4.1.2.tgz",
724 "integrity": "sha512-GQM6R78DceZDcQod8KxlDFwXIiUvlvuy1EOzxTDsjuDjW5NlnlZi0MOk6iI4itAj/2vcvdqcEExYbVpC/dJcEw==",
725 "license": "MIT",
726 "dependencies": {
727 "bare-fs": "^4.0.1",
728 "bare-path": "^3.0.0",
729 "random-access-storage": "^3.0.0"
730 },
731 "optionalDependencies": {
732 "fs-native-extensions": "^1.3.1"
733 }
734 },
735 "node_modules/random-access-storage": {
736 "version": "3.0.2",
737 "resolved": "https://registry.npmjs.org/random-access-storage/-/random-access-storage-3.0.2.tgz",
738 "integrity": "sha512-Es9maUyWdJXWKckKy9s1+vT+DEgAt+PBb9lxPaake/0EDUsHehloKGv9v1zimS2V3gpFAcQXubvc1Rgci2sDPQ==",
739 "license": "MIT",
740 "dependencies": {
741 "bare-events": "^2.2.0",
742 "queue-tick": "^1.0.0"
743 }
744 },
745 "node_modules/random-array-iterator": {
746 "version": "1.0.0",
747 "resolved": "https://registry.npmjs.org/random-array-iterator/-/random-array-iterator-1.0.0.tgz",
748 "integrity": "sha512-u7xCM93XqKEvPTP6xZp2ehttcAemKnh73oKNf1FvzuVCfpt6dILDt1Kxl1LeBjm2iNIeR49VGFhy4Iz3yOun+Q==",
749 "license": "MIT"
750 },
751 "node_modules/read-write-mutexify": {
752 "version": "2.1.0",
753 "resolved": "https://registry.npmjs.org/read-write-mutexify/-/read-write-mutexify-2.1.0.tgz",
754 "integrity": "sha512-fDw/p5/acI1ytVY1UbxEDma/ej1yJH/n9NcjS9YNzcE6sPBPWdlru3ydRa/UBowUg4zqOvNMD5SOGYJrlQ6MzQ==",
755 "license": "MIT"
756 },
757 "node_modules/ready-resource": {
758 "version": "1.2.0",
759 "resolved": "https://registry.npmjs.org/ready-resource/-/ready-resource-1.2.0.tgz",
760 "integrity": "sha512-nfcco/8iAFV0M+2PYnmIc+/xY0iRb35d42HFHQ7AfjulbGEAFa+XWpByfwSyeVeiBoMLLFVMv1HixxNCqzSQ1g==",
761 "license": "MIT",
762 "dependencies": {
763 "bare-events": "^2.2.0"
764 }
765 },
766 "node_modules/refcounter": {
767 "version": "1.0.0",
768 "resolved": "https://registry.npmjs.org/refcounter/-/refcounter-1.0.0.tgz",
769 "integrity": "sha512-1WosVzUy0kPUaPMEtlNDwm99UsteALIhXXR8rerELoa63WkYIXAl0hxgwPFrIYBRWZPGUyekQ04FRtPJ7dHk9w==",
770 "license": "Apache-2.0"
771 },
772 "node_modules/require-addon": {
773 "version": "1.2.0",
774 "resolved": "https://registry.npmjs.org/require-addon/-/require-addon-1.2.0.tgz",
775 "integrity": "sha512-VNPDZlYgIYQwWp9jMTzljx+k0ZtatKlcvOhktZ/anNPI3dQ9NXk7cq2U4iJ1wd9IrytRnYhyEocFWbkdPb+MYA==",
776 "license": "Apache-2.0",
777 "dependencies": {
778 "bare-addon-resolve": "^1.3.0"
779 },
780 "engines": {
781 "bare": ">=1.10.0"
782 }
783 },
784 "node_modules/resolve-reject-promise": {
785 "version": "1.1.0",
786 "resolved": "https://registry.npmjs.org/resolve-reject-promise/-/resolve-reject-promise-1.1.0.tgz",
787 "integrity": "sha512-LWsTOA91AqzBTjSGgX79Tc130pwcBK6xjpJEO+qRT5IKZ6bGnHKcc8QL3upUBcWuU8OTIDzKK2VNSwmmlqvAVg==",
788 "license": "MIT"
789 },
790 "node_modules/rocksdb-native": {
791 "version": "3.15.0",
792 "resolved": "https://registry.npmjs.org/rocksdb-native/-/rocksdb-native-3.15.0.tgz",
793 "integrity": "sha512-czYx0hOzKAy+HYmJROZm7thvJ1tHFWHNkGI3nomumXWzrJghJdrWo4MIhehGX4OTff0lnOCoB2zu6ekzIKY0rQ==",
794 "license": "Apache-2.0",
795 "dependencies": {
796 "compact-encoding": "^2.15.0",
797 "ready-resource": "^1.0.0",
798 "refcounter": "^1.0.0",
799 "require-addon": "^1.0.2",
800 "resolve-reject-promise": "^1.1.0",
801 "signal-promise": "^1.0.3",
802 "streamx": "^2.16.1"
803 },
804 "engines": {
805 "bare": ">=1.16.0"
806 }
807 },
808 "node_modules/safety-catch": {
809 "version": "1.0.3",
810 "resolved": "https://registry.npmjs.org/safety-catch/-/safety-catch-1.0.3.tgz",
811 "integrity": "sha512-Zq+J1TefpoEq/HTUabo0YXX5MNvttjWYODGohgPBO2jfko8Wqx3JYMgE823szDFVamdH5PlpByvfiWScTdSYDA==",
812 "license": "MIT"
813 },
814 "node_modules/same-data": {
815 "version": "1.0.0",
816 "resolved": "https://registry.npmjs.org/same-data/-/same-data-1.0.0.tgz",
817 "integrity": "sha512-Eqn7N2yV+aKMlUHTRqUwYG1Iv0cJqjlvLKj/GoP5PozJn361QaOYX14+v87r7NqQUZC22noP/LfLrSQiPwAygw==",
818 "license": "MIT"
819 },
820 "node_modules/signal-promise": {
821 "version": "1.0.3",
822 "resolved": "https://registry.npmjs.org/signal-promise/-/signal-promise-1.0.3.tgz",
823 "integrity": "sha512-WBgv0UnIq2C+Aeh0/n+IRpP6967eIx9WpynTUoiW3isPpfe1zu2LJzyfXdo9Tgef8yR/sGjcMvoUXD7EYdiz+g==",
824 "license": "MIT"
825 },
826 "node_modules/signed-varint": {
827 "version": "2.0.1",
828 "resolved": "https://registry.npmjs.org/signed-varint/-/signed-varint-2.0.1.tgz",
829 "integrity": "sha512-abgDPg1106vuZZOvw7cFwdCABddfJRz5akcCcchzTbhyhYnsG31y4AlZEgp315T7W3nQq5P4xeOm186ZiPVFzw==",
830 "license": "MIT",
831 "dependencies": {
832 "varint": "~5.0.0"
833 }
834 },
835 "node_modules/simdle-native": {
836 "version": "1.3.9",
837 "resolved": "https://registry.npmjs.org/simdle-native/-/simdle-native-1.3.9.tgz",
838 "integrity": "sha512-Isc8sP4OiiIU0mpslD4GHEnR0VQWvR/54WN7YtwEDkNdTJVWtpmvsSvsgRlw5BNGxdYXlVRegdnrSu10H/PhvA==",
839 "license": "Apache-2.0",
840 "optional": true,
841 "dependencies": {
842 "b4a": "^1.6.0",
843 "require-addon": "^1.1.0"
844 }
845 },
846 "node_modules/simdle-universal": {
847 "version": "1.1.2",
848 "resolved": "https://registry.npmjs.org/simdle-universal/-/simdle-universal-1.1.2.tgz",
849 "integrity": "sha512-3n3w1bs+uwgHKQjt6arez83EywNlhZzYvNOhvAASTl/8KqNIcqr6aHyGt3JRlfuUC7iB0tomJRPlJ2cRGIpBzA==",
850 "license": "ISC",
851 "dependencies": {
852 "b4a": "^1.6.0"
853 },
854 "optionalDependencies": {
855 "simdle-native": "^1.1.1"
856 }
857 },
858 "node_modules/sodium-native": {
859 "version": "4.3.3",
860 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.3.tgz",
861 "integrity": "sha512-OnxSlN3uyY8D0EsLHpmm2HOFmKddQVvEMmsakCrXUzSd8kjjbzL413t4ZNF3n0UxSwNgwTyUvkmZHTfuCeiYSw==",
862 "license": "MIT",
863 "dependencies": {
864 "require-addon": "^1.1.0"
865 }
866 },
867 "node_modules/sodium-secretstream": {
868 "version": "1.2.0",
869 "resolved": "https://registry.npmjs.org/sodium-secretstream/-/sodium-secretstream-1.2.0.tgz",
870 "integrity": "sha512-q/DbraNFXm1KfCiiZvapmz5UC3OlpirYFIvBK2MhGaOFSb3gRyk8OXTi17UI9SGfshQNCpsVvlopogbzZNyW6Q==",
871 "license": "MIT",
872 "dependencies": {
873 "b4a": "^1.1.1",
874 "sodium-universal": "^5.0.0"
875 }
876 },
877 "node_modules/sodium-secretstream/node_modules/sodium-native": {
878 "version": "5.1.0",
879 "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-5.1.0.tgz",
880 "integrity": "sha512-3RxgyWyJlhTsABPnJVpCI5CoTDANZTqqFrEPqr+kjfnRaBihpVtMUE3yTF40ukdoB1APXeoBNKF3MzZAIHg39g==",
881 "license": "MIT",
882 "dependencies": {
883 "bare-assert": "^1.2.0",
884 "require-addon": "^1.1.0",
885 "which-runtime": "^1.2.1"
886 },
887 "engines": {
888 "bare": ">=1.16.0"
889 }
890 },
891 "node_modules/sodium-secretstream/node_modules/sodium-universal": {
892 "version": "5.0.1",
893 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-5.0.1.tgz",
894 "integrity": "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q==",
895 "license": "MIT",
896 "dependencies": {
897 "sodium-native": "^5.0.1"
898 },
899 "peerDependencies": {
900 "sodium-javascript": "~0.8.0"
901 },
902 "peerDependenciesMeta": {
903 "sodium-javascript": {
904 "optional": true
905 }
906 }
907 },
908 "node_modules/sodium-universal": {
909 "version": "4.0.1",
910 "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-4.0.1.tgz",
911 "integrity": "sha512-sNp13PrxYLaUFHTGoDKkSDFvoEu51bfzE12RwGlqU1fcrkpAOK0NvizaJzOWV0Omtk9me2+Pnbjcf/l0efxuGQ==",
912 "license": "MIT",
913 "dependencies": {
914 "sodium-native": "^4.0.0"
915 },
916 "peerDependencies": {
917 "sodium-javascript": "~0.8.0"
918 },
919 "peerDependenciesMeta": {
920 "sodium-javascript": {
921 "optional": true
922 }
923 }
924 },
925 "node_modules/speedometer": {
926 "version": "1.1.0",
927 "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-1.1.0.tgz",
928 "integrity": "sha512-z/wAiTESw2XVPssY2XRcme4niTc4S5FkkJ4gknudtVoc33Zil8TdTxHy5torRcgqMqksJV2Yz8HQcvtbsnw0mQ==",
929 "license": "MIT"
930 },
931 "node_modules/streamx": {
932 "version": "2.25.0",
933 "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz",
934 "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==",
935 "license": "MIT",
936 "dependencies": {
937 "events-universal": "^1.0.0",
938 "fast-fifo": "^1.3.2",
939 "text-decoder": "^1.1.0"
940 }
941 },
942 "node_modules/sub-encoder": {
943 "version": "2.1.3",
944 "resolved": "https://registry.npmjs.org/sub-encoder/-/sub-encoder-2.1.3.tgz",
945 "integrity": "sha512-Xxx04ygZo/1J3yHvaSA6VhDmiSaBQkw/PmO3YnnYFXle+tfOGToC6FcDpIfMztWZXJzuKG14b/57HMkiL58C6A==",
946 "license": "Apache-2.0",
947 "dependencies": {
948 "b4a": "^1.6.0",
949 "codecs": "^3.1.0"
950 }
951 },
952 "node_modules/teex": {
953 "version": "1.0.1",
954 "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz",
955 "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==",
956 "license": "MIT",
957 "dependencies": {
958 "streamx": "^2.12.5"
959 }
960 },
961 "node_modules/text-decoder": {
962 "version": "1.2.7",
963 "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz",
964 "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==",
965 "license": "Apache-2.0",
966 "dependencies": {
967 "b4a": "^1.6.4"
968 }
969 },
970 "node_modules/timeout-refresh": {
971 "version": "2.0.1",
972 "resolved": "https://registry.npmjs.org/timeout-refresh/-/timeout-refresh-2.0.1.tgz",
973 "integrity": "sha512-SVqEcMZBsZF9mA78rjzCrYrUs37LMJk3ShZ851ygZYW1cMeIjs9mL57KO6Iv5mmjSQnOe/29/VAfGXo+oRCiVw==",
974 "license": "MIT"
975 },
976 "node_modules/unix-path-resolve": {
977 "version": "1.0.2",
978 "resolved": "https://registry.npmjs.org/unix-path-resolve/-/unix-path-resolve-1.0.2.tgz",
979 "integrity": "sha512-kG4g5nobBBaMnH2XbrS4sLUXEpx4nY2J3C6KAlAUcnahG2HChxSPVKWYrqEq76iTo+cyMkLUjqxGaQR2tz097Q==",
980 "license": "MIT"
981 },
982 "node_modules/unslab": {
983 "version": "1.3.0",
984 "resolved": "https://registry.npmjs.org/unslab/-/unslab-1.3.0.tgz",
985 "integrity": "sha512-YATkfKAFj47kTzmiQrWXMyRvaVrHsW6MEALa4bm+FhiA2YG4oira+Z3DXN6LrYOYn2Y8eO94Lwl9DOHjs1FpoQ==",
986 "license": "Apache-2.0",
987 "dependencies": {
988 "b4a": "^1.6.6"
989 }
990 },
991 "node_modules/varint": {
992 "version": "5.0.0",
993 "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.0.tgz",
994 "integrity": "sha512-gC13b/bWrqQoKY2EmROCZ+AR0jitc6DnDGaQ6Ls9QpKmuSgJB1eQ7H3KETtQm7qSdMWMKCmsshyCmUwMLh3OAA==",
995 "license": "MIT"
996 },
997 "node_modules/which-runtime": {
998 "version": "1.3.2",
999 "resolved": "https://registry.npmjs.org/which-runtime/-/which-runtime-1.3.2.tgz",
1000 "integrity": "sha512-5kwCfWml7+b2NO7KrLMhYihjRx0teKkd3yGp1Xk5Vaf2JGdSh+rgVhEALAD9c/59dP+YwJHXoEO7e8QPy7gOkw==",
1001 "license": "Apache-2.0"
1002 },
1003 "node_modules/xache": {
1004 "version": "1.2.1",
1005 "resolved": "https://registry.npmjs.org/xache/-/xache-1.2.1.tgz",
1006 "integrity": "sha512-igRS6jPreJ54ABdzhh4mCDXcz+XMaWO2q1ABRV2yWYuk29jlp8VT7UBdCqNkX7rpYBbXsebVVKkwIuYZjyZNqA==",
1007 "license": "MIT"
1008 },
1009 "node_modules/z32": {
1010 "version": "1.1.0",
1011 "resolved": "https://registry.npmjs.org/z32/-/z32-1.1.0.tgz",
1012 "integrity": "sha512-1WUHy+VS6d0HPNspDxvLssBbeQjXMjSnpv0vH82vRAUfg847NmX3OXozp/hRP5jPhxBbrVzrgvAt+UsGNzRFQQ==",
1013 "license": "MIT",
1014 "dependencies": {
1015 "b4a": "^1.5.3"
1016 }
1017 }
1018 }
1019}
package.json +21 -0
……@@ -0,0 +1,21 @@
1{
2 "name": "hyper-inspector",
3 "version": "0.1.0",
4 "description": "Inspect, audit, and manage Hypercore/Hyperdrive corestores",
5 "type": "module",
6 "main": "index.js",
7 "bin": {
8 "hyper-inspector": "./bin/cli.js"
9 },
10 "scripts": {
11 "test": "brittle test/*.js"
12 },
13 "dependencies": {
14 "b4a": "^1.6.7",
15 "corestore": "^6.18.0",
16 "hyperdrive": "^11.13.0",
17 "rocksdb-native": "^3.13.0",
18 "paparam": "^1.10.0"
19 },
20 "license": "MIT"
21}