@grain/stdlib 0.6.5 → 0.7.0

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 (139) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE +1 -1
  3. package/README.md +2 -2
  4. package/array.gr +55 -7
  5. package/array.md +123 -77
  6. package/bigint.md +30 -30
  7. package/buffer.gr +20 -53
  8. package/buffer.md +47 -47
  9. package/bytes.gr +111 -35
  10. package/bytes.md +111 -32
  11. package/char.gr +201 -99
  12. package/char.md +361 -34
  13. package/exception.gr +11 -11
  14. package/exception.md +26 -1
  15. package/float32.gr +327 -3
  16. package/float32.md +606 -19
  17. package/float64.gr +320 -3
  18. package/float64.md +606 -19
  19. package/fs.gr +1082 -0
  20. package/fs.md +630 -0
  21. package/hash.gr +142 -88
  22. package/hash.md +102 -14
  23. package/int16.md +23 -23
  24. package/int32.gr +25 -4
  25. package/int32.md +65 -30
  26. package/int64.gr +26 -1
  27. package/int64.md +65 -30
  28. package/int8.md +23 -23
  29. package/json.gr +366 -51
  30. package/json.md +418 -2
  31. package/list.gr +387 -49
  32. package/list.md +492 -69
  33. package/map.gr +20 -12
  34. package/map.md +44 -38
  35. package/marshal.gr +41 -40
  36. package/marshal.md +2 -2
  37. package/number.gr +159 -30
  38. package/number.md +215 -38
  39. package/option.md +21 -21
  40. package/package.json +5 -3
  41. package/path.gr +48 -0
  42. package/path.md +103 -12
  43. package/pervasives.gr +2 -2
  44. package/pervasives.md +37 -37
  45. package/priorityqueue.gr +7 -7
  46. package/priorityqueue.md +19 -19
  47. package/queue.gr +183 -29
  48. package/queue.md +296 -40
  49. package/random.md +6 -6
  50. package/range.gr +4 -4
  51. package/range.md +6 -6
  52. package/rational.md +16 -16
  53. package/regex.gr +52 -51
  54. package/regex.md +11 -11
  55. package/result.md +16 -16
  56. package/runtime/atof/common.md +39 -39
  57. package/runtime/atof/decimal.gr +6 -6
  58. package/runtime/atof/decimal.md +8 -8
  59. package/runtime/atof/lemire.gr +5 -5
  60. package/runtime/atof/lemire.md +1 -1
  61. package/runtime/atof/parse.gr +16 -16
  62. package/runtime/atof/parse.md +2 -2
  63. package/runtime/atof/slow.md +1 -1
  64. package/runtime/atof/table.md +2 -2
  65. package/runtime/atoi/parse.gr +3 -3
  66. package/runtime/atoi/parse.md +1 -1
  67. package/runtime/bigint.gr +15 -47
  68. package/runtime/bigint.md +54 -60
  69. package/runtime/compare.gr +2 -2
  70. package/runtime/compare.md +1 -1
  71. package/runtime/dataStructures.md +33 -33
  72. package/runtime/debugPrint.gr +4 -1
  73. package/runtime/debugPrint.md +9 -9
  74. package/runtime/equal.gr +99 -77
  75. package/runtime/equal.md +1 -1
  76. package/runtime/exception.gr +62 -82
  77. package/runtime/exception.md +62 -11
  78. package/runtime/gc.gr +39 -45
  79. package/runtime/gc.md +4 -4
  80. package/runtime/malloc.gr +7 -7
  81. package/runtime/malloc.md +4 -4
  82. package/runtime/math/kernel/cos.gr +70 -0
  83. package/runtime/math/kernel/cos.md +14 -0
  84. package/runtime/math/kernel/sin.gr +65 -0
  85. package/runtime/math/kernel/sin.md +14 -0
  86. package/runtime/math/kernel/tan.gr +136 -0
  87. package/runtime/math/kernel/tan.md +14 -0
  88. package/runtime/math/rempio2.gr +244 -0
  89. package/runtime/math/rempio2.md +14 -0
  90. package/runtime/math/trig.gr +130 -0
  91. package/runtime/math/trig.md +28 -0
  92. package/runtime/math/umuldi.gr +26 -0
  93. package/runtime/math/umuldi.md +14 -0
  94. package/runtime/numberUtils.gr +29 -29
  95. package/runtime/numberUtils.md +12 -12
  96. package/runtime/numbers.gr +373 -381
  97. package/runtime/numbers.md +79 -73
  98. package/runtime/string.gr +37 -105
  99. package/runtime/string.md +3 -9
  100. package/runtime/unsafe/constants.md +24 -24
  101. package/runtime/unsafe/conv.md +13 -13
  102. package/runtime/unsafe/memory.gr +24 -20
  103. package/runtime/unsafe/memory.md +27 -7
  104. package/runtime/unsafe/offsets.gr +36 -0
  105. package/runtime/unsafe/offsets.md +88 -0
  106. package/runtime/unsafe/panic.gr +28 -0
  107. package/runtime/unsafe/panic.md +14 -0
  108. package/runtime/unsafe/tags.md +32 -32
  109. package/runtime/unsafe/wasmf32.md +28 -28
  110. package/runtime/unsafe/wasmf64.md +28 -28
  111. package/runtime/unsafe/wasmi32.md +47 -47
  112. package/runtime/unsafe/wasmi64.md +50 -50
  113. package/runtime/utf8.gr +189 -0
  114. package/runtime/utf8.md +117 -0
  115. package/runtime/wasi.gr +4 -2
  116. package/runtime/wasi.md +138 -138
  117. package/set.gr +18 -11
  118. package/set.md +42 -36
  119. package/stack.gr +171 -2
  120. package/stack.md +297 -15
  121. package/string.gr +352 -557
  122. package/string.md +77 -34
  123. package/uint16.gr +81 -0
  124. package/uint16.md +183 -22
  125. package/uint32.gr +25 -4
  126. package/uint32.md +63 -28
  127. package/uint64.gr +25 -5
  128. package/uint64.md +63 -28
  129. package/uint8.gr +81 -0
  130. package/uint8.md +183 -22
  131. package/uri.gr +57 -53
  132. package/uri.md +11 -12
  133. package/wasi/file.gr +67 -59
  134. package/wasi/file.md +39 -39
  135. package/wasi/process.md +5 -5
  136. package/wasi/random.md +3 -3
  137. package/wasi/time.md +4 -4
  138. package/runtime/utils/printing.gr +0 -60
  139. package/runtime/utils/printing.md +0 -26
