@grain/stdlib 0.6.6 → 0.7.1
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 +67 -0
- package/LICENSE +1 -1
- package/README.md +2 -2
- package/array.gr +55 -7
- package/array.md +606 -560
- package/bigint.md +228 -228
- package/buffer.gr +85 -53
- package/buffer.md +442 -319
- package/bytes.gr +112 -35
- package/bytes.md +299 -219
- package/char.gr +201 -99
- package/char.md +447 -120
- package/exception.gr +11 -11
- package/exception.md +29 -4
- package/float32.gr +327 -3
- package/float32.md +698 -111
- package/float64.gr +320 -3
- package/float64.md +698 -111
- package/fs.gr +1082 -0
- package/fs.md +630 -0
- package/hash.gr +142 -88
- package/hash.md +105 -17
- package/int16.md +178 -178
- package/int32.gr +26 -5
- package/int32.md +266 -231
- package/int64.gr +27 -2
- package/int64.md +266 -231
- package/int8.md +178 -178
- package/json.gr +366 -51
- package/json.md +431 -15
- package/list.gr +328 -31
- package/list.md +759 -336
- package/map.gr +20 -12
- package/map.md +266 -260
- package/marshal.gr +41 -40
- package/marshal.md +14 -14
- package/number.gr +278 -35
- package/number.md +688 -269
- package/option.md +162 -162
- package/package.json +5 -3
- package/path.gr +48 -0
- package/path.md +180 -89
- package/pervasives.gr +2 -2
- package/pervasives.md +275 -275
- package/priorityqueue.gr +7 -7
- package/priorityqueue.md +131 -131
- package/queue.gr +183 -29
- package/queue.md +404 -148
- package/random.md +43 -43
- package/range.gr +4 -4
- package/range.md +42 -42
- package/rational.md +123 -123
- package/regex.gr +52 -51
- package/regex.md +102 -102
- package/result.md +118 -118
- package/runtime/atof/common.md +39 -39
- package/runtime/atof/decimal.gr +6 -6
- package/runtime/atof/decimal.md +14 -14
- package/runtime/atof/lemire.gr +5 -5
- package/runtime/atof/lemire.md +1 -1
- package/runtime/atof/parse.gr +16 -16
- package/runtime/atof/parse.md +2 -2
- package/runtime/atof/slow.md +1 -1
- package/runtime/atof/table.md +2 -2
- package/runtime/atoi/parse.gr +3 -3
- package/runtime/atoi/parse.md +1 -1
- package/runtime/bigint.gr +15 -47
- package/runtime/bigint.md +54 -60
- package/runtime/compare.gr +2 -2
- package/runtime/compare.md +8 -8
- package/runtime/dataStructures.md +211 -211
- package/runtime/debugPrint.gr +4 -1
- package/runtime/debugPrint.md +9 -9
- package/runtime/equal.gr +99 -77
- package/runtime/equal.md +8 -8
- package/runtime/exception.gr +62 -82
- package/runtime/exception.md +62 -11
- package/runtime/gc.gr +39 -45
- package/runtime/gc.md +4 -4
- package/runtime/malloc.gr +7 -7
- package/runtime/malloc.md +13 -13
- package/runtime/math/kernel/cos.gr +70 -0
- package/runtime/math/kernel/cos.md +14 -0
- package/runtime/math/kernel/sin.gr +65 -0
- package/runtime/math/kernel/sin.md +14 -0
- package/runtime/math/kernel/tan.gr +136 -0
- package/runtime/math/kernel/tan.md +14 -0
- package/runtime/math/rempio2.gr +244 -0
- package/runtime/math/rempio2.md +14 -0
- package/runtime/math/trig.gr +130 -0
- package/runtime/math/trig.md +28 -0
- package/runtime/math/umuldi.gr +26 -0
- package/runtime/math/umuldi.md +14 -0
- package/runtime/numberUtils.gr +29 -29
- package/runtime/numberUtils.md +12 -12
- package/runtime/numbers.gr +373 -381
- package/runtime/numbers.md +348 -342
- package/runtime/string.gr +37 -105
- package/runtime/string.md +20 -26
- package/runtime/unsafe/constants.md +24 -24
- package/runtime/unsafe/conv.md +19 -19
- package/runtime/unsafe/memory.gr +24 -20
- package/runtime/unsafe/memory.md +27 -7
- package/runtime/unsafe/offsets.gr +36 -0
- package/runtime/unsafe/offsets.md +88 -0
- package/runtime/unsafe/panic.gr +28 -0
- package/runtime/unsafe/panic.md +14 -0
- package/runtime/unsafe/tags.md +32 -32
- package/runtime/unsafe/wasmf32.md +28 -28
- package/runtime/unsafe/wasmf64.md +28 -28
- package/runtime/unsafe/wasmi32.md +47 -47
- package/runtime/unsafe/wasmi64.md +50 -50
- package/runtime/utf8.gr +189 -0
- package/runtime/utf8.md +117 -0
- package/runtime/wasi.gr +4 -2
- package/runtime/wasi.md +147 -147
- package/set.gr +18 -11
- package/set.md +253 -247
- package/stack.gr +171 -2
- package/stack.md +371 -89
- package/string.gr +352 -557
- package/string.md +298 -255
- package/uint16.md +170 -170
- package/uint32.gr +25 -4
- package/uint32.md +249 -214
- package/uint64.gr +25 -5
- package/uint64.md +249 -214
- package/uint8.md +170 -170
- package/uri.gr +57 -53
- package/uri.md +88 -89
- package/wasi/file.gr +67 -59
- package/wasi/file.md +308 -308
- package/wasi/process.md +26 -26
- package/wasi/random.md +12 -12
- package/wasi/time.md +16 -16
- package/runtime/utils/printing.gr +0 -60
- package/runtime/utils/printing.md +0 -26
package/hash.gr
CHANGED
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @example from "hash" include Hash
|
|
5
5
|
*
|
|
6
|
-
* @example
|
|
7
|
-
*
|
|
6
|
+
* @example
|
|
7
|
+
* let hashInstance = Hash.make()
|
|
8
|
+
* assert Hash.hash(hashInstance, "Hello World") == Hash.hash(hashInstance, "Hello World")
|
|
9
|
+
* @example
|
|
10
|
+
* let hashInstance = Hash.makeSeeded(10)
|
|
11
|
+
* assert Hash.hash(hashInstance, "Hello World") == Hash.hash(hashInstance, "Hello World")
|
|
8
12
|
*
|
|
9
13
|
* @since v0.1.0
|
|
10
14
|
*/
|
|
@@ -34,7 +38,7 @@ from "runtime/unsafe/wasmi64" include WasmI64
|
|
|
34
38
|
from "runtime/unsafe/tags" include Tags
|
|
35
39
|
|
|
36
40
|
from "runtime/dataStructures" include DataStructures
|
|
37
|
-
use DataStructures.{ tagSimpleNumber }
|
|
41
|
+
use DataStructures.{ tagSimpleNumber, untagSimpleNumber }
|
|
38
42
|
from "runtime/numbers" include Numbers
|
|
39
43
|
use Numbers.{ coerceNumberToWasmI32 }
|
|
40
44
|
from "runtime/bigint" include Bigint as BI
|
|
@@ -42,18 +46,6 @@ from "runtime/bigint" include Bigint as BI
|
|
|
42
46
|
from "wasi/random" include Random
|
|
43
47
|
from "result" include Result
|
|
44
48
|
|
|
45
|
-
@unsafe
|
|
46
|
-
let mut seed = 0n
|
|
47
|
-
|
|
48
|
-
@unsafe
|
|
49
|
-
let initalize = () => {
|
|
50
|
-
// Delay initialization to the first call to `hash` to prevent WASI calls
|
|
51
|
-
// during startup
|
|
52
|
-
let random = Random.random()
|
|
53
|
-
seed = coerceNumberToWasmI32(Result.unwrap(random))
|
|
54
|
-
seed
|
|
55
|
-
}
|
|
56
|
-
|
|
57
49
|
@unsafe
|
|
58
50
|
let _MAX_HASH_DEPTH = 31n
|
|
59
51
|
|
|
@@ -71,58 +63,56 @@ let m = 5n
|
|
|
71
63
|
let n = 0xe6546b64n
|
|
72
64
|
|
|
73
65
|
@unsafe
|
|
74
|
-
let
|
|
75
|
-
|
|
76
|
-
@unsafe
|
|
77
|
-
let hash32 = k => {
|
|
66
|
+
let hash32 = (h, k) => {
|
|
78
67
|
let mut k = k * c1
|
|
79
68
|
k = WasmI32.rotl(k, r1)
|
|
80
69
|
k *= c2
|
|
81
70
|
|
|
82
|
-
h = h ^ k
|
|
83
|
-
h = WasmI32.rotl(h, r2)
|
|
84
|
-
h
|
|
71
|
+
let h = h ^ k
|
|
72
|
+
let h = WasmI32.rotl(h, r2)
|
|
73
|
+
h * m + n
|
|
85
74
|
}
|
|
86
75
|
|
|
87
76
|
@unsafe
|
|
88
|
-
let hash64 = k => {
|
|
77
|
+
let hash64 = (h, k) => {
|
|
89
78
|
use WasmI64.{ (>>>) }
|
|
90
79
|
// convenience function for hashing 64-bit values
|
|
91
|
-
hash32(WasmI32.wrapI64(k))
|
|
92
|
-
hash32(WasmI32.wrapI64(k >>> 32N))
|
|
80
|
+
let h = hash32(h, WasmI32.wrapI64(k))
|
|
81
|
+
let h = hash32(h, WasmI32.wrapI64(k >>> 32N))
|
|
82
|
+
h
|
|
93
83
|
}
|
|
94
84
|
|
|
95
85
|
@unsafe
|
|
96
|
-
let hashRemaining = r => {
|
|
86
|
+
let hashRemaining = (h, r) => {
|
|
97
87
|
// Note: wasm is little-endian so no swap is necessary
|
|
98
88
|
|
|
99
89
|
let mut r = r * c1
|
|
100
90
|
r = WasmI32.rotl(r, r1)
|
|
101
91
|
r *= c2
|
|
102
92
|
|
|
103
|
-
h
|
|
93
|
+
h ^ r
|
|
104
94
|
}
|
|
105
95
|
|
|
106
96
|
@unsafe
|
|
107
|
-
let finalize = len => {
|
|
108
|
-
h = h ^ len
|
|
97
|
+
let finalize = (h, len) => {
|
|
98
|
+
let h = h ^ len
|
|
109
99
|
|
|
110
|
-
h = h ^ h >>> 16n
|
|
111
|
-
h
|
|
112
|
-
h = h ^ h >>> 13n
|
|
113
|
-
h
|
|
114
|
-
h
|
|
100
|
+
let h = h ^ h >>> 16n
|
|
101
|
+
let h = h * 0x85ebca6bn
|
|
102
|
+
let h = h ^ h >>> 13n
|
|
103
|
+
let h = h * 0xc2b2ae35n
|
|
104
|
+
h ^ h >>> 16n
|
|
115
105
|
}
|
|
116
106
|
|
|
117
107
|
@unsafe
|
|
118
|
-
let rec hashOne = (val, depth) => {
|
|
108
|
+
let rec hashOne = (h, val, depth) => {
|
|
119
109
|
if (depth > _MAX_HASH_DEPTH) {
|
|
120
|
-
|
|
110
|
+
h
|
|
121
111
|
} else if ((val & Tags._GRAIN_NUMBER_TAG_MASK) != 0n) {
|
|
122
|
-
hash32(val)
|
|
112
|
+
hash32(h, val)
|
|
123
113
|
} else if (
|
|
124
|
-
(val & Tags._GRAIN_GENERIC_TAG_MASK)
|
|
125
|
-
Tags._GRAIN_GENERIC_HEAP_TAG_TYPE
|
|
114
|
+
(val & Tags._GRAIN_GENERIC_TAG_MASK)
|
|
115
|
+
== Tags._GRAIN_GENERIC_HEAP_TAG_TYPE
|
|
126
116
|
) {
|
|
127
117
|
let heapPtr = val
|
|
128
118
|
match (WasmI32.load(heapPtr, 0n)) {
|
|
@@ -130,141 +120,205 @@ let rec hashOne = (val, depth) => {
|
|
|
130
120
|
let length = WasmI32.load(heapPtr, 4n)
|
|
131
121
|
let extra = length % 4n
|
|
132
122
|
let l = length - extra
|
|
123
|
+
let mut h = h
|
|
133
124
|
for (let mut i = 0n; i < l; i += 4n) {
|
|
134
|
-
hash32(WasmI32.load(heapPtr + i, 8n))
|
|
125
|
+
h = hash32(h, WasmI32.load(heapPtr + i, 8n))
|
|
135
126
|
}
|
|
136
127
|
let mut rem = 0n
|
|
137
128
|
for (let mut i = 0n; i < extra; i += 1n) {
|
|
138
129
|
rem = rem << 8n
|
|
139
130
|
rem = rem | WasmI32.load8U(heapPtr + l + i, 8n)
|
|
140
131
|
}
|
|
141
|
-
if (rem != 0n) hashRemaining(rem)
|
|
142
|
-
finalize(length)
|
|
132
|
+
if (rem != 0n) h = hashRemaining(h, rem)
|
|
133
|
+
finalize(h, length)
|
|
143
134
|
},
|
|
144
135
|
t when t == Tags._GRAIN_ADT_HEAP_TAG => {
|
|
145
136
|
// moduleId
|
|
146
|
-
hash32(WasmI32.load(heapPtr, 4n))
|
|
137
|
+
let h = hash32(h, WasmI32.load(heapPtr, 4n))
|
|
147
138
|
// typeId
|
|
148
|
-
hash32(WasmI32.load(heapPtr, 8n))
|
|
139
|
+
let h = hash32(h, WasmI32.load(heapPtr, 8n))
|
|
149
140
|
// variantId
|
|
150
|
-
hash32(WasmI32.load(heapPtr, 12n))
|
|
141
|
+
let h = hash32(h, WasmI32.load(heapPtr, 12n))
|
|
151
142
|
|
|
152
143
|
let arity = WasmI32.load(heapPtr, 16n)
|
|
153
144
|
|
|
154
145
|
let a = arity * 4n
|
|
146
|
+
let mut h = h
|
|
155
147
|
for (let mut i = 0n; i < a; i += 4n) {
|
|
156
|
-
hashOne(WasmI32.load(heapPtr + i, 20n), depth + 1n)
|
|
148
|
+
h = hashOne(h, WasmI32.load(heapPtr + i, 20n), depth + 1n)
|
|
157
149
|
}
|
|
158
150
|
|
|
159
|
-
finalize(arity)
|
|
151
|
+
finalize(h, arity)
|
|
160
152
|
},
|
|
161
153
|
t when t == Tags._GRAIN_RECORD_HEAP_TAG => {
|
|
162
154
|
// moduleId
|
|
163
|
-
hash32(WasmI32.load(heapPtr, 4n))
|
|
155
|
+
let h = hash32(h, WasmI32.load(heapPtr, 4n))
|
|
164
156
|
// typeId
|
|
165
|
-
hash32(WasmI32.load(heapPtr, 8n))
|
|
157
|
+
let h = hash32(h, WasmI32.load(heapPtr, 8n))
|
|
166
158
|
|
|
167
159
|
let arity = WasmI32.load(heapPtr, 12n)
|
|
168
160
|
|
|
169
161
|
let a = arity * 4n
|
|
162
|
+
let mut h = h
|
|
170
163
|
for (let mut i = 0n; i < a; i += 4n) {
|
|
171
|
-
hashOne(WasmI32.load(heapPtr + i, 16n), depth + 1n)
|
|
164
|
+
h = hashOne(h, WasmI32.load(heapPtr + i, 16n), depth + 1n)
|
|
172
165
|
}
|
|
173
|
-
finalize(arity)
|
|
166
|
+
finalize(h, arity)
|
|
174
167
|
},
|
|
175
168
|
t when t == Tags._GRAIN_ARRAY_HEAP_TAG => {
|
|
176
169
|
let arity = WasmI32.load(heapPtr, 4n)
|
|
177
170
|
|
|
178
171
|
let a = arity * 4n
|
|
172
|
+
let mut h = h
|
|
179
173
|
for (let mut i = 0n; i < a; i += 4n) {
|
|
180
|
-
hashOne(WasmI32.load(heapPtr + i, 8n), depth + 1n)
|
|
174
|
+
h = hashOne(h, WasmI32.load(heapPtr + i, 8n), depth + 1n)
|
|
181
175
|
}
|
|
182
|
-
finalize(arity)
|
|
176
|
+
finalize(h, arity)
|
|
183
177
|
},
|
|
184
178
|
t when t == Tags._GRAIN_TUPLE_HEAP_TAG => {
|
|
185
179
|
let tupleLength = WasmI32.load(heapPtr, 4n)
|
|
186
180
|
let l = tupleLength * 4n
|
|
181
|
+
let mut h = h
|
|
187
182
|
for (let mut i = 0n; i < l; i += 4n) {
|
|
188
|
-
hashOne(WasmI32.load(heapPtr + i, 8n), depth + 1n)
|
|
183
|
+
h = hashOne(h, WasmI32.load(heapPtr + i, 8n), depth + 1n)
|
|
189
184
|
}
|
|
190
|
-
finalize(tupleLength)
|
|
185
|
+
finalize(h, tupleLength)
|
|
191
186
|
},
|
|
192
187
|
t when t == Tags._GRAIN_LAMBDA_HEAP_TAG => {
|
|
193
|
-
hash32(heapPtr)
|
|
188
|
+
hash32(h, heapPtr)
|
|
194
189
|
},
|
|
195
190
|
t when t == Tags._GRAIN_BOXED_NUM_HEAP_TAG => {
|
|
196
191
|
let tag = WasmI32.load(heapPtr, 4n)
|
|
197
192
|
match (tag) {
|
|
198
193
|
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
199
|
-
hash32(WasmI32.load(heapPtr, 8n))
|
|
200
|
-
hash32(WasmI32.load(heapPtr, 12n))
|
|
194
|
+
let h = hash32(h, WasmI32.load(heapPtr, 8n))
|
|
195
|
+
hash32(h, WasmI32.load(heapPtr, 12n))
|
|
201
196
|
},
|
|
202
197
|
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
203
198
|
// TODO(#1187): should include fixint size once implemented
|
|
204
199
|
let size = BI.getSize(heapPtr)
|
|
205
|
-
hash32(size)
|
|
206
|
-
hash32(BI.getFlags(heapPtr))
|
|
200
|
+
let h = hash32(h, size)
|
|
201
|
+
let mut h = hash32(h, BI.getFlags(heapPtr))
|
|
207
202
|
for (let mut i = 0n; i < size; i += 1n) {
|
|
208
|
-
hash64(BI.getLimb(heapPtr, i))
|
|
203
|
+
h = hash64(h, BI.getLimb(heapPtr, i))
|
|
209
204
|
}
|
|
205
|
+
h
|
|
210
206
|
},
|
|
211
207
|
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
212
|
-
hash32(WasmI32.load(heapPtr, 8n))
|
|
213
|
-
hash32(WasmI32.load(heapPtr, 12n))
|
|
208
|
+
let h = hash32(h, WasmI32.load(heapPtr, 8n))
|
|
209
|
+
let h = hash32(h, WasmI32.load(heapPtr, 12n))
|
|
210
|
+
h
|
|
214
211
|
},
|
|
215
212
|
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
216
|
-
hashOne(WasmI32.load(heapPtr, 8n), depth + 1n)
|
|
217
|
-
hashOne(WasmI32.load(heapPtr, 12n), depth + 1n)
|
|
213
|
+
let h = hashOne(h, WasmI32.load(heapPtr, 8n), depth + 1n)
|
|
214
|
+
let h = hashOne(h, WasmI32.load(heapPtr, 12n), depth + 1n)
|
|
215
|
+
h
|
|
218
216
|
},
|
|
219
217
|
_ => {
|
|
220
|
-
hash32(heapPtr)
|
|
218
|
+
hash32(h, heapPtr)
|
|
221
219
|
},
|
|
222
220
|
}
|
|
223
221
|
},
|
|
224
|
-
t when t == Tags._GRAIN_INT32_HEAP_TAG
|
|
225
|
-
t == Tags._GRAIN_FLOAT32_HEAP_TAG
|
|
226
|
-
t == Tags._GRAIN_UINT32_HEAP_TAG => {
|
|
227
|
-
hash32(WasmI32.load(heapPtr, 4n))
|
|
222
|
+
t when t == Tags._GRAIN_INT32_HEAP_TAG
|
|
223
|
+
|| t == Tags._GRAIN_FLOAT32_HEAP_TAG
|
|
224
|
+
|| t == Tags._GRAIN_UINT32_HEAP_TAG => {
|
|
225
|
+
hash32(h, WasmI32.load(heapPtr, 4n))
|
|
228
226
|
},
|
|
229
227
|
t when t == Tags._GRAIN_UINT64_HEAP_TAG => {
|
|
230
|
-
hash32(WasmI32.load(heapPtr, 8n))
|
|
231
|
-
hash32(WasmI32.load(heapPtr, 12n))
|
|
228
|
+
let h = hash32(h, WasmI32.load(heapPtr, 8n))
|
|
229
|
+
let h = hash32(h, WasmI32.load(heapPtr, 12n))
|
|
230
|
+
h
|
|
232
231
|
},
|
|
233
232
|
_ => {
|
|
234
|
-
hash32(heapPtr)
|
|
233
|
+
hash32(h, heapPtr)
|
|
235
234
|
},
|
|
236
235
|
}
|
|
237
236
|
} else {
|
|
238
237
|
// Handle non-heap values: booleans, chars, void, etc.
|
|
239
|
-
hash32(val)
|
|
238
|
+
hash32(h, val)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Represents a particular hashing instance.
|
|
244
|
+
*
|
|
245
|
+
* @since v0.7.0
|
|
246
|
+
*/
|
|
247
|
+
abstract type HashInstance = Number
|
|
248
|
+
|
|
249
|
+
let mut seed: HashInstance = 0
|
|
250
|
+
@unsafe
|
|
251
|
+
let getSeed = () => {
|
|
252
|
+
if (WasmI32.eqz(untagSimpleNumber(seed))) {
|
|
253
|
+
// Delay initialization to the first call to `hash` to prevent WASI calls
|
|
254
|
+
// during startup
|
|
255
|
+
let random = Random.random()
|
|
256
|
+
seed = Result.unwrap(random)
|
|
240
257
|
}
|
|
258
|
+
seed: HashInstance
|
|
241
259
|
}
|
|
242
260
|
|
|
243
261
|
/**
|
|
244
|
-
*
|
|
262
|
+
* Produces a generic hash instance using a random seed value.
|
|
263
|
+
*
|
|
264
|
+
* @returns A hashing instance that can be consumed during hashing
|
|
265
|
+
*
|
|
266
|
+
* @throws Failure(String): If WASI random_get fails
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* let hashInstance = Hash.make()
|
|
270
|
+
* assert Hash.hash(hashInstance," Hello World") == Hash.hash(hashInstance, "Hello World)
|
|
245
271
|
*
|
|
272
|
+
* @since v0.7.0
|
|
273
|
+
*/
|
|
274
|
+
provide let make = () => {
|
|
275
|
+
let seed = getSeed()
|
|
276
|
+
seed
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Produces a hashInstance using the given seed.
|
|
281
|
+
*
|
|
282
|
+
* @param seed: The seed to use while hashing
|
|
283
|
+
* @returns A hashing instance that can be consumed during hashing
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* let hashInstance = Hash.makeSeeded(1)
|
|
287
|
+
* assert Hash.hash(hashInstance," Hello World") == Hash.hash(hashInstance, "Hello World)
|
|
288
|
+
* @example
|
|
289
|
+
* let hashInstance1 = Hash.makeSeeded(1)
|
|
290
|
+
* let hashInstance2 = Hash.makeSeeded(2)
|
|
291
|
+
* assert Hash.hash(hashInstance1," Hello World") != Hash.hash(hashInstance2, "Hello World)
|
|
292
|
+
*
|
|
293
|
+
* @since v0.7.0
|
|
294
|
+
*/
|
|
295
|
+
@unsafe
|
|
296
|
+
provide let makeSeeded = (seed: Number) => {
|
|
297
|
+
return seed: HashInstance
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* A generic hash function that produces an integer from any value given a hashing instance. If `a == b` then `Hash.hash(h, a) == Hash.hash(h, b)`.
|
|
302
|
+
*
|
|
303
|
+
* @param hashInstance: The hashing instance to use as a seed
|
|
246
304
|
* @param anything: The value to hash
|
|
305
|
+
*
|
|
247
306
|
* @returns A hash for the given value
|
|
248
|
-
*
|
|
249
|
-
* @throws Failure(String): If WASI random_get fails
|
|
250
307
|
*
|
|
251
|
-
* @example
|
|
252
|
-
*
|
|
308
|
+
* @example
|
|
309
|
+
* let hashInstance = Hash.makeSeeded(1)
|
|
310
|
+
* assert Hash.hash(hashInstance," Hello World") == Hash.hash(hashInstance, "Hello World)
|
|
253
311
|
*
|
|
254
312
|
* @since v0.1.0
|
|
313
|
+
* @history v0.7.0: Added `hashInstance` parameter instead of using a global seed
|
|
255
314
|
*/
|
|
256
315
|
@unsafe
|
|
257
|
-
provide let hash = anything => {
|
|
258
|
-
h =
|
|
259
|
-
|
|
260
|
-
} else {
|
|
261
|
-
seed
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
hashOne(WasmI32.fromGrain(anything), 0n)
|
|
316
|
+
provide let hash = (hashInstance: HashInstance, anything) => {
|
|
317
|
+
let h = coerceNumberToWasmI32(hashInstance)
|
|
318
|
+
let h = hashOne(h, WasmI32.fromGrain(anything), 0n)
|
|
265
319
|
ignore(anything)
|
|
266
320
|
|
|
267
|
-
finalize(0n)
|
|
321
|
+
let h = finalize(h, 0n)
|
|
268
322
|
|
|
269
323
|
// Tag the number on the way out.
|
|
270
324
|
// Since Grain has proper modulus, negative numbers are okay.
|
package/hash.md
CHANGED
|
@@ -14,41 +14,54 @@ from "hash" include Hash
|
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
```grain
|
|
17
|
-
Hash.
|
|
17
|
+
let hashInstance = Hash.make()
|
|
18
|
+
assert Hash.hash(hashInstance, "Hello World") == Hash.hash(hashInstance, "Hello World")
|
|
18
19
|
```
|
|
19
20
|
|
|
20
21
|
```grain
|
|
21
|
-
Hash.
|
|
22
|
+
let hashInstance = Hash.makeSeeded(10)
|
|
23
|
+
assert Hash.hash(hashInstance, "Hello World") == Hash.hash(hashInstance, "Hello World")
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
##
|
|
26
|
+
## Types
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
Type declarations included in the Hash module.
|
|
27
29
|
|
|
28
|
-
### Hash.**
|
|
30
|
+
### Hash.**HashInstance**
|
|
29
31
|
|
|
30
32
|
<details disabled>
|
|
31
|
-
<summary tabindex="-1">Added in <code>0.
|
|
33
|
+
<summary tabindex="-1">Added in <code>0.7.0</code></summary>
|
|
32
34
|
No other changes yet.
|
|
33
35
|
</details>
|
|
34
36
|
|
|
35
37
|
```grain
|
|
36
|
-
|
|
38
|
+
type HashInstance
|
|
37
39
|
```
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
Represents a particular hashing instance.
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
## Values
|
|
44
|
+
|
|
45
|
+
Functions and constants included in the Hash module.
|
|
46
|
+
|
|
47
|
+
### Hash.**make**
|
|
48
|
+
|
|
49
|
+
<details disabled>
|
|
50
|
+
<summary tabindex="-1">Added in <code>0.7.0</code></summary>
|
|
51
|
+
No other changes yet.
|
|
52
|
+
</details>
|
|
53
|
+
|
|
54
|
+
```grain
|
|
55
|
+
make: () => HashInstance
|
|
56
|
+
```
|
|
42
57
|
|
|
43
|
-
|
|
44
|
-
|-----|----|-----------|
|
|
45
|
-
|`anything`|`a`|The value to hash|
|
|
58
|
+
Produces a generic hash instance using a random seed value.
|
|
46
59
|
|
|
47
60
|
Returns:
|
|
48
61
|
|
|
49
|
-
|type|description|
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
| type | description |
|
|
63
|
+
| -------------- | ------------------------------------------------------ |
|
|
64
|
+
| `HashInstance` | A hashing instance that can be consumed during hashing |
|
|
52
65
|
|
|
53
66
|
Throws:
|
|
54
67
|
|
|
@@ -59,10 +72,85 @@ Throws:
|
|
|
59
72
|
Examples:
|
|
60
73
|
|
|
61
74
|
```grain
|
|
62
|
-
|
|
75
|
+
let hashInstance = Hash.make()
|
|
76
|
+
assert Hash.hash(hashInstance," Hello World") == Hash.hash(hashInstance, "Hello World)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Hash.**makeSeeded**
|
|
80
|
+
|
|
81
|
+
<details disabled>
|
|
82
|
+
<summary tabindex="-1">Added in <code>0.7.0</code></summary>
|
|
83
|
+
No other changes yet.
|
|
84
|
+
</details>
|
|
85
|
+
|
|
86
|
+
```grain
|
|
87
|
+
makeSeeded: (seed: Number) => HashInstance
|
|
63
88
|
```
|
|
64
89
|
|
|
90
|
+
Produces a hashInstance using the given seed.
|
|
91
|
+
|
|
92
|
+
Parameters:
|
|
93
|
+
|
|
94
|
+
| param | type | description |
|
|
95
|
+
| ------ | -------- | ----------------------------- |
|
|
96
|
+
| `seed` | `Number` | The seed to use while hashing |
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
|
|
100
|
+
| type | description |
|
|
101
|
+
| -------------- | ------------------------------------------------------ |
|
|
102
|
+
| `HashInstance` | A hashing instance that can be consumed during hashing |
|
|
103
|
+
|
|
104
|
+
Examples:
|
|
105
|
+
|
|
106
|
+
```grain
|
|
107
|
+
let hashInstance = Hash.makeSeeded(1)
|
|
108
|
+
assert Hash.hash(hashInstance," Hello World") == Hash.hash(hashInstance, "Hello World)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```grain
|
|
112
|
+
let hashInstance1 = Hash.makeSeeded(1)
|
|
113
|
+
let hashInstance2 = Hash.makeSeeded(2)
|
|
114
|
+
assert Hash.hash(hashInstance1," Hello World") != Hash.hash(hashInstance2, "Hello World)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Hash.**hash**
|
|
118
|
+
|
|
119
|
+
<details>
|
|
120
|
+
<summary>Added in <code>0.1.0</code></summary>
|
|
121
|
+
<table>
|
|
122
|
+
<thead>
|
|
123
|
+
<tr><th>version</th><th>changes</th></tr>
|
|
124
|
+
</thead>
|
|
125
|
+
<tbody>
|
|
126
|
+
<tr><td><code>0.7.0</code></td><td>Added `hashInstance` parameter instead of using a global seed</td></tr>
|
|
127
|
+
</tbody>
|
|
128
|
+
</table>
|
|
129
|
+
</details>
|
|
130
|
+
|
|
131
|
+
```grain
|
|
132
|
+
hash: (hashInstance: HashInstance, anything: a) => Number
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
A generic hash function that produces an integer from any value given a hashing instance. If `a == b` then `Hash.hash(h, a) == Hash.hash(h, b)`.
|
|
136
|
+
|
|
137
|
+
Parameters:
|
|
138
|
+
|
|
139
|
+
| param | type | description |
|
|
140
|
+
| -------------- | -------------- | ------------------------------------- |
|
|
141
|
+
| `hashInstance` | `HashInstance` | The hashing instance to use as a seed |
|
|
142
|
+
| `anything` | `a` | The value to hash |
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
|
|
146
|
+
| type | description |
|
|
147
|
+
| -------- | -------------------------- |
|
|
148
|
+
| `Number` | A hash for the given value |
|
|
149
|
+
|
|
150
|
+
Examples:
|
|
151
|
+
|
|
65
152
|
```grain
|
|
66
|
-
|
|
153
|
+
let hashInstance = Hash.makeSeeded(1)
|
|
154
|
+
assert Hash.hash(hashInstance," Hello World") == Hash.hash(hashInstance, "Hello World)
|
|
67
155
|
```
|
|
68
156
|
|