@grain/stdlib 0.4.2 → 0.4.6

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/LICENSE +1 -1
  3. package/array.gr +200 -89
  4. package/array.md +81 -5
  5. package/buffer.gr +93 -36
  6. package/bytes.gr +10 -10
  7. package/char.gr +112 -56
  8. package/char.md +200 -0
  9. package/float32.gr +120 -4
  10. package/float32.md +315 -0
  11. package/float64.gr +120 -4
  12. package/float64.md +315 -0
  13. package/hash.gr +42 -15
  14. package/hash.md +44 -0
  15. package/int32.gr +370 -75
  16. package/int32.md +833 -0
  17. package/int64.gr +370 -75
  18. package/int64.md +833 -0
  19. package/list.gr +121 -50
  20. package/map.gr +106 -110
  21. package/number.gr +37 -1
  22. package/number.md +66 -0
  23. package/option.gr +260 -53
  24. package/option.md +579 -0
  25. package/package.json +1 -1
  26. package/pervasives.gr +32 -20
  27. package/queue.gr +102 -30
  28. package/queue.md +191 -0
  29. package/range.gr +26 -26
  30. package/range.md +1 -1
  31. package/regex.md +9 -9
  32. package/result.gr +216 -70
  33. package/result.md +446 -0
  34. package/runtime/dataStructures.gr +28 -29
  35. package/runtime/debug.gr +0 -1
  36. package/runtime/equal.gr +37 -16
  37. package/runtime/exception.gr +28 -15
  38. package/runtime/gc.gr +33 -20
  39. package/runtime/malloc.gr +19 -11
  40. package/runtime/numberUtils.gr +208 -103
  41. package/runtime/numbers.gr +217 -118
  42. package/runtime/string.gr +98 -39
  43. package/runtime/stringUtils.gr +176 -0
  44. package/runtime/unsafe/conv.gr +10 -10
  45. package/runtime/unsafe/memory.gr +14 -3
  46. package/runtime/unsafe/printWasm.gr +4 -4
  47. package/runtime/unsafe/tags.gr +2 -2
  48. package/runtime/unsafe/wasmf32.gr +9 -2
  49. package/runtime/unsafe/wasmf64.gr +9 -2
  50. package/runtime/unsafe/wasmi32.gr +65 -47
  51. package/runtime/unsafe/wasmi64.gr +78 -50
  52. package/runtime/wasi.gr +199 -45
  53. package/set.gr +281 -119
  54. package/set.md +502 -0
  55. package/stack.gr +26 -26
  56. package/string.gr +657 -341
  57. package/string.md +815 -0
  58. package/sys/file.gr +356 -177
  59. package/sys/process.gr +10 -6
  60. package/sys/random.gr +3 -6
  61. package/sys/time.gr +3 -3
package/string.gr CHANGED
@@ -1,24 +1,71 @@
1
+ /**
2
+ * @module String: Utilities for working with strings.
3
+ * @example import String from "string"
4
+ *
5
+ * @since v0.2.0
6
+ * @history v0.1.0: Originally named `strings`
7
+ * @history v0.2.0: Renamed to `string`
8
+ */
1
9
  import WasmI32 from "runtime/unsafe/wasmi32"
2
10
  import Memory from "runtime/unsafe/memory"
3
11
  import Exception from "runtime/exception"
4
- import { tagSimpleNumber, allocateArray, allocateChar, allocateString, allocateBytes } from "runtime/dataStructures"
12
+ import {
13
+ tagSimpleNumber,
14
+ allocateArray,
15
+ allocateChar,
16
+ allocateString,
17
+ allocateBytes,
18
+ } from "runtime/dataStructures"
19
+
20
+ /**
21
+ * @section Types: Type declarations included in the String module.
22
+ */
23
+
24
+ /**
25
+ * Byte encodings
26
+ */
27
+ export enum Encoding {
28
+ UTF8,
29
+ UTF16_BE,
30
+ UTF16_LE,
31
+ UTF32_BE,
32
+ UTF32_LE,
33
+ }
5
34
 
6
- // Concatenate two strings.
7
- // @param str1: String - The first string
8
- // @param str2: String - The second string
9
- // @returns String
35
+ /**
36
+ * @section Values: Functions for working with the String data type.
37
+ */
38
+
39
+ /**
40
+ * Concatenate two strings.
41
+ *
42
+ * @param str1: The beginning string
43
+ * @param str2: The ending string
44
+ * @returns The combined string
45
+ *
46
+ * @example String.concat("Foo", " Bar") == "FooBar"
47
+ *
48
+ * @since v0.1.0
49
+ */
10
50
  export let concat = (++)
11
51
 
12
- // Get the character length of a string.
13
- // @param input: String - The string to check
14
- // @returns Number
52
+ /**
53
+ * Returns the character length of the input string.
54
+ *
55
+ * @param string: The string to inspect
56
+ * @returns The number of characters in the string
57
+ *
58
+ * @example String.length("Hello world") == 11
59
+ *
60
+ * @since v0.1.0
61
+ */
15
62
  @disableGC
