@grain/stdlib 0.4.3 → 0.4.4
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/CHANGELOG.md +22 -0
- package/array.gr +118 -49
- package/array.md +60 -5
- package/buffer.gr +95 -41
- package/hash.gr +7 -2
- package/list.gr +54 -0
- package/number.gr +24 -6
- package/number.md +32 -0
- package/option.gr +244 -37
- package/option.md +579 -0
- package/package.json +1 -1
- package/queue.gr +98 -29
- package/queue.md +191 -0
- package/range.md +1 -1
- package/regex.md +9 -9
- package/result.gr +216 -70
- package/result.md +446 -0
- package/runtime/stringUtils.gr +172 -0
- package/set.gr +172 -5
- package/set.md +502 -0
- package/string.gr +30 -3
- package/string.md +31 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
### [0.4.4](https://www.github.com/grain-lang/grain/compare/stdlib-v0.4.3...stdlib-v0.4.4) (2021-12-11)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **stdlib:** Add reverse function to String module ([#1027](https://www.github.com/grain-lang/grain/issues/1027)) ([df761db](https://www.github.com/grain-lang/grain/commit/df761db55b3e14e31190090ae008ce5047135c09))
|
|
9
|
+
* **stdlib:** Add rotate function in Array module ([#838](https://www.github.com/grain-lang/grain/issues/838)) ([98fc577](https://www.github.com/grain-lang/grain/commit/98fc577ee754317cd2421bfaa8e3c1e049488949))
|
|
10
|
+
* **stdlib:** Add sort function to Array module ([#1012](https://www.github.com/grain-lang/grain/issues/1012)) ([9091930](https://www.github.com/grain-lang/grain/commit/9091930344224925bb7b2e1ef6f879c79a5c2f62))
|
|
11
|
+
* **stdlib:** Implement List.sort via mergesort ([#1014](https://www.github.com/grain-lang/grain/issues/1014)) ([a076e20](https://www.github.com/grain-lang/grain/commit/a076e200013114ccf16c2e6cbe814af1ec09c1ce))
|
|
12
|
+
* **stdlib:** Number.parseInt ([#1051](https://www.github.com/grain-lang/grain/issues/1051)) ([abafb58](https://www.github.com/grain-lang/grain/commit/abafb587e54219a32ed77ba09863bb2d6a80bac8))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **graindoc:** Ensure value_description is resolved to outcome before printing ([#1070](https://www.github.com/grain-lang/grain/issues/1070)) ([5eb05cc](https://www.github.com/grain-lang/grain/commit/5eb05cc2dedc3b933e194be86dd5d3c3656d6490))
|
|
18
|
+
* **stdlib:** Add bounds checking to Buffer addStringSlice & addBytesSlice ([#1065](https://www.github.com/grain-lang/grain/issues/1065)) ([06fe512](https://www.github.com/grain-lang/grain/commit/06fe512e863aeeb855ccf3e3b83bcd3bc8854723))
|
|
19
|
+
* **stdlib:** Fix String.encode GC ([#1067](https://www.github.com/grain-lang/grain/issues/1067)) ([0ab38c9](https://www.github.com/grain-lang/grain/commit/0ab38c9f4aa0ee84688ba5c6bec1521b380d38b1))
|
|
20
|
+
* **stdlib:** Removed memory leak in Hash module ([#1045](https://www.github.com/grain-lang/grain/issues/1045)) ([01a81c6](https://www.github.com/grain-lang/grain/commit/01a81c6a2573cca94b2d57d0fc70693d39f810a1))
|
|
21
|
+
* **stdlib:** Removed memory leaks in Buffer module ([#1047](https://www.github.com/grain-lang/grain/issues/1047)) ([d33017b](https://www.github.com/grain-lang/grain/commit/d33017b37e988d3facbca2e30e3de4fb8c7b5b8a))
|
|
22
|
+
* **stdlib:** Support arrays of any type in Array rotate ([#1048](https://www.github.com/grain-lang/grain/issues/1048)) ([3ceb1cf](https://www.github.com/grain-lang/grain/commit/3ceb1cf04c1604f49077e8733dcccb6cdaaf9f3a))
|
|
23
|
+
* **stdlib:** Support empty arrays in Array rotate ([3ceb1cf](https://www.github.com/grain-lang/grain/commit/3ceb1cf04c1604f49077e8733dcccb6cdaaf9f3a))
|
|
24
|
+
|
|
3
25
|
### [0.4.3](https://www.github.com/grain-lang/grain/compare/stdlib-v0.4.2...stdlib-v0.4.3) (2021-10-27)
|
|
4
26
|
|
|
5
27
|
|
package/array.gr
CHANGED
|
@@ -243,15 +243,10 @@ export let copy = (array) => {
|
|
|
243
243
|
*/
|
|
244
244
|
export let cycle = (fn, n, array) => {
|
|
245
245
|
let length = length(array)
|
|
246
|
-
let mut iteration = 0
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
while (count < length) {
|
|
250
|
-
fn(array[count]): Void
|
|
251
|
-
count = incr(count)
|
|
246
|
+
for (let mut iteration = 0; iteration < n; iteration += 1) {
|
|
247
|
+
for (let mut count = 0; count < length; count += 1) {
|
|
248
|
+
fn(array[count]): (Void)
|
|
252
249
|
}
|
|
253
|
-
iteration = incr(iteration)
|
|
254
|
-
count = 0
|
|
255
250
|
}
|
|
256
251
|
}
|
|
257
252
|
|
|
@@ -266,10 +261,8 @@ export let cycle = (fn, n, array) => {
|
|
|
266
261
|
*/
|
|
267
262
|
export let forEach = (fn, array) => {
|
|
268
263
|
let length = length(array)
|
|
269
|
-
let mut count = 0
|
|
270
|
-
|
|
271
|
-
fn(array[count]): Void
|
|
272
|
-
count = incr(count)
|
|
264
|
+
for (let mut count = 0; count < length; count += 1) {
|
|
265
|
+
fn(array[count]): (Void)
|
|
273
266
|
}
|
|
274
267
|
}
|
|
275
268
|
|
|
@@ -285,10 +278,8 @@ export let forEach = (fn, array) => {
|
|
|
285
278
|
*/
|
|
286
279
|
export let forEachi = (fn, array) => {
|
|
287
280
|
let length = length(array)
|
|
288
|
-
let mut count = 0
|
|
289
|
-
while (count < length) {
|
|
281
|
+
for (let mut count = 0; count < length; count += 1) {
|
|
290
282
|
fn(array[count], count): (Void)
|
|
291
|
-
count = incr(count)
|
|
292
283
|
}
|
|
293
284
|
}
|
|
294
285
|
|
|
@@ -458,9 +449,12 @@ export let fillRange = (value, start, stop, array) => {
|
|
|
458
449
|
}
|
|
459
450
|
|
|
460
451
|
let mut index = startIndex
|
|
461
|
-
|
|
462
|
-
|
|
452
|
+
for (
|
|
453
|
+
let mut index = startIndex;
|
|
454
|
+
index < stopIndex && index < length;
|
|
463
455
|
index += 1
|
|
456
|
+
) {
|
|
457
|
+
array[index] = value
|
|
464
458
|
}
|
|
465
459
|
void
|
|
466
460
|
}
|
|
@@ -543,11 +537,9 @@ export let fromList = (list) => {
|
|
|
543
537
|
export let contains = (search, array) => {
|
|
544
538
|
// TODO: This should use recursion when we can pattern match arrays
|
|
545
539
|
let len = length(array)
|
|
546
|
-
let mut index = 0
|
|
547
540
|
let mut found = false
|
|
548
|
-
|
|
549
|
-
found =
|
|
550
|
-
index += 1
|
|
541
|
+
for (let mut index = 0; !found && index < len; index += 1) {
|
|
542
|
+
found = array[index] == search
|
|
551
543
|
}
|
|
552
544
|
found
|
|
553
545
|
}
|
|
@@ -575,7 +567,7 @@ export let find = (fn, array) => {
|
|
|
575
567
|
matchedItem = array[count]
|
|
576
568
|
count = length
|
|
577
569
|
} else {
|
|
578
|
-
count
|
|
570
|
+
count += 1
|
|
579
571
|
}
|
|
580
572
|
}
|
|
581
573
|
if(!matching) {
|
|
@@ -609,7 +601,7 @@ export let findIndex = (fn, array) => {
|
|
|
609
601
|
matchedIndex = count
|
|
610
602
|
count = length
|
|
611
603
|
} else {
|
|
612
|
-
count
|
|
604
|
+
count += 1
|
|
613
605
|
}
|
|
614
606
|
}
|
|
615
607
|
if(!matching) {
|
|
@@ -637,7 +629,7 @@ export let product = (array1: Array<a>, array2: Array<b>) => {
|
|
|
637
629
|
|
|
638
630
|
init(lenA * lenB, n => {
|
|
639
631
|
if(n % lenB == 0){
|
|
640
|
-
indexA
|
|
632
|
+
indexA += 1
|
|
641
633
|
} else {
|
|
642
634
|
indexA = indexA
|
|
643
635
|
}
|
|
@@ -658,12 +650,9 @@ export let count = (fn, array) => {
|
|
|
658
650
|
let length = length(array)
|
|
659
651
|
let mut position = 0
|
|
660
652
|
let mut count = 0
|
|
661
|
-
|
|
653
|
+
for (let mut position = 0; position < length; position += 1) {
|
|
662
654
|
if(fn(array[position])) {
|
|
663
|
-
count
|
|
664
|
-
position = incr(position)
|
|
665
|
-
} else {
|
|
666
|
-
position = incr(position)
|
|
655
|
+
count += 1
|
|
667
656
|
}
|
|
668
657
|
}
|
|
669
658
|
count
|
|
@@ -681,14 +670,10 @@ export let count = (fn, array) => {
|
|
|
681
670
|
*/
|
|
682
671
|
export let counti = (fn, array) => {
|
|
683
672
|
let length = length(array)
|
|
684
|
-
let mut position = 0
|
|
685
673
|
let mut count = 0
|
|
686
|
-
|
|
687
|
-
if(fn(array[position], position)) {
|
|
688
|
-
count
|
|
689
|
-
position = incr(position)
|
|
690
|
-
} else {
|
|
691
|
-
position = incr(position)
|
|
674
|
+
for (let mut position = 0; position < length; position += 1) {
|
|
675
|
+
if (fn(array[position], position)) {
|
|
676
|
+
count += 1
|
|
692
677
|
}
|
|
693
678
|
}
|
|
694
679
|
count
|
|
@@ -711,7 +696,7 @@ export let filter = (fn, array) => {
|
|
|
711
696
|
forEach((el) => {
|
|
712
697
|
if (fn(el)) {
|
|
713
698
|
filtered[position] = el
|
|
714
|
-
position
|
|
699
|
+
position += 1
|
|
715
700
|
}
|
|
716
701
|
}, array)
|
|
717
702
|
init(position, (index) => {
|
|
@@ -736,7 +721,7 @@ export let filteri = (fn, array) => {
|
|
|
736
721
|
forEachi((el, index) => {
|
|
737
722
|
if (fn(el, index)) {
|
|
738
723
|
filtered[position] = el
|
|
739
|
-
position
|
|
724
|
+
position += 1
|
|
740
725
|
}
|
|
741
726
|
}, array)
|
|
742
727
|
init(position, (index) => {
|
|
@@ -828,6 +813,18 @@ export let join = (separator: String, items: Array<String>) => {
|
|
|
828
813
|
}
|
|
829
814
|
}
|
|
830
815
|
|
|
816
|
+
/**
|
|
817
|
+
* A simple helper function to convert a negative array index
|
|
818
|
+
* number to its positive positional equivalent.
|
|
819
|
+
*/
|
|
820
|
+
let wrapNegativeIndex = (arrLen, idx) => {
|
|
821
|
+
if (idx >= 0) {
|
|
822
|
+
idx
|
|
823
|
+
} else {
|
|
824
|
+
arrLen + idx
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
831
828
|
/**
|
|
832
829
|
* Slices an array given zero-based start and end indexes. The value
|
|
833
830
|
* at the end index will not be included in the result.
|
|
@@ -844,17 +841,8 @@ export let join = (separator: String, items: Array<String>) => {
|
|
|
844
841
|
*/
|
|
845
842
|
export let slice = (startIndex, endIndex, array) => {
|
|
846
843
|
let arrayLength = length(array)
|
|
847
|
-
|
|
848
|
-
let
|
|
849
|
-
if (idx >= 0) {
|
|
850
|
-
idx
|
|
851
|
-
} else {
|
|
852
|
-
arrayLength + idx
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
let startIndex = wrapNegativeIndex(startIndex)
|
|
857
|
-
let endIndex = wrapNegativeIndex(endIndex)
|
|
844
|
+
let startIndex = wrapNegativeIndex(arrayLength, startIndex)
|
|
845
|
+
let endIndex = wrapNegativeIndex(arrayLength, endIndex)
|
|
858
846
|
// Ensure we aren't working with an `end` value that is too big
|
|
859
847
|
let endIndex = if (endIndex > arrayLength) {
|
|
860
848
|
arrayLength
|
|
@@ -871,3 +859,84 @@ export let slice = (startIndex, endIndex, array) => {
|
|
|
871
859
|
init(newLength, n => array[startIndex + n])
|
|
872
860
|
}
|
|
873
861
|
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Sorts an array in-place.
|
|
865
|
+
*
|
|
866
|
+
* Ordering is calculated using a comparator function which takes two array elements and must return 0 if both are equal, a positive number if the first is greater, and a negative number if the first is smaller.
|
|
867
|
+
* @param comp: The comparator function used to indicate sort order
|
|
868
|
+
* @param array: The array to be sorted
|
|
869
|
+
* @since v0.4.5
|
|
870
|
+
*/
|
|
871
|
+
export let sort = (comp, array) => {
|
|
872
|
+
let partition = (low, high) => {
|
|
873
|
+
let pivot = array[high]
|
|
874
|
+
let mut i = low - 1
|
|
875
|
+
for(let mut j = low; j < high; j += 1) {
|
|
876
|
+
if(comp(array[j], pivot) < 0){
|
|
877
|
+
i += 1
|
|
878
|
+
let temp = array[i]
|
|
879
|
+
array[i] = array[j]
|
|
880
|
+
array[j] = temp
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
let temp = array[i + 1]
|
|
884
|
+
array[i + 1] = array[high]
|
|
885
|
+
array[high] = temp
|
|
886
|
+
i + 1
|
|
887
|
+
}
|
|
888
|
+
let rec quicksort = (low, high) => {
|
|
889
|
+
if(low < high){
|
|
890
|
+
let partitionIndex = partition(low, high)
|
|
891
|
+
quicksort(partitionIndex + 1, high)
|
|
892
|
+
quicksort(low, partitionIndex - 1)
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
let len = length(array)
|
|
896
|
+
quicksort(0, len - 1)
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* Rotates an array by n elements to the right, in place.
|
|
901
|
+
*
|
|
902
|
+
* If n is negative, the array will be rotated by n elements
|
|
903
|
+
* to the left. See examples.
|
|
904
|
+
*
|
|
905
|
+
* @param n: The number of elements to rotate by
|
|
906
|
+
* @param arr: The array to be rotated
|
|
907
|
+
*
|
|
908
|
+
* @example let array = [> 1, 2, 3, 4, 5]; rotate(2, arr); arr == [> 4, 5, 1, 2, 3]
|
|
909
|
+
* @example let array = [> 1, 2, 3, 4, 5]; rotate(-1, arr); arr == [> 2, 3, 4, 5, 1]
|
|
910
|
+
* @since v0.4.5
|
|
911
|
+
*/
|
|
912
|
+
export let rotate = (n, arr) => {
|
|
913
|
+
let rec gcd = (a, b) => {
|
|
914
|
+
if (b == 0) {
|
|
915
|
+
a
|
|
916
|
+
}
|
|
917
|
+
else{
|
|
918
|
+
gcd(b, a % b)
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
let arrLen = length(arr)
|
|
923
|
+
if (arrLen > 0) {
|
|
924
|
+
let k = n % arrLen
|
|
925
|
+
let mut d = -1
|
|
926
|
+
let mut j = 0
|
|
927
|
+
for (let mut i = 0; i < gcd(arrLen, k); i += 1) {
|
|
928
|
+
j = i
|
|
929
|
+
let temp = arr[i]
|
|
930
|
+
while (true) {
|
|
931
|
+
d = (j - k) % arrLen
|
|
932
|
+
if (d == i) {
|
|
933
|
+
break
|
|
934
|
+
}
|
|
935
|
+
let newVal = arr[d]
|
|
936
|
+
arr[j] = newVal
|
|
937
|
+
j = d
|
|
938
|
+
}
|
|
939
|
+
arr[j] = temp
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
package/array.md
CHANGED
|
@@ -371,7 +371,7 @@ Returns:
|
|
|
371
371
|
|
|
372
372
|
|type|description|
|
|
373
373
|
|----|-----------|
|
|
374
|
-
|`Array<
|
|
374
|
+
|`Array<b>`|The new array with mapped values|
|
|
375
375
|
|
|
376
376
|
### Array.**mapi**
|
|
377
377
|
|
|
@@ -398,7 +398,7 @@ Returns:
|
|
|
398
398
|
|
|
399
399
|
|type|description|
|
|
400
400
|
|----|-----------|
|
|
401
|
-
|`Array<
|
|
401
|
+
|`Array<b>`|The new array with mapped values|
|
|
402
402
|
|
|
403
403
|
### Array.**reduce**
|
|
404
404
|
|
|
@@ -425,7 +425,7 @@ Parameters:
|
|
|
425
425
|
|-----|----|-----------|
|
|
426
426
|
|`fn`|`(a, b) -> a`|The reducer function to call on each element, where the value returned will be the next accumulator value|
|
|
427
427
|
|`initial`|`a`|The initial value to use for the accumulator on the first iteration|
|
|
428
|
-
|`array`|`Array<
|
|
428
|
+
|`array`|`Array<b>`|The array to iterate|
|
|
429
429
|
|
|
430
430
|
Returns:
|
|
431
431
|
|
|
@@ -465,7 +465,7 @@ Parameters:
|
|
|
465
465
|
|-----|----|-----------|
|
|
466
466
|
|`fn`|`(a, b, Number) -> a`|The reducer function to call on each element, where the value returned will be the next accumulator value|
|
|
467
467
|
|`initial`|`a`|The initial value to use for the accumulator on the first iteration|
|
|
468
|
-
|`array`|`Array<
|
|
468
|
+
|`array`|`Array<b>`|The array to iterate|
|
|
469
469
|
|
|
470
470
|
Returns:
|
|
471
471
|
|
|
@@ -500,7 +500,7 @@ Returns:
|
|
|
500
500
|
|
|
501
501
|
|type|description|
|
|
502
502
|
|----|-----------|
|
|
503
|
-
|`Array<
|
|
503
|
+
|`Array<b>`|The new array|
|
|
504
504
|
|
|
505
505
|
### Array.**every**
|
|
506
506
|
|
|
@@ -1027,3 +1027,58 @@ Returns:
|
|
|
1027
1027
|
|----|-----------|
|
|
1028
1028
|
|`Array<a>`|The subset of the array that was sliced|
|
|
1029
1029
|
|
|
1030
|
+
### Array.**sort**
|
|
1031
|
+
|
|
1032
|
+
<details disabled>
|
|
1033
|
+
<summary tabindex="-1">Added in <code>next</code></summary>
|
|
1034
|
+
No other changes yet.
|
|
1035
|
+
</details>
|
|
1036
|
+
|
|
1037
|
+
```grain
|
|
1038
|
+
sort : (((a, a) -> Number), Array<a>) -> Void
|
|
1039
|
+
```
|
|
1040
|
+
|
|
1041
|
+
Sorts an array in-place.
|
|
1042
|
+
|
|
1043
|
+
Ordering is calculated using a comparator function which takes two array elements and must return 0 if both are equal, a positive number if the first is greater, and a negative number if the first is smaller.
|
|
1044
|
+
|
|
1045
|
+
Parameters:
|
|
1046
|
+
|
|
1047
|
+
|param|type|description|
|
|
1048
|
+
|-----|----|-----------|
|
|
1049
|
+
|`comp`|`(a, a) -> Number`|The comparator function used to indicate sort order|
|
|
1050
|
+
|`array`|`Array<a>`|The array to be sorted|
|
|
1051
|
+
|
|
1052
|
+
### Array.**rotate**
|
|
1053
|
+
|
|
1054
|
+
<details disabled>
|
|
1055
|
+
<summary tabindex="-1">Added in <code>next</code></summary>
|
|
1056
|
+
No other changes yet.
|
|
1057
|
+
</details>
|
|
1058
|
+
|
|
1059
|
+
```grain
|
|
1060
|
+
rotate : (Number, Array<a>) -> Void
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
Rotates an array by n elements to the right, in place.
|
|
1064
|
+
|
|
1065
|
+
If n is negative, the array will be rotated by n elements
|
|
1066
|
+
to the left. See examples.
|
|
1067
|
+
|
|
1068
|
+
Parameters:
|
|
1069
|
+
|
|
1070
|
+
|param|type|description|
|
|
1071
|
+
|-----|----|-----------|
|
|
1072
|
+
|`n`|`Number`|The number of elements to rotate by|
|
|
1073
|
+
|`arr`|`Array<a>`|The array to be rotated|
|
|
1074
|
+
|
|
1075
|
+
Examples:
|
|
1076
|
+
|
|
1077
|
+
```grain
|
|
1078
|
+
let array = [> 1, 2, 3, 4, 5]; rotate(2, arr); arr == [> 4, 5, 1, 2, 3]
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
```grain
|
|
1082
|
+
let array = [> 1, 2, 3, 4, 5]; rotate(-1, arr); arr == [> 2, 3, 4, 5, 1]
|
|
1083
|
+
```
|
|
1084
|
+
|
package/buffer.gr
CHANGED
|
@@ -16,24 +16,20 @@ import Bytes from "bytes"
|
|
|
16
16
|
import String from "string"
|
|
17
17
|
import { coerceNumberToWasmI32 } from "runtime/numbers"
|
|
18
18
|
|
|
19
|
-
record Buffer {
|
|
20
|
-
mut len: Number,
|
|
21
|
-
initialSize: Number,
|
|
22
|
-
mut data: Bytes,
|
|
23
|
-
}
|
|
19
|
+
record Buffer { mut len: Number, initialSize: Number, mut data: Bytes }
|
|
24
20
|
|
|
25
21
|
@disableGC
|
|
26
|
-
let mut _SIZE_OFFSET = 1n
|
|
22
|
+
let mut _SIZE_OFFSET = 1n
|
|
27
23
|
|
|
28
24
|
@disableGC
|
|
29
|
-
let mut _VALUE_OFFSET = 1n
|
|
25
|
+
let mut _VALUE_OFFSET = 1n
|
|
30
26
|
|
|
31
27
|
@disableGC
|
|
32
28
|
let initOffsets = () => {
|
|
33
|
-
_SIZE_OFFSET = 4n
|
|
34
|
-
_VALUE_OFFSET = 8n
|
|
29
|
+
_SIZE_OFFSET = 4n
|
|
30
|
+
_VALUE_OFFSET = 8n
|
|
35
31
|
}
|
|
36
|
-
initOffsets()
|
|
32
|
+
initOffsets()
|
|
37
33
|
|
|
38
34
|
let _8BIT_LEN = 1
|
|
39
35
|
|
|
@@ -45,27 +41,28 @@ let _64BIT_LEN = 8
|
|
|
45
41
|
|
|
46
42
|
/* Gets the size of a Bytes via its ptr */
|
|
47
43
|
@disableGC
|
|
48
|
-
let getSize =
|
|
44
|
+
let getSize = ptr => WasmI32.load(ptr, _SIZE_OFFSET)
|
|
49
45
|
|
|
50
46
|
/* Doubles the size of buffer's underlying byte sequence, if the given size is larger than the size of a buffer's underlying byte sequence */
|
|
51
47
|
let autogrow = (len, buf) => {
|
|
52
48
|
while (buf.len + len > Bytes.length(buf.data)) {
|
|
53
49
|
let mut n = Bytes.length(buf.data)
|
|
54
|
-
if (n == 0) n = 4
|
|
50
|
+
if (n == 0) n = 4
|
|
51
|
+
// Make sure bytes of 0 length grow too
|
|
55
52
|
buf.data = Bytes.resize(0, n, buf.data)
|
|
56
53
|
}
|
|
57
54
|
}
|
|
58
55
|
|
|
59
56
|
/* Gets the pointer for a char's bytes following the char's tag */
|
|
60
57
|
@disableGC
|
|
61
|
-
let rec getCharAsWasmI32 =
|
|
58
|
+
let rec getCharAsWasmI32 = char => {
|
|
62
59
|
let c = WasmI32.fromGrain(char)
|
|
63
60
|
WasmI32.load(c, 4n)
|
|
64
61
|
}
|
|
65
62
|
|
|
66
63
|
/* Gets the UTF-8 byte length of a char */
|
|
67
64
|
@disableGC
|
|
68
|
-
let rec getCharByteLength =
|
|
65
|
+
let rec getCharByteLength = byte => {
|
|
69
66
|
let (+) = WasmI32.add
|
|
70
67
|
let (&) = WasmI32.and
|
|
71
68
|
let (==) = WasmI32.eq
|
|
@@ -132,13 +129,11 @@ let addInt32help = (value, buffer) => {
|
|
|
132
129
|
*
|
|
133
130
|
* @since v0.4.0
|
|
134
131
|
*/
|
|
135
|
-
export let make =
|
|
136
|
-
if (initialSize < 0) throw Exception.InvalidArgument(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
data: Bytes.make(initialSize),
|
|
141
|
-
}
|
|
132
|
+
export let make = initialSize => {
|
|
133
|
+
if (initialSize < 0) throw Exception.InvalidArgument(
|
|
134
|
+
"Buffers size must be >= 0",
|
|
135
|
+
)
|
|
136
|
+
{ len: 0, initialSize, data: Bytes.make(initialSize) }
|
|
142
137
|
}
|
|
143
138
|
|
|
144
139
|
/**
|
|
@@ -149,7 +144,7 @@ export let make = (initialSize) => {
|
|
|
149
144
|
*
|
|
150
145
|
* @since v0.4.0
|
|
151
146
|
*/
|
|
152
|
-
export let length =
|
|
147
|
+
export let length = buffer => buffer.len
|
|
153
148
|
|
|
154
149
|
/**
|
|
155
150
|
* Clears data in the buffer and sets its length to zero.
|
|
@@ -160,7 +155,7 @@ export let length = (buffer) => buffer.len
|
|
|
160
155
|
*
|
|
161
156
|
* @since v0.4.0
|
|
162
157
|
*/
|
|
163
|
-
export let clear =
|
|
158
|
+
export let clear = buffer => {
|
|
164
159
|
Bytes.fill(0x0l, buffer.data)
|
|
165
160
|
buffer.len = 0
|
|
166
161
|
}
|
|
@@ -174,7 +169,7 @@ export let clear = (buffer) => {
|
|
|
174
169
|
*
|
|
175
170
|
* @since v0.4.0
|
|
176
171
|
*/
|
|
177
|
-
export let reset =
|
|
172
|
+
export let reset = buffer => {
|
|
178
173
|
buffer.data = Bytes.make(buffer.initialSize)
|
|
179
174
|
buffer.len = 0
|
|
180
175
|
}
|
|
@@ -192,7 +187,6 @@ export let reset = (buffer) => {
|
|
|
192
187
|
@disableGC
|
|
193
188
|
export let rec truncate = (length, buffer) => {
|
|
194
189
|
Memory.incRef(WasmI32.fromGrain((<)))
|
|
195
|
-
Memory.incRef(WasmI32.fromGrain((||)))
|
|
196
190
|
Memory.incRef(WasmI32.fromGrain((>)))
|
|
197
191
|
if (length < 0 || length > buffer.len) throw Exception.IndexOutOfBounds
|
|
198
192
|
|
|
@@ -217,7 +211,7 @@ export let rec truncate = (length, buffer) => {
|
|
|
217
211
|
*
|
|
218
212
|
* @since v0.4.0
|
|
219
213
|
*/
|
|
220
|
-
export let toBytes =
|
|
214
|
+
export let toBytes = buffer => {
|
|
221
215
|
let len = Bytes.length(buffer.data)
|
|
222
216
|
if (buffer.len == len) {
|
|
223
217
|
buffer.data
|
|
@@ -249,7 +243,7 @@ export let toBytesSlice = (start, length, buffer) => {
|
|
|
249
243
|
*
|
|
250
244
|
* @since v0.4.0
|
|
251
245
|
*/
|
|
252
|
-
export let toString =
|
|
246
|
+
export let toString = buffer => {
|
|
253
247
|
Bytes.toString(toBytes(buffer))
|
|
254
248
|
}
|
|
255
249
|
|
|
@@ -286,6 +280,8 @@ export let rec addChar = (char: Char, buffer: Buffer) => {
|
|
|
286
280
|
Memory.incRef(WasmI32.fromGrain(c))
|
|
287
281
|
Memory.incRef(WasmI32.fromGrain(buffer))
|
|
288
282
|
addInt8help(c, buffer)
|
|
283
|
+
Memory.decRef(WasmI32.fromGrain(c))
|
|
284
|
+
void
|
|
289
285
|
},
|
|
290
286
|
2n => {
|
|
291
287
|
let c = Conv.toInt32(n)
|
|
@@ -293,6 +289,8 @@ export let rec addChar = (char: Char, buffer: Buffer) => {
|
|
|
293
289
|
Memory.incRef(WasmI32.fromGrain(c))
|
|
294
290
|
Memory.incRef(WasmI32.fromGrain(buffer))
|
|
295
291
|
addInt16help(c, buffer)
|
|
292
|
+
Memory.decRef(WasmI32.fromGrain(c))
|
|
293
|
+
void
|
|
296
294
|
},
|
|
297
295
|
3n => {
|
|
298
296
|
let (<) = WasmI32.ltU
|
|
@@ -300,12 +298,14 @@ export let rec addChar = (char: Char, buffer: Buffer) => {
|
|
|
300
298
|
let (*) = WasmI32.mul
|
|
301
299
|
let (&) = WasmI32.and
|
|
302
300
|
let (>>) = WasmI32.shrU
|
|
303
|
-
for (let mut i = 0n; i < 3n; i
|
|
304
|
-
let c = Conv.toInt32(n >>
|
|
301
|
+
for (let mut i = 0n; i < 3n; i += 1n) {
|
|
302
|
+
let c = Conv.toInt32(n >> i * 8n & 0xffn)
|
|
305
303
|
Memory.incRef(WasmI32.fromGrain(addInt8help))
|
|
306
304
|
Memory.incRef(WasmI32.fromGrain(c))
|
|
307
305
|
Memory.incRef(WasmI32.fromGrain(buffer))
|
|
308
306
|
addInt8help(c, buffer)
|
|
307
|
+
Memory.decRef(WasmI32.fromGrain(c))
|
|
308
|
+
void
|
|
309
309
|
}
|
|
310
310
|
},
|
|
311
311
|
_ => {
|
|
@@ -314,6 +314,8 @@ export let rec addChar = (char: Char, buffer: Buffer) => {
|
|
|
314
314
|
Memory.incRef(WasmI32.fromGrain(c))
|
|
315
315
|
Memory.incRef(WasmI32.fromGrain(buffer))
|
|
316
316
|
addInt32help(c, buffer)
|
|
317
|
+
Memory.decRef(WasmI32.fromGrain(c))
|
|
318
|
+
void
|
|
317
319
|
},
|
|
318
320
|
}
|
|
319
321
|
|
|
@@ -406,28 +408,58 @@ export let rec addString = (string, buffer) => {
|
|
|
406
408
|
* @since v0.4.0
|
|
407
409
|
*/
|
|
408
410
|
@disableGC
|
|
409
|
-
export let rec addStringSlice = (start, length, string, buffer) => {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
411
|
+
export let rec addStringSlice = (start: Number, length, string, buffer) => {
|
|
412
|
+
// Handle negative start index (needed before #1071 is fixed)
|
|
413
|
+
let start = {
|
|
414
|
+
// this is a block to avoid making all of these operators
|
|
415
|
+
// overriden in the whole function
|
|
416
|
+
let (<<) = WasmI32.shl
|
|
417
|
+
let (>>) = WasmI32.shrS
|
|
418
|
+
let (+) = WasmI32.add
|
|
419
|
+
let (!=) = WasmI32.ne
|
|
420
|
+
let (&) = WasmI32.and
|
|
421
|
+
Memory.incRef(WasmI32.fromGrain(String.length))
|
|
422
|
+
Memory.incRef(WasmI32.fromGrain(string))
|
|
423
|
+
let strlen = WasmI32.fromGrain(String.length(string)) >> 1n
|
|
424
|
+
let mut startW = WasmI32.fromGrain(start)
|
|
425
|
+
if ((startW & 1n) != 1n) {
|
|
426
|
+
throw InvalidArgument("Invalid start index")
|
|
427
|
+
}
|
|
428
|
+
startW = startW >> 1n
|
|
429
|
+
if (WasmI32.ltS(startW, 0n)) {
|
|
430
|
+
WasmI32.toGrain(WasmI32.shl(startW + strlen, 1n) + 1n)
|
|
431
|
+
} else {
|
|
432
|
+
start
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
let end = start + length
|
|
436
|
+
Memory.incRef(WasmI32.fromGrain(String.slice))
|
|
437
|
+
// no incref for start since we know it's a simple num. Add back for good measure after #1071 is fixed!
|
|
438
|
+
Memory.incRef(WasmI32.fromGrain(end))
|
|
413
439
|
Memory.incRef(WasmI32.fromGrain(string))
|
|
414
|
-
let
|
|
440
|
+
let slice = String.slice(start, end, string)
|
|
441
|
+
|
|
442
|
+
Memory.incRef(WasmI32.fromGrain(String.byteLength))
|
|
443
|
+
Memory.incRef(WasmI32.fromGrain(slice))
|
|
444
|
+
let bytelen = String.byteLength(slice)
|
|
415
445
|
|
|
416
446
|
Memory.incRef(WasmI32.fromGrain(autogrow))
|
|
417
447
|
Memory.incRef(WasmI32.fromGrain(bytelen))
|
|
418
448
|
Memory.incRef(WasmI32.fromGrain(buffer))
|
|
419
449
|
autogrow(bytelen, buffer)
|
|
420
450
|
|
|
421
|
-
let srcOff =
|
|
451
|
+
let srcOff = 0n
|
|
422
452
|
let dstOff = coerceNumberToWasmI32(buffer.len)
|
|
423
|
-
let src = WasmI32.fromGrain(
|
|
453
|
+
let src = WasmI32.fromGrain(slice)
|
|
424
454
|
let dst = WasmI32.fromGrain(buffer.data)
|
|
425
455
|
appendBytes(srcOff, dstOff, coerceNumberToWasmI32(bytelen), src, dst)
|
|
456
|
+
Memory.decRef(WasmI32.fromGrain(slice))
|
|
426
457
|
|
|
427
458
|
Memory.incRef(WasmI32.fromGrain((+)))
|
|
428
459
|
Memory.incRef(WasmI32.fromGrain(buffer.len))
|
|
429
460
|
Memory.incRef(WasmI32.fromGrain(bytelen))
|
|
430
461
|
buffer.len = buffer.len + bytelen
|
|
462
|
+
Memory.decRef(WasmI32.fromGrain(bytelen))
|
|
431
463
|
|
|
432
464
|
Memory.decRef(WasmI32.fromGrain(start))
|
|
433
465
|
Memory.decRef(WasmI32.fromGrain(length))
|
|
@@ -448,17 +480,40 @@ export let rec addStringSlice = (start, length, string, buffer) => {
|
|
|
448
480
|
* @since v0.4.0
|
|
449
481
|
*/
|
|
450
482
|
@disableGC
|
|
451
|
-
export let rec addBytesSlice =
|
|
483
|
+
export let rec addBytesSlice =
|
|
484
|
+
(
|
|
485
|
+
start: Number,
|
|
486
|
+
length: Number,
|
|
487
|
+
bytes: Bytes,
|
|
488
|
+
buffer: Buffer,
|
|
489
|
+
) => {
|
|
490
|
+
let (-) = WasmI32.sub
|
|
491
|
+
let (<) = WasmI32.ltS
|
|
492
|
+
let (>) = WasmI32.gtS
|
|
493
|
+
let (>=) = WasmI32.geS
|
|
494
|
+
|
|
495
|
+
// bounds check start
|
|
496
|
+
let bytelen = WasmI32.load(WasmI32.fromGrain(bytes), 4n)
|
|
497
|
+
let srcOff = coerceNumberToWasmI32(start)
|
|
498
|
+
if (srcOff < 0n || srcOff >= bytelen) {
|
|
499
|
+
throw Exception.IndexOutOfBounds
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// bounds check length
|
|
503
|
+
let len = coerceNumberToWasmI32(length)
|
|
504
|
+
if (len < 0n || len > bytelen - srcOff) {
|
|
505
|
+
throw Exception.IndexOutOfBounds
|
|
506
|
+
}
|
|
507
|
+
|
|
452
508
|
Memory.incRef(WasmI32.fromGrain(autogrow))
|
|
453
509
|
Memory.incRef(WasmI32.fromGrain(length))
|
|
454
510
|
Memory.incRef(WasmI32.fromGrain(buffer))
|
|
455
511
|
autogrow(length, buffer)
|
|
456
512
|
|
|
457
|
-
let srcOff = coerceNumberToWasmI32(start)
|
|
458
513
|
let dstOff = coerceNumberToWasmI32(buffer.len)
|
|
459
514
|
let src = WasmI32.fromGrain(bytes)
|
|
460
515
|
let dst = WasmI32.fromGrain(buffer.data)
|
|
461
|
-
appendBytes(srcOff, dstOff,
|
|
516
|
+
appendBytes(srcOff, dstOff, len, src, dst)
|
|
462
517
|
|
|
463
518
|
Memory.incRef(WasmI32.fromGrain((+)))
|
|
464
519
|
Memory.incRef(WasmI32.fromGrain(buffer.len))
|
|
@@ -507,7 +562,6 @@ export let addBufferSlice = (start, length, srcBuffer, dstBuffer) => {
|
|
|
507
562
|
* @section Binary operations on integers: Functions for encoding and decoding integers stored in a buffer.
|
|
508
563
|
*/
|
|
509
564
|
|
|
510
|
-
|
|
511
565
|
/**
|
|
512
566
|
* Gets a signed 8-bit integer starting at the given byte index.
|
|
513
567
|
*
|
|
@@ -783,4 +837,4 @@ export let addFloat64 = (value, buffer) => {
|
|
|
783
837
|
let index = buffer.len
|
|
784
838
|
buffer.len = buffer.len + _64BIT_LEN
|
|
785
839
|
setFloat64(index, value, buffer)
|
|
786
|
-
}
|
|
840
|
+
}
|