Skip to content

Commit

Permalink
Add SentinelTypeNode (#204)
Browse files Browse the repository at this point in the history
  • Loading branch information
lorisleiva authored Apr 11, 2024
1 parent 484da01 commit 89b6be7
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/thick-deers-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@metaplex-foundation/kinobi": minor
---

Add SentinelTypeNode
12 changes: 8 additions & 4 deletions src/nodes/typeNodes/NestedTypeNode.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { Node, isNode } from '../Node';
import { FixedSizeTypeNode } from './FixedSizeTypeNode';
import { PostOffsetTypeNode } from './PostOffsetTypeNode';
import { PreOffsetTypeNode } from './PreOffsetTypeNode';
import { SizePrefixTypeNode } from './SizePrefixTypeNode';
import type { FixedSizeTypeNode } from './FixedSizeTypeNode';
import type { PostOffsetTypeNode } from './PostOffsetTypeNode';
import type { PreOffsetTypeNode } from './PreOffsetTypeNode';
import type { SentinelTypeNode } from './SentinelTypeNode';
import type { SizePrefixTypeNode } from './SizePrefixTypeNode';
import { TYPE_NODES, TypeNode } from './TypeNode';

export type NestedTypeNode<TType extends TypeNode> =
| TType
| FixedSizeTypeNode<NestedTypeNode<TType>>
| PostOffsetTypeNode<NestedTypeNode<TType>>
| PreOffsetTypeNode<NestedTypeNode<TType>>
| SentinelTypeNode<NestedTypeNode<TType>>
| SizePrefixTypeNode<NestedTypeNode<TType>>;

export function resolveNestedTypeNode<TType extends TypeNode>(
Expand All @@ -19,6 +21,7 @@ export function resolveNestedTypeNode<TType extends TypeNode>(
case 'fixedSizeTypeNode':
case 'postOffsetTypeNode':
case 'preOffsetTypeNode':
case 'sentinelTypeNode':
case 'sizePrefixTypeNode':
return resolveNestedTypeNode<TType>(
typeNode.type as NestedTypeNode<TType>
Expand All @@ -39,6 +42,7 @@ export function transformNestedTypeNode<
case 'fixedSizeTypeNode':
case 'postOffsetTypeNode':
case 'preOffsetTypeNode':
case 'sentinelTypeNode':
case 'sizePrefixTypeNode':
return {
...typeNode,
Expand Down
20 changes: 20 additions & 0 deletions src/nodes/typeNodes/SentinelTypeNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ConstantValueNode } from '../valueNodes';
import { TypeNode } from './TypeNode';

export interface SentinelTypeNode<
TType extends TypeNode = TypeNode,
TSentinel extends ConstantValueNode = ConstantValueNode,
> {
readonly kind: 'sentinelTypeNode';

// Children.
readonly type: TType;
readonly sentinel: TSentinel;
}

export function sentinelTypeNode<
TType extends TypeNode,
TSentinel extends ConstantValueNode,
>(type: TType, sentinel: TSentinel): SentinelTypeNode<TType, TSentinel> {
return { kind: 'sentinelTypeNode', type, sentinel };
}
3 changes: 3 additions & 0 deletions src/nodes/typeNodes/TypeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { OptionTypeNode, optionTypeNodeFromIdl } from './OptionTypeNode';
import { PostOffsetTypeNode } from './PostOffsetTypeNode';
import { PreOffsetTypeNode } from './PreOffsetTypeNode';
import { PublicKeyTypeNode, publicKeyTypeNode } from './PublicKeyTypeNode';
import { SentinelTypeNode } from './SentinelTypeNode';
import { SetTypeNode, setTypeNodeFromIdl } from './SetTypeNode';
import { SizePrefixTypeNode, sizePrefixTypeNode } from './SizePrefixTypeNode';
import { SolAmountTypeNode } from './SolAmountTypeNode';
Expand All @@ -42,6 +43,7 @@ export type StandaloneTypeNode =
| PostOffsetTypeNode
| PreOffsetTypeNode
| PublicKeyTypeNode
| SentinelTypeNode
| SetTypeNode
| SizePrefixTypeNode
| SolAmountTypeNode
Expand All @@ -62,6 +64,7 @@ export const STANDALONE_TYPE_NODE_KINDS = [
'postOffsetTypeNode',
'preOffsetTypeNode',
'publicKeyTypeNode',
'sentinelTypeNode',
'setTypeNode',
'sizePrefixTypeNode',
'solAmountTypeNode',
Expand Down
1 change: 1 addition & 0 deletions src/nodes/typeNodes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export * from './OptionTypeNode';
export * from './PostOffsetTypeNode';
export * from './PreOffsetTypeNode';
export * from './PublicKeyTypeNode';
export * from './SentinelTypeNode';
export * from './SetTypeNode';
export * from './SizePrefixTypeNode';
export * from './SolAmountTypeNode';
Expand Down
13 changes: 13 additions & 0 deletions src/visitors/identityVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
removeNullAndAssertIsNodeFilter,
resolverValueNode,
rootNode,
sentinelTypeNode,
setTypeNode,
setValueNode,
sizePrefixTypeNode,
Expand Down Expand Up @@ -643,6 +644,18 @@ export function identityVisitor<TNodeKind extends NodeKind = NodeKind>(
};
}

if (castedNodeKeys.includes('sentinelTypeNode')) {
visitor.visitSentinelType = function visitSentinelType(node) {
const sentinel = visit(this)(node.sentinel);
if (sentinel === null) return null;
assertIsNode(sentinel, 'constantValueNode');
const type = visit(this)(node.type);
if (type === null) return null;
assertIsNode(type, TYPE_NODES);
return sentinelTypeNode(type, sentinel);
};
}

if (castedNodeKeys.includes('constantDiscriminatorNode')) {
visitor.visitConstantDiscriminator = function visitConstantDiscriminator(
node
Expand Down
9 changes: 9 additions & 0 deletions src/visitors/mergeVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,15 @@ export function mergeVisitor<TReturn, TNodeKind extends NodeKind = NodeKind>(
};
}

if (castedNodeKeys.includes('sentinelTypeNode')) {
visitor.visitSentinelType = function visitSentinelType(node) {
return merge(node, [
...visit(this)(node.sentinel),
...visit(this)(node.type),
]);
};
}

if (castedNodeKeys.includes('constantDiscriminatorNode')) {
visitor.visitConstantDiscriminator = function visitConstantDiscriminator(
node
Expand Down
34 changes: 34 additions & 0 deletions test/visitors/nodes/typeNodes/SentinelTypeNode.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import test from 'ava';
import {
constantValueNodeFromBytes,
sentinelTypeNode,
stringTypeNode,
} from '../../../../src';
import {
deleteNodesVisitorMacro,
getDebugStringVisitorMacro,
identityVisitorMacro,
mergeVisitorMacro,
} from '../_setup';

const node = sentinelTypeNode(
stringTypeNode('utf8'),
constantValueNodeFromBytes('base16', 'ffff')
);

test(mergeVisitorMacro, node, 5);
test(identityVisitorMacro, node);
test(deleteNodesVisitorMacro, node, '[sentinelTypeNode]', null);
test(deleteNodesVisitorMacro, node, '[stringTypeNode]', null);
test(deleteNodesVisitorMacro, node, '[constantValueNode]', null);
test(
getDebugStringVisitorMacro,
node,
`
sentinelTypeNode
| constantValueNode
| | bytesTypeNode
| | bytesValueNode [base16.ffff]
| stringTypeNode [utf8]
`
);

0 comments on commit 89b6be7

Please sign in to comment.