Skip to content

Commit

Permalink
Fix Identity serialization/deserialization
Browse files Browse the repository at this point in the history
After the format of keeping the identity on the server was changed we
have to update how we serialize and deserialize Identity values
  • Loading branch information
drogus committed Oct 12, 2023
1 parent a99c6eb commit 7f86add
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 29 deletions.
47 changes: 26 additions & 21 deletions src/identity.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,57 @@
// Helper function convert from string to Uint8Array
function hexStringToUint8Array(str: string): Uint8Array {
let matches = str.match(/.{1,2}/g) || [];
let data = Uint8Array.from(matches.map((byte: string) => parseInt(byte, 16)));
return data;
}

// Helper function for converting Uint8Array to hex string
function uint8ArrayToHexString(array: Uint8Array): string {
return Array.prototype.map
.call(array, (x) => ("00" + x.toString(16)).slice(-2))
.join("");
}

/**
* A unique public identifier for a client connected to a database.
*/
export class Identity {
private data: Uint8Array;
private data: string;

/**
* Creates a new `Identity`.
*/
constructor(data: Uint8Array) {
this.data = data;
constructor(data: { __identity_bytes: string } | Uint8Array) {
// we get a JSON with __identity_bytes when getting a token with a JSON API
// and an Uint8Array when using BSATN
this.data =
data.constructor === Uint8Array
? uint8ArrayToHexString(data as Uint8Array)
: (data as { __identity_bytes: string }).__identity_bytes;
}

/**
* Compare two identities for equality.
*/
isEqual(other: Identity): boolean {
if (this.data.length !== other.data.length) {
return false;
}
for (let i = 0; i < this.data.length; i++) {
if (this.data[i] !== other.data[i]) {
return false;
}
}
return true;
return this.toHexString() === other.toHexString();
}

/**
* Print the identity as a hexadecimal string.
*/
toHexString(): string {
return Array.prototype.map
.call(this.data, (x) => ("00" + x.toString(16)).slice(-2))
.join("");
return this.data;
}

toUint8Array(): Uint8Array {
return this.data;
return hexStringToUint8Array(this.toHexString());
}

/**
* Parse an Identity from a hexadecimal string.
*/
static fromString(str: string): Identity {
let matches = str.match(/.{1,2}/g) || [];
let data = Uint8Array.from(
matches.map((byte: string) => parseInt(byte, 16))
);
return new Identity(data);
return new Identity({ __identity_bytes: str });
}
}
27 changes: 22 additions & 5 deletions src/serializer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AlgebraicType, BuiltinType } from "./algebraic_type";
import BinaryWriter from "./binary_writer";
import { Identity } from "./identity";

export interface Serializer {
write(type: AlgebraicType, value: any): any;
Expand Down Expand Up @@ -42,10 +43,19 @@ export class JSONSerializer {
case AlgebraicType.Type.ProductType:
let serializedArray: any[] = [];
for (const element of type.product.elements) {
const serialized = this.serializeType(
element.algebraicType,
value[element.name]
);
let serialized: any;
// If the value is an identity we can't use the `[]` operator, so we're
// special casing the identity type. It might be possible to define the
// `__identity_bytes` property on Identity, but I don't have time to check
// at the moment
if (value.constructor === Identity) {
serialized = value.toHexString();
} else {
serialized = this.serializeType(
element.algebraicType,
value[element.name]
);
}
serializedArray.push(serialized);
}
return serializedArray;
Expand Down Expand Up @@ -97,7 +107,14 @@ export class BinarySerializer {
break;
case AlgebraicType.Type.ProductType:
for (const element of type.product.elements) {
this.write(element.algebraicType, value[element.name]);
this.write(
element.algebraicType,
// If the value is an Identity we have to return an Uint8Array instead of trying
// to use the `[]` operator.
value.constructor === Identity
? value.toUint8Array()
: value[element.name]
);
}
break;
case AlgebraicType.Type.SumType:
Expand Down
4 changes: 1 addition & 3 deletions src/spacetimedb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -989,9 +989,7 @@ export class SpacetimeDBClient {

const event = txUpdate["event"] as any;
const functionCall = event["function_call"] as any;
const identity: Identity = Identity.fromString(
event["caller_identity"]
);
const identity: Identity = new Identity(event["caller_identity"]);
const originalReducerName: string = functionCall["reducer"];
const reducerName: string = toPascalCase(originalReducerName);
const args = JSON.parse(functionCall["args"]);
Expand Down

0 comments on commit 7f86add

Please sign in to comment.