16
- export let rec length = (s: String) => {
17
- let s = WasmI32.fromGrain(s)
18
- let size = WasmI32.load(s, 4n)
63
+ export let rec length = (string: String) => {
64
+ let string = WasmI32.fromGrain(string)
65
+ let size = WasmI32.load(string, 4n)
19
66
 
20
67
  let mut len = 0n
21
- let mut ptr = WasmI32.add(s, 8n)
68
+ let mut ptr = WasmI32.add(string, 8n)
22
69
  let end = WasmI32.add(ptr, size)
23
70
 
24
71
  while (WasmI32.ltU(ptr, end)) {
@@ -31,7 +78,7 @@ export let rec length = (s: String) => {
31
78
 
32
79
  let ret = tagSimpleNumber(len)
33
80
  Memory.decRef(WasmI32.fromGrain(length))
34
- Memory.decRef(WasmI32.fromGrain(s))
81
+ Memory.decRef(WasmI32.fromGrain(string))
35
82
  ret
36
83
  }
37
84
 
@@ -43,38 +90,51 @@ let wasmSafeLength = (s: String) => {
43
90
  length(s)
44
91
  }
45
92
 
46
- // Get the byte length of a string.
47
- // @param input: String - The string to check
48
- // @returns Number
93
+ /**
94
+ * Returns the byte length of the input string.
95
+ *
96
+ * @param string: The string to inspect
97
+ * @returns The number of bytes in the string
98
+ *
99
+ * @example String.byteLength("🌾") == 4
100
+ *
101
+ * @since v0.1.0
102
+ */
49
103
  @disableGC
50
- export let rec byteLength = (s: String) => {
51
- let s = WasmI32.fromGrain(s)
52
- let ret = tagSimpleNumber(WasmI32.load(s, 4n))
104
+ export let rec byteLength = (string: String) => {
105
+ let string = WasmI32.fromGrain(string)
106
+ let ret = tagSimpleNumber(WasmI32.load(string, 4n))
53
107
  Memory.decRef(WasmI32.fromGrain(byteLength))
54
- Memory.decRef(WasmI32.fromGrain(s))
108
+ Memory.decRef(WasmI32.fromGrain(string))
55
109
  ret
56
110
  }
57
111
 
58
-
59
112
  // @disableGC-safe wrapper
60
113
  @disableGC
61
- let wasmSafeByteLength = (s: String) => {
114
+ let wasmSafeByteLength = (string: String) => {
62
115
  Memory.incRef(WasmI32.fromGrain(byteLength))
63
- Memory.incRef(WasmI32.fromGrain(s))
64
- byteLength(s)
116
+ Memory.incRef(WasmI32.fromGrain(string))
117
+ byteLength(string)
65
118
  }
66
119
 
67
- // Find the start index of a substring.
68
- // @param sub: String - The substring to find
69
- // @param input: String - The string to check
70
- // @returns Option<Number>
120
+ /**
121
+ * Finds the position of a substring in the input string.
122
+ *
123
+ * @param search: The substring to find
124
+ * @param string: The string to inspect
125
+ * @returns `Some(position)` containing the starting position of the substring if found or `None` otherwise
126
+ *
127
+ * @example String.indexOf("world", "Hello world") == Some(6)
128
+ *
129
+ * @since v0.3.0
130
+ */
71
131
  @disableGC
72
- export let rec indexOf = (p: String, s: String) => {
73
- let p = WasmI32.fromGrain(p)
74
- let s = WasmI32.fromGrain(s)
132
+ export let rec indexOf = (search: String, string: String) => {
133
+ let search = WasmI32.fromGrain(search)
134
+ let string = WasmI32.fromGrain(string)
75
135
 
76
- let size = WasmI32.load(s, 4n)
77
- let psize = WasmI32.load(p, 4n)
136
+ let size = WasmI32.load(string, 4n)
137
+ let psize = WasmI32.load(search, 4n)
78
138
 
79
139
  let (>) = WasmI32.gtU
80
140
  let (<) = WasmI32.ltU
@@ -89,8 +149,8 @@ export let rec indexOf = (p: String, s: String) => {
89
149
  none
90
150
  } else {
91
151
  let mut idx = 0n
92
- let mut ptr = s + 8n
93
- let mut pptr = p + 8n
152
+ let mut ptr = string + 8n
153
+ let mut pptr = search + 8n
94
154
  let end = ptr + size - psize + 1n
95
155
 
96
156
  let mut result = -1n
@@ -122,19 +182,36 @@ export let rec indexOf = (p: String, s: String) => {
122
182
  Some(tagSimpleNumber(result))
123
183
  }
124
184
  }
125
- Memory.decRef(WasmI32.fromGrain(p))
126
- Memory.decRef(WasmI32.fromGrain(s))
185
+ Memory.decRef(WasmI32.fromGrain(search))
186
+ Memory.decRef(WasmI32.fromGrain(string))
127
187
  Memory.decRef(WasmI32.fromGrain(indexOf))
128
188
  ret
129
189
  }
130
190
 
191
+ /**
192
+ * Get the character at the position in the input string.
193
+ *
194
+ * @param position: The position to check
195
+ * @param string: The string to search
196
+ * @returns The character at the provided position
197
+ *
198
+ * @example String.charAt(5, "Hello world") == ' '
199
+ *
200
+ * @since v0.4.0
201
+ */
131
202
  @disableGC
132
- export let rec charAt = (idx, s: String) => {
203
+ export let rec charAt = (position, string: String) => {
133
204
  Memory.incRef(WasmI32.fromGrain((<=)))
134
- if (wasmSafeLength(s) <= idx || {Memory.incRef(WasmI32.fromGrain((<))); idx < 0}) {
205
+ if (
206
+ wasmSafeLength(string) <= position ||
207
+ {
208
+ Memory.incRef(WasmI32.fromGrain((<)))
209
+ position < 0
210
+ }
211
+ ) {
135
212
  Memory.incRef(WasmI32.fromGrain((++)))
136
213
  Memory.incRef(WasmI32.fromGrain(toString))
137
- fail ("Invalid offset: " ++ toString(idx))
214
+ fail "Invalid offset: " ++ toString(position)
138
215
  }
139
216
  // Implementation is similar to explodeHelp, but doesn't perform unneeded memory allocations
140
217
  let (>>>) = WasmI32.shrU
@@ -142,13 +219,13 @@ export let rec charAt = (idx, s: String) => {
142
219
  let (&) = WasmI32.and
143
220
  let (<) = WasmI32.ltU
144
221
  let (==) = WasmI32.eq
145
- let size = WasmI32.fromGrain(wasmSafeByteLength(s)) >>> 1n
146
- let len = WasmI32.fromGrain(wasmSafeLength(s)) >>> 1n
147
- let idx = WasmI32.fromGrain(idx) >>> 1n
148
- let s = WasmI32.fromGrain(s)
149
- let mut ptr = s + 8n;
150
- let end = ptr + size;
151
- let mut counter = 0n;
222
+ let size = WasmI32.fromGrain(wasmSafeByteLength(string)) >>> 1n
223
+ let len = WasmI32.fromGrain(wasmSafeLength(string)) >>> 1n
224
+ let position = WasmI32.fromGrain(position) >>> 1n
225
+ let string = WasmI32.fromGrain(string)
226
+ let mut ptr = string + 8n
227
+ let end = ptr + size
228
+ let mut counter = 0n
152
229
  let mut result = 0n
153
230
  while (ptr < end) {
154
231
  let byte = WasmI32.load8U(ptr, 0n)
@@ -161,7 +238,7 @@ export let rec charAt = (idx, s: String) => {
161
238
  } else {
162
239
  2n
163
240
  }
164
- if (counter == idx) {
241
+ if (counter == position) {
165
242
  let c = allocateChar()
166
243
  Memory.copy(c + 4n, ptr, n)
167
244
  result = c
@@ -174,7 +251,7 @@ export let rec charAt = (idx, s: String) => {
174
251
  fail "charAt: should be impossible (please report)"
175
252
  }
176
253
  let ret = WasmI32.toGrain(result): Char
177
- Memory.decRef(WasmI32.fromGrain(s))
254
+ Memory.decRef(WasmI32.fromGrain(string))
178
255
  Memory.decRef(WasmI32.fromGrain(charAt))
179
256
  ret
180
257
  }
@@ -228,17 +305,37 @@ let explodeHelp = (s: String, chars) => {
228
305
  arr
229
306
  }
230
307
 
231
- // Split a string into its UTF-8 characters
232
- // @param input: String - The string to split
233
- // @returns Array<Char>
308
+ /**
309
+ * Split a string into its Unicode characters.
310
+ *
311
+ * @param string: The string to split
312
+ * @returns An array containing all characters in the string
313
+ *
314
+ * @example String.explode("Hello") == [> 'H', 'e', 'l', 'l', 'o']
315
+ *
316
+ * @since v0.3.0
317
+ */
234
318
  @disableGC
235
- export let explode = (str) => {
236
- WasmI32.toGrain(explodeHelp(str, true)): Array<Char>
319
+ export let rec explode = string => {
320
+ // `explodeHelp` and `string` do not need to be incRef'd as they are not
321
+ // decRef'd in `explodeHelp`
322
+ let ret = WasmI32.toGrain(explodeHelp(string, true)): (Array<Char>)
323
+
324
+ Memory.decRef(WasmI32.fromGrain(string))
325
+ Memory.decRef(WasmI32.fromGrain(explode))
326
+ ret
237
327
  }
238
328
 
239
- // Create a string from an array of characters
240
- // @param input: Array<Char> - The array to implode
241
- // @returns String
329
+ /**
330
+ * Create a string from an array of characters.
331
+ *
332
+ * @param arr: The array to combine
333
+ * @returns A string representation of the array of characters
334
+ *
335
+ * @example String.implode([> 'H', 'e', 'l', 'l', 'o']) == "Hello"
336
+ *
337
+ * @since v0.3.0
338
+ */
242
339
  @disableGC
243
340
  export let rec implode = (arr: Array<Char>) => {
244
341
  let (+) = WasmI32.add
@@ -297,12 +394,44 @@ export let rec implode = (arr: Array<Char>) => {
297
394
  ret
298
395
  }
299
396
 
300
- // Split a string by the given sequence
301
- // @param sequence: String - The sequence to split on
302
- // @param input: String - The string to split
303
- // @returns Array<String>
397
+ // Helper to get the length in constant time without depending on Array
398
+ primitive arrayLength: Array<a> -> Number = "@array.length"
399
+
400
+ /**
401
+ * Create a string that is the given string reversed.
402
+ *
403
+ * @param string: The string to reverse
404
+ * @returns A string whose characters are in the reverse order of the given string
405
+ *
406
+ * @example String.reverse("olleH") == "Hello"
407
+ *
408
+ * @since v0.4.5
409
+ */
410
+ export let reverse = string => {
411
+ let mut arr = explode(string)
412
+ let len = arrayLength(arr)
413
+ let halfLen = len / 2
414
+ for (let mut i = 0; i < halfLen; i += 1) {
415
+ let lastIdx = len - i - 1
416
+ let last = arr[lastIdx]
417
+ let first = arr[i]
418
+ arr[i] = last
419
+ arr[lastIdx] = first
420
+ }
421
+ implode(arr)
422
+ }
423
+
424
+ /**
425
+ * Split a string by the given separator.
426
+ *
427
+ * @param separator: The separator to split on
428
+ * @param string: The string to split
429
+ * @returns An array of substrings from the initial string
430
+ *
431
+ * @example String.split(" ", "Hello world") == [> "Hello", "world"]
432
+ */
304
433
  @disableGC
305
- export let rec split = (p: String, s: String) => {
434
+ export let rec split = (separator: String, string: String) => {
306
435
  let (+) = WasmI32.add
307
436
  let (-) = WasmI32.sub
308
437
  let (==) = WasmI32.eq
@@ -312,22 +441,22 @@ export let rec split = (p: String, s: String) => {
312
441
  let (>>) = WasmI32.shrS
313
442
  let (&) = WasmI32.and
314
443
 
315
- let size = WasmI32.fromGrain(wasmSafeByteLength(s)) >> 1n
316
- let psize = WasmI32.fromGrain(wasmSafeByteLength(p)) >> 1n
444
+ let size = WasmI32.fromGrain(wasmSafeByteLength(string)) >> 1n
445
+ let psize = WasmI32.fromGrain(wasmSafeByteLength(separator)) >> 1n
317
446
 
318
447
  let ret = if (psize == 0n) {
319
- WasmI32.toGrain(explodeHelp(s, false)): Array<String>
448
+ WasmI32.toGrain(explodeHelp(string, false)): (Array<String>)
320
449
  } else if (psize > size) {
321
- let s = WasmI32.fromGrain(s)
450
+ let string = WasmI32.fromGrain(string)
322
451
  let ptr = allocateArray(1n)
323
- WasmI32.store(ptr, Memory.incRef(s), 8n)
324
- WasmI32.toGrain(ptr): Array<String>
452
+ WasmI32.store(ptr, Memory.incRef(string), 8n)
453
+ WasmI32.toGrain(ptr): (Array<String>)
325
454
  } else {
326
- let s = WasmI32.fromGrain(s)
327
- let p = WasmI32.fromGrain(p)
455
+ let string = WasmI32.fromGrain(string)
456
+ let separator = WasmI32.fromGrain(separator)
328
457
 
329
- let mut ptr = s + 8n
330
- let mut pptr = p + 8n
458
+ let mut ptr = string + 8n
459
+ let mut pptr = separator + 8n
331
460
  let end = ptr + size - psize + 1n
332
461
 
333
462
  let mut numStrings = 1n
@@ -348,7 +477,7 @@ export let rec split = (p: String, s: String) => {
348
477
  }
349
478
  }
350
479
 
351
- ptr = s + 8n
480
+ ptr = string + 8n
352
481
  let mut last = ptr
353
482
  let arr = allocateArray(numStrings)
354
483
  let mut arrIdx = 0n
@@ -377,26 +506,33 @@ export let rec split = (p: String, s: String) => {
377
506
  }
378
507
 
379
508
  // Grab last string
380
- let strSize = s + 8n + size - last
509
+ let strSize = string + 8n + size - last
381
510
  let lastStr = allocateString(strSize)
382
511
  Memory.copy(lastStr + 8n, last, strSize)
383
512
  WasmI32.store(arr + arrIdx, lastStr, 8n)
384
513
 
385
- WasmI32.toGrain(arr): Array<String>
514
+ WasmI32.toGrain(arr): (Array<String>)
386
515
  }
387
- Memory.decRef(WasmI32.fromGrain(p))
388
- Memory.decRef(WasmI32.fromGrain(s))
516
+ Memory.decRef(WasmI32.fromGrain(separator))
517
+ Memory.decRef(WasmI32.fromGrain(string))
389
518
  Memory.decRef(WasmI32.fromGrain(split))
390
519
  ret
391
520
  }
392
521
 
393
- // Get a portion of a string.
394
- // @param from: Number - The start index of the substring
395
- // @param to: Number - The end index of the substring
396
- // @param input: String - The input string
397
- // @returns String
522
+ /**
523
+ * Get a portion of a string.
524
+ *
525
+ * @param start: The start position of the substring
526
+ * @param to: The end position of the substring, exclusive
527
+ * @param string: The input string
528
+ * @returns The substring from the initial string
529
+ *
530
+ * @example String.slice(0, 5, "Hello world") == "Hello"
531
+ *
532
+ * @since v0.1.0
533
+ */
398
534
  @disableGC
399
- export let rec slice = (start: Number, to: Number, s: String) => {
535
+ export let rec slice = (start: Number, to: Number, string: String) => {
400
536
  let (+) = WasmI32.add
401
537
  let (-) = WasmI32.sub
402
538
  let (==) = WasmI32.eq
@@ -409,10 +545,10 @@ export let rec slice = (start: Number, to: Number, s: String) => {
409
545
  let startOrig = start
410
546
  let toOrig = to
411
547
 
412
- let len = WasmI32.fromGrain(wasmSafeLength(s)) >> 1n
413
- let size = WasmI32.fromGrain(wasmSafeByteLength(s)) >> 1n
548
+ let len = WasmI32.fromGrain(wasmSafeLength(string)) >> 1n
549
+ let size = WasmI32.fromGrain(wasmSafeByteLength(string)) >> 1n
414
550
 
415
- let s = WasmI32.fromGrain(s)
551
+ let string = WasmI32.fromGrain(string)
416
552
 
417
553
  let mut start = WasmI32.fromGrain(start)
418
554
  if ((start & 1n) != 1n) {
@@ -441,7 +577,7 @@ export let rec slice = (start: Number, to: Number, s: String) => {
441
577
  throw InvalidArgument("Start index exceeds end index")
442
578
  }
443
579
 
444
- let mut ptr = s + 8n
580
+ let mut ptr = string + 8n
445
581
  let mut begin = ptr
446
582
  let mut end = ptr
447
583
  let stop = ptr + size
@@ -462,7 +598,7 @@ export let rec slice = (start: Number, to: Number, s: String) => {
462
598
  ptr += 1n
463
599
  }
464
600
  if (to == len) {
465
- end = s + 8n + size
601
+ end = string + 8n + size
466
602
  }
467
603
  if (start == to) {
468
604
  begin = end
@@ -476,17 +612,24 @@ export let rec slice = (start: Number, to: Number, s: String) => {
476
612
  let ret = WasmI32.toGrain(newString): String
477
613
  Memory.decRef(WasmI32.fromGrain(startOrig))
478
614
  Memory.decRef(WasmI32.fromGrain(toOrig))
479
- Memory.decRef(WasmI32.fromGrain(s))
615
+ Memory.decRef(WasmI32.fromGrain(string))
480
616
  Memory.decRef(WasmI32.fromGrain(slice))
481
617
  ret
482
618
  }
483
619
 
484
- // Check if a string contains a substring.
485
- // @param pattern: String - The substring to check
486
- // @param input: String - The input string
487
- // @returns Bool
620
+ /**
621
+ * Check if a string contains a substring.
622
+ *
623
+ * @param search: The substring to check
624
+ * @param string: The string to search
625
+ * @returns `true` if the input string contains the search value or `false` otherwise
626
+ *
627
+ * @example String.contains("world", "Hello world") == true
628
+ *
629
+ * @since v0.1.0
630
+ */
488
631
  @disableGC
489
- export let rec contains = (p: String, s: String) => {
632
+ export let rec contains = (search: String, string: String) => {
490
633
  // "Not So Naive" string search algorithm
491
634
  // searching phase in O(nm) time complexity
492
635
  // slightly (by coefficient) sub-linear in the average case
@@ -500,17 +643,17 @@ export let rec contains = (p: String, s: String) => {
500
643
  let (<=) = WasmI32.leU
501
644
  let (>) = WasmI32.gtU
502
645
  let (>>) = WasmI32.shrS
503
- let pOrig = p
504
- let sOrig = s
646
+ let pOrig = search
647
+ let sOrig = string
505
648
 
506
- let n = WasmI32.fromGrain(wasmSafeByteLength(s)) >> 1n
507
- let m = WasmI32.fromGrain(wasmSafeByteLength(p)) >> 1n
649
+ let n = WasmI32.fromGrain(wasmSafeByteLength(string)) >> 1n
650
+ let m = WasmI32.fromGrain(wasmSafeByteLength(search)) >> 1n
508
651
 
509
- let mut s = WasmI32.fromGrain(s)
510
- let mut p = WasmI32.fromGrain(p)
652
+ let mut string = WasmI32.fromGrain(string)
653
+ let mut search = WasmI32.fromGrain(search)
511
654
 
512
- s += 8n
513
- p += 8n
655
+ string += 8n
656
+ search += 8n
514
657
 
515
658
  let mut j = 0n, k = 0n, ell = 0n
516
659
 
@@ -522,10 +665,10 @@ export let rec contains = (p: String, s: String) => {
522
665
  if (m == 0n) {
523
666
  true
524
667
  } else {
525
- let pat = WasmI32.load8U(p, 0n)
668
+ let pat = WasmI32.load8U(search, 0n)
526
669
  let mut result = false
527
670
  while (j < n) {
528
- if (pat == WasmI32.load8U(s + j, 0n)) {
671
+ if (pat == WasmI32.load8U(string + j, 0n)) {
529
672
  result = true
530
673
  break
531
674
  } else {
@@ -536,7 +679,7 @@ export let rec contains = (p: String, s: String) => {
536
679
  }
537
680
  } else {
538
681
  // NSM preprocessing
539
- if (WasmI32.load8U(p, 0n) == WasmI32.load8U(p, 1n)) {
682
+ if (WasmI32.load8U(search, 0n) == WasmI32.load8U(search, 1n)) {
540
683
  k = 2n
541
684
  ell = 1n
542
685
  } else {
@@ -547,10 +690,13 @@ export let rec contains = (p: String, s: String) => {
547
690
  let mut result = false
548
691
  // NSM searching
549
692
  while (j <= n - m) {
550
- if (WasmI32.load8U(p, 1n) != WasmI32.load8U(s + j, 1n)) {
693
+ if (WasmI32.load8U(search, 1n) != WasmI32.load8U(string + j, 1n)) {
551
694
  j += k
552
695
  } else {
553
- if (Memory.compare(p + 2n, s + j + 2n, m - 2n) == 0n && WasmI32.load8U(p, 0n) == WasmI32.load8U(s + j, 0n)) {
696
+ if (
697
+ Memory.compare(search + 2n, string + j + 2n, m - 2n) == 0n &&
698
+ WasmI32.load8U(search, 0n) == WasmI32.load8U(string + j, 0n)
699
+ ) {
554
700
  result = true
555
701
  break
556
702
  }
@@ -565,32 +711,39 @@ export let rec contains = (p: String, s: String) => {
565
711
  ret
566
712
  }
567
713
 
568
- // Check if a string begins with another string.
569
- // @param pattern: String - The substring to check
570
- // @param input: String - The input string
571
- // @returns Bool
714
+ /**
715
+ * Check if a string begins with another string.
716
+ *
717
+ * @param search: The string to compare to the start
718
+ * @param string: The string to search
719
+ * @returns `true` if the input string starts with the search value or `false` otherwise
720
+ *
721
+ * @example String.startsWith("Hello", "Hello world") == true
722
+ *
723
+ * @since v0.1.0
724
+ */
572
725
  @disableGC
573
- export let rec startsWith = (p: String, s: String) => {
726
+ export let rec startsWith = (search: String, string: String) => {
574
727
  let (+) = WasmI32.add
575
728
  let (>) = WasmI32.gtU
576
729
  let (==) = WasmI32.eq
577
- let pOrig = p
578
- let sOrig = s
730
+ let pOrig = search
731
+ let sOrig = string
579
732
 
580
- let mut p = WasmI32.fromGrain(p)
581
- let mut s = WasmI32.fromGrain(s)
733
+ let mut search = WasmI32.fromGrain(search)
734
+ let mut string = WasmI32.fromGrain(string)
582
735
 
583
- let n = WasmI32.load(s, 4n)
584
- let m = WasmI32.load(p, 4n)
736
+ let n = WasmI32.load(string, 4n)
737
+ let m = WasmI32.load(search, 4n)
585
738
 
586
- s += 8n
587
- p += 8n
739
+ string += 8n
740
+ search += 8n
588
741
 
589
742
  // Bail if pattern length is longer than input length
590
743
  let ret = if (m > n) {
591
744
  false
592
745
  } else {
593
- Memory.compare(p, s, m) == 0n
746
+ Memory.compare(search, string, m) == 0n
594
747
  }
595
748
  Memory.decRef(WasmI32.fromGrain(pOrig))
596
749
  Memory.decRef(WasmI32.fromGrain(sOrig))
@@ -598,33 +751,40 @@ export let rec startsWith = (p: String, s: String) => {
598
751
  ret
599
752
  }
600
753
 
601
- // Check if a string ends with another string.
602
- // @param pattern: String - The substring to check
603
- // @param input: String - The input string
604
- // @returns Bool
754
+ /**
755
+ * Check if a string ends with another string.
756
+ *
757
+ * @param search: The string to compare to the end
758
+ * @param string: The string to search
759
+ * @returns `true` if the input string ends with the search value or `false` otherwise
760
+ *
761
+ * @example String.endsWith("world", "Hello world") == true
762
+ *
763
+ * @since v0.1.0
764
+ */
605
765
  @disableGC
606
- export let rec endsWith = (p: String, s: String) => {
766
+ export let rec endsWith = (search: String, string: String) => {
607
767
  let (+) = WasmI32.add
608
768
  let (-) = WasmI32.sub
609
769
  let (>) = WasmI32.gtU
610
770
  let (==) = WasmI32.eq
611
- let pOrig = p
612
- let sOrig = s
771
+ let pOrig = search
772
+ let sOrig = string
613
773
 
614
- let mut p = WasmI32.fromGrain(p)
615
- let mut s = WasmI32.fromGrain(s)
774
+ let mut search = WasmI32.fromGrain(search)
775
+ let mut string = WasmI32.fromGrain(string)
616
776
 
617
- let n = WasmI32.load(s, 4n)
618
- let m = WasmI32.load(p, 4n)
777
+ let n = WasmI32.load(string, 4n)
778
+ let m = WasmI32.load(search, 4n)
619
779
 
620
- s += 8n
621
- p += 8n
780
+ string += 8n
781
+ search += 8n
622
782
 
623
783
  // Bail if pattern length is longer than input length
624
784
  let ret = if (m > n) {
625
785
  false
626
786
  } else {
627
- Memory.compare(p, s + n - m, m) == 0n
787
+ Memory.compare(search, string + n - m, m) == 0n
628
788
  }
629
789
  Memory.decRef(WasmI32.fromGrain(pOrig))
630
790
  Memory.decRef(WasmI32.fromGrain(sOrig))
@@ -632,14 +792,6 @@ export let rec endsWith = (p: String, s: String) => {
632
792
  ret
633
793
  }
634
794
 
635
- export enum Encoding {
636
- UTF8,
637
- UTF16_BE,
638
- UTF16_LE,
639
- UTF32_BE,
640
- UTF32_LE,
641
- }
642
-
643
795
  // String->Byte encoding and helper functions:
644
796
 
645
797
  // these are globals to avoid memory leaks
@@ -712,7 +864,7 @@ let utf16Length = (s: String) => {
712
864
 
713
865
  @disableGC
714
866
  let encodedLength = (s: String, encoding) => {
715
- match(encoding) {
867
+ match (encoding) {
716
868
  UTF32_BE => {
717
869
  Memory.incRef(WasmI32.fromGrain((*)))
718
870
  wasmSafeLength(s) * 4
@@ -780,7 +932,7 @@ let getCodePoint = (ptr: WasmI32) => {
780
932
  }
781
933
  lowerBoundary = 0x80n
782
934
  upperBoundary = 0xBFn
783
- codePoint = (codePoint << 6n) | (byte & 0x3Fn)
935
+ codePoint = codePoint << 6n | byte & 0x3Fn
784
936
  bytesSeen += 1n
785
937
  if (bytesSeen == bytesNeeded) {
786
938
  result = codePoint
@@ -792,26 +944,26 @@ let getCodePoint = (ptr: WasmI32) => {
792
944
 
793
945
  // hack to avoid incRef on this pointer
794
946
  @disableGC
795
- let mut _BYTES_SIZE_OFFSET = 1n;
947
+ let mut _BYTES_SIZE_OFFSET = 1n
796
948
  @disableGC
797
- let mut _BYTES_OFFSET = 1n;
949
+ let mut _BYTES_OFFSET = 1n
798
950
 
799
951
  @disableGC
800
952
  let initPtr = () => {
801
953
  _BYTES_SIZE_OFFSET = 4n
802
954
  _BYTES_OFFSET = 8n
803
955
  }
804
- initPtr();
805
-
806
- // Encodes the given string using the given encoding scheme
807
- // @param s: String - The input string
808
- // @param encoding: Encoding - The encoding to use
809
- // @param includeBom: Bool - Whether to include the byte-order marker in the encoded output
810
- // @param dest: Bytes - The bytes object to write the encoded output into
811
- // @param destPos: Number - The location in the byte array to write the output
812
- // @returns Bytes - Returns `dest`
956
+ initPtr()
957
+
813
958
  @disableGC
814
- let rec encodeAtHelp = (s: String, encoding: Encoding, includeBom: Bool, dest: Bytes, destPos: Number) => {
959
+ let rec encodeAtHelp =
960
+ (
961
+ string: String,
962
+ encoding: Encoding,
963
+ includeBom: Bool,
964
+ dest: Bytes,
965
+ destPos: Number,
966
+ ) => {
815
967
  let (>>>) = WasmI32.shrU
816
968
  let (-) = WasmI32.sub
817
969
  let (&) = WasmI32.and
@@ -820,12 +972,12 @@ let rec encodeAtHelp = (s: String, encoding: Encoding, includeBom: Bool, dest: B
820
972
  let (<=) = WasmI32.leU
821
973
  let (==) = WasmI32.eq
822
974
  let (+) = WasmI32.add
823
- let byteSize = WasmI32.fromGrain(wasmSafeByteLength(s)) >>> 1n
824
- let len = WasmI32.fromGrain(wasmSafeLength(s)) >>> 1n
975
+ let byteSize = WasmI32.fromGrain(wasmSafeByteLength(string)) >>> 1n
976
+ let len = WasmI32.fromGrain(wasmSafeLength(string)) >>> 1n
825
977
 
826
- let s = WasmI32.fromGrain(s)
978
+ let string = WasmI32.fromGrain(string)
827
979
 
828
- let mut ptr = s + 8n
980
+ let mut ptr = string + 8n
829
981
  let end = ptr + byteSize
830
982
 
831
983
  let bytes = WasmI32.fromGrain(dest)
@@ -834,9 +986,9 @@ let rec encodeAtHelp = (s: String, encoding: Encoding, includeBom: Bool, dest: B
834
986
  let destSize = WasmI32.load(bytes, _BYTES_SIZE_OFFSET)
835
987
 
836
988
  if (includeBom) {
837
- match(encoding) {
989
+ match (encoding) {
838
990
  UTF8 => {
839
- if ((bytesIdx + 3n) > destSize) {
991
+ if (bytesIdx + 3n > destSize) {
840
992
  throw Exception.IndexOutOfBounds
841
993
  }
842
994
  WasmI32.store8(bytes + bytesIdx, 0xEFn, _BYTES_OFFSET)
@@ -845,7 +997,7 @@ let rec encodeAtHelp = (s: String, encoding: Encoding, includeBom: Bool, dest: B
845
997
  bytesIdx += 3n
846
998
  },
847
999
  UTF16_BE => {
848
- if ((bytesIdx + 2n) > destSize) {
1000
+ if (bytesIdx + 2n > destSize) {
849
1001
  throw Exception.IndexOutOfBounds
850
1002
  }
851
1003
  WasmI32.store8(bytes + bytesIdx, 0xFEn, _BYTES_OFFSET)
@@ -853,7 +1005,7 @@ let rec encodeAtHelp = (s: String, encoding: Encoding, includeBom: Bool, dest: B
853
1005
  bytesIdx += 2n
854
1006
  },
855
1007
  UTF16_LE => {
856
- if ((bytesIdx + 2n) > destSize) {
1008
+ if (bytesIdx + 2n > destSize) {
857
1009
  throw Exception.IndexOutOfBounds
858
1010
  }
859
1011
  WasmI32.store8(bytes + bytesIdx, 0xFFn, _BYTES_OFFSET)
@@ -861,7 +1013,7 @@ let rec encodeAtHelp = (s: String, encoding: Encoding, includeBom: Bool, dest: B
861
1013
  bytesIdx += 2n
862
1014
  },
863
1015
  UTF32_BE => {
864
- if ((bytesIdx + 4n) > destSize) {
1016
+ if (bytesIdx + 4n > destSize) {
865
1017
  throw Exception.IndexOutOfBounds
866
1018
  }
867
1019
  WasmI32.store8(bytes + bytesIdx, 0n, _BYTES_OFFSET)
@@ -871,7 +1023,7 @@ let rec encodeAtHelp = (s: String, encoding: Encoding, includeBom: Bool, dest: B
871
1023
  bytesIdx += 4n
872
1024
  },
873
1025
  UTF32_LE => {
874
- if ((bytesIdx + 4n) > destSize) {
1026
+ if (bytesIdx + 4n > destSize) {
875
1027
  throw Exception.IndexOutOfBounds
876
1028
  }
877
1029
  WasmI32.store8(bytes + bytesIdx, 0xFFn, _BYTES_OFFSET)
@@ -879,16 +1031,16 @@ let rec encodeAtHelp = (s: String, encoding: Encoding, includeBom: Bool, dest: B
879
1031
  WasmI32.store8(bytes + bytesIdx + 2n, 0n, _BYTES_OFFSET)
880
1032
  WasmI32.store8(bytes + bytesIdx + 3n, 0n, _BYTES_OFFSET)
881
1033
  bytesIdx += 4n
882
- }
1034
+ },
883
1035
  }
884
1036
  }
885
1037
 
886
- match(encoding) {
1038
+ match (encoding) {
887
1039
  UTF8 => {
888
1040
  // Optimization: since internally strings in Grain are UTF8 encoded, when
889
1041
  // the target encoding is UTF8 as well, then copy the entire memory range
890
1042
  // in bulk. No need to iterate individual characters.
891
- if ((bytesIdx + byteSize) > destSize) {
1043
+ if (bytesIdx + byteSize > destSize) {
892
1044
  throw Exception.IndexOutOfBounds
893
1045
  }
894
1046
  Memory.copy(bytes + bytesIdx + _BYTES_OFFSET, ptr, byteSize)
@@ -906,37 +1058,55 @@ let rec encodeAtHelp = (s: String, encoding: Encoding, includeBom: Bool, dest: B
906
1058
  } else {
907
1059
  2n
908
1060
  }
909
- match(encoding) {
1061
+ match (encoding) {
910
1062
  UTF8 => {
911
1063
  // With the optimization above for bulk memory copy, this match
912
1064
  // should never occur for the UTF8 case.
913
- if ((bytesIdx + n) > destSize) {
1065
+ if (bytesIdx + n > destSize) {
914
1066
  throw Exception.IndexOutOfBounds
915
1067
  }
916
- Memory.copy(bytes + bytesIdx + _BYTES_OFFSET, ptr, n);
1068
+ Memory.copy(bytes + bytesIdx + _BYTES_OFFSET, ptr, n)
917
1069
  bytesIdx += n
918
1070
  },
919
1071
  UTF16_BE => {
920
1072
  let codePoint = getCodePoint(ptr)
921
1073
  if (codePoint <= 0xFFFFn) {
922
1074
  // <hi><lo>
923
- if ((bytesIdx + 2n) > destSize) {
1075
+ if (bytesIdx + 2n > destSize) {
924
1076
  throw Exception.IndexOutOfBounds
925
1077
  }
926
- WasmI32.store8(bytes + bytesIdx, (codePoint & 0xff00n) >>> 8n, _BYTES_OFFSET)
927
- WasmI32.store8(bytes + bytesIdx + 1n, codePoint & 0xffn, _BYTES_OFFSET)
1078
+ WasmI32.store8(
1079
+ bytes + bytesIdx,
1080
+ (codePoint & 0xff00n) >>> 8n,
1081
+ _BYTES_OFFSET
1082
+ )
1083
+ WasmI32.store8(
1084
+ bytes + bytesIdx + 1n,
1085
+ codePoint & 0xffn,
1086
+ _BYTES_OFFSET
1087
+ )
928
1088
  bytesIdx += 2n
929
1089
  } else {
930
1090
  // https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF
931
- if ((bytesIdx + 4n) > destSize) {
1091
+ if (bytesIdx + 4n > destSize) {
932
1092
  throw Exception.IndexOutOfBounds
933
1093
  }
934
1094
  let uPrime = codePoint - 0x10000n
935
- let w1 = ((uPrime & 0b11111111110000000000n) >>> 10n) + 0xD800n // High surrogate
936
- let w2 = (uPrime & 0b00000000001111111111n) + 0xDC00n // Low surrogate
937
- WasmI32.store8(bytes + bytesIdx, (w1 & 0xff00n) >>> 8n, _BYTES_OFFSET)
1095
+ let w1 = ((uPrime & 0b11111111110000000000n) >>> 10n) +
1096
+ 0xD800n // High surrogate
1097
+ let w2 = (uPrime & 0b00000000001111111111n) +
1098
+ 0xDC00n // Low surrogate
1099
+ WasmI32.store8(
1100
+ bytes + bytesIdx,
1101
+ (w1 & 0xff00n) >>> 8n,
1102
+ _BYTES_OFFSET
1103
+ )
938
1104
  WasmI32.store8(bytes + bytesIdx + 1n, w1 & 0xffn, _BYTES_OFFSET)
939
- WasmI32.store8(bytes + bytesIdx + 2n, (w2 & 0xff00n) >>> 8n, _BYTES_OFFSET)
1105
+ WasmI32.store8(
1106
+ bytes + bytesIdx + 2n,
1107
+ (w2 & 0xff00n) >>> 8n,
1108
+ _BYTES_OFFSET
1109
+ )
940
1110
  WasmI32.store8(bytes + bytesIdx + 3n, w2 & 0xffn, _BYTES_OFFSET)
941
1111
  bytesIdx += 4n
942
1112
  }
@@ -944,133 +1114,192 @@ let rec encodeAtHelp = (s: String, encoding: Encoding, includeBom: Bool, dest: B
944
1114
  UTF16_LE => {
945
1115
  let codePoint = getCodePoint(ptr)
946
1116
  if (codePoint <= 0xFFFFn) {
947
- if ((bytesIdx + 2n) > destSize) {
1117
+ if (bytesIdx + 2n > destSize) {
948
1118
  throw Exception.IndexOutOfBounds
949
1119
  }
950
1120
  // <lo><hi>
951
1121
  WasmI32.store8(bytes + bytesIdx, codePoint & 0xffn, _BYTES_OFFSET)
952
- WasmI32.store8(bytes + bytesIdx + 1n, (codePoint & 0xff00n) >>> 8n, _BYTES_OFFSET)
1122
+ WasmI32.store8(
1123
+ bytes + bytesIdx + 1n,
1124
+ (codePoint & 0xff00n) >>> 8n,
1125
+ _BYTES_OFFSET
1126
+ )
953
1127
  bytesIdx += 2n
954
1128
  } else {
955
1129
  // https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF
956
- if ((bytesIdx + 4n) > destSize) {
1130
+ if (bytesIdx + 4n > destSize) {
957
1131
  throw Exception.IndexOutOfBounds
958
1132
  }
959
1133
  let uPrime = codePoint - 0x10000n
960
- let w1 = ((uPrime & 0b11111111110000000000n) >>> 10n) + 0xD800n // High surrogate
961
- let w2 = (uPrime & 0b00000000001111111111n) + 0xDC00n // Low surrogate
1134
+ let w1 = ((uPrime & 0b11111111110000000000n) >>> 10n) +
1135
+ 0xD800n // High surrogate
1136
+ let w2 = (uPrime & 0b00000000001111111111n) +
1137
+ 0xDC00n // Low surrogate
962
1138
  WasmI32.store8(bytes + bytesIdx, w1 & 0xffn, _BYTES_OFFSET)
963
- WasmI32.store8(bytes + bytesIdx + 1n, (w1 & 0xff00n) >>> 8n, _BYTES_OFFSET)
1139
+ WasmI32.store8(
1140
+ bytes + bytesIdx + 1n,
1141
+ (w1 & 0xff00n) >>> 8n,
1142
+ _BYTES_OFFSET
1143
+ )
964
1144
  WasmI32.store8(bytes + bytesIdx + 2n, w2 & 0xffn, _BYTES_OFFSET)
965
- WasmI32.store8(bytes + bytesIdx + 3n, (w2 & 0xff00n) >>> 8n, _BYTES_OFFSET)
1145
+ WasmI32.store8(
1146
+ bytes + bytesIdx + 3n,
1147
+ (w2 & 0xff00n) >>> 8n,
1148
+ _BYTES_OFFSET
1149
+ )
966
1150
  bytesIdx += 4n
967
1151
  }
968
1152
  },
969
1153
  UTF32_BE => {
970
- if ((bytesIdx + 4n) > destSize) {
1154
+ if (bytesIdx + 4n > destSize) {
971
1155
  throw Exception.IndexOutOfBounds
972
1156
  }
973
1157
  let codePoint = getCodePoint(ptr)
974
- WasmI32.store8(bytes + bytesIdx, (codePoint & 0xff000000n) >>> 24n, _BYTES_OFFSET)
975
- WasmI32.store8(bytes + bytesIdx + 1n, (codePoint & 0xff0000n) >>> 16n, _BYTES_OFFSET)
976
- WasmI32.store8(bytes + bytesIdx + 2n, (codePoint & 0xff00n) >>> 8n, _BYTES_OFFSET)
977
- WasmI32.store8(bytes + bytesIdx + 3n, codePoint & 0xffn, _BYTES_OFFSET)
1158
+ WasmI32.store8(
1159
+ bytes + bytesIdx,
1160
+ (codePoint & 0xff000000n) >>> 24n,
1161
+ _BYTES_OFFSET
1162
+ )
1163
+ WasmI32.store8(
1164
+ bytes + bytesIdx + 1n,
1165
+ (codePoint & 0xff0000n) >>> 16n,
1166
+ _BYTES_OFFSET
1167
+ )
1168
+ WasmI32.store8(
1169
+ bytes + bytesIdx + 2n,
1170
+ (codePoint & 0xff00n) >>> 8n,
1171
+ _BYTES_OFFSET
1172
+ )
1173
+ WasmI32.store8(
1174
+ bytes + bytesIdx + 3n,
1175
+ codePoint & 0xffn,
1176
+ _BYTES_OFFSET
1177
+ )
978
1178
  bytesIdx += 4n
979
1179
  },
980
1180
  UTF32_LE => {
981
- if ((bytesIdx + 4n) > destSize) {
1181
+ if (bytesIdx + 4n > destSize) {
982
1182
  throw Exception.IndexOutOfBounds
983
1183
  }
984
1184
  let codePoint = getCodePoint(ptr)
985
1185
  WasmI32.store8(bytes + bytesIdx, codePoint & 0xffn, _BYTES_OFFSET)
986
- WasmI32.store8(bytes + bytesIdx + 1n, (codePoint & 0xff00n) >>> 8n, _BYTES_OFFSET)
987
- WasmI32.store8(bytes + bytesIdx + 2n, (codePoint & 0xff0000n) >>> 16n, _BYTES_OFFSET)
988
- WasmI32.store8(bytes + bytesIdx + 3n, (codePoint & 0xff000000n) >>> 24n, _BYTES_OFFSET)
1186
+ WasmI32.store8(
1187
+ bytes + bytesIdx + 1n,
1188
+ (codePoint & 0xff00n) >>> 8n,
1189
+ _BYTES_OFFSET
1190
+ )
1191
+ WasmI32.store8(
1192
+ bytes + bytesIdx + 2n,
1193
+ (codePoint & 0xff0000n) >>> 16n,
1194
+ _BYTES_OFFSET
1195
+ )
1196
+ WasmI32.store8(
1197
+ bytes + bytesIdx + 3n,
1198
+ (codePoint & 0xff000000n) >>> 24n,
1199
+ _BYTES_OFFSET
1200
+ )
989
1201
  bytesIdx += 4n
990
1202
  },
991
- };
1203
+ }
992
1204
  ptr += n
993
1205
  }
994
- }
1206
+ },
995
1207
  }
996
1208
 
997
- let ret = WasmI32.toGrain(bytes): Bytes
998
- Memory.decRef(WasmI32.fromGrain(s))
1209
+ Memory.decRef(WasmI32.fromGrain(string))
999
1210
  Memory.decRef(WasmI32.fromGrain(encoding))
1000
1211
  Memory.decRef(WasmI32.fromGrain(includeBom))
1001
- Memory.decRef(WasmI32.fromGrain(dest))
1002
1212
  Memory.decRef(WasmI32.fromGrain(destPos))
1003
1213
  Memory.decRef(WasmI32.fromGrain(encodeAtHelp))
1004
- ret
1214
+
1215
+ // We don't decRef `dest` because we're returning it
1216
+ dest
1005
1217
  }
1006
1218
 
1007
- // Encodes the given string using the given encoding scheme
1008
- // @param s: String - The input string
1009
- // @param encoding: Encoding - The encoding to use
1010
- // @param dest: Bytes - The bytes object to write the encoded output into
1011
- // @param destPos: Number - The location in the byte array to write the output
1012
- // @returns Bytes - Returns `dest`
1013
- export let encodeAt = (s, encoding, dest, destPos) => {
1014
- encodeAtHelp(s, encoding, false, dest, destPos)
1219
+ /**
1220
+ * Encodes the given string into a byte sequence at the supplied position, excluding any byte-order marker, using the encoding scheme provided.
1221
+ *
1222
+ * @param string: The input string
1223
+ * @param encoding: The encoding to use
1224
+ * @param dest: The byte sequence that will be copied
1225
+ * @param destPos: The location in the byte sequence to write the output
1226
+ * @returns A copy of the input bytes with the encoded string replaced at the given position
1227
+ *
1228
+ * @since v0.4.0
1229
+ */
1230
+ export let encodeAt = (string, encoding, dest, destPos) => {
1231
+ encodeAtHelp(string, encoding, false, dest, destPos)
1015
1232
  }
1016
1233
 
1017
- // Encodes the given string using the given encoding scheme
1018
- // @param s: String - The input string
1019
- // @param encoding: Encoding - The encoding to use
1020
- // @param dest: Bytes - The bytes object to write the encoded output into
1021
- // @param destPos: Number - The location in the byte array to write the output
1022
- // @returns Bytes - Returns `dest`
1023
- export let encodeAtWithBom = (s, encoding, dest, destPos) => {
1024
- encodeAtHelp(s, encoding, true, dest, destPos)
1234
+ /**
1235
+ * Encodes the given string into a byte sequence at the supplied position, including any byte-order marker, using the encoding scheme provided.
1236
+ *
1237
+ * @param string: The input string
1238
+ * @param encoding: The encoding to use
1239
+ * @param dest: The byte sequence that will be copied
1240
+ * @param destPos: The location in the byte sequence to write the output
1241
+ * @returns A copy of the input bytes with the encoded string replaced at the given position
1242
+ *
1243
+ * @since v0.4.0
1244
+ */
1245
+ export let encodeAtWithBom = (string, encoding, dest, destPos) => {
1246
+ encodeAtHelp(string, encoding, true, dest, destPos)
1025
1247
  }
1026
1248
 
1027
- // Encodes the given string using the given encoding scheme
1028
- // @param s: String - The input string
1029
- // @param encoding: Encoding - The encoding to use
1030
- // @param includeBom: Bool - Whether to include the byte-order marker in the encoded output
1031
- // @returns Bytes
1032
1249
  @disableGC
1033
- let rec encodeHelp = (s: String, encoding: Encoding, includeBom: Bool) => {
1250
+ let rec encodeHelp = (string: String, encoding: Encoding, includeBom: Bool) => {
1034
1251
  Memory.incRef(WasmI32.fromGrain((+)))
1035
- let size = encodedLength(s, encoding) + if (includeBom) {
1036
- match(encoding) {
1037
- UTF8 => 3,
1038
- UTF16_LE => 2,
1039
- UTF16_BE => 2,
1040
- UTF32_LE => 4,
1041
- UTF32_BE => 4,
1042
- }
1043
- } else 0
1252
+ let size = encodedLength(string, encoding) +
1253
+ (if (includeBom) {
1254
+ match (encoding) {
1255
+ UTF8 => 3,
1256
+ UTF16_LE => 2,
1257
+ UTF16_BE => 2,
1258
+ UTF32_LE => 4,
1259
+ UTF32_BE => 4,
1260
+ }
1261
+ } else {
1262
+ 0
1263
+ })
1044
1264
  let (>>>) = WasmI32.shrU
1045
1265
  let bytes = WasmI32.toGrain(allocateBytes(WasmI32.fromGrain(size) >>> 1n))
1046
1266
  Memory.incRef(WasmI32.fromGrain(encodeAtHelp))
1047
- Memory.incRef(WasmI32.fromGrain(s))
1267
+ Memory.incRef(WasmI32.fromGrain(string))
1048
1268
  Memory.incRef(WasmI32.fromGrain(encoding))
1049
1269
  Memory.incRef(WasmI32.fromGrain(includeBom))
1050
1270
  Memory.incRef(WasmI32.fromGrain(bytes))
1051
- let ret = encodeAtHelp(s, encoding, includeBom, bytes, 0)
1052
- Memory.decRef(WasmI32.fromGrain(s))
1271
+ let ret = encodeAtHelp(string, encoding, includeBom, bytes, 0)
1272
+ Memory.decRef(WasmI32.fromGrain(string))
1053
1273
  Memory.decRef(WasmI32.fromGrain(encoding))
1054
1274
  Memory.decRef(WasmI32.fromGrain(includeBom))
1055
1275
  Memory.decRef(WasmI32.fromGrain(encodeHelp))
1056
1276
  ret
1057
1277
  }
1058
1278
 
1059
- // Encodes the given string using the given encoding scheme. A byte-order marker
1060
- // will not be included in the output.
1061
- // @param s: String - The input string
1062
- // @param encoding: Encoding - The encoding to use
1063
- // @returns Bytes
1064
- export let encode = (s: String, encoding: Encoding) => {
1065
- encodeHelp(s, encoding, false)
1279
+ /**
1280
+ * Encodes the given string using the given encoding scheme, excluding any byte-order marker.
1281
+ *
1282
+ * @param string: The input string
1283
+ * @param encoding: The encoding to use
1284
+ * @returns The byte representation of the string in the given encoding
1285
+ *
1286
+ * @since v0.4.0
1287
+ */
1288
+ export let encode = (string: String, encoding: Encoding) => {
1289
+ encodeHelp(string, encoding, false)
1066
1290
  }
1067
1291
 
1068
- // Encodes the given string using the given encoding scheme, including a byte-order marker
1069
- // @param s: String - The input string
1070
- // @param encoding: Encoding - The encoding to use
1071
- // @returns Bytes
1072
- export let encodeWithBom = (s: String, encoding: Encoding) => {
1073
- encodeHelp(s, encoding, true)
1292
+ /**
1293
+ * Encodes the given string using the given encoding scheme, including any byte-order marker.
1294
+ *
1295
+ * @param string: The input string
1296
+ * @param encoding: The encoding to use
1297
+ * @returns The byte representation of the string in the given encoding
1298
+ *
1299
+ * @since v0.4.0
1300
+ */
1301
+ export let encodeWithBom = (string: String, encoding: Encoding) => {
1302
+ encodeHelp(string, encoding, true)
1074
1303
  }
1075
1304
 
1076
1305
  // Byte->String decoding and helper functions:
@@ -1098,8 +1327,8 @@ let writeUtf8CodePoint = (ptr, codePoint) => {
1098
1327
  // The first byte has a three bit prefix of 110, followed by 5 bits of the
1099
1328
  // codepoint. The second byte has a two bit prefix of 10, followed by 6 bits
1100
1329
  // of the codepoint.
1101
- let high = ((codePoint >>> 6n) & 0b000_11111n) | 0b110_00000n
1102
- let low = ( codePoint & 0b00_111111n) | 0b10_000000n
1330
+ let high = codePoint >>> 6n & 0b000_11111n | 0b110_00000n
1331
+ let low = codePoint & 0b00_111111n | 0b10_000000n
1103
1332
  WasmI32.store8(ptr, high, 0n)
1104
1333
  WasmI32.store8(ptr + 1n, low, 0n)
1105
1334
  2n
@@ -1108,9 +1337,9 @@ let writeUtf8CodePoint = (ptr, codePoint) => {
1108
1337
  // The first byte has a four bit prefix of 1110, followed by 4 bits of the
1109
1338
  // codepoint. Remaining bytes each have a two bit prefix of 10, followed by
1110
1339
  // 6 bits of the codepoint.
1111
- let high = ((codePoint >>> 12n) & 0b0000_1111n) | 0b1110_0000n
1112
- let mid = ((codePoint >>> 6n) & 0b00_111111n) | 0b10_000000n
1113
- let low = ( codePoint & 0b00_111111n) | 0b10_000000n
1340
+ let high = codePoint >>> 12n & 0b0000_1111n | 0b1110_0000n
1341
+ let mid = codePoint >>> 6n & 0b00_111111n | 0b10_000000n
1342
+ let low = codePoint & 0b00_111111n | 0b10_000000n
1114
1343
  WasmI32.store8(ptr, high, 0n)
1115
1344
  WasmI32.store8(ptr + 1n, mid, 0n)
1116
1345
  WasmI32.store8(ptr + 2n, low, 0n)
@@ -1120,10 +1349,10 @@ let writeUtf8CodePoint = (ptr, codePoint) => {
1120
1349
  // The first byte has a five bit prefix of 11110, followed by 3 bits of the
1121
1350
  // codepoint. Remaining bytes each have a two bit prefix of 10, followed by
1122
1351
  // 6 bits of the codepoint.
1123
- let high = ((codePoint >>> 18n) & 0b00000_111n) | 0b11110_000n
1124
- let mid1 = ((codePoint >>> 12n) & 0b00_111111n) | 0b10_000000n
1125
- let mid2 = ((codePoint >>> 6n) & 0b00_111111n) | 0b10_000000n
1126
- let low = ( codePoint & 0b00_111111n) | 0b10_000000n
1352
+ let high = codePoint >>> 18n & 0b00000_111n | 0b11110_000n
1353
+ let mid1 = codePoint >>> 12n & 0b00_111111n | 0b10_000000n
1354
+ let mid2 = codePoint >>> 6n & 0b00_111111n | 0b10_000000n
1355
+ let low = codePoint & 0b00_111111n | 0b10_000000n
1127
1356
  WasmI32.store8(ptr, high, 0n)
1128
1357
  WasmI32.store8(ptr + 1n, mid1, 0n)
1129
1358
  WasmI32.store8(ptr + 2n, mid2, 0n)
@@ -1142,25 +1371,46 @@ let bytesHaveBom = (bytes: Bytes, encoding: Encoding, start: WasmI32) => {
1142
1371
  let ptr = ptr + start
1143
1372
  match (encoding) {
1144
1373
  UTF8 => {
1145
- bytesSize >= 3n && WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xEFn && WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xBBn && WasmI32.load8U(ptr + 2n, _BYTES_OFFSET) == 0xBFn
1374
+ bytesSize >= 3n &&
1375
+ WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xEFn &&
1376
+ WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xBBn &&
1377
+ WasmI32.load8U(ptr + 2n, _BYTES_OFFSET) == 0xBFn
1146
1378
  },
1147
1379
  UTF16_BE => {
1148
- bytesSize >= 2n && WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xFEn && WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xFFn
1380
+ bytesSize >= 2n &&
1381
+ WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xFEn &&
1382
+ WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xFFn
1149
1383
  },
1150
1384
  UTF16_LE => {
1151
- bytesSize >= 2n && WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xFFn && WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xFEn
1385
+ bytesSize >= 2n &&
1386
+ WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xFFn &&
1387
+ WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xFEn
1152
1388
  },
1153
1389
  UTF32_BE => {
1154
- bytesSize >= 4n && WasmI32.load8U(ptr, _BYTES_OFFSET) == 0x00n && WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0x00n && WasmI32.load8U(ptr + 2n, _BYTES_OFFSET) == 0xFEn && WasmI32.load8U(ptr + 3n, _BYTES_OFFSET) == 0xFFn
1390
+ bytesSize >= 4n &&
1391
+ WasmI32.load8U(ptr, _BYTES_OFFSET) == 0x00n &&
1392
+ WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0x00n &&
1393
+ WasmI32.load8U(ptr + 2n, _BYTES_OFFSET) == 0xFEn &&
1394
+ WasmI32.load8U(ptr + 3n, _BYTES_OFFSET) == 0xFFn
1155
1395
  },
1156
1396
  UTF32_LE => {
1157
- bytesSize >= 4n && WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xFFn && WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xFEn && WasmI32.load8U(ptr + 2n, _BYTES_OFFSET) == 0x00n && WasmI32.load8U(ptr + 3n, _BYTES_OFFSET) == 0x00n
1158
- }
1397
+ bytesSize >= 4n &&
1398
+ WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xFFn &&
1399
+ WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xFEn &&
1400
+ WasmI32.load8U(ptr + 2n, _BYTES_OFFSET) == 0x00n &&
1401
+ WasmI32.load8U(ptr + 3n, _BYTES_OFFSET) == 0x00n
1402
+ },
1159
1403
  }
1160
1404
  }
1161
1405
 
1162
1406
  @disableGC
1163
- let decodedLength = (bytes: Bytes, encoding: Encoding, start: WasmI32, size: WasmI32) => {
1407
+ let decodedLength =
1408
+ (
1409
+ bytes: Bytes,
1410
+ encoding: Encoding,
1411
+ start: WasmI32,
1412
+ size: WasmI32,
1413
+ ) => {
1164
1414
  let (+) = WasmI32.add
1165
1415
  let (-) = WasmI32.sub
1166
1416
  let (==) = WasmI32.eq
@@ -1183,20 +1433,21 @@ let decodedLength = (bytes: Bytes, encoding: Encoding, start: WasmI32, size: Was
1183
1433
  }
1184
1434
  }
1185
1435
  let start = ptr + _BYTES_OFFSET + start
1186
- match(encoding) {
1436
+ match (encoding) {
1187
1437
  UTF8 => bytesSize,
1188
1438
  UTF16_BE => {
1189
1439
  let end = start + bytesSize
1190
1440
  let mut ptr = start
1191
1441
  let mut count = 0n
1192
1442
  while (ptr < end) {
1193
- let codeWord = (WasmI32.load8U(ptr, 0n) << 8n) | (WasmI32.load8U(ptr, 1n))
1443
+ let codeWord = WasmI32.load8U(ptr, 0n) << 8n | WasmI32.load8U(ptr, 1n)
1194
1444
  let codeWord = if (codeWord >= 0xD800n && codeWord <= 0xDBFFn) {
1195
1445
  // high surrogate. need to check that next character is low srurrogate
1196
1446
  let ret = if (ptr + 2n >= end) {
1197
1447
  throw MalformedUnicode
1198
1448
  } else {
1199
- let nextCodeWord = (WasmI32.load8U(ptr, 2n) << 8n) | (WasmI32.load8U(ptr, 3n))
1449
+ let nextCodeWord = WasmI32.load8U(ptr, 2n) << 8n |
1450
+ WasmI32.load8U(ptr, 3n)
1200
1451
  if (nextCodeWord < 0xDC00n || nextCodeWord > 0xDFFFn) {
1201
1452
  // high surrogate without low surrogate
1202
1453
  throw MalformedUnicode
@@ -1230,13 +1481,14 @@ let decodedLength = (bytes: Bytes, encoding: Encoding, start: WasmI32, size: Was
1230
1481
  let mut ptr = start
1231
1482
  let mut count = 0n
1232
1483
  while (ptr < end) {
1233
- let codeWord = (WasmI32.load8U(ptr, 1n) << 8n) | (WasmI32.load8U(ptr, 0n))
1484
+ let codeWord = WasmI32.load8U(ptr, 1n) << 8n | WasmI32.load8U(ptr, 0n)
1234
1485
  let codeWord = if (codeWord >= 0xD800n && codeWord <= 0xDBFFn) {
1235
1486
  // high surrogate. need to check that next character is low srurrogate
1236
1487
  let ret = if (ptr + 2n >= end) {
1237
1488
  throw MalformedUnicode
1238
1489
  } else {
1239
- let nextCodeWord = (WasmI32.load8U(ptr, 3n) << 8n) | (WasmI32.load8U(ptr, 2n))
1490
+ let nextCodeWord = WasmI32.load8U(ptr, 3n) << 8n |
1491
+ WasmI32.load8U(ptr, 2n)
1240
1492
  if (nextCodeWord < 0xDC00n || nextCodeWord > 0xDFFFn) {
1241
1493
  // high surrogate without low surrogate
1242
1494
  throw MalformedUnicode
@@ -1274,7 +1526,10 @@ let decodedLength = (bytes: Bytes, encoding: Encoding, start: WasmI32, size: Was
1274
1526
  let mut ptr = start
1275
1527
  let mut count = 0n
1276
1528
  while (ptr < end) {
1277
- let codeWord = (WasmI32.load8U(ptr, 0n) << 24n) | (WasmI32.load8U(ptr, 1n) << 16n) | (WasmI32.load8U(ptr, 2n) << 8n) | (WasmI32.load8U(ptr, 3n))
1529
+ let codeWord = WasmI32.load8U(ptr, 0n) << 24n |
1530
+ WasmI32.load8U(ptr, 1n) << 16n |
1531
+ WasmI32.load8U(ptr, 2n) << 8n |
1532
+ WasmI32.load8U(ptr, 3n)
1278
1533
  ptr += 4n
1279
1534
  if (codeWord <= 0x007Fn) {
1280
1535
  count += 1n
@@ -1297,7 +1552,10 @@ let decodedLength = (bytes: Bytes, encoding: Encoding, start: WasmI32, size: Was
1297
1552
  let mut ptr = start
1298
1553
  let mut count = 0n
1299
1554
  while (ptr < end) {
1300
- let codeWord = (WasmI32.load8U(ptr, 3n) << 24n) | (WasmI32.load8U(ptr, 2n) << 16n) | (WasmI32.load8U(ptr, 1n) << 8n) | (WasmI32.load8U(ptr, 0n))
1555
+ let codeWord = WasmI32.load8U(ptr, 3n) << 24n |
1556
+ WasmI32.load8U(ptr, 2n) << 16n |
1557
+ WasmI32.load8U(ptr, 1n) << 8n |
1558
+ WasmI32.load8U(ptr, 0n)
1301
1559
  ptr += 4n
1302
1560
  if (codeWord <= 0x007Fn) {
1303
1561
  count += 1n
@@ -1310,19 +1568,19 @@ let decodedLength = (bytes: Bytes, encoding: Encoding, start: WasmI32, size: Was
1310
1568
  }
1311
1569
  }
1312
1570
  count
1313
- }
1571
+ },
1314
1572
  }
1315
1573
  }
1316
1574
 
1317
- // Decodes the given byte sequence into a string using the given encoding scheme
1318
- // @param bytes: Bytes - The input bytes
1319
- // @param encoding: Encoding - The encoding to use
1320
- // @param skipBom: Bool - Whether to include the byte-order marker (if present) in the decoded output
1321
- // @param start: Number - The byte offset to begin decoding from
1322
- // @param size: Number - The maximum number of bytes to decode
1323
- // @returns String
1324
1575
  @disableGC
1325
- let rec decodeRangeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool, start: Number, size: Number) => {
1576
+ let rec decodeRangeHelp =
1577
+ (
1578
+ bytes: Bytes,
1579
+ encoding: Encoding,
1580
+ skipBom: Bool,
1581
+ start: Number,
1582
+ size: Number,
1583
+ ) => {
1326
1584
  let (+) = WasmI32.add
1327
1585
  let (-) = WasmI32.sub
1328
1586
  let (<) = WasmI32.ltU
@@ -1337,7 +1595,7 @@ let rec decodeRangeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool, star
1337
1595
  let size = grainToWasmNumber(size, _SIZE_NAME)
1338
1596
  let hasBom = bytesHaveBom(bytes, encoding, start)
1339
1597
  let stringSize = decodedLength(bytes, encoding, start, size)
1340
- let stringSize = if (skipBom && hasBom) (stringSize - 3n) else stringSize
1598
+ let stringSize = if (skipBom && hasBom) stringSize - 3n else stringSize
1341
1599
  let str = allocateString(stringSize)
1342
1600
  let mut bytesPtr = WasmI32.fromGrain(bytes)
1343
1601
  let bytesSize = {
@@ -1352,7 +1610,7 @@ let rec decodeRangeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool, star
1352
1610
  let mut strPtr = str + 8n
1353
1611
  let mut bomRead = false
1354
1612
  if (skipBom && hasBom) {
1355
- bytesPtr += match(encoding) {
1613
+ bytesPtr += match (encoding) {
1356
1614
  UTF8 => 3n,
1357
1615
  UTF16_LE => 2n,
1358
1616
  UTF16_BE => 2n,
@@ -1361,9 +1619,9 @@ let rec decodeRangeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool, star
1361
1619
  }
1362
1620
  }
1363
1621
  let ret = if (stringSize == 0n) {
1364
- WasmI32.toGrain(str) : String
1622
+ WasmI32.toGrain(str): String
1365
1623
  } else {
1366
- match(encoding) {
1624
+ match (encoding) {
1367
1625
  UTF8 => {
1368
1626
  Memory.copy(strPtr, bytesPtr, stringSize)
1369
1627
  },
@@ -1371,11 +1629,14 @@ let rec decodeRangeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool, star
1371
1629
  // NOTE: Because the size check passed, we know the string is well-formed
1372
1630
  let end = bytesPtr + bytesSize
1373
1631
  while (bytesPtr < end) {
1374
- let w1 = (WasmI32.load8U(bytesPtr, 0n) << 8n) | (WasmI32.load8U(bytesPtr, 1n))
1632
+ let w1 = WasmI32.load8U(bytesPtr, 0n) << 8n |
1633
+ WasmI32.load8U(bytesPtr, 1n)
1375
1634
  let codeWord = if (w1 >= 0xD800n && w1 <= 0xDBFFn) {
1376
1635
  // high surrogate. next character is low srurrogate
1377
1636
  let w1 = (w1 & 0x03FFn) << 10n
1378
- let w2 = ((WasmI32.load8U(bytesPtr, 2n) << 8n) | (WasmI32.load8U(bytesPtr, 3n))) & 0x03FFn
1637
+ let w2 = (WasmI32.load8U(bytesPtr, 2n) << 8n |
1638
+ WasmI32.load8U(bytesPtr, 3n)) &
1639
+ 0x03FFn
1379
1640
  let codeWord = w1 + w2 + 0x10000n
1380
1641
  // no problems, so go past both code words
1381
1642
  bytesPtr += 4n
@@ -1391,11 +1652,14 @@ let rec decodeRangeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool, star
1391
1652
  // NOTE: Because the size check passed, we know the string is well-formed
1392
1653
  let end = bytesPtr + bytesSize
1393
1654
  while (bytesPtr < end) {
1394
- let w1 = (WasmI32.load8U(bytesPtr, 1n) << 8n) | (WasmI32.load8U(bytesPtr, 0n))
1655
+ let w1 = WasmI32.load8U(bytesPtr, 1n) << 8n |
1656
+ WasmI32.load8U(bytesPtr, 0n)
1395
1657
  let codeWord = if (w1 >= 0xD800n && w1 <= 0xDBFFn) {
1396
1658
  // high surrogate. next character is low srurrogate
1397
1659
  let w1 = (w1 & 0x03FFn) << 10n
1398
- let w2 = ((WasmI32.load8U(bytesPtr, 3n) << 8n) | (WasmI32.load8U(bytesPtr, 2n))) & 0x03FFn
1660
+ let w2 = (WasmI32.load8U(bytesPtr, 3n) << 8n |
1661
+ WasmI32.load8U(bytesPtr, 2n)) &
1662
+ 0x03FFn
1399
1663
  //let uPrime = codePoint - 0x10000n
1400
1664
  //let w1 = ((uPrime & 0b11111111110000000000n) >>> 10n) + 0xD800n // High surrogate
1401
1665
  //let w2 = (uPrime & 0b00000000001111111111n) + 0xDC00n // Low surrogate
@@ -1413,7 +1677,10 @@ let rec decodeRangeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool, star
1413
1677
  UTF32_BE => {
1414
1678
  let end = bytesPtr + bytesSize
1415
1679
  while (bytesPtr < end) {
1416
- let codeWord = (WasmI32.load8U(bytesPtr, 0n) << 24n) | (WasmI32.load8U(bytesPtr, 1n) << 16n) | (WasmI32.load8U(bytesPtr, 2n) << 8n) | (WasmI32.load8U(bytesPtr, 3n))
1680
+ let codeWord = WasmI32.load8U(bytesPtr, 0n) << 24n |
1681
+ WasmI32.load8U(bytesPtr, 1n) << 16n |
1682
+ WasmI32.load8U(bytesPtr, 2n) << 8n |
1683
+ WasmI32.load8U(bytesPtr, 3n)
1417
1684
  bytesPtr += 4n
1418
1685
  strPtr += writeUtf8CodePoint(strPtr, codeWord)
1419
1686
  }
@@ -1421,13 +1688,16 @@ let rec decodeRangeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool, star
1421
1688
  UTF32_LE => {
1422
1689
  let end = bytesPtr + bytesSize
1423
1690
  while (bytesPtr < end) {
1424
- let codeWord = (WasmI32.load8U(bytesPtr, 3n) << 24n) | (WasmI32.load8U(bytesPtr, 2n) << 16n) | (WasmI32.load8U(bytesPtr, 1n) << 8n) | (WasmI32.load8U(bytesPtr, 0n))
1691
+ let codeWord = WasmI32.load8U(bytesPtr, 3n) << 24n |
1692
+ WasmI32.load8U(bytesPtr, 2n) << 16n |
1693
+ WasmI32.load8U(bytesPtr, 1n) << 8n |
1694
+ WasmI32.load8U(bytesPtr, 0n)
1425
1695
  bytesPtr += 4n
1426
1696
  strPtr += writeUtf8CodePoint(strPtr, codeWord)
1427
1697
  }
1428
- }
1698
+ },
1429
1699
  }
1430
- WasmI32.toGrain(str) : String
1700
+ WasmI32.toGrain(str): String
1431
1701
  }
1432
1702
  // bytes: Bytes, encoding: Encoding, skipBom: Bool, start: Number, size: Number
1433
1703
  Memory.decRef(WasmI32.fromGrain(bytes))
@@ -1437,33 +1707,48 @@ let rec decodeRangeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool, star
1437
1707
  ret
1438
1708
  }
1439
1709
 
1440
- // Decodes the given byte sequence into a string using the given encoding scheme, skipping
1441
- // the byte-order marker, if it's present.
1442
- // @param bytes: Bytes - The input bytes
1443
- // @param encoding: Encoding - The encoding to use
1444
- // @param start: Number - The byte offset to begin decoding from
1445
- // @param size: Number - The maximum number of bytes to decode
1446
- // @returns String
1447
- export let decodeRange = (bytes: Bytes, encoding: Encoding, start: Number, size: Number) => {
1710
+ /**
1711
+ * Decodes the given byte sequence of the specified range into a string, excluding any byte-order marker, using encoding scheme provided.
1712
+ *
1713
+ * @param bytes: The input bytes
1714
+ * @param encoding: The encoding to use
1715
+ * @param start: The byte offset to begin decoding from
1716
+ * @param size: The maximum number of bytes to decode
1717
+ * @returns The decoded string
1718
+ *
1719
+ * @since v0.4.0
1720
+ */
1721
+ export let decodeRange =
1722
+ (
1723
+ bytes: Bytes,
1724
+ encoding: Encoding,
1725
+ start: Number,
1726
+ size: Number,
1727
+ ) => {
1448
1728
  decodeRangeHelp(bytes, encoding, true, start, size)
1449
1729
  }
1450
1730
 
1451
- // Decodes the given byte sequence into a string using the given encoding scheme, including
1452
- // the byte-order marker, if it's present.
1453
- // @param bytes: Bytes - The input bytes
1454
- // @param encoding: Encoding - The encoding to use
1455
- // @param start: Number - The byte offset to begin decoding from
1456
- // @param size: Number - The maximum number of bytes to decode
1457
- // @returns String
1458
- export let decodeRangeKeepBom = (bytes: Bytes, encoding: Encoding, start: Number, size: Number) => {
1731
+ /**
1732
+ * Decodes the given byte sequence of the specified range into a string, including any byte-order marker, using encoding scheme provided.
1733
+ *
1734
+ * @param bytes: The input bytes
1735
+ * @param encoding: The encoding to use
1736
+ * @param start: The byte offset to begin decoding from
1737
+ * @param size: The maximum number of bytes to decode
1738
+ * @returns The decoded string
1739
+ *
1740
+ * @since v0.4.0
1741
+ */
1742
+ export let decodeRangeKeepBom =
1743
+ (
1744
+ bytes: Bytes,
1745
+ encoding: Encoding,
1746
+ start: Number,
1747
+ size: Number,
1748
+ ) => {
1459
1749
  decodeRangeHelp(bytes, encoding, false, start, size)
1460
1750
  }
1461
1751
 
1462
- // Decodes the given byte sequence into a string using the given encoding scheme
1463
- // @param bytes: Bytes - The input bytes
1464
- // @param encoding: Encoding - The encoding to use
1465
- // @param skipBom: Bool - Whether to include the byte-order marker (if present) in the decoded output
1466
- // @returns String
1467
1752
  @disableGC
1468
1753
  let rec decodeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool) => {
1469
1754
  let bytesPtr = WasmI32.fromGrain(bytes)
@@ -1471,27 +1756,41 @@ let rec decodeHelp = (bytes: Bytes, encoding: Encoding, skipBom: Bool) => {
1471
1756
  Memory.incRef(WasmI32.fromGrain(decodeRangeHelp))
1472
1757
  Memory.incRef(WasmI32.fromGrain(bytes))
1473
1758
  Memory.incRef(WasmI32.fromGrain(encoding))
1474
- let ret = decodeRangeHelp(bytes, encoding, skipBom, 0, tagSimpleNumber(bytesSize))
1759
+ let ret = decodeRangeHelp(
1760
+ bytes,
1761
+ encoding,
1762
+ skipBom,
1763
+ 0,
1764
+ tagSimpleNumber(bytesSize)
1765
+ )
1475
1766
  Memory.incRef(WasmI32.fromGrain(bytes))
1476
1767
  Memory.incRef(WasmI32.fromGrain(encoding))
1477
1768
  Memory.incRef(WasmI32.fromGrain(decodeHelp))
1478
1769
  ret
1479
1770
  }
1480
1771
 
1481
- // Decodes the given byte sequence into a string using the given encoding scheme,
1482
- // skipping the byte-order marker, if it's present.
1483
- // @param bytes: Bytes - The input bytes
1484
- // @param encoding: Encoding - The encoding to use
1485
- // @returns String
1772
+ /**
1773
+ * Decodes the given byte sequence into a string using the given encoding scheme, excluding any byte-order marker.
1774
+ *
1775
+ * @param bytes: The input bytes
1776
+ * @param encoding: The encoding to use
1777
+ * @returns The decoded string
1778
+ *
1779
+ * @since v0.4.0
1780
+ */
1486
1781
  export let decode = (bytes: Bytes, encoding: Encoding) => {
1487
1782
  decodeHelp(bytes, encoding, true)
1488
1783
  }
1489
1784
 
1490
- // Decodes the given byte sequence into a string using the given encoding scheme,
1491
- // including the byte-order marker, if it's present
1492
- // @param bytes: Bytes - The input bytes
1493
- // @param encoding: Encoding - The encoding to use
1494
- // @returns String
1785
+ /**
1786
+ * Decodes the given byte sequence into a string using the given encoding scheme, including any byte-order marker.
1787
+ *
1788
+ * @param bytes: The input bytes
1789
+ * @param encoding: The encoding to use
1790
+ * @returns The decoded string
1791
+ *
1792
+ * @since v0.4.0
1793
+ */
1495
1794
  export let decodeKeepBom = (bytes: Bytes, encoding: Encoding) => {
1496
1795
  decodeHelp(bytes, encoding, false)
1497
1796
  }
@@ -1501,9 +1800,13 @@ export let decodeKeepBom = (bytes: Bytes, encoding: Encoding) => {
1501
1800
  *
1502
1801
  * @param fn: The iterator function
1503
1802
  * @param str: The string to iterate
1803
+ *
1804
+ * @example String.forEachCodePoint(print, "Hello world")
1805
+ *
1806
+ * @since v0.4.0
1504
1807
  */
1505
1808
  @disableGC
1506
- export let rec forEachCodePoint = (fn: (Number) -> Void, str: String) => {
1809
+ export let rec forEachCodePoint = (fn: Number -> Void, str: String) => {
1507
1810
  let (>>>) = WasmI32.shrU
1508
1811
  let (-) = WasmI32.sub
1509
1812
  let (&) = WasmI32.and
@@ -1559,9 +1862,17 @@ export let rec forEachCodePoint = (fn: (Number) -> Void, str: String) => {
1559
1862
  *
1560
1863
  * @param fn: The iterator function
1561
1864
  * @param str: The string to iterate
1865
+ *
1866
+ * @example String.forEachCodePointi((codepoint, index) => print((codepoint, index)), "Hello world")
1867
+ *
1868
+ * @since v0.4.0
1562
1869
  */
1563
1870
  @disableGC
1564
- export let rec forEachCodePointi = (fn: (Number, Number) -> Void, str: String) => {
1871
+ export let rec forEachCodePointi =
1872
+ (
1873
+ fn: (Number, Number) -> Void,
1874
+ str: String,
1875
+ ) => {
1565
1876
  let (>>>) = WasmI32.shrU
1566
1877
  let (-) = WasmI32.sub
1567
1878
  let (&) = WasmI32.and
@@ -1613,35 +1924,36 @@ let trimString = (str: String, end: Bool) => {
1613
1924
  let chars = explode(str), charsLength = length(str)
1614
1925
  let mut i = 0, offset = 1
1615
1926
  if (end) {
1616
- i = charsLength-1
1927
+ i = charsLength - 1
1617
1928
  offset = -1
1618
1929
  }
1619
1930
  for (; i < charsLength && i > -1; i += offset) {
1620
- let currentChar = chars[i];
1931
+ let currentChar = chars[i]
1621
1932
  // TODO: Use unicode whitespace property and unicode line terminator once github issue #661 is completed
1622
1933
  if (
1623
1934
  // Spacing
1624
- currentChar != '\u{0009}' && // Tab
1625
- currentChar != '\u{000B}' && // LINE TABULATION
1626
- currentChar != '\u{000C}' && // FORM FEED (FF)
1627
- currentChar != '\u{0020}' && // Space
1628
- currentChar != '\u{00A0}' && // No Break Space
1629
- currentChar != '\u{FEFF}' && // ZERO WIDTH NO-BREAK SPACE
1935
+ currentChar != '\u{0009}' && // Tab
1936
+ currentChar != '\u{000B}' && // LINE TABULATION
1937
+ currentChar != '\u{000C}' && // FORM FEED (FF)
1938
+ currentChar != '\u{0020}' && // Space
1939
+ currentChar != '\u{00A0}' && // No Break Space
1940
+ currentChar != '\u{FEFF}' && // ZERO WIDTH NO-BREAK SPACE
1630
1941
  // Line Terminators
1631
1942
  currentChar != '\n' && // LF
1632
1943
  currentChar != '\r' // CR
1633
1944
  ) break
1634
1945
  }
1635
- if (end) slice(0, i+1, str)
1636
- else slice(i, charsLength, str)
1946
+ if (end) slice(0, i + 1, str) else slice(i, charsLength, str)
1637
1947
  }
1638
1948
  /**
1639
1949
  * Trims the beginning of a string—removing any leading whitespace characters.
1640
1950
  *
1641
1951
  * @param string: The string to be trimmed
1642
1952
  * @returns The trimmed string
1643
- *
1953
+ *
1644
1954
  * @example String.trimStart(" Hello World") == "Hello World"
1955
+ *
1956
+ * @since v0.4.2
1645
1957
  */
1646
1958
  export let trimStart = (string: String) => trimString(string, false)
1647
1959
  /**
@@ -1649,8 +1961,10 @@ export let trimStart = (string: String) => trimString(string, false)
1649
1961
  *
1650
1962
  * @param string: The string to be trimmed
1651
1963
  * @returns The trimmed string
1652
- *
1964
+ *
1653
1965
  * @example String.trimEnd("Hello World ") == "Hello World"
1966
+ *
1967
+ * @since v0.4.2
1654
1968
  */
1655
1969
  export let trimEnd = (string: String) => trimString(string, true)
1656
1970
  /**
@@ -1658,7 +1972,9 @@ export let trimEnd = (string: String) => trimString(string, true)
1658
1972
  *
1659
1973
  * @param string: The string to be trimmed
1660
1974
  * @returns The trimmed string
1661
- *
1975
+ *
1662
1976
  * @example String.trim(" Hello World ") == "Hello World"
1977
+ *
1978
+ * @since v0.4.2
1663
1979
  */
1664
1980
  export let trim = (string: String) => trimEnd(trimStart(string))