@poe-platform/safe-bash 0.1.511 → 0.1.513
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/safe-bash/chunks/{chunk-5HT35GTV.js → chunk-5MSOBYRG.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-B637PJBS.js → chunk-5OCQTFXT.js} +1 -1
- package/dist/safe-bash/chunks/{chunk-B637PJBS.js.map → chunk-5OCQTFXT.js.map} +2 -2
- package/dist/safe-bash/chunks/{chunk-4OKU6JXB.js → chunk-NYHAKXQ7.js} +2 -2
- package/dist/safe-bash/commands/cmp.d.ts +3 -0
- package/dist/safe-bash/commands/cmp.d.ts.map +1 -0
- package/dist/safe-bash/commands/cmp.js +595 -0
- package/dist/safe-bash/commands/cmp.js.map +1 -0
- package/dist/safe-bash/commands/fmt.d.ts +3 -0
- package/dist/safe-bash/commands/fmt.d.ts.map +1 -0
- package/dist/safe-bash/commands/fmt.js +839 -0
- package/dist/safe-bash/commands/fmt.js.map +1 -0
- package/dist/safe-bash/commands/metadata/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/metadata/index.js +2 -1
- package/dist/safe-bash/commands/metadata/index.js.map +1 -1
- package/dist/safe-bash/commands/numfmt.d.ts +3 -0
- package/dist/safe-bash/commands/numfmt.d.ts.map +1 -0
- package/dist/safe-bash/commands/numfmt.js +1180 -0
- package/dist/safe-bash/commands/numfmt.js.map +1 -0
- package/dist/safe-bash/commands/regex-execution/bounded-provider.d.ts +1 -1
- package/dist/safe-bash/commands/regex-execution/bounded-provider.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/bounded-provider.js +7 -35
- package/dist/safe-bash/commands/regex-execution/bounded-provider.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/ere/matcher.d.ts +2 -0
- package/dist/safe-bash/commands/regex-execution/ere/matcher.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/ere/matcher.js +55 -1
- package/dist/safe-bash/commands/regex-execution/ere/matcher.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/ere/syntax.js +1 -1
- package/dist/safe-bash/commands/regex-execution/ere/syntax.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/ere/types.d.ts +1 -0
- package/dist/safe-bash/commands/regex-execution/ere/types.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/utf8.d.ts +3 -0
- package/dist/safe-bash/commands/regex-execution/utf8.d.ts.map +1 -0
- package/dist/safe-bash/commands/regex-execution/utf8.js +24 -0
- package/dist/safe-bash/commands/regex-execution/utf8.js.map +1 -0
- package/dist/safe-bash/commands/shuf.d.ts +3 -0
- package/dist/safe-bash/commands/shuf.d.ts.map +1 -0
- package/dist/safe-bash/commands/shuf.js +768 -0
- package/dist/safe-bash/commands/shuf.js.map +1 -0
- package/dist/safe-bash/commands/standard.d.ts.map +1 -1
- package/dist/safe-bash/commands/standard.js +5 -0
- package/dist/safe-bash/commands/standard.js.map +1 -1
- package/dist/safe-bash/commands/truncate.d.ts +4 -0
- package/dist/safe-bash/commands/truncate.d.ts.map +1 -0
- package/dist/safe-bash/commands/truncate.js +668 -0
- package/dist/safe-bash/commands/truncate.js.map +1 -0
- package/dist/safe-bash/commands/which/which.d.ts.map +1 -1
- package/dist/safe-bash/commands/which/which.js +1 -0
- package/dist/safe-bash/commands/which/which.js.map +1 -1
- package/dist/safe-bash/commands/xml/index.browser.js +2 -2
- package/dist/safe-bash/commands/yq/index.browser.js +2 -2
- package/dist/safe-bash/contracts/command.d.ts +11 -1
- package/dist/safe-bash/contracts/command.d.ts.map +1 -1
- package/dist/safe-bash/contracts/command.js.map +1 -1
- package/dist/safe-bash/contracts/filesystem.d.ts +1 -1
- package/dist/safe-bash/contracts/filesystem.d.ts.map +1 -1
- package/dist/safe-bash/core.browser.js +9481 -789
- package/dist/safe-bash/core.browser.js.map +4 -4
- package/dist/safe-bash/shell/input.d.ts +15 -4
- package/dist/safe-bash/shell/input.d.ts.map +1 -1
- package/dist/safe-bash/shell/input.js +211 -9
- package/dist/safe-bash/shell/input.js.map +1 -1
- package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
- package/dist/safe-bash/shell/runtime.js +16 -4
- package/dist/safe-bash/shell/runtime.js.map +1 -1
- package/package.json +2 -2
- /package/dist/safe-bash/chunks/{chunk-5HT35GTV.js.map → chunk-5MSOBYRG.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-4OKU6JXB.js.map → chunk-NYHAKXQ7.js.map} +0 -0
|
@@ -0,0 +1,768 @@
|
|
|
1
|
+
import { FsError, getCommandArguments, writeBytes } from "../contracts/index.js";
|
|
2
|
+
import { assertCommandRequirements } from "../contracts/command-requirements.js";
|
|
3
|
+
import { createOutputOperation } from "../contracts/output.js";
|
|
4
|
+
import { shellValueByteLength } from "../contracts/value.js";
|
|
5
|
+
import { yieldTurn } from "../contracts/yield.js";
|
|
6
|
+
import { PublicDiagnostic } from "../diagnostics.js";
|
|
7
|
+
import { ByteInputBudget } from "./bytes/input-budget.js";
|
|
8
|
+
import { bufferLimit, diagnostic, pathOf } from "./internal.js";
|
|
9
|
+
import { textOutputRequirements } from "./portable-requirements.js";
|
|
10
|
+
import { RecordBuffer } from "./record-buffer.js";
|
|
11
|
+
const maximumLines = 1024 * 1024;
|
|
12
|
+
const reservoirThreshold = 8 * 1024 * 1024;
|
|
13
|
+
const unsignedMaximum = (1n << 64n) - 1n;
|
|
14
|
+
const glibc231PrintableRanges = [
|
|
15
|
+
0x20, 0x7e, 0xa0, 0x377, 0x37a, 0x37f, 0x384, 0x38a, 0x38c, 0x38c, 0x38e, 0x3a1, 0x3a3, 0x52f, 0x531, 0x556,
|
|
16
|
+
0x559, 0x55f, 0x561, 0x587, 0x589, 0x58a, 0x58d, 0x58f, 0x591, 0x5c7, 0x5d0, 0x5ea, 0x5f0, 0x5f4, 0x600, 0x61c,
|
|
17
|
+
0x61e, 0x70d, 0x70f, 0x74a, 0x74d, 0x7b1, 0x7c0, 0x7fa, 0x800, 0x82d, 0x830, 0x83e, 0x840, 0x85b, 0x85e, 0x85e,
|
|
18
|
+
0x8a0, 0x8b4, 0x8b6, 0x8bd, 0x8d4, 0x983, 0x985, 0x98c, 0x98f, 0x990, 0x993, 0x9a8, 0x9aa, 0x9b0, 0x9b2, 0x9b2,
|
|
19
|
+
0x9b6, 0x9b9, 0x9bc, 0x9c4, 0x9c7, 0x9c8, 0x9cb, 0x9ce, 0x9d7, 0x9d7, 0x9dc, 0x9dd, 0x9df, 0x9e3, 0x9e6, 0x9fb,
|
|
20
|
+
0xa01, 0xa03, 0xa05, 0xa0a, 0xa0f, 0xa10, 0xa13, 0xa28, 0xa2a, 0xa30, 0xa32, 0xa33, 0xa35, 0xa36, 0xa38, 0xa39,
|
|
21
|
+
0xa3c, 0xa3c, 0xa3e, 0xa42, 0xa47, 0xa48, 0xa4b, 0xa4d, 0xa51, 0xa51, 0xa59, 0xa5c, 0xa5e, 0xa5e, 0xa66, 0xa75,
|
|
22
|
+
0xa81, 0xa83, 0xa85, 0xa8d, 0xa8f, 0xa91, 0xa93, 0xaa8, 0xaaa, 0xab0, 0xab2, 0xab3, 0xab5, 0xab9, 0xabc, 0xac5,
|
|
23
|
+
0xac7, 0xac9, 0xacb, 0xacd, 0xad0, 0xad0, 0xae0, 0xae3, 0xae6, 0xaf1, 0xaf9, 0xaf9, 0xb01, 0xb03, 0xb05, 0xb0c,
|
|
24
|
+
0xb0f, 0xb10, 0xb13, 0xb28, 0xb2a, 0xb30, 0xb32, 0xb33, 0xb35, 0xb39, 0xb3c, 0xb44, 0xb47, 0xb48, 0xb4b, 0xb4d,
|
|
25
|
+
0xb56, 0xb57, 0xb5c, 0xb5d, 0xb5f, 0xb63, 0xb66, 0xb77, 0xb82, 0xb83, 0xb85, 0xb8a, 0xb8e, 0xb90, 0xb92, 0xb95,
|
|
26
|
+
0xb99, 0xb9a, 0xb9c, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, 0xba8, 0xbaa, 0xbae, 0xbb9, 0xbbe, 0xbc2, 0xbc6, 0xbc8,
|
|
27
|
+
0xbca, 0xbcd, 0xbd0, 0xbd0, 0xbd7, 0xbd7, 0xbe6, 0xbfa, 0xc00, 0xc03, 0xc05, 0xc0c, 0xc0e, 0xc10, 0xc12, 0xc28,
|
|
28
|
+
0xc2a, 0xc39, 0xc3d, 0xc44, 0xc46, 0xc48, 0xc4a, 0xc4d, 0xc55, 0xc56, 0xc58, 0xc5a, 0xc60, 0xc63, 0xc66, 0xc6f,
|
|
29
|
+
0xc78, 0xc83, 0xc85, 0xc8c, 0xc8e, 0xc90, 0xc92, 0xca8, 0xcaa, 0xcb3, 0xcb5, 0xcb9, 0xcbc, 0xcc4, 0xcc6, 0xcc8,
|
|
30
|
+
0xcca, 0xccd, 0xcd5, 0xcd6, 0xcde, 0xcde, 0xce0, 0xce3, 0xce6, 0xcef, 0xcf1, 0xcf2, 0xd01, 0xd03, 0xd05, 0xd0c,
|
|
31
|
+
0xd0e, 0xd10, 0xd12, 0xd3a, 0xd3d, 0xd44, 0xd46, 0xd48, 0xd4a, 0xd4f, 0xd54, 0xd63, 0xd66, 0xd7f, 0xd82, 0xd83,
|
|
32
|
+
0xd85, 0xd96, 0xd9a, 0xdb1, 0xdb3, 0xdbb, 0xdbd, 0xdbd, 0xdc0, 0xdc6, 0xdca, 0xdca, 0xdcf, 0xdd4, 0xdd6, 0xdd6,
|
|
33
|
+
0xdd8, 0xddf, 0xde6, 0xdef, 0xdf2, 0xdf4, 0xe01, 0xe3a, 0xe3f, 0xe5b, 0xe81, 0xe82, 0xe84, 0xe84, 0xe87, 0xe88,
|
|
34
|
+
0xe8a, 0xe8a, 0xe8d, 0xe8d, 0xe94, 0xe97, 0xe99, 0xe9f, 0xea1, 0xea3, 0xea5, 0xea5, 0xea7, 0xea7, 0xeaa, 0xeab,
|
|
35
|
+
0xead, 0xeb9, 0xebb, 0xebd, 0xec0, 0xec4, 0xec6, 0xec6, 0xec8, 0xecd, 0xed0, 0xed9, 0xedc, 0xedf, 0xf00, 0xf47,
|
|
36
|
+
0xf49, 0xf6c, 0xf71, 0xf97, 0xf99, 0xfbc, 0xfbe, 0xfcc, 0xfce, 0xfda, 0x1000, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd,
|
|
37
|
+
0x10d0, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0,
|
|
38
|
+
0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a,
|
|
39
|
+
0x135d, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f5, 0x13f8, 0x13fd, 0x1400, 0x169c, 0x16a0, 0x16f8, 0x1700, 0x170c, 0x170e, 0x1714,
|
|
40
|
+
0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9,
|
|
41
|
+
0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191e, 0x1920, 0x192b, 0x1930, 0x193b,
|
|
42
|
+
0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x19de, 0x1a1b, 0x1a1e, 0x1a5e,
|
|
43
|
+
0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, 0x1ab0, 0x1abe, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3,
|
|
44
|
+
0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c88, 0x1cc0, 0x1cc7, 0x1cd0, 0x1cf6, 0x1cf8, 0x1cf9, 0x1d00, 0x1df5, 0x1dfb, 0x1f15,
|
|
45
|
+
0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d,
|
|
46
|
+
0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2027,
|
|
47
|
+
0x202a, 0x2064, 0x2066, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, 0x20a0, 0x20be, 0x20d0, 0x20f0, 0x2100, 0x218b, 0x2190, 0x23fe,
|
|
48
|
+
0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, 0x2b98, 0x2bb9, 0x2bbd, 0x2bc8, 0x2bca, 0x2bd1, 0x2bec, 0x2bef,
|
|
49
|
+
0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d70,
|
|
50
|
+
0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6,
|
|
51
|
+
0x2dd8, 0x2dde, 0x2de0, 0x2e44, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096,
|
|
52
|
+
0x3099, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5,
|
|
53
|
+
0x4dc0, 0x9fd5, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, 0xa700, 0xa7ae, 0xa7b0, 0xa7b7, 0xa7f7, 0xa82b,
|
|
54
|
+
0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c5, 0xa8ce, 0xa8d9, 0xa8e0, 0xa8fd, 0xa900, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd,
|
|
55
|
+
0xa9cf, 0xa9d9, 0xa9de, 0xa9fe, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa5c, 0xaac2, 0xaadb, 0xaaf6, 0xab01, 0xab06,
|
|
56
|
+
0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xab30, 0xab65, 0xab70, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3,
|
|
57
|
+
0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xe000, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c,
|
|
58
|
+
0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbc1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfd,
|
|
59
|
+
0xfe00, 0xfe19, 0xfe20, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe,
|
|
60
|
+
0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0xfffd, 0x10000, 0x1000b,
|
|
61
|
+
0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133,
|
|
62
|
+
0x10137, 0x1018e, 0x10190, 0x1019b, 0x101a0, 0x101a0, 0x101d0, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x102e0, 0x102fb, 0x10300, 0x10323,
|
|
63
|
+
0x10330, 0x1034a, 0x10350, 0x1037a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x104b0, 0x104d3,
|
|
64
|
+
0x104d8, 0x104fb, 0x10500, 0x10527, 0x10530, 0x10563, 0x1056f, 0x1056f, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, 0x10800, 0x10805,
|
|
65
|
+
0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10857, 0x1089e, 0x108a7, 0x108af, 0x108e0, 0x108f2,
|
|
66
|
+
0x108f4, 0x108f5, 0x108fb, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10980, 0x109b7, 0x109bc, 0x109cf, 0x109d2, 0x10a03, 0x10a05, 0x10a06,
|
|
67
|
+
0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, 0x10a60, 0x10a9f, 0x10ac0, 0x10ae6,
|
|
68
|
+
0x10aeb, 0x10af6, 0x10b00, 0x10b35, 0x10b39, 0x10b55, 0x10b58, 0x10b72, 0x10b78, 0x10b91, 0x10b99, 0x10b9c, 0x10ba9, 0x10baf, 0x10c00, 0x10c48,
|
|
69
|
+
0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, 0x10cfa, 0x10cff, 0x10e60, 0x10e7e, 0x11000, 0x1104d, 0x11052, 0x1106f, 0x1107f, 0x110c1, 0x110d0, 0x110e8,
|
|
70
|
+
0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x11143, 0x11150, 0x11176, 0x11180, 0x111cd, 0x111d0, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211,
|
|
71
|
+
0x11213, 0x1123e, 0x11280, 0x11286, 0x11288, 0x11288, 0x1128a, 0x1128d, 0x1128f, 0x1129d, 0x1129f, 0x112a9, 0x112b0, 0x112ea, 0x112f0, 0x112f9,
|
|
72
|
+
0x11300, 0x11303, 0x11305, 0x1130c, 0x1130f, 0x11310, 0x11313, 0x11328, 0x1132a, 0x11330, 0x11332, 0x11333, 0x11335, 0x11339, 0x1133c, 0x11344,
|
|
73
|
+
0x11347, 0x11348, 0x1134b, 0x1134d, 0x11350, 0x11350, 0x11357, 0x11357, 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, 0x11400, 0x11459,
|
|
74
|
+
0x1145b, 0x1145b, 0x1145d, 0x1145d, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, 0x115b8, 0x115dd, 0x11600, 0x11644, 0x11650, 0x11659,
|
|
75
|
+
0x11660, 0x1166c, 0x11680, 0x116b7, 0x116c0, 0x116c9, 0x11700, 0x11719, 0x1171d, 0x1172b, 0x11730, 0x1173f, 0x118a0, 0x118f2, 0x118ff, 0x118ff,
|
|
76
|
+
0x11ac0, 0x11af8, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c45, 0x11c50, 0x11c6c, 0x11c70, 0x11c8f, 0x11c92, 0x11ca7, 0x11ca9, 0x11cb6,
|
|
77
|
+
0x12000, 0x12399, 0x12400, 0x1246e, 0x12470, 0x12474, 0x12480, 0x12543, 0x13000, 0x1342e, 0x14400, 0x14646, 0x16800, 0x16a38, 0x16a40, 0x16a5e,
|
|
78
|
+
0x16a60, 0x16a69, 0x16a6e, 0x16a6f, 0x16ad0, 0x16aed, 0x16af0, 0x16af5, 0x16b00, 0x16b45, 0x16b50, 0x16b59, 0x16b5b, 0x16b61, 0x16b63, 0x16b77,
|
|
79
|
+
0x16b7d, 0x16b8f, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, 0x16fe0, 0x16fe0, 0x17000, 0x187ec, 0x18800, 0x18af2, 0x1b000, 0x1b001,
|
|
80
|
+
0x1bc00, 0x1bc6a, 0x1bc70, 0x1bc7c, 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9c, 0x1bca3, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1e8,
|
|
81
|
+
0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6,
|
|
82
|
+
0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c,
|
|
83
|
+
0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1da8b,
|
|
84
|
+
0x1da9b, 0x1da9f, 0x1daa1, 0x1daaf, 0x1e000, 0x1e006, 0x1e008, 0x1e018, 0x1e01b, 0x1e021, 0x1e023, 0x1e024, 0x1e026, 0x1e02a, 0x1e800, 0x1e8c4,
|
|
85
|
+
0x1e8c7, 0x1e8d6, 0x1e900, 0x1e94a, 0x1e950, 0x1e959, 0x1e95e, 0x1e95f, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24,
|
|
86
|
+
0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49,
|
|
87
|
+
0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d,
|
|
88
|
+
0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e,
|
|
89
|
+
0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x1eef0, 0x1eef1, 0x1f000, 0x1f02b, 0x1f030, 0x1f093,
|
|
90
|
+
0x1f0a0, 0x1f0ae, 0x1f0b1, 0x1f0bf, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0f5, 0x1f100, 0x1f10c, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f1ac,
|
|
91
|
+
0x1f1e6, 0x1f202, 0x1f210, 0x1f23b, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f300, 0x1f6d2, 0x1f6e0, 0x1f6ec, 0x1f6f0, 0x1f6f6, 0x1f700, 0x1f773,
|
|
92
|
+
0x1f780, 0x1f7d4, 0x1f800, 0x1f80b, 0x1f810, 0x1f847, 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, 0x1f910, 0x1f91e, 0x1f920, 0x1f927,
|
|
93
|
+
0x1f930, 0x1f930, 0x1f933, 0x1f93e, 0x1f940, 0x1f94b, 0x1f950, 0x1f95e, 0x1f980, 0x1f991, 0x1f9c0, 0x1f9c0, 0x20000, 0x2a6d6, 0x2a700, 0x2b734,
|
|
94
|
+
0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2f800, 0x2fa1d, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xf0000, 0xffffd, 0x100000, 0x10fffd,
|
|
95
|
+
];
|
|
96
|
+
class ShufDiagnostic extends Error {
|
|
97
|
+
detail;
|
|
98
|
+
usage;
|
|
99
|
+
constructor(detail, usage = false) {
|
|
100
|
+
super(detail);
|
|
101
|
+
this.detail = detail;
|
|
102
|
+
this.usage = usage;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function unicodeLocale(context) {
|
|
106
|
+
const locale = (context.env.LC_ALL || context.env.LC_CTYPE || context.env.LANG || "C").toLowerCase();
|
|
107
|
+
return locale.endsWith("utf-8") || locale.endsWith("utf8");
|
|
108
|
+
}
|
|
109
|
+
function quote(text, filename = false, unicode = false) {
|
|
110
|
+
const controls = { "\u0007": "\\a", "\b": "\\b", "\t": "\\t", "\n": "\\n", "\v": "\\v", "\f": "\\f", "\r": "\\r" };
|
|
111
|
+
const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
112
|
+
const units = [];
|
|
113
|
+
for (let offset = 0; offset < text.length;) {
|
|
114
|
+
const first = text.charCodeAt(offset);
|
|
115
|
+
let length = 1;
|
|
116
|
+
let point = first;
|
|
117
|
+
let valid = first < 128;
|
|
118
|
+
if (unicode && first >= 0xc2 && first <= 0xf4) {
|
|
119
|
+
const size = first < 0xe0 ? 2 : first < 0xf0 ? 3 : 4;
|
|
120
|
+
try {
|
|
121
|
+
point = decoder.decode(Uint8Array.from(text.slice(offset, offset + size), character => character.charCodeAt(0))).codePointAt(0);
|
|
122
|
+
length = size;
|
|
123
|
+
valid = true;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
valid = false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
let printable = valid && point >= 32 && point < 127;
|
|
130
|
+
if (valid && point >= 128) {
|
|
131
|
+
let low = 0, high = glibc231PrintableRanges.length / 2;
|
|
132
|
+
while (low < high) {
|
|
133
|
+
const middle = Math.floor((low + high) / 2);
|
|
134
|
+
if (point < glibc231PrintableRanges[middle * 2])
|
|
135
|
+
high = middle;
|
|
136
|
+
else if (point > glibc231PrintableRanges[middle * 2 + 1])
|
|
137
|
+
low = middle + 1;
|
|
138
|
+
else {
|
|
139
|
+
printable = true;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const unit = text.slice(offset, offset + length);
|
|
145
|
+
const shellSpecial = '!"$&()*;<=>?[\\^`|'.includes(unit);
|
|
146
|
+
const positional = "#~".includes(unit) ? offset === 0 : "{}".includes(unit) && text.length === 1;
|
|
147
|
+
units.push({ text: unit, printable, shellSpecial: shellSpecial || positional,
|
|
148
|
+
cAndShellCompatible: printable && !shellSpecial && (!"#~{}".includes(unit) || positional) });
|
|
149
|
+
offset += length;
|
|
150
|
+
}
|
|
151
|
+
if (filename && text && units.every(unit => unit.printable && !unit.shellSpecial && !" ':".includes(unit.text)))
|
|
152
|
+
return text;
|
|
153
|
+
if (filename && text.includes("'") && units.every(unit => unit.cAndShellCompatible))
|
|
154
|
+
return `"${text}"`;
|
|
155
|
+
const left = !filename && unicode ? "\xe2\x80\x98" : "'";
|
|
156
|
+
const right = !filename && unicode ? "\xe2\x80\x99" : "'";
|
|
157
|
+
let result = left;
|
|
158
|
+
let escaping = filename && text.includes("'") && units.length > 0 && !units[units.length - 1].printable;
|
|
159
|
+
for (const unit of units) {
|
|
160
|
+
if (filename && unit.text === "'") {
|
|
161
|
+
result += "'\\''";
|
|
162
|
+
escaping = false;
|
|
163
|
+
}
|
|
164
|
+
else if (!unit.printable) {
|
|
165
|
+
if (filename && !escaping)
|
|
166
|
+
result += "'$'";
|
|
167
|
+
escaping = true;
|
|
168
|
+
result += controls[unit.text] ?? Array.from(unit.text, character => `\\${character.charCodeAt(0).toString(8).padStart(3, "0")}`).join("");
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
if (filename && escaping)
|
|
172
|
+
result += "''";
|
|
173
|
+
escaping = false;
|
|
174
|
+
if (!filename && (unit.text === right || unit.text === "\\"))
|
|
175
|
+
result += "\\";
|
|
176
|
+
result += unit.text;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return result + right;
|
|
180
|
+
}
|
|
181
|
+
function decimal(text, count, unicode) {
|
|
182
|
+
let offset = 0;
|
|
183
|
+
while (text.charCodeAt(offset) === 32 || text.charCodeAt(offset) >= 9 && text.charCodeAt(offset) <= 13)
|
|
184
|
+
offset++;
|
|
185
|
+
if (text[offset] === "+")
|
|
186
|
+
offset++;
|
|
187
|
+
const start = offset;
|
|
188
|
+
let value = 0n;
|
|
189
|
+
while (text.charCodeAt(offset) >= 48 && text.charCodeAt(offset) <= 57) {
|
|
190
|
+
value = value > unsignedMaximum ? unsignedMaximum + 1n : value * 10n + BigInt(text.charCodeAt(offset) - 48);
|
|
191
|
+
offset++;
|
|
192
|
+
}
|
|
193
|
+
if (offset === start || !count && offset !== text.length || !count && value > unsignedMaximum) {
|
|
194
|
+
throw new ShufDiagnostic(`invalid ${count ? "line count" : "input range"}: ${quote(text, false, unicode)}${!count && offset === text.length && value > unsignedMaximum ? ": Value too large for defined data type" : ""}`);
|
|
195
|
+
}
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
function parse(context) {
|
|
199
|
+
const unicode = unicodeLocale(context);
|
|
200
|
+
if (context.args.length > 4096)
|
|
201
|
+
throw new PublicDiagnostic("argument limit exceeded");
|
|
202
|
+
let total = 0;
|
|
203
|
+
for (const argument of context.args) {
|
|
204
|
+
total += context.argumentValues === undefined ? Buffer.byteLength(argument) : argument.length;
|
|
205
|
+
if (total > 65536)
|
|
206
|
+
throw new PublicDiagnostic("argument limit exceeded");
|
|
207
|
+
}
|
|
208
|
+
const carrier = getCommandArguments(context);
|
|
209
|
+
total = 0;
|
|
210
|
+
for (const value of carrier.values) {
|
|
211
|
+
total += shellValueByteLength(value);
|
|
212
|
+
if (total > 65536)
|
|
213
|
+
throw new PublicDiagnostic("argument limit exceeded");
|
|
214
|
+
}
|
|
215
|
+
const args = context.args.map((_argument, index) => Array.from(carrier.bytes(index), byte => String.fromCharCode(byte)).join(""));
|
|
216
|
+
const settings = { echo: false, repeat: false, separator: 10, count: unsignedMaximum, operands: [] };
|
|
217
|
+
const long = { echo: "e", "input-range": "i", "head-count": "n", output: "o", "random-source": "random", repeat: "r", "zero-terminated": "z", help: "help", version: "version" };
|
|
218
|
+
const apply = (key, value = "") => {
|
|
219
|
+
if (key === "e")
|
|
220
|
+
settings.echo = true;
|
|
221
|
+
else if (key === "r")
|
|
222
|
+
settings.repeat = true;
|
|
223
|
+
else if (key === "z")
|
|
224
|
+
settings.separator = 0;
|
|
225
|
+
else if (key === "help" || key === "version")
|
|
226
|
+
settings.information = key;
|
|
227
|
+
else if (key === "n") {
|
|
228
|
+
const number = decimal(value, true, unicode);
|
|
229
|
+
if (number < settings.count)
|
|
230
|
+
settings.count = number;
|
|
231
|
+
}
|
|
232
|
+
else if (key === "i") {
|
|
233
|
+
if (settings.range)
|
|
234
|
+
throw new ShufDiagnostic("multiple -i options specified");
|
|
235
|
+
const dash = value.indexOf("-");
|
|
236
|
+
const low = dash < 0 ? unsignedMaximum : decimal(value.slice(0, dash), false, unicode);
|
|
237
|
+
const high = decimal(value.slice(dash + 1), false, unicode);
|
|
238
|
+
const length = high - low + 1n;
|
|
239
|
+
if (dash < 0 || length < 0n || length > unsignedMaximum)
|
|
240
|
+
throw new ShufDiagnostic(`invalid input range: ${quote(value, false, unicode)}`);
|
|
241
|
+
settings.range = { low, length };
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
const property = key === "o" ? "output" : "random";
|
|
245
|
+
if (settings[property] !== undefined && settings[property] !== value)
|
|
246
|
+
throw new ShufDiagnostic(`multiple ${property === "output" ? "output files" : "random sources"} specified`);
|
|
247
|
+
settings[property] = value;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
let stopped = false;
|
|
251
|
+
for (let index = 0; index < args.length; index++) {
|
|
252
|
+
const argument = args[index];
|
|
253
|
+
if (stopped || argument === "-" || !argument.startsWith("-")) {
|
|
254
|
+
settings.operands.push(argument);
|
|
255
|
+
if (context.env.POSIXLY_CORRECT !== undefined)
|
|
256
|
+
stopped = true;
|
|
257
|
+
}
|
|
258
|
+
else if (argument === "--")
|
|
259
|
+
stopped = true;
|
|
260
|
+
else if (argument.startsWith("--")) {
|
|
261
|
+
const equals = argument.indexOf("=");
|
|
262
|
+
const name = argument.slice(2, equals < 0 ? undefined : equals);
|
|
263
|
+
const matches = Object.keys(long).filter(candidate => candidate.startsWith(name));
|
|
264
|
+
const selected = Object.hasOwn(long, name) ? name : matches.length === 1 ? matches[0] : undefined;
|
|
265
|
+
if (!selected)
|
|
266
|
+
throw new ShufDiagnostic(matches.length > 1 ? `option '${argument}' is ambiguous; possibilities: ${matches.map(candidate => `'--${candidate}'`).join(" ")}` : `unrecognized option '${argument}'`, true);
|
|
267
|
+
const key = long[selected];
|
|
268
|
+
const required = ["i", "n", "o", "random"].includes(key);
|
|
269
|
+
if (!required && equals >= 0)
|
|
270
|
+
throw new ShufDiagnostic(`option '--${selected}' doesn't allow an argument`, true);
|
|
271
|
+
const value = required ? equals < 0 ? args[++index] : argument.slice(equals + 1) : "";
|
|
272
|
+
if (value === undefined)
|
|
273
|
+
throw new ShufDiagnostic(`option '--${selected}' requires an argument`, true);
|
|
274
|
+
apply(key, value);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
for (let position = 1; position < argument.length; position++) {
|
|
278
|
+
const key = argument[position];
|
|
279
|
+
if (!"einorz".includes(key))
|
|
280
|
+
throw new ShufDiagnostic(`invalid option -- '${key}'`, true);
|
|
281
|
+
let value = "";
|
|
282
|
+
if ("ino".includes(key)) {
|
|
283
|
+
const supplied = argument.slice(position + 1) || args[++index];
|
|
284
|
+
if (supplied === undefined)
|
|
285
|
+
throw new ShufDiagnostic(`option requires an argument -- '${key}'`, true);
|
|
286
|
+
value = supplied;
|
|
287
|
+
position = argument.length;
|
|
288
|
+
}
|
|
289
|
+
apply(key, value);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (settings.information)
|
|
293
|
+
return settings;
|
|
294
|
+
}
|
|
295
|
+
if (settings.echo && settings.range)
|
|
296
|
+
throw new ShufDiagnostic("cannot combine -e and -i options", true);
|
|
297
|
+
const maximum = settings.range ? 0 : settings.echo ? Infinity : 1;
|
|
298
|
+
if (settings.operands.length > maximum)
|
|
299
|
+
throw new ShufDiagnostic(`extra operand ${quote(settings.operands[maximum], false, unicode)}`, true);
|
|
300
|
+
return settings;
|
|
301
|
+
}
|
|
302
|
+
function filePath(context, name) {
|
|
303
|
+
let decoded;
|
|
304
|
+
try {
|
|
305
|
+
decoded = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(Uint8Array.from(name, character => character.charCodeAt(0)));
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
throw new FsError("ENOENT");
|
|
309
|
+
}
|
|
310
|
+
return pathOf(context, decoded);
|
|
311
|
+
}
|
|
312
|
+
function ioError(error, label) {
|
|
313
|
+
if (!(error instanceof FsError))
|
|
314
|
+
return error;
|
|
315
|
+
const descriptions = { ENOENT: "No such file or directory", EACCES: "Permission denied", EPERM: "Operation not permitted", EISDIR: "Is a directory", ENOTDIR: "Not a directory", EBADF: "Bad file descriptor", EIO: "Input/output error", ENOSPC: "No space left on device", EPIPE: "Broken pipe", ELOOP: "Too many levels of symbolic links", ENAMETOOLONG: "File name too long", ENOTSUP: "Operation not supported" };
|
|
316
|
+
return descriptions[error.code] ? new ShufDiagnostic(`${label}: ${descriptions[error.code]}`) : error;
|
|
317
|
+
}
|
|
318
|
+
class Input {
|
|
319
|
+
context;
|
|
320
|
+
budget;
|
|
321
|
+
label;
|
|
322
|
+
stat;
|
|
323
|
+
position = 0;
|
|
324
|
+
seekable = false;
|
|
325
|
+
iterator;
|
|
326
|
+
reader;
|
|
327
|
+
handle;
|
|
328
|
+
pending;
|
|
329
|
+
rawRead;
|
|
330
|
+
closing;
|
|
331
|
+
ended = false;
|
|
332
|
+
retired;
|
|
333
|
+
controller = new AbortController();
|
|
334
|
+
signal;
|
|
335
|
+
empty = 0;
|
|
336
|
+
chunks = 0;
|
|
337
|
+
constructor(context, operation, budget, label) {
|
|
338
|
+
this.context = context;
|
|
339
|
+
this.budget = budget;
|
|
340
|
+
this.label = label;
|
|
341
|
+
this.signal = AbortSignal.any([operation.signal, this.controller.signal]);
|
|
342
|
+
operation.registerCleanup(() => this.close());
|
|
343
|
+
}
|
|
344
|
+
async open(name) {
|
|
345
|
+
const { context, signal } = this;
|
|
346
|
+
signal.throwIfAborted();
|
|
347
|
+
let file;
|
|
348
|
+
if (name !== undefined) {
|
|
349
|
+
try {
|
|
350
|
+
const path = filePath(context, name);
|
|
351
|
+
const capabilities = await context.fs.capabilitiesFor?.(path, { signal }) ?? context.fs.capabilities;
|
|
352
|
+
signal.throwIfAborted();
|
|
353
|
+
assertCommandRequirements(context, textOutputRequirements, ["file"], capabilities);
|
|
354
|
+
const retained = Boolean(context.fs.openReadFile && capabilities.retainedRead !== false);
|
|
355
|
+
if (!retained) {
|
|
356
|
+
this.stat = capabilities.stat !== false ? await context.fs.stat(path, { signal }) : undefined;
|
|
357
|
+
signal.throwIfAborted();
|
|
358
|
+
}
|
|
359
|
+
file = { path, capabilities, retained };
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
signal.throwIfAborted();
|
|
363
|
+
throw ioError(error, quote(name, true, unicodeLocale(context)));
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const pending = Promise.resolve().then(async () => {
|
|
367
|
+
signal.throwIfAborted();
|
|
368
|
+
let source;
|
|
369
|
+
if (name === undefined) {
|
|
370
|
+
this.stat = context.stdinInput?.stat;
|
|
371
|
+
this.position = context.stdinInput?.position ?? 0;
|
|
372
|
+
this.seekable = typeof context.stdinInput?.seek === "function";
|
|
373
|
+
source = context.stdinInput ? { [Symbol.asyncIterator]: () => ({ next: () => context.stdinInput.read(65536, signal) }) } : context.stdin;
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
try {
|
|
377
|
+
const { path, capabilities, retained } = file;
|
|
378
|
+
if (retained) {
|
|
379
|
+
this.handle = await context.fs.openReadFile(path, { signal });
|
|
380
|
+
signal.throwIfAborted();
|
|
381
|
+
}
|
|
382
|
+
if (this.handle) {
|
|
383
|
+
this.stat = await this.handle.stat({ signal });
|
|
384
|
+
signal.throwIfAborted();
|
|
385
|
+
this.seekable = this.stat.type === "file";
|
|
386
|
+
source = { [Symbol.asyncIterator]: () => ({ next: async () => {
|
|
387
|
+
const bytes = await this.handle.read(this.position, 65536, { signal });
|
|
388
|
+
return bytes.length ? { done: false, value: bytes } : { done: true, value: undefined };
|
|
389
|
+
} }) };
|
|
390
|
+
}
|
|
391
|
+
else if (context.fs.readStream && capabilities.streamingRead !== false) {
|
|
392
|
+
source = context.fs.readStream(path, { signal, chunkSize: 65536 });
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
if (capabilities.read === false)
|
|
396
|
+
throw new FsError("ENOTSUP");
|
|
397
|
+
source = { async *[Symbol.asyncIterator]() { yield await context.fs.readFile(path, { signal, maxBytes: bufferLimit }); } };
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
signal.throwIfAborted();
|
|
402
|
+
throw ioError(error, quote(name, true, unicodeLocale(context)));
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
signal.throwIfAborted();
|
|
406
|
+
this.iterator = source[Symbol.asyncIterator]();
|
|
407
|
+
this.reader = this.budget.read({ [Symbol.asyncIterator]: () => ({
|
|
408
|
+
next: async () => {
|
|
409
|
+
this.rawRead = Promise.resolve().then(() => this.iterator.next());
|
|
410
|
+
const item = await this.rawRead;
|
|
411
|
+
this.ended = Boolean(item.done);
|
|
412
|
+
return item;
|
|
413
|
+
},
|
|
414
|
+
return: async () => { await this.retire(); return { done: true, value: undefined }; },
|
|
415
|
+
}) }, signal)[Symbol.asyncIterator]();
|
|
416
|
+
});
|
|
417
|
+
this.pending = pending;
|
|
418
|
+
return pending;
|
|
419
|
+
}
|
|
420
|
+
next() {
|
|
421
|
+
const pending = (async () => {
|
|
422
|
+
this.signal.throwIfAborted();
|
|
423
|
+
while (true) {
|
|
424
|
+
let item;
|
|
425
|
+
try {
|
|
426
|
+
item = await this.reader.next();
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
this.signal.throwIfAborted();
|
|
430
|
+
if (error instanceof FsError && error.code === "EFBIG")
|
|
431
|
+
throw new PublicDiagnostic("byte command input limit exceeded");
|
|
432
|
+
throw ioError(error, this.label);
|
|
433
|
+
}
|
|
434
|
+
this.signal.throwIfAborted();
|
|
435
|
+
if (item.done)
|
|
436
|
+
return null;
|
|
437
|
+
const owned = new Uint8Array(item.value);
|
|
438
|
+
this.position += owned.length;
|
|
439
|
+
if (++this.chunks % 256 === 0)
|
|
440
|
+
await yieldTurn(this.signal);
|
|
441
|
+
if (owned.length) {
|
|
442
|
+
this.empty = 0;
|
|
443
|
+
return owned;
|
|
444
|
+
}
|
|
445
|
+
if (++this.empty > 4096)
|
|
446
|
+
throw new PublicDiagnostic("empty input chunk limit exceeded");
|
|
447
|
+
}
|
|
448
|
+
})();
|
|
449
|
+
this.pending = pending;
|
|
450
|
+
return pending;
|
|
451
|
+
}
|
|
452
|
+
retire() {
|
|
453
|
+
this.retired ??= Promise.resolve().then(async () => { if (!this.ended)
|
|
454
|
+
await this.iterator?.return?.(); });
|
|
455
|
+
return this.retired;
|
|
456
|
+
}
|
|
457
|
+
close() {
|
|
458
|
+
this.closing ??= Promise.resolve().then(async () => {
|
|
459
|
+
await this.pending?.catch(() => undefined);
|
|
460
|
+
const results = await Promise.allSettled([this.retire(), this.reader?.return?.()]);
|
|
461
|
+
await this.rawRead?.catch(() => undefined);
|
|
462
|
+
try {
|
|
463
|
+
for (const result of results)
|
|
464
|
+
if (result.status === "rejected")
|
|
465
|
+
throw result.reason;
|
|
466
|
+
}
|
|
467
|
+
finally {
|
|
468
|
+
await this.handle?.close();
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
this.controller.abort(new Error("shuf input closed"));
|
|
472
|
+
return this.closing;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
class Random {
|
|
476
|
+
input;
|
|
477
|
+
name;
|
|
478
|
+
signal;
|
|
479
|
+
unicode;
|
|
480
|
+
number = 0;
|
|
481
|
+
maximum = 0;
|
|
482
|
+
bytes = new Uint8Array();
|
|
483
|
+
offset = 0;
|
|
484
|
+
consumed = 0;
|
|
485
|
+
state;
|
|
486
|
+
constructor(input, name, signal, unicode, needsRandom) {
|
|
487
|
+
this.input = input;
|
|
488
|
+
this.name = name;
|
|
489
|
+
this.signal = signal;
|
|
490
|
+
this.unicode = unicode;
|
|
491
|
+
if (!input && needsRandom) {
|
|
492
|
+
this.state = crypto.getRandomValues(new Uint32Array(4));
|
|
493
|
+
if (this.state.every(value => value === 0))
|
|
494
|
+
this.state[0] = 1;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
async byte() {
|
|
498
|
+
this.signal.throwIfAborted();
|
|
499
|
+
if (++this.consumed > 4 * 1024 * 1024)
|
|
500
|
+
throw new PublicDiagnostic("random byte limit exceeded");
|
|
501
|
+
if (this.offset === this.bytes.length) {
|
|
502
|
+
if (this.input) {
|
|
503
|
+
const bytes = await this.input.next();
|
|
504
|
+
if (!bytes)
|
|
505
|
+
throw new ShufDiagnostic(`${quote(this.name, false, this.unicode)}: end of file`);
|
|
506
|
+
this.bytes = bytes;
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
const state = this.state;
|
|
510
|
+
const product = Math.imul(state[1], 5);
|
|
511
|
+
const result = Math.imul((product << 7) | (product >>> 25), 9) >>> 0;
|
|
512
|
+
const shifted = state[1] << 9;
|
|
513
|
+
state[2] = state[2] ^ state[0];
|
|
514
|
+
state[3] = state[3] ^ state[1];
|
|
515
|
+
state[1] = state[1] ^ state[2];
|
|
516
|
+
state[0] = state[0] ^ state[3];
|
|
517
|
+
state[2] = state[2] ^ shifted;
|
|
518
|
+
state[3] = (state[3] << 11) | (state[3] >>> 21);
|
|
519
|
+
this.bytes = Uint8Array.of(result & 255, (result >>> 8) & 255, (result >>> 16) & 255, result >>> 24);
|
|
520
|
+
}
|
|
521
|
+
this.offset = 0;
|
|
522
|
+
}
|
|
523
|
+
return this.bytes[this.offset++];
|
|
524
|
+
}
|
|
525
|
+
async choose(choices) {
|
|
526
|
+
const target = choices - 1;
|
|
527
|
+
for (let attempt = 0; attempt < 4096; attempt++) {
|
|
528
|
+
if (attempt % 256 === 255)
|
|
529
|
+
await yieldTurn(this.signal);
|
|
530
|
+
while (this.maximum < target) {
|
|
531
|
+
this.number = this.number * 256 + await this.byte();
|
|
532
|
+
this.maximum = this.maximum * 256 + 255;
|
|
533
|
+
}
|
|
534
|
+
if (this.maximum === target) {
|
|
535
|
+
const result = this.number;
|
|
536
|
+
this.number = this.maximum = 0;
|
|
537
|
+
return result;
|
|
538
|
+
}
|
|
539
|
+
const excess = this.maximum - target;
|
|
540
|
+
const unusable = excess % choices;
|
|
541
|
+
const reduced = this.number % choices;
|
|
542
|
+
if (this.number <= this.maximum - unusable) {
|
|
543
|
+
this.number = Math.floor(this.number / choices);
|
|
544
|
+
this.maximum = Math.floor(excess / choices);
|
|
545
|
+
return reduced;
|
|
546
|
+
}
|
|
547
|
+
this.number = reduced;
|
|
548
|
+
this.maximum = unusable - 1;
|
|
549
|
+
}
|
|
550
|
+
throw new PublicDiagnostic("random selection work limit exceeded");
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
async function* records(input, separator) {
|
|
554
|
+
const pending = new RecordBuffer(bufferLimit);
|
|
555
|
+
let recordCount = 0;
|
|
556
|
+
try {
|
|
557
|
+
while (true) {
|
|
558
|
+
const bytes = await input.next();
|
|
559
|
+
if (!bytes)
|
|
560
|
+
break;
|
|
561
|
+
let start = 0;
|
|
562
|
+
for (let offset = 0; offset < bytes.length; offset++) {
|
|
563
|
+
if (offset % 65536 === 65535)
|
|
564
|
+
await yieldTurn(input.signal);
|
|
565
|
+
if (bytes[offset] !== separator)
|
|
566
|
+
continue;
|
|
567
|
+
if (++recordCount > maximumLines)
|
|
568
|
+
throw new PublicDiagnostic("input line limit exceeded");
|
|
569
|
+
yield pending.finish(undefined, bytes, start, offset + 1);
|
|
570
|
+
start = offset + 1;
|
|
571
|
+
}
|
|
572
|
+
pending.append(bytes, start);
|
|
573
|
+
}
|
|
574
|
+
if (pending.size) {
|
|
575
|
+
if (++recordCount > maximumLines)
|
|
576
|
+
throw new PublicDiagnostic("input line limit exceeded");
|
|
577
|
+
yield pending.finish(undefined, Uint8Array.of(separator));
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
finally {
|
|
581
|
+
pending.clear();
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
async function permutation(random, count, length, signal) {
|
|
585
|
+
if (count === 0)
|
|
586
|
+
return new Uint32Array();
|
|
587
|
+
const sparse = count > 1 && length >= 128 * 1024 && Math.floor(length / count) >= 32;
|
|
588
|
+
const indices = new Uint32Array(length);
|
|
589
|
+
for (let index = 0; index < length; index++) {
|
|
590
|
+
indices[index] = index;
|
|
591
|
+
if (index % 65536 === 65535)
|
|
592
|
+
await yieldTurn(signal);
|
|
593
|
+
}
|
|
594
|
+
for (let index = 0; index < count; index++) {
|
|
595
|
+
const selected = index + await random.choose(length - index);
|
|
596
|
+
if (sparse && index === selected)
|
|
597
|
+
indices[index] = index;
|
|
598
|
+
else {
|
|
599
|
+
const previous = indices[index];
|
|
600
|
+
indices[index] = indices[selected];
|
|
601
|
+
indices[selected] = previous;
|
|
602
|
+
}
|
|
603
|
+
if (index % 1024 === 1023)
|
|
604
|
+
await yieldTurn(signal);
|
|
605
|
+
}
|
|
606
|
+
return indices.subarray(0, count);
|
|
607
|
+
}
|
|
608
|
+
export function shufCommand() {
|
|
609
|
+
return { name: "shuf", filesystemRequirements: textOutputRequirements, async execute(context) {
|
|
610
|
+
context.signal.throwIfAborted();
|
|
611
|
+
const root = createOutputOperation(context, { async write() { } });
|
|
612
|
+
let operation = root;
|
|
613
|
+
let failure = false;
|
|
614
|
+
const run = async () => {
|
|
615
|
+
try {
|
|
616
|
+
const unicode = unicodeLocale(context);
|
|
617
|
+
const settings = parse(context);
|
|
618
|
+
operation = settings.output === undefined || settings.information ? root.child(context.stdout) : root;
|
|
619
|
+
const signal = operation.signal;
|
|
620
|
+
if (settings.information) {
|
|
621
|
+
await writeBytes(operation.output, new TextEncoder().encode(settings.information === "version" ? "shuf (virtual-bash)\n" : "Usage: shuf [OPTION]... [FILE]\n or: shuf -e [OPTION]... [ARG]...\n or: shuf -i LO-HI [OPTION]...\n -e, --echo shuffle arguments\n -i, --input-range=LO-HI shuffle an inclusive range\n -n, --head-count=COUNT output at most COUNT records\n -o, --output=FILE write to a VFS file\n --random-source=FILE read random bytes from a VFS file\n -r, --repeat sample with replacement (requires -n)\n -z, --zero-terminated delimit records with NUL\n --help display help\n --version display virtual command identity\n"), signal);
|
|
622
|
+
return { exitCode: 0 };
|
|
623
|
+
}
|
|
624
|
+
if (settings.repeat && settings.count === unsignedMaximum)
|
|
625
|
+
throw new PublicDiagnostic("repeat requires a bounded head count (-n)");
|
|
626
|
+
if (settings.count !== 0n && settings.range && settings.range.length > BigInt(maximumLines))
|
|
627
|
+
throw new PublicDiagnostic("input range limit exceeded");
|
|
628
|
+
if (settings.repeat && settings.count > BigInt(maximumLines))
|
|
629
|
+
throw new PublicDiagnostic("output line limit exceeded");
|
|
630
|
+
const budget = new ByteInputBudget(bufferLimit);
|
|
631
|
+
let input;
|
|
632
|
+
let reservoir = false;
|
|
633
|
+
let lines = [];
|
|
634
|
+
if (settings.echo)
|
|
635
|
+
lines = settings.operands.map(text => Uint8Array.from(text + String.fromCharCode(settings.separator), character => character.charCodeAt(0)));
|
|
636
|
+
else if (!settings.range) {
|
|
637
|
+
input = new Input(context, operation, budget, "read error");
|
|
638
|
+
const name = settings.operands[0];
|
|
639
|
+
await input.open(settings.count === 0n || name === "-" ? undefined : name);
|
|
640
|
+
reservoir = !settings.repeat && settings.count !== unsignedMaximum && (settings.count === 0n || !input.seekable || input.stat.size - input.position > reservoirThreshold);
|
|
641
|
+
if (!reservoir)
|
|
642
|
+
for await (const line of records(input, settings.separator))
|
|
643
|
+
lines.push(line);
|
|
644
|
+
}
|
|
645
|
+
let length = settings.range ? Number(settings.range.length) : lines.length;
|
|
646
|
+
let count = Number(settings.count > BigInt(maximumLines) ? BigInt(maximumLines) : settings.count);
|
|
647
|
+
if (!settings.repeat && !reservoir)
|
|
648
|
+
count = Math.min(count, length);
|
|
649
|
+
const needsRandom = reservoir || settings.repeat || count > 0 && length > 1;
|
|
650
|
+
let randomInput;
|
|
651
|
+
if (settings.random !== undefined && needsRandom) {
|
|
652
|
+
randomInput = new Input(context, operation, new ByteInputBudget(bufferLimit), `${quote(settings.random, false, unicode)}: read error`);
|
|
653
|
+
await randomInput.open(settings.random);
|
|
654
|
+
}
|
|
655
|
+
const random = new Random(randomInput, settings.random, signal, unicode, needsRandom);
|
|
656
|
+
if (reservoir && count > 0) {
|
|
657
|
+
const iterator = records(input, settings.separator);
|
|
658
|
+
try {
|
|
659
|
+
while (lines.length < count) {
|
|
660
|
+
const item = await iterator.next();
|
|
661
|
+
if (item.done)
|
|
662
|
+
break;
|
|
663
|
+
lines.push(item.value);
|
|
664
|
+
}
|
|
665
|
+
if (lines.length === count) {
|
|
666
|
+
let seen = count;
|
|
667
|
+
while (true) {
|
|
668
|
+
const selected = await random.choose(seen + 1);
|
|
669
|
+
const item = await iterator.next();
|
|
670
|
+
if (item.done)
|
|
671
|
+
break;
|
|
672
|
+
if (selected < count)
|
|
673
|
+
lines[selected] = item.value;
|
|
674
|
+
if (++seen % 1024 === 0)
|
|
675
|
+
await yieldTurn(signal);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
finally {
|
|
680
|
+
await iterator.return(undefined);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
if (reservoir) {
|
|
684
|
+
length = lines.length;
|
|
685
|
+
count = length;
|
|
686
|
+
}
|
|
687
|
+
await input?.close();
|
|
688
|
+
const indices = settings.repeat ? undefined : await permutation(random, count, length, signal);
|
|
689
|
+
let outputBytes = 0;
|
|
690
|
+
const generated = { async *[Symbol.asyncIterator]() {
|
|
691
|
+
if (settings.repeat && count > 0 && length === 0)
|
|
692
|
+
throw new ShufDiagnostic("no lines to repeat");
|
|
693
|
+
for (let index = 0; index < count; index++) {
|
|
694
|
+
signal.throwIfAborted();
|
|
695
|
+
const selected = settings.repeat ? await random.choose(length) : indices[index];
|
|
696
|
+
const line = settings.range ? new TextEncoder().encode(String(settings.range.low + BigInt(selected)) + String.fromCharCode(settings.separator)) : lines[selected];
|
|
697
|
+
outputBytes += line.length;
|
|
698
|
+
if (outputBytes > bufferLimit)
|
|
699
|
+
throw new PublicDiagnostic("output byte limit exceeded");
|
|
700
|
+
yield line;
|
|
701
|
+
if (index % 1024 === 1023)
|
|
702
|
+
await yieldTurn(signal);
|
|
703
|
+
}
|
|
704
|
+
} };
|
|
705
|
+
if (settings.output === undefined) {
|
|
706
|
+
for await (const bytes of generated)
|
|
707
|
+
await writeBytes(operation.output, bytes, signal);
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
const name = settings.output;
|
|
711
|
+
try {
|
|
712
|
+
const path = filePath(context, name);
|
|
713
|
+
const capabilities = await context.fs.capabilitiesFor?.(path, { signal }) ?? context.fs.capabilities;
|
|
714
|
+
signal.throwIfAborted();
|
|
715
|
+
assertCommandRequirements(context, textOutputRequirements, ["output"], capabilities);
|
|
716
|
+
await operation.acquire(async (signal) => {
|
|
717
|
+
if (context.fs.writeStream && capabilities.streamingWrite !== false)
|
|
718
|
+
await context.fs.writeStream(path, generated, { signal });
|
|
719
|
+
else {
|
|
720
|
+
await context.fs.writeFile(path, new Uint8Array(), { signal });
|
|
721
|
+
const parts = [];
|
|
722
|
+
for await (const bytes of generated)
|
|
723
|
+
parts.push(bytes);
|
|
724
|
+
const bytes = new Uint8Array(outputBytes);
|
|
725
|
+
let offset = 0;
|
|
726
|
+
for (const part of parts) {
|
|
727
|
+
bytes.set(part, offset);
|
|
728
|
+
offset += part.length;
|
|
729
|
+
}
|
|
730
|
+
await context.fs.writeFile(path, bytes, { signal });
|
|
731
|
+
}
|
|
732
|
+
}, () => { });
|
|
733
|
+
}
|
|
734
|
+
catch (error) {
|
|
735
|
+
signal.throwIfAborted();
|
|
736
|
+
throw ioError(error, quote(name, true, unicode));
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return { exitCode: 0 };
|
|
740
|
+
}
|
|
741
|
+
catch (error) {
|
|
742
|
+
failure = true;
|
|
743
|
+
context.signal.throwIfAborted();
|
|
744
|
+
if (operation.signal.aborted)
|
|
745
|
+
throw operation.signal.reason;
|
|
746
|
+
if (error instanceof ShufDiagnostic)
|
|
747
|
+
await writeBytes(context.stderr, Uint8Array.from(`shuf: ${error.detail}\n${error.usage ? "Try 'shuf --help' for more information.\n" : ""}`, character => character.charCodeAt(0)), context.signal);
|
|
748
|
+
else
|
|
749
|
+
await diagnostic(context, error);
|
|
750
|
+
return { exitCode: 1 };
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
const outcome = await run().then(result => ({ ok: true, result }), error => ({ ok: false, error }));
|
|
754
|
+
try {
|
|
755
|
+
await root.close();
|
|
756
|
+
}
|
|
757
|
+
catch (error) {
|
|
758
|
+
if (!failure) {
|
|
759
|
+
context.signal.throwIfAborted();
|
|
760
|
+
throw error;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
if (!outcome.ok)
|
|
764
|
+
throw outcome.error;
|
|
765
|
+
return outcome.result;
|
|
766
|
+
} };
|
|
767
|
+
}
|
|
768
|
+
//# sourceMappingURL=shuf.js.map
|