package/bytes.md CHANGED
@@ -33,7 +33,7 @@ No other changes yet.
33
33
  </details>
34
34
 
35
35
  ```grain
36
- make : (size: Number) => Bytes
36
+ make: (size: Number) => Bytes
37
37
  ```
38
38
 
39
39
  Creates a new byte sequence of the input size.
@@ -68,7 +68,7 @@ No other changes yet.
68
68
  </details>
69
69
 
70
70
  ```grain
71
- empty : Bytes
71
+ empty: Bytes
72
72
  ```
73
73
 
74
74
  An empty byte sequence.
@@ -87,7 +87,7 @@ No other changes yet.
87
87
  </details>
88
88
 
89
89
  ```grain
90
- fromString : (string: String) => Bytes
90
+ fromString: (string: String) => Bytes
91
91
  ```
92
92
 
93
93
  Creates a new byte sequence from the input string.
@@ -118,7 +118,7 @@ No other changes yet.
118
118
  </details>
119
119
 
120
120
  ```grain
121
- toString : (bytes: Bytes) => String
121
+ toString: (bytes: Bytes) => String
122
122
  ```
123
123
 
124
124
  Creates a new string from the input bytes.
@@ -153,7 +153,7 @@ No other changes yet.
153
153
  </details>
154
154
 
155
155
  ```grain
156
- length : (bytes: Bytes) => Number
156
+ length: (bytes: Bytes) => Number
157
157
  ```
158
158
 
159
159
  Returns the length of a byte sequence.
@@ -188,7 +188,7 @@ No other changes yet.
188
188
  </details>
189
189
 
190
190
  ```grain
191
- copy : (bytes: Bytes) => Bytes
191
+ copy: (bytes: Bytes) => Bytes
192
192
  ```
193
193
 
194
194
  Creates a new byte sequence that contains the same bytes as the input byte sequence.
@@ -219,7 +219,7 @@ No other changes yet.
219
219
  </details>
220
220
 
