Skip to content

Commit 3cc5081

Browse files
fix: parse float32 in cddl2ts
1 parent e5cc9d0 commit 3cc5081

2 files changed

Lines changed: 95 additions & 14 deletions

File tree

packages/cddl2ts/src/index.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,35 @@ const b = types.builders
2727
const NATIVE_TYPES: Record<string, any> = {
2828
any: b.tsAnyKeyword(),
2929
number: b.tsNumberKeyword(),
30+
integer: b.tsNumberKeyword(),
3031
int: b.tsNumberKeyword(),
31-
float: b.tsNumberKeyword(),
3232
uint: b.tsNumberKeyword(),
33+
nint: b.tsNumberKeyword(),
34+
unsigned: b.tsNumberKeyword(),
35+
float: b.tsNumberKeyword(),
36+
float16: b.tsNumberKeyword(),
37+
float32: b.tsNumberKeyword(),
38+
float64: b.tsNumberKeyword(),
39+
'float16-32': b.tsNumberKeyword(),
40+
'float32-64': b.tsNumberKeyword(),
3341
bool: b.tsBooleanKeyword(),
42+
false: b.tsBooleanKeyword(),
43+
true: b.tsBooleanKeyword(),
44+
bstr: b.tsTypeReference(b.identifier('Uint8Array')),
45+
bytes: b.tsTypeReference(b.identifier('Uint8Array')),
3446
str: b.tsStringKeyword(),
3547
text: b.tsStringKeyword(),
3648
tstr: b.tsStringKeyword(),
3749
range: b.tsNumberKeyword(),
50+
undefined: b.tsUndefinedKeyword(),
3851
nil: b.tsNullKeyword(),
3952
null: b.tsNullKeyword()
4053
}
54+
const RECORD_KEY_TYPES = new Set([
55+
'int', 'uint', 'nint', 'integer', 'unsigned', 'number',
56+
'float', 'float16', 'float32', 'float64', 'float16-32', 'float32-64',
57+
'str', 'text', 'tstr'
58+
])
4159
type ObjectEntry = types.namedTypes.TSCallSignatureDeclaration | types.namedTypes.TSConstructSignatureDeclaration | types.namedTypes.TSIndexSignature | types.namedTypes.TSMethodSignature | types.namedTypes.TSPropertySignature
4260
type ObjectBody = ObjectEntry[]
4361
type TSTypeKind = types.namedTypes.TSAsExpression['typeAnnotation']
@@ -195,7 +213,7 @@ function parseAssignment (assignment: Assignment) {
195213
if (props.length === 1) {
196214
const prop = props[0]
197215
const propType = Array.isArray(prop.Type) ? prop.Type : [prop.Type]
198-
if (propType.length === 1 && Object.keys(NATIVE_TYPES).includes(prop.Name)) {
216+
if (propType.length === 1 && RECORD_KEY_TYPES.has(prop.Name)) {
199217
const value = parseUnionType(assignment)
200218
const expr = b.tsTypeAliasDeclaration(id, value)
201219
expr.comments = assignment.Comments.map((c) => b.commentLine(` ${c.Content}`, true))
@@ -578,7 +596,7 @@ function parseUnionType (t: PropertyType | Assignment): TSTypeKind {
578596
/**
579597
* {*text => text} which will be transformed to `Record<string, string>`
580598
*/
581-
if (prop.length === 1 && Object.keys(NATIVE_TYPES).includes((prop[0] as Property).Name)) {
599+
if (prop.length === 1 && RECORD_KEY_TYPES.has((prop[0] as Property).Name)) {
582600
return b.tsTypeReference(
583601
b.identifier('Record'),
584602
b.tsTypeParameterInstantiation([
Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,84 @@
11
import { describe, it, expect } from 'vitest'
22
import { transform } from '../src/index.js'
3-
import type { Variable } from 'cddl'
3+
import type { Group, Property, Variable } from 'cddl'
4+
5+
function variable(name: string, propertyType: Variable['PropertyType']): Variable {
6+
return {
7+
Type: 'variable',
8+
Name: name,
9+
PropertyType: propertyType,
10+
Comments: [],
11+
IsChoiceAddition: false
12+
}
13+
}
14+
15+
function property(name: string, type: Property['Type']): Property {
16+
return {
17+
HasCut: false,
18+
Occurrence: { n: 1, m: 1 },
19+
Name: name,
20+
Type: type,
21+
Comments: []
22+
}
23+
}
24+
25+
function group(name: string, properties: Group['Properties']): Group {
26+
return {
27+
Type: 'group',
28+
Name: name,
29+
IsChoiceAddition: false,
30+
Properties: properties,
31+
Comments: []
32+
}
33+
}
434

535
describe('literal transformation direct', () => {
636
it('should transform bigint literals correctly', () => {
7-
const assignment: Variable = {
8-
Type: 'variable',
9-
Name: 'MyBigInt',
10-
PropertyType: {
11-
Type: 'literal',
12-
Value: 9007199254740995n
13-
} as any,
14-
Comments: [],
15-
IsChoiceAddition: false
16-
}
37+
const assignment = variable('MyBigInt', {
38+
Type: 'literal',
39+
Value: 9007199254740995n
40+
} as any)
1741

1842
const output = transform([assignment])
1943
expect(output).toContain('export type MyBigInt = 9007199254740995n;')
2044
})
45+
46+
it('should transform float32 aliases correctly', () => {
47+
const assignment = variable('score', 'float32')
48+
49+
const output = transform([assignment])
50+
expect(output).toContain('export type Score = number;')
51+
})
52+
53+
it.each([
54+
['integer-value', 'integer', 'number'],
55+
['negative-value', 'nint', 'number'],
56+
['unsigned-value', 'unsigned', 'number'],
57+
['half-float', 'float16', 'number'],
58+
['double-float', 'float64', 'number'],
59+
['float-window', 'float16-32', 'number'],
60+
['float-range', 'float32-64', 'number'],
61+
['binary-payload', 'bytes', 'Uint8Array'],
62+
['binary-blob', 'bstr', 'Uint8Array'],
63+
['missing-value', 'undefined', 'undefined']
64+
] as const)('should map %s (%s) to %s', (name, propertyType, expectedType) => {
65+
const output = transform([variable(name, propertyType)])
66+
expect(output).toContain(`export type ${name.split('-').map((part) => `${part[0]!.toUpperCase()}${part.slice(1)}`).join('')} = ${expectedType};`)
67+
})
68+
69+
it('should keep bytes fields as object properties instead of record aliases', () => {
70+
const output = transform([
71+
group('network-get-data-result', [
72+
property('bytes', {
73+
Type: 'group',
74+
Value: 'network.BytesValue',
75+
Unwrapped: false
76+
} as any)
77+
])
78+
])
79+
80+
expect(output).toContain('export interface NetworkGetDataResult {')
81+
expect(output).toContain('bytes: NetworkBytesValue;')
82+
expect(output).not.toContain('export type NetworkGetDataResult = Record')
83+
})
2184
})

0 commit comments

Comments
 (0)