Skip to content

Commit 3194644

Browse files
authored
Use type cast on codecs of fixed-size data enums (#733)
1 parent 71caa87 commit 3194644

File tree

11 files changed

+65
-6
lines changed

11 files changed

+65
-6
lines changed

.changeset/true-readers-enter.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@codama/renderers-js': patch
3+
---
4+
5+
Use type cast on generated encoder and decoder functions when dealing with fixed-size data enums. This is because the `getDiscriminatedUnion(Encoder|Decoder)` functions do not propagate the fixed-size information.

packages/renderers-js/public/templates/fragments/typeDecoder.njk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
{{ macros.docblock(docs) }}
44
export function {{ decoderFunction }}(): {{ decoderType }}<{{ strictName }}> {
5-
return {{ manifest.decoder.render }};
5+
return {{ manifest.decoder.render }}{% if useTypeCast %} as {{ decoderType }}<{{ strictName }}>{% endif %};
66
}

packages/renderers-js/public/templates/fragments/typeEncoder.njk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
{{ macros.docblock(docs) }}
44
export function {{ encoderFunction }}(): {{ encoderType }}<{{ looseName }}> {
5-
return {{ manifest.encoder.render }};
5+
return {{ manifest.encoder.render }}{% if useTypeCast %} as {{ encoderType }}<{{ looseName }}>{% endif %};
66
}

packages/renderers-js/src/fragments/accountType.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AccountNode } from '@codama/nodes';
1+
import { AccountNode, resolveNestedTypeNode } from '@codama/nodes';
22
import { getLastNodeFromPath, NodePath } from '@codama/visitors-core';
33

44
import type { GlobalFragmentScope } from '../getRenderMapVisitor';
@@ -24,6 +24,7 @@ export function getAccountTypeFragment(
2424
manifest: typeManifest,
2525
name: accountNode.name,
2626
nameApi,
27+
node: resolveNestedTypeNode(accountNode.data),
2728
size: scope.size,
2829
});
2930
}

packages/renderers-js/src/fragments/instructionData.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { InstructionNode } from '@codama/nodes';
1+
import { InstructionNode, structTypeNodeFromInstructionArgumentNodes } from '@codama/nodes';
22
import { getLastNodeFromPath, NodePath } from '@codama/visitors-core';
33

44
import type { GlobalFragmentScope } from '../getRenderMapVisitor';
@@ -24,6 +24,7 @@ export function getInstructionDataFragment(
2424
manifest: dataArgsManifest,
2525
name: instructionDataName,
2626
nameApi,
27+
node: structTypeNodeFromInstructionArgumentNodes(instructionNode.arguments),
2728
size: scope.size,
2829
});
2930
}

packages/renderers-js/src/fragments/typeCodec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { TypeNode } from '@codama/nodes';
2+
13
import { GlobalFragmentScope } from '../getRenderMapVisitor';
24
import { TypeManifest } from '../TypeManifest';
35
import { Fragment, fragmentFromTemplate, mergeFragments } from './common';
@@ -11,6 +13,7 @@ export function getTypeCodecFragment(
1113
encoderDocs?: string[];
1214
manifest: Pick<TypeManifest, 'decoder' | 'encoder'>;
1315
name: string;
16+
node: TypeNode;
1417
size: number | null;
1518
},
1619
): Fragment {

packages/renderers-js/src/fragments/typeDecoder.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { isDataEnum, isNode, TypeNode } from '@codama/nodes';
2+
13
import type { GlobalFragmentScope } from '../getRenderMapVisitor';
24
import { TypeManifest } from '../TypeManifest';
35
import { Fragment, fragmentFromTemplate } from './common';
@@ -7,18 +9,22 @@ export function getTypeDecoderFragment(
79
docs?: string[];
810
manifest: Pick<TypeManifest, 'decoder'>;
911
name: string;
12+
node: TypeNode;
1013
size: number | null;
1114
},
1215
): Fragment {
13-
const { name, manifest, nameApi, docs = [] } = scope;
16+
const { name, node, manifest, nameApi, docs = [] } = scope;
1417
const decoderType = typeof scope.size === 'number' ? 'FixedSizeDecoder' : 'Decoder';
18+
const useTypeCast = isNode(node, 'enumTypeNode') && isDataEnum(node) && typeof scope.size === 'number';
19+
1520
return fragmentFromTemplate('typeDecoder.njk', {
1621
decoderFunction: nameApi.decoderFunction(name),
1722
decoderType,
1823
docs,
1924
looseName: nameApi.dataArgsType(name),
2025
manifest,
2126
strictName: nameApi.dataType(name),
27+
useTypeCast,
2228
})
2329
.mergeImportsWith(manifest.decoder)
2430
.addImports('solanaCodecsCore', `type ${decoderType}`);

packages/renderers-js/src/fragments/typeEncoder.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { isDataEnum, isNode, TypeNode } from '@codama/nodes';
2+
13
import type { GlobalFragmentScope } from '../getRenderMapVisitor';
24
import { TypeManifest } from '../TypeManifest';
35
import { Fragment, fragmentFromTemplate } from './common';
@@ -7,18 +9,22 @@ export function getTypeEncoderFragment(
79
docs?: string[];
810
manifest: Pick<TypeManifest, 'encoder'>;
911
name: string;
12+
node: TypeNode;
1013
size: number | null;
1114
},
1215
): Fragment {
13-
const { name, manifest, nameApi, docs = [] } = scope;
16+
const { name, node, manifest, nameApi, docs = [] } = scope;
1417
const encoderType = typeof scope.size === 'number' ? 'FixedSizeEncoder' : 'Encoder';
18+
const useTypeCast = isNode(node, 'enumTypeNode') && isDataEnum(node) && typeof scope.size === 'number';
19+
1520
return fragmentFromTemplate('typeEncoder.njk', {
1621
docs,
1722
encoderFunction: nameApi.encoderFunction(name),
1823
encoderType,
1924
looseName: nameApi.dataArgsType(name),
2025
manifest,
2126
strictName: nameApi.dataType(name),
27+
useTypeCast,
2228
})
2329
.mergeImportsWith(manifest.encoder)
2430
.addImports('solanaCodecsCore', `type ${encoderType}`);

packages/renderers-js/src/fragments/typeWithCodec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { TypeNode } from '@codama/nodes';
2+
13
import type { GlobalFragmentScope } from '../getRenderMapVisitor';
24
import { TypeManifest } from '../TypeManifest';
35
import { Fragment, mergeFragments } from './common';
@@ -11,6 +13,7 @@ export function getTypeWithCodecFragment(
1113
encoderDocs?: string[];
1214
manifest: TypeManifest;
1315
name: string;
16+
node: TypeNode;
1417
size: number | null;
1518
typeDocs?: string[];
1619
},

packages/renderers-js/src/getRenderMapVisitor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) {
194194
encoderDocs: [],
195195
manifest: visit(node, typeManifestVisitor),
196196
name: node.name,
197+
node: node.type,
197198
size: visit(node, byteSizeVisitor),
198199
typeDocs: node.docs,
199200
typeNode: node.type,

0 commit comments

Comments
 (0)