221
221
  ```grain
222
- slice : (start: Number, length: Number, bytes: Bytes) => Bytes
222
+ slice: (start: Number, length: Number, bytes: Bytes) => Bytes
223
223
  ```
224
224
 
225
225
  Returns a copy of a subset of the input byte sequence.
@@ -260,7 +260,7 @@ No other changes yet.
260
260
  </details>
261
261
 
262
262
  ```grain
263
- resize : (left: Number, right: Number, bytes: Bytes) => Bytes
263
+ resize: (left: Number, right: Number, bytes: Bytes) => Bytes
264
264
  ```
265
265
 
266
266
  Returns a copy of a byte sequence with bytes added or removed from the beginning and/or end.
@@ -301,7 +301,7 @@ No other changes yet.
301
301
  </details>
302
302
 
303
303
  ```grain
304
- move :
304
+ move:
305
305
  (srcIndex: Number, dstIndex: Number, length: Number, src: Bytes, dst: Bytes) =>
306
306
  Void
307
307
  ```
@@ -342,7 +342,7 @@ No other changes yet.
342
342
  </details>
343
343
 
344
344
  ```grain
345
- concat : (bytes1: Bytes, bytes2: Bytes) => Bytes
345
+ concat: (bytes1: Bytes, bytes2: Bytes) => Bytes
346
346
  ```
347
347
 
348
348
  Creates a new byte sequence that contains the bytes of both byte sequences.
@@ -383,7 +383,7 @@ assert Bytes.toString(Bytes.concat(helloBytes, worldBytes)) == "Hello World"
383
383
  </details>
384
384
 
385
385
  ```grain
386
- fill : (value: Uint8, bytes: Bytes) => Void
386
+ fill: (value: Uint8, bytes: Bytes) => Void
387
387
  ```
388
388
 
389
389
  Replaces all bytes in a byte sequnce with the new value provided.
@@ -411,7 +411,7 @@ No other changes yet.
411
411
  </details>
412
412
 
413
413
  ```grain
414
- clear : (bytes: Bytes) => Void
414
+ clear: (bytes: Bytes) => Void
415
415
  ```
416
416
 
417
417
  Replaces all bytes in a byte sequence with zeroes.
@@ -431,6 +431,85 @@ Bytes.clear(bytes)
431
431
  assert bytes == b"\x00\x00\x00\x00\x00"
432
432
  ```
433
433
 
434
+ ### Bytes.**getChar**
435
+
436
+ <details disabled>
437
+ <summary tabindex="-1">Added in <code>0.7.0</code></summary>
438
+ No other changes yet.
439
+ </details>
440
+
441
+ ```grain
442
+ getChar: (index: Number, bytes: Bytes) => Char
443
+ ```
444
+
445
+ Gets the UTF-8 encoded character at the given byte index.
446
+
447
+ Parameters:
448
+
449
+ |param|type|description|
450
+ |-----|----|-----------|
451
+ |`index`|`Number`|The byte index to access|
452
+ |`bytes`|`Bytes`|The byte sequence to access|
453
+
454
+ Returns:
455
+
456
+ |type|description|
457
+ |----|-----------|
458
+ |`Char`|The character that starts at the given index|
459
+
460
+ Throws:
461
+
462
+ `IndexOutOfBounds`
463
+
464
+ * When `index` is negative
465
+
466
+ `MalformedUnicode`
467
+
468
+ * When the requested character is not a valid UTF-8 sequence
469
+
470
+ Examples:
471
+
472
+ ```grain
473
+ let bytes = Bytes.fromString("Hello")
474
+ assert Bytes.getChar(0, bytes) == 'H'
475
+ ```
476
+
477
+ ### Bytes.**setChar**
478
+
479
+ <details disabled>
480
+ <summary tabindex="-1">Added in <code>0.7.0</code></summary>
481
+ No other changes yet.
482
+ </details>
483
+
484
+ ```grain
485
+ setChar: (index: Number, value: Char, bytes: Bytes) => Void
486
+ ```
487
+
488
+ UTF-8 encodes a character starting at the given byte index.
489
+
490
+ Parameters:
491
+
492
+ |param|type|description|
493
+ |-----|----|-----------|
494
+ |`index`|`Number`|The byte index to update|
495
+ |`value`|`Char`|The value to set|
496
+ |`bytes`|`Bytes`|The byte sequence to mutate|
497
+
498
+ Throws:
499
+
500
+ `IndexOutOfBounds`
501
+
502
+ * When `index` is negative
503
+ * When `index + charSize` is greater than the bytes size, `charSize` is the number of bytes in the character ranging from 1 to 4
504
+
505
+ Examples:
506
+
507
+ ```grain
508
+ let bytes = Bytes.make(1)
509
+ Bytes.setChar(0, 'a', bytes)
510
+ assert Bytes.getChar(0, bytes) == 'a'
511
+ ```
512
+
434
513
  ### Bytes.**getInt8**
435
514
 
436
515
  <details>
@@ -446,7 +525,7 @@ assert bytes == b"\x00\x00\x00\x00\x00"
446
525
  </details>
447
526
 
448
527
  ```grain
