Skip to content

Commit bc43362

Browse files
Fixes #3299 (#3330)
# Description of Changes Two variants were missing from `intoMapKey`, causing the infinite loop reported in #3299 # API and ABI breaking changes No breaking changes # Expected complexity level and risk 1 # Testing - [x] I added a regression test for this case
1 parent 7002768 commit bc43362

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

crates/bindings-typescript/src/lib/algebraic_type.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,10 @@ export const AlgebraicType: {
250250
case 'U256':
251251
case 'I8':
252252
case 'I16':
253+
case 'I32':
253254
case 'I64':
254255
case 'I128':
256+
case 'I256':
255257
case 'F32':
256258
case 'F64':
257259
case 'String':
@@ -260,8 +262,9 @@ export const AlgebraicType: {
260262
case 'Product':
261263
return ProductType.intoMapKey(ty.value, value);
262264
default: {
265+
// The fallback is to serialize and base64 encode the bytes.
263266
const writer = new BinaryWriter(10);
264-
this.serialize(writer, value);
267+
AlgebraicType.serializeValue(writer, ty, value);
265268
return writer.toBase64();
266269
}
267270
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { describe, expect, test } from 'vitest';
2+
import { AlgebraicType } from '../src/index';
3+
4+
describe('AlgebraicType', () => {
5+
test('intoMapKey handles all primitive types', () => {
6+
const primitiveTypes: Array<[any['tag'], any]> = [
7+
['Bool', true],
8+
['I8', -8],
9+
['U8', 8],
10+
['I16', -16],
11+
['U16', 16],
12+
['I32', -32],
13+
['U32', 32],
14+
['I64', -64n],
15+
['U64', 64n],
16+
['I128', -128n],
17+
['U128', 128n],
18+
['I256', -256n],
19+
['U256', 256n],
20+
['F32', 32.32],
21+
['F64', 64.64],
22+
['String', 'hello'],
23+
];
24+
25+
for (const [tag, value] of primitiveTypes) {
26+
const algebraicType = { tag, value: undefined };
27+
const mapKey = AlgebraicType.intoMapKey(algebraicType, value);
28+
expect(mapKey).toBe(value);
29+
}
30+
});
31+
32+
test('intoMapKey handles complex types', () => {
33+
const productType = AlgebraicType.Product({
34+
elements: [{ name: 'a', algebraicType: AlgebraicType.I32 }],
35+
});
36+
const productValue = { a: 42 };
37+
38+
const mapKey = AlgebraicType.intoMapKey(productType, productValue);
39+
// Fallback for complex types is base64 encoding of serialized value
40+
expect(typeof mapKey).toBe('string');
41+
// 42 as i32 little-endian is 2A000000, which is KgAAAA== in base64
42+
expect(mapKey).toBe('KgAAAA==');
43+
});
44+
45+
test('intoMapKey fallback serializes array types', () => {
46+
const arrayType = AlgebraicType.Array(AlgebraicType.U16);
47+
const arrayValue = [1, 2, 3];
48+
49+
const mapKey = AlgebraicType.intoMapKey(arrayType, arrayValue);
50+
expect(typeof mapKey).toBe('string');
51+
// Serialized as: [len (u32), val1 (u16), val2 (u16), val3 (u16)]
52+
expect(mapKey).toBe('AwAAAAEAAgADAA==');
53+
});
54+
});

0 commit comments

Comments
 (0)