Skip to content

Commit

Permalink
refactor(uint64): replace custom Uint64 class with bigint
Browse files Browse the repository at this point in the history
Now that there is support in the major browsers for bigint and
optimization of the uint64 as bigint case, the custom Uint64 class can
be removed.
  • Loading branch information
jbms committed Feb 21, 2025
1 parent 0534765 commit ce4d217
Show file tree
Hide file tree
Showing 95 changed files with 1,369 additions and 2,362 deletions.
12 changes: 4 additions & 8 deletions src/annotation/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import type {
AnnotationId,
SerializedAnnotations,
} from "#src/annotation/index.js";
import { fixAnnotationAfterStructuredCloning } from "#src/annotation/index.js";
import type { ChunkManager } from "#src/chunk_manager/backend.js";
import {
Chunk,
Expand Down Expand Up @@ -67,7 +66,6 @@ import {
import type { TransformedSource } from "#src/sliceview/base.js";
import { registerNested, WatchableValue } from "#src/trackable_value.js";
import type { Borrowed } from "#src/util/disposable.js";
import type { Uint64 } from "#src/util/uint64.js";
import {
getBasePriority,
getPriorityTier,
Expand Down Expand Up @@ -153,7 +151,7 @@ export class AnnotationGeometryChunk extends GeometryChunkMixin(

export class AnnotationSubsetGeometryChunk extends GeometryChunkMixin(Chunk) {
declare source: AnnotationSubsetGeometryChunkSource;
objectId: Uint64;
objectId: bigint;
}

@registerSharedObject(ANNOTATION_METADATA_CHUNK_SOURCE_RPC_ID)
Expand Down Expand Up @@ -193,14 +191,14 @@ class AnnotationSubsetGeometryChunkSource extends ChunkSource {
parent: Borrowed<AnnotationSource> | undefined = undefined;
declare chunks: Map<string, AnnotationSubsetGeometryChunk>;
relationshipIndex: number;
getChunk(objectId: Uint64) {
getChunk(objectId: bigint) {
const key = getObjectKey(objectId);
const { chunks } = this;
let chunk = chunks.get(key);
if (chunk === undefined) {
chunk = this.getNewChunk_(AnnotationSubsetGeometryChunk);
chunk.initialize(key);
chunk.objectId = objectId.clone();
chunk.objectId = objectId;
this.addChunk(chunk);
}
return chunk;
Expand Down Expand Up @@ -303,9 +301,7 @@ registerRPC(ANNOTATION_REFERENCE_DELETE_RPC_ID, function (x: any) {
registerRPC(ANNOTATION_COMMIT_UPDATE_RPC_ID, function (x: any) {
const obj = <AnnotationSource>this.get(x.id);
const annotationId: AnnotationId | undefined = x.annotationId;
const newAnnotation: Annotation | null = fixAnnotationAfterStructuredCloning(
x.newAnnotation,
);
const newAnnotation: Annotation | null = x.newAnnotation;

let promise: Promise<Annotation | null>;
if (annotationId === undefined) {
Expand Down
6 changes: 2 additions & 4 deletions src/annotation/frontend_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import {
AnnotationType,
annotationTypeHandlers,
annotationTypes,
fixAnnotationAfterStructuredCloning,
makeAnnotationId,
makeAnnotationPropertySerializers,
} from "#src/annotation/index.js";
Expand Down Expand Up @@ -250,7 +249,7 @@ export class AnnotationMetadataChunk extends Chunk {
annotation: Annotation | null;
constructor(source: Borrowed<AnnotationMetadataChunkSource>, x: any) {
super(source);
this.annotation = fixAnnotationAfterStructuredCloning(x.annotation);
this.annotation = x.annotation;
}
}

Expand Down Expand Up @@ -1008,8 +1007,7 @@ registerRPC(ANNOTATION_COMMIT_UPDATE_RESULT_RPC_ID, function (x) {
if (error !== undefined) {
source.handleFailedUpdate(annotationId, error);
} else {
const newAnnotation: Annotation | null =
fixAnnotationAfterStructuredCloning(x.newAnnotation);
const newAnnotation: Annotation | null = x.newAnnotation;
source.handleSuccessfulUpdate(annotationId, newAnnotation);
}
});
40 changes: 14 additions & 26 deletions src/annotation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
expectArray,
parseArray,
parseFixedLengthArray,
parseUint64,
verifyEnumString,
verifyFiniteFloat,
verifyFiniteNonNegativeFloat,
Expand All @@ -54,7 +55,6 @@ import {
import { parseDataTypeValue } from "#src/util/lerp.js";
import { getRandomHexString } from "#src/util/random.js";
import { NullarySignal, Signal } from "#src/util/signal.js";
import { Uint64 } from "#src/util/uint64.js";

export type AnnotationId = string;

Expand Down Expand Up @@ -642,7 +642,7 @@ export interface AnnotationBase {
id: AnnotationId;
type: AnnotationType;

relatedSegments?: Uint64[][];
relatedSegments?: BigUint64Array[];
properties: any[];
}

Expand Down Expand Up @@ -1017,7 +1017,7 @@ export function annotationToJson(
const { relatedSegments } = annotation;
if (relatedSegments?.some((x) => x.length !== 0)) {
result.segments = relatedSegments.map((segments) =>
segments.map((x) => x.toString()),
Array.from(segments, (x) => x.toString()),
);
}
if (schema.properties.length !== 0) {
Expand Down Expand Up @@ -1053,11 +1053,20 @@ function restoreAnnotation(
return schema.relationships.map(() => []);
}
if (schema.relationships.length === 1 && !Array.isArray(a[0])) {
return [parseArray(a, (x) => Uint64.parseString(x))];
return [
parseFixedLengthArray(new BigUint64Array(a.length), a, parseUint64),
];
}
return parseArray(
expectArray(relObj, schema.relationships.length),
(segments) => parseArray(segments, (y) => Uint64.parseString(y)),
(segments) => {
segments = expectArray(segments);
return parseFixedLengthArray(
new BigUint64Array(segments.length),
segments,
parseUint64,
);
},
);
});
const properties = verifyObjectProperty(obj, "props", (propsObj) => {
Expand Down Expand Up @@ -1438,24 +1447,3 @@ export class AnnotationSerializer {
return serializeAnnotations(this.annotations, this.propertySerializers);
}
}

export function fixAnnotationAfterStructuredCloning(obj: Annotation | null) {
if (obj == null) {
return obj;
}
const { relatedSegments } = obj;
if (relatedSegments !== undefined) {
for (
let i = 0, numRelationships = relatedSegments.length;
i < numRelationships;
++i
) {
const segments = relatedSegments[i];
if (segments === undefined) continue;
relatedSegments[i] = segments.map(
(x: { low: number; high: number }) => new Uint64(x.low, x.high),
);
}
}
return obj;
}
6 changes: 2 additions & 4 deletions src/annotation/renderlayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ import type { MessageList } from "#src/util/message_list.js";
import { MessageSeverity } from "#src/util/message_list.js";
import type { AnyConstructor, MixinConstructor } from "#src/util/mixin.js";
import { NullarySignal } from "#src/util/signal.js";
import type { Uint64 } from "#src/util/uint64.js";
import { withSharedVisibility } from "#src/visibility_priority/frontend.js";
import { GLBuffer } from "#src/webgl/buffer.js";
import type { ParameterizedContextDependentShaderGetter } from "#src/webgl/dynamic_shader.js";
Expand Down Expand Up @@ -639,8 +638,7 @@ function AnnotationRenderLayer<
pickId = renderContext.pickIDs.register(
this,
chunk.numPickIds,
0,
0,
0n,
chunk,
);
}
Expand Down Expand Up @@ -701,7 +699,7 @@ function AnnotationRenderLayer<

updateMouseState(
mouseState: MouseSelectionState,
_pickedValue: Uint64,
_pickedValue: bigint,
pickedOffset: number,
data: any,
) {
Expand Down
11 changes: 1 addition & 10 deletions src/async_computation/encode_compressed_segmentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,7 @@ registerAsyncComputation(
encodeCompressedSegmentationUint64,
async (rawData, shape, blockSize) => {
tempBuffer.clear();
encodeChannelsUint64(
tempBuffer,
blockSize,
new BigUint64Array(
rawData.buffer,
rawData.byteOffset,
rawData.length / 2,
),
shape,
);
encodeChannelsUint64(tempBuffer, blockSize, rawData, shape);
return { value: tempBuffer.view };
},
);
22 changes: 8 additions & 14 deletions src/datasource/brainmaps/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@ import { kInfinityVec, kZeroVec, vec3, vec3Key } from "#src/util/geom.js";
import {
parseArray,
parseFixedLengthArray,
parseUint64,
verifyObject,
verifyObjectProperty,
verifyOptionalString,
verifyString,
verifyStringArray,
} from "#src/util/json.js";
import { defaultStringCompare } from "#src/util/string.js";
import { Uint64 } from "#src/util/uint64.js";
import * as vector from "#src/util/vector.js";
import {
decodeZIndexCompressed,
Expand Down Expand Up @@ -215,13 +215,8 @@ function getFragmentCorner(
yBits: number,
zBits: number,
): Uint32Array {
const id = new Uint64();
if (!id.tryParseString(fragmentId, 16)) {
throw new Error(
`Couldn't parse fragmentId ${fragmentId} as hex-encoded Uint64`,
);
}
return decodeZIndexCompressed(id.toBigInt(), xBits, yBits, zBits);
const value = parseUint64(BigInt("0x" + fragmentId));
return decodeZIndexCompressed(value, xBits, yBits, zBits);
}

interface BrainmapsMultiscaleManifestChunk extends MultiscaleManifestChunk {
Expand Down Expand Up @@ -383,9 +378,8 @@ function decodeBatchMeshResponse(
if (index + headerSize > length) {
throw new Error("Invalid batch mesh fragment response.");
}
const objectIdLow = dataView.getUint32(index, /*littleEndian=*/ true);
const objectIdHigh = dataView.getUint32(index + 4, /*littleEndian=*/ true);
const objectIdString = new Uint64(objectIdLow, objectIdHigh).toString();
const objectId = dataView.getBigUint64(index, /*littleEndian=*/ true);
const objectIdString = objectId.toString();
const prefix = objectIdString + "\0";
index += 8;
const fragmentKeyLength = dataView.getUint32(index, /*littleEndian=*/ true);
Expand Down Expand Up @@ -892,11 +886,11 @@ function parseBrainmapsAnnotationId(idPrefix: string, fullId: string) {
return id;
}

function parseObjectLabels(obj: any): Uint64[][] | undefined {
function parseObjectLabels(obj: any): BigUint64Array[] | undefined {
if (obj == null) {
return undefined;
}
return [parseArray(obj, (x) => Uint64.parseString("" + x, 10))];
return [BigUint64Array.from(parseArray(obj, parseUint64))];
}

function parseAnnotation(
Expand Down Expand Up @@ -1064,7 +1058,7 @@ function annotationToBrainmaps(annotation: Annotation): any {
const objectLabels =
annotation.relatedSegments === undefined
? undefined
: annotation.relatedSegments[0].map((x) => x.toString());
: Array.from(annotation.relatedSegments[0], (x) => x.toString());
switch (annotation.type) {
case AnnotationType.LINE: {
const { pointA, pointB } = annotation;
Expand Down
Loading

0 comments on commit ce4d217

Please sign in to comment.