449
- getInt8 : (index: Number, bytes: Bytes) => Int8
528
+ getInt8: (index: Number, bytes: Bytes) => Int8
450
529
  ```
451
530
 
452
531
  Gets a signed 8-bit integer starting at the given byte index.
@@ -494,7 +573,7 @@ assert Bytes.getInt8(0, bytes) == 1s
494
573
  </details>
495
574
 
496
575
  ```grain
497
- setInt8 : (index: Number, value: Int8, bytes: Bytes) => Void
576
+ setInt8: (index: Number, value: Int8, bytes: Bytes) => Void
498
577
  ```
499
578
 
500
579
  Sets a signed 8-bit integer starting at the given byte index.
@@ -537,7 +616,7 @@ assert Bytes.getInt8(0, bytes) == 2s
537
616
  </details>
538
617
 
539
618
  ```grain
540
- getUint8 : (index: Number, bytes: Bytes) => Uint8
619
+ getUint8: (index: Number, bytes: Bytes) => Uint8
541
620
  ```
542
621
 
543
622
  Gets an unsigned 8-bit integer starting at the given byte index.
@@ -578,7 +657,7 @@ No other changes yet.
578
657
  </details>
579
658
 
580
659
  ```grain
581
- setUint8 : (index: Number, value: Uint8, bytes: Bytes) => Void
660
+ setUint8: (index: Number, value: Uint8, bytes: Bytes) => Void
582
661
  ```
583
662
 
584
663
  Sets an unsigned 8-bit integer starting at the given byte index.
@@ -621,7 +700,7 @@ assert Bytes.getUint8(1, bytes) == 2us
621
700
  </details>
622
701
 
623
702
  ```grain
624
- getInt16 : (index: Number, bytes: Bytes) => Int16
703
+ getInt16: (index: Number, bytes: Bytes) => Int16
625
704
  ```
626
705
 
627
706
  Gets a signed 16-bit integer starting at the given byte index.
@@ -669,7 +748,7 @@ assert Bytes.getInt16(0, bytes) == -2S
669
748
  </details>
670
749
 
671
750
  ```grain
672
- setInt16 : (index: Number, value: Int16, bytes: Bytes) => Void
751
+ setInt16: (index: Number, value: Int16, bytes: Bytes) => Void
673
752
  ```
674
753
 
675
754
  Sets a signed 16-bit integer starting at the given byte index.
@@ -712,7 +791,7 @@ assert Bytes.getInt16(0, bytes) == -1S
712
791
  </details>
713
792
 
714
793
  ```grain
715
- getUint16 : (index: Number, bytes: Bytes) => Uint16
794
+ getUint16: (index: Number, bytes: Bytes) => Uint16
716
795
  ```
717
796
 
718
797
  Gets an unsigned 16-bit integer starting at the given byte index.
@@ -753,7 +832,7 @@ No other changes yet.
753
832
  </details>
754
833
 
755
834
  ```grain
756
- setUint16 : (index: Number, value: Uint16, bytes: Bytes) => Void
835
+ setUint16: (index: Number, value: Uint16, bytes: Bytes) => Void
757
836
  ```
758
837
 
759
838
  Sets an unsigned 16-bit integer starting at the given byte index.
@@ -789,7 +868,7 @@ No other changes yet.
789
868
  </details>
790
869
 
791
870
  ```grain
