nucleation 0.10.21 → 0.10.23
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/BlockPos.mjs +1 -0
- package/Dimensions.mjs +1 -0
- package/FieldRange.mjs +1 -0
- package/ItemScale.mjs +1 -0
- package/MeshBounds.mjs +1 -0
- package/MeshProgress.mjs +1 -0
- package/README.md +12 -0
- package/RegionBounds.mjs +1 -0
- package/Schematic.d.mts +32 -0
- package/Schematic.d.ts +32 -0
- package/Schematic.mjs +100 -0
- package/SdfBounds.mjs +1 -0
- package/SdfNormal.mjs +1 -0
- package/TextureInfo.mjs +1 -0
- package/diplomat-runtime.mjs +19 -14
- package/nucleation.wasm +0 -0
- package/package.json +7 -2
- package/renderer/AnimationEffect.d.mts +44 -0
- package/renderer/AnimationEffect.d.ts +44 -0
- package/renderer/AnimationEffect.mjs +204 -0
- package/renderer/Autostack.d.mts +43 -0
- package/renderer/Autostack.d.ts +43 -0
- package/renderer/Autostack.mjs +134 -0
- package/renderer/BlockPos.d.mts +28 -0
- package/renderer/BlockPos.d.ts +28 -0
- package/renderer/BlockPos.mjs +130 -0
- package/renderer/BlockState.d.mts +39 -0
- package/renderer/BlockState.d.ts +39 -0
- package/renderer/BlockState.mjs +134 -0
- package/renderer/Blocks.d.mts +91 -0
- package/renderer/Blocks.d.ts +91 -0
- package/renderer/Blocks.mjs +308 -0
- package/renderer/Brush.d.mts +99 -0
- package/renderer/Brush.d.ts +99 -0
- package/renderer/Brush.mjs +335 -0
- package/renderer/BuildAnimation.d.mts +179 -0
- package/renderer/BuildAnimation.d.ts +179 -0
- package/renderer/BuildAnimation.mjs +1148 -0
- package/renderer/BuildingTool.d.mts +46 -0
- package/renderer/BuildingTool.d.ts +46 -0
- package/renderer/BuildingTool.mjs +121 -0
- package/renderer/CellExecutor.d.mts +51 -0
- package/renderer/CellExecutor.d.ts +51 -0
- package/renderer/CellExecutor.mjs +171 -0
- package/renderer/CellularSdfConfig.d.mts +22 -0
- package/renderer/CellularSdfConfig.d.ts +22 -0
- package/renderer/CellularSdfConfig.mjs +69 -0
- package/renderer/ChunkMeshResult.d.mts +75 -0
- package/renderer/ChunkMeshResult.d.ts +75 -0
- package/renderer/ChunkMeshResult.mjs +253 -0
- package/renderer/CircuitBuilder.d.mts +118 -0
- package/renderer/CircuitBuilder.d.ts +118 -0
- package/renderer/CircuitBuilder.mjs +516 -0
- package/renderer/Curve3D.d.mts +27 -0
- package/renderer/Curve3D.d.ts +27 -0
- package/renderer/Curve3D.mjs +101 -0
- package/renderer/DefinitionRegion.d.mts +274 -0
- package/renderer/DefinitionRegion.d.ts +274 -0
- package/renderer/DefinitionRegion.mjs +973 -0
- package/renderer/Design.d.mts +348 -0
- package/renderer/Design.d.ts +348 -0
- package/renderer/Design.mjs +1334 -0
- package/renderer/Diff.d.mts +88 -0
- package/renderer/Diff.d.ts +88 -0
- package/renderer/Diff.mjs +316 -0
- package/renderer/Dimensions.d.mts +28 -0
- package/renderer/Dimensions.d.ts +28 -0
- package/renderer/Dimensions.mjs +130 -0
- package/renderer/DistanceField.d.mts +39 -0
- package/renderer/DistanceField.d.ts +39 -0
- package/renderer/DistanceField.mjs +114 -0
- package/renderer/ExecutionMode.d.mts +42 -0
- package/renderer/ExecutionMode.d.ts +42 -0
- package/renderer/ExecutionMode.mjs +127 -0
- package/renderer/Field3.d.mts +40 -0
- package/renderer/Field3.d.ts +40 -0
- package/renderer/Field3.mjs +160 -0
- package/renderer/FieldProgram.d.mts +40 -0
- package/renderer/FieldProgram.d.ts +40 -0
- package/renderer/FieldProgram.mjs +167 -0
- package/renderer/FieldProgramBinaryOp.d.mts +42 -0
- package/renderer/FieldProgramBinaryOp.d.ts +42 -0
- package/renderer/FieldProgramBinaryOp.mjs +118 -0
- package/renderer/FieldProgramBuilder.d.mts +104 -0
- package/renderer/FieldProgramBuilder.d.ts +104 -0
- package/renderer/FieldProgramBuilder.mjs +486 -0
- package/renderer/FieldProgramDistanceKind.d.mts +26 -0
- package/renderer/FieldProgramDistanceKind.d.ts +26 -0
- package/renderer/FieldProgramDistanceKind.mjs +78 -0
- package/renderer/FieldProgramUnaryOp.d.mts +34 -0
- package/renderer/FieldProgramUnaryOp.d.ts +34 -0
- package/renderer/FieldProgramUnaryOp.mjs +102 -0
- package/renderer/FieldProgramValueType.d.mts +25 -0
- package/renderer/FieldProgramValueType.d.ts +25 -0
- package/renderer/FieldProgramValueType.mjs +75 -0
- package/renderer/FieldRange.d.mts +15 -0
- package/renderer/FieldRange.d.ts +15 -0
- package/renderer/FieldRange.mjs +109 -0
- package/renderer/Fingerprint.d.mts +44 -0
- package/renderer/Fingerprint.d.ts +44 -0
- package/renderer/Fingerprint.mjs +197 -0
- package/renderer/GeneratedChunk.d.mts +35 -0
- package/renderer/GeneratedChunk.d.ts +35 -0
- package/renderer/GeneratedChunk.mjs +178 -0
- package/renderer/GeneratedChunkCoverage.d.mts +25 -0
- package/renderer/GeneratedChunkCoverage.d.ts +25 -0
- package/renderer/GeneratedChunkCoverage.mjs +75 -0
- package/renderer/GeneratedChunkOverlayMode.d.mts +24 -0
- package/renderer/GeneratedChunkOverlayMode.d.ts +24 -0
- package/renderer/GeneratedChunkOverlayMode.mjs +72 -0
- package/renderer/GeneratedWorldStream.d.mts +28 -0
- package/renderer/GeneratedWorldStream.d.ts +28 -0
- package/renderer/GeneratedWorldStream.mjs +86 -0
- package/renderer/Geo.d.mts +41 -0
- package/renderer/Geo.d.ts +41 -0
- package/renderer/Geo.mjs +121 -0
- package/renderer/Hdl.d.mts +56 -0
- package/renderer/Hdl.d.ts +56 -0
- package/renderer/Hdl.mjs +163 -0
- package/renderer/InterpolationSpace.d.mts +25 -0
- package/renderer/InterpolationSpace.d.ts +25 -0
- package/renderer/InterpolationSpace.mjs +73 -0
- package/renderer/IoLayout.d.mts +26 -0
- package/renderer/IoLayout.d.ts +26 -0
- package/renderer/IoLayout.mjs +81 -0
- package/renderer/IoLayoutBuilder.d.mts +73 -0
- package/renderer/IoLayoutBuilder.d.ts +73 -0
- package/renderer/IoLayoutBuilder.mjs +315 -0
- package/renderer/IoType.d.mts +41 -0
- package/renderer/IoType.d.ts +41 -0
- package/renderer/IoType.mjs +125 -0
- package/renderer/ItemModelConfig.d.mts +65 -0
- package/renderer/ItemModelConfig.d.ts +65 -0
- package/renderer/ItemModelConfig.mjs +223 -0
- package/renderer/ItemModelPackBuilder.d.mts +32 -0
- package/renderer/ItemModelPackBuilder.d.ts +32 -0
- package/renderer/ItemModelPackBuilder.mjs +104 -0
- package/renderer/ItemModelResult.d.mts +72 -0
- package/renderer/ItemModelResult.d.ts +72 -0
- package/renderer/ItemModelResult.mjs +268 -0
- package/renderer/ItemScale.d.mts +31 -0
- package/renderer/ItemScale.d.ts +31 -0
- package/renderer/ItemScale.mjs +133 -0
- package/renderer/LayoutFunction.d.mts +52 -0
- package/renderer/LayoutFunction.d.ts +52 -0
- package/renderer/LayoutFunction.mjs +159 -0
- package/renderer/MchprsWorld.d.mts +131 -0
- package/renderer/MchprsWorld.d.ts +131 -0
- package/renderer/MchprsWorld.mjs +423 -0
- package/renderer/MeshBounds.d.mts +40 -0
- package/renderer/MeshBounds.d.ts +40 -0
- package/renderer/MeshBounds.mjs +181 -0
- package/renderer/MeshConfig.d.mts +101 -0
- package/renderer/MeshConfig.d.ts +101 -0
- package/renderer/MeshConfig.mjs +306 -0
- package/renderer/MeshJob.d.mts +44 -0
- package/renderer/MeshJob.d.ts +44 -0
- package/renderer/MeshJob.mjs +116 -0
- package/renderer/MeshPhase.d.mts +38 -0
- package/renderer/MeshPhase.d.ts +38 -0
- package/renderer/MeshPhase.mjs +90 -0
- package/renderer/MeshProgress.d.mts +32 -0
- package/renderer/MeshProgress.d.ts +32 -0
- package/renderer/MeshProgress.mjs +134 -0
- package/renderer/MeshResult.d.mts +76 -0
- package/renderer/MeshResult.d.ts +76 -0
- package/renderer/MeshResult.mjs +269 -0
- package/renderer/MultiMeshResult.d.mts +50 -0
- package/renderer/MultiMeshResult.d.ts +50 -0
- package/renderer/MultiMeshResult.mjs +166 -0
- package/renderer/Nbt.d.mts +50 -0
- package/renderer/Nbt.d.ts +50 -0
- package/renderer/Nbt.mjs +161 -0
- package/renderer/NucleationError.d.mts +53 -0
- package/renderer/NucleationError.d.ts +53 -0
- package/renderer/NucleationError.mjs +136 -0
- package/renderer/OutputCondition.d.mts +45 -0
- package/renderer/OutputCondition.d.ts +45 -0
- package/renderer/OutputCondition.mjs +129 -0
- package/renderer/Palette.d.mts +157 -0
- package/renderer/Palette.d.ts +157 -0
- package/renderer/Palette.mjs +487 -0
- package/renderer/PaletteBuilder.d.mts +119 -0
- package/renderer/PaletteBuilder.d.ts +119 -0
- package/renderer/PaletteBuilder.mjs +457 -0
- package/renderer/README.md +67 -0
- package/renderer/RawMeshExport.d.mts +74 -0
- package/renderer/RawMeshExport.d.ts +74 -0
- package/renderer/RawMeshExport.mjs +243 -0
- package/renderer/RedstoneGraph.d.mts +58 -0
- package/renderer/RedstoneGraph.d.ts +58 -0
- package/renderer/RedstoneGraph.mjs +242 -0
- package/renderer/RegionBounds.d.mts +41 -0
- package/renderer/RegionBounds.d.ts +41 -0
- package/renderer/RegionBounds.mjs +182 -0
- package/renderer/RenderConfig.d.mts +101 -0
- package/renderer/RenderConfig.d.ts +101 -0
- package/renderer/RenderConfig.mjs +271 -0
- package/renderer/Renderer.d.mts +51 -0
- package/renderer/Renderer.d.ts +51 -0
- package/renderer/Renderer.mjs +219 -0
- package/renderer/ResourcePack.d.mts +105 -0
- package/renderer/ResourcePack.d.ts +105 -0
- package/renderer/ResourcePack.mjs +447 -0
- package/renderer/ResourcePackList.d.mts +32 -0
- package/renderer/ResourcePackList.d.ts +32 -0
- package/renderer/ResourcePackList.mjs +96 -0
- package/renderer/Routing.d.mts +66 -0
- package/renderer/Routing.d.ts +66 -0
- package/renderer/Routing.mjs +220 -0
- package/renderer/Schematic.d.mts +977 -0
- package/renderer/Schematic.d.ts +977 -0
- package/renderer/Schematic.mjs +3820 -0
- package/renderer/SchematicBuilder.d.mts +103 -0
- package/renderer/SchematicBuilder.d.ts +103 -0
- package/renderer/SchematicBuilder.mjs +401 -0
- package/renderer/SchematicRegions.d.mts +93 -0
- package/renderer/SchematicRegions.d.ts +93 -0
- package/renderer/SchematicRegions.mjs +411 -0
- package/renderer/SchematicSplitResult.d.mts +26 -0
- package/renderer/SchematicSplitResult.d.ts +26 -0
- package/renderer/SchematicSplitResult.mjs +84 -0
- package/renderer/Scripting.d.mts +40 -0
- package/renderer/Scripting.d.ts +40 -0
- package/renderer/Scripting.mjs +138 -0
- package/renderer/Sdf.d.mts +234 -0
- package/renderer/Sdf.d.ts +234 -0
- package/renderer/Sdf.mjs +1234 -0
- package/renderer/SdfAxis.d.mts +25 -0
- package/renderer/SdfAxis.d.ts +25 -0
- package/renderer/SdfAxis.mjs +75 -0
- package/renderer/SdfBounds.d.mts +19 -0
- package/renderer/SdfBounds.d.ts +19 -0
- package/renderer/SdfBounds.mjs +161 -0
- package/renderer/SdfCellMode.d.mts +26 -0
- package/renderer/SdfCellMode.d.ts +26 -0
- package/renderer/SdfCellMode.mjs +78 -0
- package/renderer/SdfNormal.d.mts +16 -0
- package/renderer/SdfNormal.d.ts +16 -0
- package/renderer/SdfNormal.mjs +122 -0
- package/renderer/Shape.d.mts +143 -0
- package/renderer/Shape.d.ts +143 -0
- package/renderer/Shape.mjs +458 -0
- package/renderer/SortStrategy.d.mts +86 -0
- package/renderer/SortStrategy.d.ts +86 -0
- package/renderer/SortStrategy.mjs +272 -0
- package/renderer/Store.d.mts +83 -0
- package/renderer/Store.d.ts +83 -0
- package/renderer/Store.mjs +369 -0
- package/renderer/StoreIo.d.mts +71 -0
- package/renderer/StoreIo.d.ts +71 -0
- package/renderer/StoreIo.mjs +292 -0
- package/renderer/TextureAtlas.d.mts +40 -0
- package/renderer/TextureAtlas.d.ts +40 -0
- package/renderer/TextureAtlas.mjs +122 -0
- package/renderer/TextureInfo.d.mts +34 -0
- package/renderer/TextureInfo.d.ts +34 -0
- package/renderer/TextureInfo.mjs +149 -0
- package/renderer/TickSettleMode.d.mts +34 -0
- package/renderer/TickSettleMode.d.ts +34 -0
- package/renderer/TickSettleMode.mjs +84 -0
- package/renderer/TickSimulation.d.mts +572 -0
- package/renderer/TickSimulation.d.ts +572 -0
- package/renderer/TickSimulation.mjs +1299 -0
- package/renderer/TypedCircuitExecutor.d.mts +101 -0
- package/renderer/TypedCircuitExecutor.d.ts +101 -0
- package/renderer/TypedCircuitExecutor.mjs +378 -0
- package/renderer/Value.d.mts +73 -0
- package/renderer/Value.d.ts +73 -0
- package/renderer/Value.mjs +275 -0
- package/renderer/VideoConfig.d.mts +15 -0
- package/renderer/VideoConfig.d.ts +15 -0
- package/renderer/VideoConfig.mjs +44 -0
- package/renderer/VoxelModel.d.mts +34 -0
- package/renderer/VoxelModel.d.ts +34 -0
- package/renderer/VoxelModel.mjs +113 -0
- package/renderer/Voxelizer.d.mts +80 -0
- package/renderer/Voxelizer.d.ts +80 -0
- package/renderer/Voxelizer.mjs +261 -0
- package/renderer/WorldChunkView.d.mts +75 -0
- package/renderer/WorldChunkView.d.ts +75 -0
- package/renderer/WorldChunkView.mjs +224 -0
- package/renderer/WorldGenerator.d.mts +75 -0
- package/renderer/WorldGenerator.d.ts +75 -0
- package/renderer/WorldGenerator.mjs +255 -0
- package/renderer/WorldSink.d.mts +50 -0
- package/renderer/WorldSink.d.ts +50 -0
- package/renderer/WorldSink.mjs +177 -0
- package/renderer/WorldStream.d.mts +45 -0
- package/renderer/WorldStream.d.ts +45 -0
- package/renderer/WorldStream.mjs +184 -0
- package/renderer/WsPartitionHints.d.mts +29 -0
- package/renderer/WsPartitionHints.d.ts +29 -0
- package/renderer/WsPartitionHints.mjs +102 -0
- package/renderer/WsProfile.d.mts +46 -0
- package/renderer/WsProfile.d.ts +46 -0
- package/renderer/WsProfile.mjs +152 -0
- package/renderer/WsRunResult.d.mts +83 -0
- package/renderer/WsRunResult.d.ts +83 -0
- package/renderer/WsRunResult.mjs +326 -0
- package/renderer/WsSegmentJob.d.mts +28 -0
- package/renderer/WsSegmentJob.d.ts +28 -0
- package/renderer/WsSegmentJob.mjs +81 -0
- package/renderer/diplomat-runtime.d.mts +15 -0
- package/renderer/diplomat-runtime.d.ts +15 -0
- package/renderer/diplomat-runtime.mjs +779 -0
- package/renderer/diplomat-wasm.mjs +52 -0
- package/renderer/diplomat.config.mjs +5 -0
- package/renderer/index.d.mts +193 -0
- package/renderer/index.d.ts +193 -0
- package/renderer/index.mjs +196 -0
- package/renderer/nucleation.wasm +0 -0
- package/renderer/veneer/design.d.ts +167 -0
- package/renderer/veneer/design.mjs +480 -0
|
@@ -0,0 +1,779 @@
|
|
|
1
|
+
/** For internal Diplomat use when constructing opaques or out structs.
|
|
2
|
+
* This is for when we're handling items that we don't want the user to touch, like an structure that's only meant to be output, or de-referencing a pointer we're handed from WASM.
|
|
3
|
+
*/
|
|
4
|
+
export const internalConstructor = Symbol("constructor");
|
|
5
|
+
/** For internal Diplomat use when accessing a from-fields/from-value constructor that's been overridden by a default constructor.
|
|
6
|
+
* If we want to pass in arguments without also passing in internalConstructor to avoid triggering some logic we don't want, we use exposeConstructor.
|
|
7
|
+
*/
|
|
8
|
+
export const exposeConstructor = Symbol("exposeConstructor");
|
|
9
|
+
|
|
10
|
+
export function readString8(wasm, ptr, len) {
|
|
11
|
+
ptr >>>= 0; // wasm32 addresses are unsigned, including above 2 GiB.
|
|
12
|
+
const buf = new Uint8Array(wasm.memory.buffer, ptr, len);
|
|
13
|
+
return (new TextDecoder("utf-8")).decode(buf)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function readString16(wasm, ptr, len) {
|
|
17
|
+
ptr >>>= 0; // wasm32 addresses are unsigned, including above 2 GiB.
|
|
18
|
+
const buf = new Uint16Array(wasm.memory.buffer, ptr, len);
|
|
19
|
+
return String.fromCharCode.apply(null, buf)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function withDiplomatWrite(wasm, callback) {
|
|
23
|
+
const write = wasm.diplomat_buffer_write_create(0);
|
|
24
|
+
try {
|
|
25
|
+
callback(write);
|
|
26
|
+
const outStringPtr = wasm.diplomat_buffer_write_get_bytes(write);
|
|
27
|
+
if (outStringPtr === null) {
|
|
28
|
+
throw Error("Out of memory");
|
|
29
|
+
}
|
|
30
|
+
const outStringLen = wasm.diplomat_buffer_write_len(write);
|
|
31
|
+
return readString8(wasm, outStringPtr, outStringLen);
|
|
32
|
+
} finally {
|
|
33
|
+
wasm.diplomat_buffer_write_destroy(write);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get the pointer returned by an FFI function.
|
|
39
|
+
*
|
|
40
|
+
* It's tempting to call `(new Uint32Array(wasm.memory.buffer, FFI_func(), 1))[0]`.
|
|
41
|
+
* However, there's a chance that `wasm.memory.buffer` will be resized between
|
|
42
|
+
* the time it's accessed and the time it's used, invalidating the view.
|
|
43
|
+
* This function ensures that the view into wasm memory is fresh.
|
|
44
|
+
*
|
|
45
|
+
* This is used for methods that return multiple types into a wasm buffer, where
|
|
46
|
+
* one of those types is another ptr. Call this method to get access to the returned
|
|
47
|
+
* ptr, so the return buffer can be freed.
|
|
48
|
+
* @param {WebAssembly.Exports} wasm Provided by diplomat generated files.
|
|
49
|
+
* @param {number} ptr Pointer of a pointer, to be read.
|
|
50
|
+
* @returns {number} The underlying pointer.
|
|
51
|
+
*/
|
|
52
|
+
export function ptrRead(wasm, ptr) {
|
|
53
|
+
ptr >>>= 0; // wasm32 addresses are unsigned, including above 2 GiB.
|
|
54
|
+
return (new Uint32Array(wasm.memory.buffer, ptr, 1))[0];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get the flag of a result type.
|
|
59
|
+
*/
|
|
60
|
+
export function resultFlag(wasm, ptr, offset) {
|
|
61
|
+
ptr >>>= 0; // wasm32 addresses are unsigned, including above 2 GiB.
|
|
62
|
+
return (new Uint8Array(wasm.memory.buffer, ptr + offset, 1))[0];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get the discriminant of a Rust enum.
|
|
67
|
+
*/
|
|
68
|
+
export function enumDiscriminant(wasm, ptr) {
|
|
69
|
+
ptr >>>= 0; // wasm32 addresses are unsigned, including above 2 GiB.
|
|
70
|
+
return (new Int32Array(wasm.memory.buffer, ptr, 1))[0]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Return an array of paddingCount zeroes to be spread into a function call
|
|
75
|
+
* if needsPaddingFields is true, else empty
|
|
76
|
+
*/
|
|
77
|
+
export function maybePaddingFields(needsPaddingFields, paddingCount) {
|
|
78
|
+
if (needsPaddingFields) {
|
|
79
|
+
return Array(paddingCount).fill(0);
|
|
80
|
+
} else {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Write a value of width `width` to a an ArrayBuffer `arrayBuffer`
|
|
87
|
+
* at byte offset `offset`, treating it as a buffer of kind `typedArrayKind`
|
|
88
|
+
* (which is a `TypedArray` variant like `Uint8Array` or `Int16Array`)
|
|
89
|
+
*/
|
|
90
|
+
export function writeToArrayBuffer(arrayBuffer, offset, value, typedArrayKind) {
|
|
91
|
+
let buffer = new typedArrayKind(arrayBuffer, offset < 0 ? offset >>> 0 : offset);
|
|
92
|
+
buffer[0] = value;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Take `jsValue` and write it to arrayBuffer at offset `offset` if it is non-null
|
|
97
|
+
* calling `writeToArrayBufferCallback(arrayBuffer, offset, jsValue)` to write to the buffer,
|
|
98
|
+
* also writing a tag bit.
|
|
99
|
+
*
|
|
100
|
+
* `size` and `align` are the size and alignment of T, not of Option<T>
|
|
101
|
+
*/
|
|
102
|
+
export function writeOptionToArrayBuffer(arrayBuffer, offset, jsValue, size, align, writeToArrayBufferCallback) {
|
|
103
|
+
// perform a nullish check, not a null check,
|
|
104
|
+
// we want identical behavior for undefined
|
|
105
|
+
if (jsValue != null) {
|
|
106
|
+
writeToArrayBufferCallback(arrayBuffer, offset, jsValue);
|
|
107
|
+
writeToArrayBuffer(arrayBuffer, offset + size, 1, Uint8Array);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* For Option<T> of given size/align (of T, not the overall option type),
|
|
113
|
+
* return an array of fields suitable for passing down to a parameter list.
|
|
114
|
+
*
|
|
115
|
+
* Calls writeToArrayBufferCallback(arrayBuffer, offset, jsValue) for non-null jsValues
|
|
116
|
+
*
|
|
117
|
+
* This array will have size<T>/align<T> elements for the actual T, then one element
|
|
118
|
+
* for the is_ok bool.
|
|
119
|
+
*
|
|
120
|
+
* See wasm_abi_quirks.md's section on Unions for understanding this ABI.
|
|
121
|
+
*/
|
|
122
|
+
export function optionToArgsForCalling(jsValue, size, align, writeToArrayBufferCallback) {
|
|
123
|
+
let args;
|
|
124
|
+
// perform a nullish check, not a null check,
|
|
125
|
+
// we want identical behavior for undefined
|
|
126
|
+
if (jsValue != null) {
|
|
127
|
+
let buffer;
|
|
128
|
+
// We need our originator array to be properly aligned
|
|
129
|
+
if (align == 8) {
|
|
130
|
+
buffer = new BigUint64Array(size / align);
|
|
131
|
+
} else if (align == 4) {
|
|
132
|
+
buffer = new Uint32Array(size / align);
|
|
133
|
+
} else if (align == 2) {
|
|
134
|
+
buffer = new Uint16Array(size / align);
|
|
135
|
+
} else {
|
|
136
|
+
buffer = new Uint8Array(size / align);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
writeToArrayBufferCallback(buffer.buffer, 0, jsValue);
|
|
141
|
+
args = Array.from(buffer);
|
|
142
|
+
args.push(1);
|
|
143
|
+
} else {
|
|
144
|
+
args = Array(size / align).fill(0);
|
|
145
|
+
args.push(0);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Unconditionally add padding
|
|
149
|
+
args = args.concat(Array(align - 1).fill(0));
|
|
150
|
+
return args;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* For Option<T> of given size/align (of T, not the overall option type),
|
|
155
|
+
* return a pointer to wasm memory, allocated in `allocator`, that stores a `jsValue`
|
|
156
|
+
* of that option type (or `null`).
|
|
157
|
+
*
|
|
158
|
+
* Calls writeToArrayBufferCallback(arrayBuffer, offset, jsValue) for non-null jsValues.
|
|
159
|
+
*
|
|
160
|
+
* This array will have size<T>/align<T> elements for the actual T, then one element
|
|
161
|
+
* for the is_ok bool.
|
|
162
|
+
*/
|
|
163
|
+
export function optionToBufferForCalling(wasm, jsValue, size, align, allocator, writeToArrayBufferCallback) {
|
|
164
|
+
let buf = DiplomatBuf.struct(wasm, size + align, align);
|
|
165
|
+
|
|
166
|
+
let buffer;
|
|
167
|
+
// Add 1 to the size since we're also accounting for the 0 or 1 is_ok field:
|
|
168
|
+
if (align == 8) {
|
|
169
|
+
buffer = new BigUint64Array(wasm.memory.buffer, buf.ptr, size / align + 1);
|
|
170
|
+
} else if (align == 4) {
|
|
171
|
+
buffer = new Uint32Array(wasm.memory.buffer, buf.ptr, size / align + 1);
|
|
172
|
+
} else if (align == 2) {
|
|
173
|
+
buffer = new Uint16Array(wasm.memory.buffer, buf.ptr, size / align + 1);
|
|
174
|
+
} else {
|
|
175
|
+
buffer = new Uint8Array(wasm.memory.buffer, buf.ptr, size / align + 1);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
buffer.fill(0);
|
|
179
|
+
|
|
180
|
+
if (jsValue != null) {
|
|
181
|
+
// Note that `buffer.buffer` is the underlying ArrayBuffer (`buffer` is just a view),
|
|
182
|
+
// so we must provide the offset pointer (buf.ptr)
|
|
183
|
+
writeToArrayBufferCallback(buffer.buffer, buf.ptr, jsValue);
|
|
184
|
+
buffer[buffer.length - 1] = 1;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return allocator.alloc(buf).ptr;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Given `ptr` in Wasm memory, treat it as an Option<T> with size for type T,
|
|
193
|
+
* and return the converted T (converted using `readCallback(wasm, ptr)`) if the Option is Some
|
|
194
|
+
* else None.
|
|
195
|
+
*/
|
|
196
|
+
export function readOption(wasm, ptr, size, readCallback) {
|
|
197
|
+
// Don't need the alignment: diplomat types don't have overridden alignment,
|
|
198
|
+
// so the flag will immediately be after the inner struct.
|
|
199
|
+
let flag = resultFlag(wasm, ptr, size);
|
|
200
|
+
if (flag) {
|
|
201
|
+
return readCallback(wasm, ptr);
|
|
202
|
+
} else {
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* A wrapper around a slice of WASM memory that can be freed manually or
|
|
209
|
+
* automatically by the garbage collector.
|
|
210
|
+
*
|
|
211
|
+
* This type is necessary for Rust functions that take a `&str` or `&[T]`, since
|
|
212
|
+
* they can create an edge to this object if they borrow from the str/slice,
|
|
213
|
+
* or we can manually free the WASM memory if they don't.
|
|
214
|
+
*/
|
|
215
|
+
export class DiplomatBuf {
|
|
216
|
+
static str8 = (wasm, string) => {
|
|
217
|
+
var utf8Length = 0;
|
|
218
|
+
for (const codepointString of string) {
|
|
219
|
+
let codepoint = codepointString.codePointAt(0);
|
|
220
|
+
if (codepoint < 0x80) {
|
|
221
|
+
utf8Length += 1
|
|
222
|
+
} else if (codepoint < 0x800) {
|
|
223
|
+
utf8Length += 2
|
|
224
|
+
} else if (codepoint < 0x10000) {
|
|
225
|
+
utf8Length += 3
|
|
226
|
+
} else {
|
|
227
|
+
utf8Length += 4
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const ptr = wasm.diplomat_alloc(utf8Length, 1) >>> 0;
|
|
232
|
+
|
|
233
|
+
const result = (new TextEncoder()).encodeInto(string, new Uint8Array(wasm.memory.buffer, ptr, utf8Length));
|
|
234
|
+
console.assert(string.length === result.read && utf8Length === result.written, "UTF-8 write error");
|
|
235
|
+
|
|
236
|
+
return new DiplomatBuf(ptr, utf8Length, () => wasm.diplomat_free(ptr, utf8Length, 1));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
static str16 = (wasm, string) => {
|
|
240
|
+
const byteLength = string.length * 2;
|
|
241
|
+
const ptr = wasm.diplomat_alloc(byteLength, 2) >>> 0;
|
|
242
|
+
|
|
243
|
+
const destination = new Uint16Array(wasm.memory.buffer, ptr, string.length);
|
|
244
|
+
for (let i = 0; i < string.length; i++) {
|
|
245
|
+
destination[i] = string.charCodeAt(i);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return new DiplomatBuf(ptr, string.length, () => wasm.diplomat_free(ptr, byteLength, 2));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
static sliceWrapper = (wasm, buf) => {
|
|
252
|
+
const ptr = wasm.diplomat_alloc(8, 4) >>> 0;
|
|
253
|
+
let dst = new Uint32Array(wasm.memory.buffer, ptr, 2);
|
|
254
|
+
|
|
255
|
+
dst[0] = buf.ptr;
|
|
256
|
+
dst[1] = buf.size;
|
|
257
|
+
return new DiplomatBuf(ptr, 8, () => {
|
|
258
|
+
wasm.diplomat_free(ptr, 8, 4);
|
|
259
|
+
buf.free();
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
static slice = (wasm, list, rustType) => {
|
|
264
|
+
const elementSize = rustType === "u8" || rustType === "i8" || rustType === "boolean" ? 1 :
|
|
265
|
+
rustType === "u16" || rustType === "i16" ? 2 :
|
|
266
|
+
rustType === "u64" || rustType === "i64" || rustType === "f64" ? 8 :
|
|
267
|
+
4;
|
|
268
|
+
|
|
269
|
+
const byteLength = list.length * elementSize;
|
|
270
|
+
const ptr = wasm.diplomat_alloc(byteLength, elementSize) >>> 0;
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Create an array view of the buffer. This gives us the `set` method which correctly handles untyped values
|
|
274
|
+
*/
|
|
275
|
+
const destination =
|
|
276
|
+
rustType === "u8" || rustType === "boolean" ? new Uint8Array(wasm.memory.buffer, ptr, list.length) :
|
|
277
|
+
rustType === "i8" ? new Int8Array(wasm.memory.buffer, ptr, list.length) :
|
|
278
|
+
rustType === "u16" ? new Uint16Array(wasm.memory.buffer, ptr, list.length) :
|
|
279
|
+
rustType === "i16" ? new Int16Array(wasm.memory.buffer, ptr, list.length) :
|
|
280
|
+
rustType === "i32" ? new Int32Array(wasm.memory.buffer, ptr, list.length) :
|
|
281
|
+
rustType === "u64" ? new BigUint64Array(wasm.memory.buffer, ptr, list.length) :
|
|
282
|
+
rustType === "i64" ? new BigInt64Array(wasm.memory.buffer, ptr, list.length) :
|
|
283
|
+
rustType === "f32" ? new Float32Array(wasm.memory.buffer, ptr, list.length) :
|
|
284
|
+
rustType === "f64" ? new Float64Array(wasm.memory.buffer, ptr, list.length) :
|
|
285
|
+
new Uint32Array(wasm.memory.buffer, ptr, list.length);
|
|
286
|
+
destination.set(list);
|
|
287
|
+
|
|
288
|
+
return new DiplomatBuf(ptr, list.length, () => wasm.diplomat_free(ptr, byteLength, elementSize));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
static strs = (wasm, strings, encoding) => {
|
|
292
|
+
let encodeStr = (encoding === "string16") ? DiplomatBuf.str16 : DiplomatBuf.str8;
|
|
293
|
+
|
|
294
|
+
const byteLength = strings.length * 4 * 2;
|
|
295
|
+
|
|
296
|
+
const ptr = wasm.diplomat_alloc(byteLength, 4) >>> 0;
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
const stringsAlloc = [];
|
|
300
|
+
|
|
301
|
+
for (let i = 0; i < strings.length; i++) {
|
|
302
|
+
stringsAlloc.push(encodeStr(wasm, strings[i]));
|
|
303
|
+
|
|
304
|
+
const destination = new Uint32Array(wasm.memory.buffer, ptr, strings.length * 2);
|
|
305
|
+
destination[2 * i] = stringsAlloc[i].ptr;
|
|
306
|
+
destination[(2 * i) + 1] = stringsAlloc[i].size;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return new DiplomatBuf(ptr, strings.length, () => {
|
|
310
|
+
wasm.diplomat_free(ptr, byteLength, 4);
|
|
311
|
+
for (let i = 0; i < stringsAlloc.length; i++) {
|
|
312
|
+
stringsAlloc[i].free();
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
static struct = (wasm, size, align) => {
|
|
318
|
+
const ptr = wasm.diplomat_alloc(size, align) >>> 0;
|
|
319
|
+
|
|
320
|
+
return new DiplomatBuf(ptr, size, () => {
|
|
321
|
+
wasm.diplomat_free(ptr, size, align);
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Generated code calls one of methods these for each allocation, to either
|
|
327
|
+
* free directly after the FFI call, to leak (to create a &'static), or to
|
|
328
|
+
* register the buffer with the garbage collector (to create a &'a).
|
|
329
|
+
*/
|
|
330
|
+
free;
|
|
331
|
+
|
|
332
|
+
constructor(ptr, size, free) {
|
|
333
|
+
this.ptr = ptr >>> 0;
|
|
334
|
+
this.size = size;
|
|
335
|
+
this.free = free;
|
|
336
|
+
this.leak = () => { };
|
|
337
|
+
this.releaseToGarbageCollector = () => DiplomatBufferFinalizer.register(this, () => this.free());
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
splat() {
|
|
341
|
+
return [this.ptr, this.size];
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Write the (ptr, len) pair to an array buffer at byte offset `offset`
|
|
346
|
+
*/
|
|
347
|
+
writePtrLenToArrayBuffer(arrayBuffer, offset) {
|
|
348
|
+
writeToArrayBuffer(arrayBuffer, offset, this.ptr, Uint32Array);
|
|
349
|
+
writeToArrayBuffer(arrayBuffer, offset + 4, this.size, Uint32Array);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Helper class for creating and managing `diplomat_buffer_write`.
|
|
355
|
+
* Meant to minimize direct calls to `wasm`.
|
|
356
|
+
*/
|
|
357
|
+
export class DiplomatWriteBuf {
|
|
358
|
+
leak;
|
|
359
|
+
|
|
360
|
+
#wasm;
|
|
361
|
+
#buffer;
|
|
362
|
+
|
|
363
|
+
constructor(wasm) {
|
|
364
|
+
this.#wasm = wasm;
|
|
365
|
+
this.#buffer = this.#wasm.diplomat_buffer_write_create(0) >>> 0;
|
|
366
|
+
|
|
367
|
+
this.leak = () => { };
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
free() {
|
|
371
|
+
this.#wasm.diplomat_buffer_write_destroy(this.#buffer);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
releaseToGarbageCollector() {
|
|
375
|
+
DiplomatBufferFinalizer.register(this, () => this.free());
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
readString8() {
|
|
379
|
+
return readString8(this.#wasm, this.ptr, this.size);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
get buffer() {
|
|
383
|
+
return this.#buffer;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
get ptr() {
|
|
387
|
+
return this.#wasm.diplomat_buffer_write_get_bytes(this.#buffer);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
get size() {
|
|
391
|
+
return this.#wasm.diplomat_buffer_write_len(this.#buffer);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Represents an underlying slice that we've grabbed from WebAssembly.
|
|
397
|
+
* You can treat this in JS as a regular slice of primitives, but it handles additional data for you behind the scenes.
|
|
398
|
+
*/
|
|
399
|
+
export class DiplomatSlice {
|
|
400
|
+
#wasm;
|
|
401
|
+
|
|
402
|
+
#bufferType;
|
|
403
|
+
get bufferType() {
|
|
404
|
+
return this.#bufferType;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
#buffer;
|
|
408
|
+
get buffer() {
|
|
409
|
+
return this.#buffer;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
#lifetimeEdges;
|
|
413
|
+
|
|
414
|
+
constructor(wasm, buffer, bufferType, lifetimeEdges) {
|
|
415
|
+
this.#wasm = wasm;
|
|
416
|
+
|
|
417
|
+
const [ptr, size] = new Uint32Array(this.#wasm.memory.buffer, buffer >>> 0, 2);
|
|
418
|
+
|
|
419
|
+
this.#buffer = new bufferType(this.#wasm.memory.buffer, ptr, size);
|
|
420
|
+
this.#bufferType = bufferType;
|
|
421
|
+
|
|
422
|
+
this.#lifetimeEdges = lifetimeEdges;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
getValue() {
|
|
426
|
+
return this.#buffer;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
[Symbol.toPrimitive]() {
|
|
430
|
+
return this.getValue();
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
valueOf() {
|
|
434
|
+
return this.getValue();
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export class DiplomatSlicePrimitive extends DiplomatSlice {
|
|
439
|
+
constructor(wasm, buffer, sliceType, lifetimeEdges) {
|
|
440
|
+
const [ptr, size] = new Uint32Array(wasm.memory.buffer, buffer >>> 0, 2);
|
|
441
|
+
|
|
442
|
+
let arrayType;
|
|
443
|
+
switch (sliceType) {
|
|
444
|
+
case "u8":
|
|
445
|
+
case "boolean":
|
|
446
|
+
arrayType = Uint8Array;
|
|
447
|
+
break;
|
|
448
|
+
case "i8":
|
|
449
|
+
arrayType = Int8Array;
|
|
450
|
+
break;
|
|
451
|
+
case "u16":
|
|
452
|
+
arrayType = Uint16Array;
|
|
453
|
+
break;
|
|
454
|
+
case "i16":
|
|
455
|
+
arrayType = Int16Array;
|
|
456
|
+
break;
|
|
457
|
+
case "i32":
|
|
458
|
+
arrayType = Int32Array;
|
|
459
|
+
break;
|
|
460
|
+
case "u32":
|
|
461
|
+
arrayType = Uint32Array;
|
|
462
|
+
break;
|
|
463
|
+
case "i64":
|
|
464
|
+
arrayType = BigInt64Array;
|
|
465
|
+
break;
|
|
466
|
+
case "u64":
|
|
467
|
+
arrayType = BigUint64Array;
|
|
468
|
+
break;
|
|
469
|
+
case "f32":
|
|
470
|
+
arrayType = Float32Array;
|
|
471
|
+
break;
|
|
472
|
+
case "f64":
|
|
473
|
+
arrayType = Float64Array;
|
|
474
|
+
break;
|
|
475
|
+
default:
|
|
476
|
+
console.error("Unrecognized bufferType ", bufferType);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
super(wasm, buffer, arrayType, lifetimeEdges);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export class DiplomatSliceStr extends DiplomatSlice {
|
|
484
|
+
#decoder;
|
|
485
|
+
|
|
486
|
+
constructor(wasm, buffer, stringEncoding, lifetimeEdges) {
|
|
487
|
+
let encoding;
|
|
488
|
+
switch (stringEncoding) {
|
|
489
|
+
case "string8":
|
|
490
|
+
encoding = Uint8Array;
|
|
491
|
+
break;
|
|
492
|
+
case "string16":
|
|
493
|
+
encoding = Uint16Array;
|
|
494
|
+
break;
|
|
495
|
+
default:
|
|
496
|
+
console.error("Unrecognized stringEncoding ", stringEncoding);
|
|
497
|
+
break;
|
|
498
|
+
}
|
|
499
|
+
super(wasm, buffer, encoding, lifetimeEdges);
|
|
500
|
+
|
|
501
|
+
if (stringEncoding === "string8") {
|
|
502
|
+
this.#decoder = new TextDecoder('utf-8');
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
getValue() {
|
|
507
|
+
switch (this.bufferType) {
|
|
508
|
+
case Uint8Array:
|
|
509
|
+
return this.#decoder.decode(super.getValue());
|
|
510
|
+
case Uint16Array:
|
|
511
|
+
return String.fromCharCode.apply(null, super.getValue());
|
|
512
|
+
default:
|
|
513
|
+
return null;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
toString() {
|
|
518
|
+
return this.getValue();
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export class DiplomatSliceStrings extends DiplomatSlice {
|
|
523
|
+
#strings = [];
|
|
524
|
+
constructor(wasm, buffer, stringEncoding, lifetimeEdges) {
|
|
525
|
+
super(wasm, buffer, Uint32Array, lifetimeEdges);
|
|
526
|
+
|
|
527
|
+
for (let i = this.buffer.byteOffset; i < this.buffer.byteLength; i += this.buffer.BYTES_PER_ELEMENT * 2) {
|
|
528
|
+
this.#strings.push(new DiplomatSliceStr(wasm, i, stringEncoding, lifetimeEdges));
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
getValue() {
|
|
533
|
+
return this.#strings;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* A number of Rust functions in WebAssembly require a buffer to populate struct, slice, Option<> or Result<> types with information.
|
|
539
|
+
* {@link DiplomatReceiveBuf} allocates a buffer in WebAssembly, which can then be passed into functions with the {@link DiplomatReceiveBuf.buffer}
|
|
540
|
+
* property.
|
|
541
|
+
*/
|
|
542
|
+
export class DiplomatReceiveBuf {
|
|
543
|
+
#wasm;
|
|
544
|
+
|
|
545
|
+
#size;
|
|
546
|
+
#align;
|
|
547
|
+
|
|
548
|
+
#hasResult;
|
|
549
|
+
|
|
550
|
+
#buffer;
|
|
551
|
+
|
|
552
|
+
constructor(wasm, size, align, hasResult) {
|
|
553
|
+
this.#wasm = wasm;
|
|
554
|
+
|
|
555
|
+
this.#size = size;
|
|
556
|
+
this.#align = align;
|
|
557
|
+
|
|
558
|
+
this.#hasResult = hasResult;
|
|
559
|
+
|
|
560
|
+
this.#buffer = this.#wasm.diplomat_alloc(this.#size, this.#align) >>> 0;
|
|
561
|
+
|
|
562
|
+
this.leak = () => { };
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
free() {
|
|
566
|
+
this.#wasm.diplomat_free(this.#buffer, this.#size, this.#align);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
get buffer() {
|
|
570
|
+
return this.#buffer;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Only for when a DiplomatReceiveBuf is allocating a buffer for an `Option<>` or a `Result<>` type.
|
|
575
|
+
*
|
|
576
|
+
* This just checks the last byte for a successful result (assuming that Rust's compiler does not change).
|
|
577
|
+
*/
|
|
578
|
+
get resultFlag() {
|
|
579
|
+
if (this.#hasResult) {
|
|
580
|
+
return resultFlag(this.#wasm, this.#buffer, this.#size - 1);
|
|
581
|
+
} else {
|
|
582
|
+
return true;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* For preallocating owned slices
|
|
589
|
+
*
|
|
590
|
+
* Doesn't actually do anything, but helps code readability of generated code
|
|
591
|
+
*/
|
|
592
|
+
export class OwnedSliceLeaker {
|
|
593
|
+
constructor() {
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Leak an item
|
|
598
|
+
* @param {DiplomatBuf} item
|
|
599
|
+
* @returns {DiplomatBuf}
|
|
600
|
+
*/
|
|
601
|
+
static alloc(item) {
|
|
602
|
+
item.leak();
|
|
603
|
+
return item;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* For cleaning up slices inside struct _intoFFI functions.
|
|
609
|
+
* Based somewhat on how the Dart backend handles slice cleanup.
|
|
610
|
+
*
|
|
611
|
+
* We want to ensure a slice only lasts as long as its struct, so we have a `functionCleanupArena` CleanupArena that we use in each method for any slice that needs to be cleaned up. It lasts only as long as the function is called for.
|
|
612
|
+
*
|
|
613
|
+
* Then we have `createWith`, which is meant for longer lasting slices. It takes an array of edges and will last as long as those edges do. Cleanup is only called later.
|
|
614
|
+
*/
|
|
615
|
+
export class CleanupArena {
|
|
616
|
+
#items = [];
|
|
617
|
+
|
|
618
|
+
constructor() {
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* When this arena is freed, call .free() on the given item.
|
|
623
|
+
* @param {DiplomatBuf} item
|
|
624
|
+
* @returns {DiplomatBuf}
|
|
625
|
+
*/
|
|
626
|
+
alloc(item) {
|
|
627
|
+
this.#items.push(item);
|
|
628
|
+
return item;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Create a new CleanupArena, append it to any edge arrays passed down, and return it.
|
|
632
|
+
* @param {Array} edgeArrays
|
|
633
|
+
* @returns {CleanupArena}
|
|
634
|
+
*/
|
|
635
|
+
static createWith(...edgeArrays) {
|
|
636
|
+
let self = new CleanupArena();
|
|
637
|
+
for (let edgeArray of edgeArrays) {
|
|
638
|
+
if (edgeArray != null) {
|
|
639
|
+
edgeArray.push(self);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
DiplomatBufferFinalizer.register(self, () => self.free());
|
|
643
|
+
return self;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* If given edge arrays, create a new CleanupArena, append it to any edge arrays passed down, and return it.
|
|
648
|
+
* Else return the function-local cleanup arena
|
|
649
|
+
* @param {CleanupArena} functionCleanupArena
|
|
650
|
+
* @param {Array} edgeArrays
|
|
651
|
+
* @returns {DiplomatBuf}
|
|
652
|
+
*/
|
|
653
|
+
static maybeCreateWith(functionCleanupArena, ...edgeArrays) {
|
|
654
|
+
if (edgeArrays.length > 0) {
|
|
655
|
+
return CleanupArena.createWith(...edgeArrays);
|
|
656
|
+
} else {
|
|
657
|
+
return functionCleanupArena
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
free() {
|
|
662
|
+
this.#items.forEach((i) => {
|
|
663
|
+
i.free();
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
this.#items.length = 0;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Similar to {@link CleanupArena}, but for holding on to slices until a method is called,
|
|
672
|
+
* after which we rely on the GC to free them.
|
|
673
|
+
*
|
|
674
|
+
* This is when you may want to use a slice longer than the body of the method.
|
|
675
|
+
*
|
|
676
|
+
* At first glance this seems unnecessary, since we will be holding these slices in edge arrays anyway,
|
|
677
|
+
* however, if an edge array ends up unused, then we do actually need something to hold it for the duration
|
|
678
|
+
* of the method call.
|
|
679
|
+
*/
|
|
680
|
+
export class GarbageCollectorGrip {
|
|
681
|
+
#items = [];
|
|
682
|
+
|
|
683
|
+
alloc(item) {
|
|
684
|
+
this.#items.push(item);
|
|
685
|
+
return item;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
releaseToGarbageCollector() {
|
|
689
|
+
this.#items.forEach((i) => {
|
|
690
|
+
i.releaseToGarbageCollector();
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
this.#items.length = 0;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
const DiplomatBufferFinalizer = new FinalizationRegistry(free => free());
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* For allocating and cleaning up structs to be passed into the C Spec WASM ABI.
|
|
701
|
+
* This is primarily intended for storing structures being passed from Javascript to Rust.
|
|
702
|
+
* The maximal size any parameters we could ever need to store can be calculated by Diplomat, so we can pre-allocate a buffer
|
|
703
|
+
* and allocate structs there.
|
|
704
|
+
*
|
|
705
|
+
* Created/reserved when we load in the WebAssembly.
|
|
706
|
+
*/
|
|
707
|
+
export class FunctionParamAllocator {
|
|
708
|
+
#ptr = 0;
|
|
709
|
+
#capacity = 0;
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* A stack of pointers to Rust types allocated with {@link alloc}.
|
|
713
|
+
* The stack is popped with {@link get}, returning the most recently allocated pointer.
|
|
714
|
+
* Note that this does NOT clear allocated memory, this must be done with {@link clean}.
|
|
715
|
+
* Each pointer is guaranteed to be within the bounds of #ptr.
|
|
716
|
+
*
|
|
717
|
+
*/
|
|
718
|
+
#allocated = [];
|
|
719
|
+
/**
|
|
720
|
+
* The size of everything currently allocated.
|
|
721
|
+
* The size is only reset with {@link clean}.
|
|
722
|
+
*/
|
|
723
|
+
#currentPtr = 0;
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Reserve {@link #ptr} with a specific capacity.
|
|
727
|
+
* @param {WebAssembly.Module} wasm Web assembly module to allocate into.
|
|
728
|
+
* @param {number} capacity How large, in bytes, the buffer should be.
|
|
729
|
+
*/
|
|
730
|
+
reserve(symbol, wasm, capacity) {
|
|
731
|
+
if (symbol !== internalConstructor) {
|
|
732
|
+
throw new Error(".reserve should only be called internally.");
|
|
733
|
+
}
|
|
734
|
+
if (this.#ptr !== 0) {
|
|
735
|
+
if (this.#currentPtr > 0) {
|
|
736
|
+
throw new Error("Cannot reserve additional space if memory has already been allocated! .clear() must be called.");
|
|
737
|
+
} else {
|
|
738
|
+
wasm.diplomat_free(this.#ptr, this.#capacity, 1);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
this.#capacity = capacity;
|
|
743
|
+
// FunctionParamAllocator is global, so this will be freed when the webpage closes:
|
|
744
|
+
this.#ptr = wasm.diplomat_alloc(this.#capacity, 1) >>> 0;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Reserves part of {@link #ptr} to be used for allocating function parameters on the stack to Rust memory.
|
|
749
|
+
* @param {number} size The size of the buffer to reserve
|
|
750
|
+
* @returns A pointer to what was just reserved.
|
|
751
|
+
*/
|
|
752
|
+
alloc(size) {
|
|
753
|
+
if (this.#currentPtr + size > this.#capacity) {
|
|
754
|
+
throw new Error(`Could not allocate size ${this.#currentPtr} + ${size} > ${this.#capacity}. Please consider adjusting reserve()`);
|
|
755
|
+
}
|
|
756
|
+
this.#allocated.push(this.#ptr + this.#currentPtr);
|
|
757
|
+
this.#currentPtr += size;
|
|
758
|
+
return this.#ptr + (this.#currentPtr - size);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Pops the most recently allocated pointer on the stack.
|
|
763
|
+
* @returns The most recently allocated pointer on the stack.
|
|
764
|
+
*/
|
|
765
|
+
pop() {
|
|
766
|
+
return this.#allocated.pop();
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Free up memory on the buffer.
|
|
771
|
+
*/
|
|
772
|
+
clean() {
|
|
773
|
+
this.#currentPtr = 0;
|
|
774
|
+
|
|
775
|
+
this.#allocated = [];
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
export const FUNCTION_PARAM_ALLOC = new FunctionParamAllocator();
|