792
- getInt32 : (index: Number, bytes: Bytes) => Int32
871
+ getInt32: (index: Number, bytes: Bytes) => Int32
793
872
  ```
794
873
 
795
874
  Gets a signed 32-bit integer starting at the given byte index.
@@ -830,7 +909,7 @@ No other changes yet.
830
909
  </details>
831
910
 
832
911
  ```grain
833
- setInt32 : (index: Number, value: Int32, bytes: Bytes) => Void
912
+ setInt32: (index: Number, value: Int32, bytes: Bytes) => Void
834
913
  ```
835
914
 
836
915
  Sets a signed 32-bit integer starting at the given byte index.
@@ -866,7 +945,7 @@ No other changes yet.
866
945
  </details>
867
946
 
868
947
  ```grain
869
- getUint32 : (index: Number, bytes: Bytes) => Uint32
948
+ getUint32: (index: Number, bytes: Bytes) => Uint32
870
949
  ```
871
950
 
872
951
  Gets an unsigned 32-bit integer starting at the given byte index.
@@ -907,7 +986,7 @@ No other changes yet.
907
986
  </details>
908
987
 
909
988
  ```grain
910
- setUint32 : (index: Number, value: Uint32, bytes: Bytes) => Void
989
+ setUint32: (index: Number, value: Uint32, bytes: Bytes) => Void
911
990
  ```
912
991
 
913
992
  Sets an unsigned 32-bit integer starting at the given byte index.
@@ -943,7 +1022,7 @@ No other changes yet.
943
1022
  </details>
944
1023
 
945
1024
  ```grain
946
- getFloat32 : (index: Number, bytes: Bytes) => Float32
1025
+ getFloat32: (index: Number, bytes: Bytes) => Float32
947
1026
  ```
948
1027
 
949
1028
  Gets a 32-bit float starting at the given byte index.
@@ -984,7 +1063,7 @@ No other changes yet.
984
1063
  </details>
985
1064
 
986
1065
  ```grain
987
- setFloat32 : (index: Number, value: Float32, bytes: Bytes) => Void
1066
+ setFloat32: (index: Number, value: Float32, bytes: Bytes) => Void
988
1067
  ```
989
1068
 
990
1069
  Sets a 32-bit float starting at the given byte index.
@@ -1020,7 +1099,7 @@ No other changes yet.
1020
1099
  </details>
1021
1100
 
1022
1101
  ```grain
1023
- getInt64 : (index: Number, bytes: Bytes) => Int64
1102
+ getInt64: (index: Number, bytes: Bytes) => Int64
1024
1103
  ```
1025
1104
 
1026
1105
  Gets a signed 64-bit integer starting at the given byte index.
@@ -1061,7 +1140,7 @@ No other changes yet.
1061
1140
  </details>
1062
1141
 
1063
1142
  ```grain
1064
- setInt64 : (index: Number, value: Int64, bytes: Bytes) => Void
1143
+ setInt64: (index: Number, value: Int64, bytes: Bytes) => Void
1065
1144
  ```
1066
1145
 
1067
1146
  Sets a signed 64-bit integer starting at the given byte index.
@@ -1097,7 +1176,7 @@ No other changes yet.
1097
1176
  </details>
1098
1177
 
1099
1178
  ```grain
1100
- getUint64 : (index: Number, bytes: Bytes) => Uint64
1179
+ getUint64: (index: Number, bytes: Bytes) => Uint64
1101
1180
  ```
1102
1181
 
1103
1182
  Gets an unsigned 64-bit integer starting at the given byte index.
@@ -1138,7 +1217,7 @@ No other changes yet.
1138
1217
  </details>
1139
1218
 
1140
1219
  ```grain
1141
- setUint64 : (index: Number, value: Uint64, bytes: Bytes) => Void
1220
+ setUint64: (index: Number, value: Uint64, bytes: Bytes) => Void
1142
1221
  ```
1143
1222
 
1144
1223
  Sets an unsigned 64-bit integer starting at the given byte index.
@@ -1174,7 +1253,7 @@ No other changes yet.
1174
1253
  </details>
1175
1254
 
1176
1255
  ```grain
1177
- getFloat64 : (index: Number, bytes: Bytes) => Float64
1256
+ getFloat64: (index: Number, bytes: Bytes) => Float64
1178
1257
  ```
1179
1258
 
1180
1259
  Gets a 64-bit float starting at the given byte index.
@@ -1215,7 +1294,7 @@ No other changes yet.
1215
1294
  </details>
1216
1295
 
1217
1296
  ```grain
1218
- setFloat64 : (index: Number, value: Float64, bytes: Bytes) => Void
1297
+ setFloat64: (index: Number, value: Float64, bytes: Bytes) => Void
1219
1298
  ```
1220
1299
 
1221
1300
  Sets a 64-bit float starting at the given byte index.
package/char.gr CHANGED
@@ -16,8 +16,8 @@ module Char
16
16
  from "runtime/unsafe/wasmi32" include WasmI32
17
17
  from "runtime/dataStructures" include DataStructures
18
18
  use DataStructures.{ tagSimpleNumber, tagChar, untagChar, allocateString }
19
-
20
- exception MalformedUtf8
19
+ from "runtime/utf8" include Utf8
20
+ use Utf8.{ usvEncodeLength, writeUtf8CodePoint }
21
21
 
22
22
  /**
23
23
  * The minimum valid Unicode scalar value.
@@ -44,9 +44,9 @@ provide let max = 0x10FFFF
44
44
  * @since v0.3.0
45
45
  */
46
46
  provide let isValid = charCode => {
47
- charCode >= min &&
48
- (charCode <= 0xD7FF || charCode >= 0xE000) &&
49
- charCode <= max
47
+ charCode >= min
48
+ && (charCode <= 0xD7FF || charCode >= 0xE000)
49
+ && charCode <= max
50
50
  }
51
51
 
52
52
  /**
@@ -164,52 +164,48 @@ provide let pred = char => {
164
164
  */
165
165
  @unsafe
166
166
  provide let toString = (char: Char) => {
167
- use WasmI32.{
168
- (+),
169
- (-),
170
- (*),
171
- (&),
172
- (|),
173
- (>>>),
174
- ltU as (<),
175
- gtU as (>),
176
- leU as (<=),
177
- }
178
-
167
+ use WasmI32.{ (+) }
179
168
  let usv = untagChar(char)
169
+ let byteCount = usvEncodeLength(usv)
170
+ let string = allocateString(byteCount)
171
+ writeUtf8CodePoint(string + 8n, usv)
172
+ WasmI32.toGrain(string): String
173
+ }
180
174
 
181
- let result = if (usv < 0x80n) {
182
- let string = allocateString(1n)
183
- WasmI32.store8(string, usv, 8n)
184
- WasmI32.toGrain(string): String
185
- } else {
186
- let mut count = 0n
187
- let mut offset = 0n
188
- if (usv <= 0x07FFn) {
189
- count = 1n
190
- offset = 0xC0n
191
- } else if (usv <= 0xFFFFn) {
192
- count = 2n
193
- offset = 0xE0n
194
- } else {
195
- count = 3n
196
- offset = 0xF0n
197
- }
198
- let string = allocateString(count + 1n)
199
- WasmI32.store8(string, (usv >>> (6n * count)) + offset, 8n)
200
-
201
- let mut n = 0n
202
- while (count > 0n) {
203
- n += 1n
204
- let temp = usv >>> (6n * (count - 1n))
205
- WasmI32.store8(string + n, 0x80n | temp & 0x3Fn, 8n)
206
- count -= 1n
207
- }
175
+ /**
176
+ * Byte encodings
177
+ *
178
+ * @since v0.7.0
179
+ */
180
+ provide enum Encoding {
181
+ UTF8,
182
+ UTF16,
183
+ UTF32,
184
+ }
208
185
 
209
- WasmI32.toGrain(string): String
186
+ /**
187
+ * Returns the byte count of a character if encoded in the given encoding.
188
+ *
189
+ * @param encoding: The encoding to check
190
+ * @param char: The character
191
+ * @returns The byte count of the character in the given encoding
192
+ *
193
+ * @example Char.encodedLength(Char.UTF8, 'a') == 1
194
+ * @example Char.encodedLength(Char.UTF8, '🌾') == 4
195
+ * @example Char.encodedLength(Char.UTF16, '©') == 1
196
+ *
197
+ * @since v0.7.0
198
+ */
199
+ @unsafe
200
+ provide let encodedLength = (encoding, char: Char) => {
201
+ let usv = untagChar(char)
202
+ let utf8ByteCount = usvEncodeLength(usv)
203
+ let utf8ByteCount = tagSimpleNumber(utf8ByteCount)
204
+ match (encoding) {
205
+ UTF32 => 4,
206
+ UTF16 => if (utf8ByteCount == 4) 2 else 1,
207
+ UTF8 => utf8ByteCount,
210
208
  }
211
-
212
- result
213
209
  }
214
210
 
215
211
  /**
@@ -315,64 +311,170 @@ provide let (>=) = (x: Char, y: Char) => {
315
311
  }
316
312
 
317
313
  /**
318
- * Checks if the character is an ASCII digit.
314
+ * Utilities for working with ASCII characters.
319
315
  *
320
- * @param char: The character to check
321
- * @returns `true` if the character is an ASCII digit or `false` otherwise
322
- *
323
- * @example assert Char.isAsciiDigit('1')
324
- * @example assert !Char.isAsciiDigit('a')
316
+ * @example Char.Ascii.isAscii('1')
325
317
  *
326
- * @since v0.6.0
318
+ * @since v0.7.0
327
319
  */
328
- provide let isAsciiDigit = char => char >= '0' && char <= '9'
320
+ provide module Ascii {
321
+ /**
322
+ * The minimum valid ASCII character code.
323
+ *
324
+ * @since v0.7.0
325
+ */
326
+ provide let min = 0x00
329
327
 
330
- /**
331
- * Checks if the character is an ASCII alphabetical character.
332
- *
333
- * @param char: The character to check
334
- * @returns `true` if the character is an ASCII alphabetical or `false` otherwise
335
- *
336
- * @example assert Char.isAsciiAlpha('a')
337
- * @example assert !Char.isAsciiAlpha('1')
338
- *
339
- * @since v0.6.0
340
- */
341
- provide let isAsciiAlpha = char =>
342
- char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z'
328
+ /**
329
+ * The maximum valid ASCII character code.
330
+ *
331
+ * @since v0.7.0
332
+ */
333
+ provide let max = 0x7F
343
334
 
344
- /**
345
- * Converts the character to ASCII lowercase if it is an ASCII uppercase character.
346
- *
347
- * @param char: The character to convert
348
- * @returns The lowercased character
349
- *
350
- * @example assert Char.toAsciiLowercase('B') == 'b'
351
- *
352
- * @since v0.6.0
353
- */
354
- provide let toAsciiLowercase = char => {
355
- if (char >= 'A' && char <= 'Z') {
356
- fromCode(code(char) + 0x20)
357
- } else {
358
- char
335
+ /**
336
+ * Checks if the character is a valid ASCII character.
337
+ *
338
+ * @param char: The character to check
339
+ * @returns `true` if the character is an ASCII character or `false` otherwise
340
+ *
341
+ * @example assert Char.Ascii.isValid('1')
342
+ * @example assert Char.Ascii.isValid('a')
343
+ * @example assert !Char.Ascii.isValid('🌾')
344
+ *
345
+ * @since v0.7.0
346
+ */
347
+ provide let isValid = char => char <= '\u{007F}'
348
+
349
+ /**
350
+ * Checks if the character is an ASCII digit.
351
+ *
352
+ * @param char: The character to check
353
+ * @returns `true` if the character is an ASCII digit or `false` otherwise
354
+ *
355
+ * @example assert Char.Ascii.isDigit('1')
356
+ * @example assert !Char.Ascii.isDigit('a')
357
+ *
358
+ * @since v0.7.0
359
+ * @history v0.6.0: Originally `Char.isAsciiDigit`
360
+ */
361
+ provide let isDigit = char => char >= '0' && char <= '9'
362
+
363
+ /**
364
+ * Checks if the character is an ASCII alphabetical character.
365
+ *
366
+ * @param char: The character to check
367
+ * @returns `true` if the character is an ASCII alphabetical or `false` otherwise
368
+ *
369
+ * @example assert Char.Ascii.isAlpha('a')
370
+ * @example assert !Char.Ascii.isAlpha('1')
371
+ *
372
+ * @since v0.7.0
373
+ * @history v0.6.0: Originally `Char.isAsciiAlpha`
374
+ */
375
+ provide let isAlpha = char =>
376
+ char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z'
377
+
378
+ /**
379
+ * Checks if the character is an ASCII control character.
380
+ *
381
+ * @param char: The character to check
382
+ * @returns `true` if the character is an ASCII control character or `false` otherwise
383
+ *
384
+ * @example assert Char.Ascii.isControl('\t')
385
+ * @example assert Char.Ascii.isControl('\n')
386
+ * @example assert !Char.Ascii.isControl('1')
387
+ * @example assert !Char.Ascii.isControl('a')
388
+ *
389
+ * @since v0.7.0
390
+ */
391
+ provide let isControl = char => char <= '\u{001F}' || char == '\u{007F}'
392
+
393
+ /**
394
+ * Checks if the character is an ASCII whitespace character.
395
+ *
396
+ * @param char: The character to check
397
+ * @returns `true` if the character is an ASCII whitespace character or `false` otherwise
398
+ *
399
+ * @example assert Char.isWhitespace('\t')
400
+ * @example assert Char.isWhitespace('\n')
401
+ * @example assert !Char.isWhitespace('1')
402
+ * @example assert !Char.isWhitespace('a')
403
+ *
404
+ * @since v0.7.0
405
+ */
406
+ provide let isWhitespace = char => {
407
+ match (char) {
408
+ '\t' | '\n' | '\x0C' | '\r' | ' ' => true,
409
+ _ => false,
410
+ }
359
411
  }
360
- }
361
412
 
362
- /**
363
- * Converts the character to ASCII uppercase if it is an ASCII lowercase character.
364
- *
365
- * @param char: The character to convert
366
- * @returns The uppercased character
367
- *
368
- * @example assert Char.toAsciiUppercase('b') == 'B'
369
- *
370
- * @since v0.6.0
371
- */
372
- provide let toAsciiUppercase = char => {
373
- if (char >= 'a' && char <= 'z') {
374
- fromCode(code(char) - 0x20)
375
- } else {
376
- char
413
+ /**
414
+ * Checks if the character is an ASCII punctuation character.
415
+ *
416
+ * @param char: The character to check
417
+ * @returns `true` if the character is an ASCII punctuation character or `false` otherwise
418
+ *
419
+ * @example assert Char.Ascii.isPunctuation('!')
420
+ * @example assert !Char.Ascii.isPunctuation('1')
421
+ *
422
+ * @since v0.7.0
423
+ */
424
+ provide let isPunctuation = char =>
425
+ char >= '!' && char <= '/'
426
+ || char >= ':' && char <= '@'
427
+ || char >= '[' && char <= '`'
428
+ || char >= '{' && char <= '~'
429
+
430
+ /**
431
+ * Checks if the character is an ASCII graphic character.
432
+ *
433
+ * @param char: The character to check
434
+ * @returns `true` if the character is an ASCII graphic character or `false` otherwise
435
+ *
436
+ * @example assert Char.Ascii.isGraphic('!')
437
+ * @example assert !Char.Ascii.isGraphic('\t')
438
+ *
439
+ * @since v0.7.0
440
+ */
441
+ provide let isGraphic = char => char >= '!' && char <= '~'
442
+
443
+ /**
444
+ * Converts the character to ASCII lowercase if it is an ASCII uppercase character.
445
+ *
446
+ * @param char: The character to convert
447
+ * @returns The lowercased character
448
+ *
449
+ * @example assert Char.Ascii.toLowercase('B') == 'b'
450
+ *
451
+ * @since v0.7.0
452
+ * @history v0.6.0: Originally `Char.toAsciiLowercase`
453
+ */
454
+ provide let toLowercase = char => {
455
+ if (char >= 'A' && char <= 'Z') {
456
+ fromCode(code(char) + 0x20)
457
+ } else {
458
+ char
459
+ }
460
+ }
461
+
462
+ /**
463
+ * Converts the character to ASCII uppercase if it is an ASCII lowercase character.
464
+ *
465
+ * @param char: The character to convert
466
+ * @returns The uppercased character
467
+ *
468
+ * @example assert Char.Ascii.toUppercase('b') == 'B'
469
+ *
470
+ * @since v0.7.0
471
+ * @history v0.6.0: Originally `Char.toAsciiUppercase`
472
+ */
473
+ provide let toUppercase = char => {
474
+ if (char >= 'a' && char <= 'z') {
475
+ fromCode(code(char) - 0x20)
476
+ } else {
477
+ char
478
+ }
377
479
  }
378
480
  }