@hla4ts/hla-api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,449 @@
1
+ /**
2
+ * Type Converters
3
+ *
4
+ * This module provides conversion functions between protobuf types and
5
+ * the TypeScript HLA API types.
6
+ */
7
+
8
+ import type {
9
+ AttributeHandleSet as ProtoAttributeHandleSet,
10
+ AttributeHandleValueMap as ProtoAttributeHandleValueMap,
11
+ ParameterHandleValueMap as ProtoParameterHandleValueMap,
12
+ FederateHandleSet as ProtoFederateHandleSet,
13
+ FederationExecutionInformationSet as ProtoFederationExecutionInformationSet,
14
+ FederationExecutionMemberInformationSet as ProtoFederationExecutionMemberInformationSet,
15
+ FederateHandleSaveStatusPairArray as ProtoFederateHandleSaveStatusPairArray,
16
+ FederateRestoreStatusArray as ProtoFederateRestoreStatusArray,
17
+ ConveyedRegionSet as ProtoConveyedRegionSet,
18
+ JoinResult as ProtoJoinResult,
19
+ TimeQueryReturn as ProtoTimeQueryReturn,
20
+ MessageRetractionReturn as ProtoMessageRetractionReturn,
21
+ FomModule as ProtoFomModule,
22
+ FomModuleSet as ProtoFomModuleSet,
23
+ RtiConfiguration as ProtoRtiConfiguration,
24
+ ConfigurationResult as ProtoConfigurationResult,
25
+ Credentials as ProtoCredentials,
26
+ ObjectClassHandle as ProtoObjectClassHandle,
27
+ AttributeHandle as ProtoAttributeHandle,
28
+ InteractionClassHandle as ProtoInteractionClassHandle,
29
+ ParameterHandle as ProtoParameterHandle,
30
+ ObjectInstanceHandle as ProtoObjectInstanceHandle,
31
+ FederateHandle as ProtoFederateHandle,
32
+ TransportationTypeHandle as ProtoTransportationTypeHandle,
33
+ LogicalTime as ProtoLogicalTime,
34
+ LogicalTimeInterval as ProtoLogicalTimeInterval,
35
+ MessageRetractionHandle as ProtoMessageRetractionHandle,
36
+ } from "@hla4ts/proto";
37
+
38
+ import type {
39
+ AttributeHandleSet,
40
+ AttributeHandleValueMap,
41
+ ParameterHandleValueMap,
42
+ FederationExecutionInformationSet,
43
+ FederationExecutionMemberInformationSet,
44
+ FederateHandleSaveStatusPairArray,
45
+ FederateRestoreStatusArray,
46
+ ConveyedRegionSet,
47
+ JoinResult,
48
+ TimeQueryReturn,
49
+ MessageRetractionReturn,
50
+ FomModule,
51
+ FomModuleSet,
52
+ RtiConfiguration,
53
+ ConfigurationResult,
54
+ Credentials,
55
+ ObjectClassHandle,
56
+ AttributeHandle,
57
+ InteractionClassHandle,
58
+ ParameterHandle,
59
+ ObjectInstanceHandle,
60
+ FederateHandle,
61
+ TransportationTypeHandle,
62
+ LogicalTime,
63
+ LogicalTimeInterval,
64
+ MessageRetractionHandle,
65
+ FederateHandleSet,
66
+ } from "./types.ts";
67
+
68
+ import {
69
+ SaveStatus,
70
+ RestoreStatus,
71
+ SynchronizationPointFailureReason,
72
+ SaveFailureReason,
73
+ RestoreFailureReason,
74
+ OrderType,
75
+ } from "@hla4ts/proto";
76
+
77
+ // =============================================================================
78
+ // Handle Conversions (Proto -> TS)
79
+ // =============================================================================
80
+
81
+ /**
82
+ * Convert a protobuf handle to TypeScript (essentially a passthrough since both are Uint8Array-like).
83
+ */
84
+ function convertHandle(protoHandle: { data: Uint8Array } | undefined): Uint8Array {
85
+ return protoHandle?.data ?? new Uint8Array(0);
86
+ }
87
+
88
+ export function convertObjectClassHandle(handle: ProtoObjectClassHandle | undefined): ObjectClassHandle {
89
+ return convertHandle(handle);
90
+ }
91
+
92
+ export function convertAttributeHandle(handle: ProtoAttributeHandle | undefined): AttributeHandle {
93
+ return convertHandle(handle);
94
+ }
95
+
96
+ export function convertInteractionClassHandle(handle: ProtoInteractionClassHandle | undefined): InteractionClassHandle {
97
+ return convertHandle(handle);
98
+ }
99
+
100
+ export function convertParameterHandle(handle: ProtoParameterHandle | undefined): ParameterHandle {
101
+ return convertHandle(handle);
102
+ }
103
+
104
+ export function convertObjectInstanceHandle(handle: ProtoObjectInstanceHandle | undefined): ObjectInstanceHandle {
105
+ return convertHandle(handle);
106
+ }
107
+
108
+ export function convertFederateHandle(handle: ProtoFederateHandle | undefined): FederateHandle {
109
+ return convertHandle(handle);
110
+ }
111
+
112
+ export function convertTransportationTypeHandle(handle: ProtoTransportationTypeHandle | undefined): TransportationTypeHandle {
113
+ return convertHandle(handle);
114
+ }
115
+
116
+ export function convertLogicalTime(time: ProtoLogicalTime | undefined): LogicalTime {
117
+ return convertHandle(time);
118
+ }
119
+
120
+ export function convertLogicalTimeInterval(interval: ProtoLogicalTimeInterval | undefined): LogicalTimeInterval {
121
+ return convertHandle(interval);
122
+ }
123
+
124
+ export function convertMessageRetractionHandle(handle: ProtoMessageRetractionHandle | undefined): MessageRetractionHandle {
125
+ return convertHandle(handle);
126
+ }
127
+
128
+ // =============================================================================
129
+ // Handle Set Conversions (Proto -> TS)
130
+ // =============================================================================
131
+
132
+ export function convertAttributeHandleSet(protoSet: ProtoAttributeHandleSet | undefined): AttributeHandleSet {
133
+ if (!protoSet?.attributeHandle) return [];
134
+ return protoSet.attributeHandle.map(h => convertHandle(h));
135
+ }
136
+
137
+ export function convertFederateHandleSet(protoSet: ProtoFederateHandleSet | undefined): FederateHandleSet {
138
+ if (!protoSet?.federateHandle) return [];
139
+ return protoSet.federateHandle.map(h => convertHandle(h));
140
+ }
141
+
142
+ // =============================================================================
143
+ // Handle-Value Map Conversions (Proto -> TS)
144
+ // =============================================================================
145
+
146
+ export function convertAttributeHandleValueMap(
147
+ protoMap: ProtoAttributeHandleValueMap | undefined
148
+ ): AttributeHandleValueMap {
149
+ if (!protoMap?.attributeHandleValue) return [];
150
+ return protoMap.attributeHandleValue.map(entry => ({
151
+ attributeHandle: convertHandle(entry.attributeHandle),
152
+ value: entry.value ?? new Uint8Array(0),
153
+ }));
154
+ }
155
+
156
+ export function convertParameterHandleValueMap(
157
+ protoMap: ProtoParameterHandleValueMap | undefined
158
+ ): ParameterHandleValueMap {
159
+ if (!protoMap?.parameterHandleValue) return [];
160
+ return protoMap.parameterHandleValue.map(entry => ({
161
+ parameterHandle: convertHandle(entry.parameterHandle),
162
+ value: entry.value ?? new Uint8Array(0),
163
+ }));
164
+ }
165
+
166
+ // =============================================================================
167
+ // Federation Information Conversions (Proto -> TS)
168
+ // =============================================================================
169
+
170
+ export function convertFederationExecutionInformationSet(
171
+ protoSet: ProtoFederationExecutionInformationSet | undefined
172
+ ): FederationExecutionInformationSet {
173
+ if (!protoSet?.federationExecutionInformation) return [];
174
+ return protoSet.federationExecutionInformation.map(info => ({
175
+ federationName: info.federationExecutionName ?? "",
176
+ logicalTimeImplementationName: info.logicalTimeImplementationName ?? "",
177
+ }));
178
+ }
179
+
180
+ export function convertFederationExecutionMemberInformationSet(
181
+ protoSet: ProtoFederationExecutionMemberInformationSet | undefined
182
+ ): FederationExecutionMemberInformationSet {
183
+ if (!protoSet?.federationExecutionMemberInformation) return [];
184
+ return protoSet.federationExecutionMemberInformation.map(info => ({
185
+ federateName: info.federateName ?? "",
186
+ federateType: info.federateType ?? "",
187
+ }));
188
+ }
189
+
190
+ // =============================================================================
191
+ // Save/Restore Conversions (Proto -> TS)
192
+ // =============================================================================
193
+
194
+ export function convertFederateHandleSaveStatusPairArray(
195
+ protoArray: ProtoFederateHandleSaveStatusPairArray | undefined
196
+ ): FederateHandleSaveStatusPairArray {
197
+ if (!protoArray?.federateHandleSaveStatusPair) return [];
198
+ return protoArray.federateHandleSaveStatusPair.map(pair => ({
199
+ federateHandle: convertHandle(pair.federateHandle),
200
+ saveStatus: pair.saveStatus ?? SaveStatus.NO_SAVE_IN_PROGRESS,
201
+ }));
202
+ }
203
+
204
+ export function convertFederateRestoreStatusArray(
205
+ protoArray: ProtoFederateRestoreStatusArray | undefined
206
+ ): FederateRestoreStatusArray {
207
+ if (!protoArray?.federateRestoreStatus) return [];
208
+ return protoArray.federateRestoreStatus.map(status => ({
209
+ preHandle: convertHandle(status.preRestoreHandle),
210
+ postHandle: convertHandle(status.postRestoreHandle),
211
+ status: status.restoreStatus ?? RestoreStatus.NO_RESTORE_IN_PROGRESS,
212
+ }));
213
+ }
214
+
215
+ // =============================================================================
216
+ // DDM Conversions (Proto -> TS)
217
+ // =============================================================================
218
+
219
+ export function convertConveyedRegionSet(
220
+ protoSet: ProtoConveyedRegionSet | undefined
221
+ ): ConveyedRegionSet | undefined {
222
+ if (!protoSet?.conveyedRegions) return undefined;
223
+ return protoSet.conveyedRegions.map((region: { dimensionAndRange?: Array<{ dimensionHandle?: { data: Uint8Array }; range?: { lower?: bigint; upper?: bigint } }> }) => {
224
+ if (!region.dimensionAndRange) return [];
225
+ return region.dimensionAndRange.map((dar: { dimensionHandle?: { data: Uint8Array }; range?: { lower?: bigint; upper?: bigint } }) => ({
226
+ dimensionHandle: convertHandle(dar.dimensionHandle),
227
+ range: {
228
+ lower: dar.range?.lower ?? 0n,
229
+ upper: dar.range?.upper ?? 0n,
230
+ },
231
+ }));
232
+ });
233
+ }
234
+
235
+ // =============================================================================
236
+ // Result Conversions (Proto -> TS)
237
+ // =============================================================================
238
+
239
+ export function convertJoinResult(protoResult: ProtoJoinResult | undefined): JoinResult {
240
+ return {
241
+ federateHandle: convertHandle(protoResult?.federateHandle),
242
+ logicalTimeImplementationName: protoResult?.logicalTimeImplementationName ?? "",
243
+ };
244
+ }
245
+
246
+ export function convertTimeQueryReturn(protoReturn: ProtoTimeQueryReturn | undefined): TimeQueryReturn {
247
+ return {
248
+ logicalTimeIsValid: protoReturn?.logicalTimeIsValid ?? false,
249
+ logicalTime: protoReturn?.logicalTime ? convertLogicalTime(protoReturn.logicalTime) : undefined,
250
+ };
251
+ }
252
+
253
+ export function convertMessageRetractionReturn(
254
+ protoReturn: ProtoMessageRetractionReturn | undefined
255
+ ): MessageRetractionReturn {
256
+ return {
257
+ retractionHandleIsValid: protoReturn?.retractionHandleIsValid ?? false,
258
+ retractionHandle: protoReturn?.messageRetractionHandle
259
+ ? convertMessageRetractionHandle(protoReturn.messageRetractionHandle)
260
+ : undefined,
261
+ };
262
+ }
263
+
264
+ // =============================================================================
265
+ // Configuration Conversions (Proto -> TS)
266
+ // =============================================================================
267
+
268
+ export function convertConfigurationResult(
269
+ protoResult: ProtoConfigurationResult | undefined
270
+ ): ConfigurationResult {
271
+ return {
272
+ configurationUsed: protoResult?.configurationUsed ?? false,
273
+ // Note: Proto ConfigurationResult has different structure than our simplified type
274
+ message: protoResult?.message,
275
+ };
276
+ }
277
+
278
+ export function convertRtiConfiguration(
279
+ protoConfig: ProtoRtiConfiguration | undefined
280
+ ): RtiConfiguration {
281
+ return {
282
+ configurationName: protoConfig?.configurationName,
283
+ rtiAddress: protoConfig?.rtiAddress,
284
+ additionalSettings: protoConfig?.additionalSettings,
285
+ };
286
+ }
287
+
288
+ // =============================================================================
289
+ // Enum Conversions (Proto -> TS)
290
+ // =============================================================================
291
+
292
+ export function convertSynchronizationPointFailureReason(
293
+ reason: SynchronizationPointFailureReason
294
+ ): SynchronizationPointFailureReason {
295
+ return reason; // Same enum type
296
+ }
297
+
298
+ export function convertSaveFailureReason(reason: SaveFailureReason): SaveFailureReason {
299
+ return reason;
300
+ }
301
+
302
+ export function convertRestoreFailureReason(reason: RestoreFailureReason): RestoreFailureReason {
303
+ return reason;
304
+ }
305
+
306
+ export function convertOrderType(orderType: OrderType): OrderType {
307
+ return orderType;
308
+ }
309
+
310
+ // =============================================================================
311
+ // Handle Conversions (TS -> Proto)
312
+ // =============================================================================
313
+
314
+ function createProtoHandle(data: Uint8Array): { data: Uint8Array } {
315
+ return { data };
316
+ }
317
+
318
+ export function toProtoObjectClassHandle(handle: ObjectClassHandle): ProtoObjectClassHandle {
319
+ return createProtoHandle(handle);
320
+ }
321
+
322
+ export function toProtoAttributeHandle(handle: AttributeHandle): ProtoAttributeHandle {
323
+ return createProtoHandle(handle);
324
+ }
325
+
326
+ export function toProtoInteractionClassHandle(handle: InteractionClassHandle): ProtoInteractionClassHandle {
327
+ return createProtoHandle(handle);
328
+ }
329
+
330
+ export function toProtoParameterHandle(handle: ParameterHandle): ProtoParameterHandle {
331
+ return createProtoHandle(handle);
332
+ }
333
+
334
+ export function toProtoObjectInstanceHandle(handle: ObjectInstanceHandle): ProtoObjectInstanceHandle {
335
+ return createProtoHandle(handle);
336
+ }
337
+
338
+ export function toProtoFederateHandle(handle: FederateHandle): ProtoFederateHandle {
339
+ return createProtoHandle(handle);
340
+ }
341
+
342
+ export function toProtoTransportationTypeHandle(handle: TransportationTypeHandle): ProtoTransportationTypeHandle {
343
+ return createProtoHandle(handle);
344
+ }
345
+
346
+ export function toProtoLogicalTime(time: LogicalTime): ProtoLogicalTime {
347
+ return createProtoHandle(time);
348
+ }
349
+
350
+ export function toProtoLogicalTimeInterval(interval: LogicalTimeInterval): ProtoLogicalTimeInterval {
351
+ return createProtoHandle(interval);
352
+ }
353
+
354
+ export function toProtoMessageRetractionHandle(handle: MessageRetractionHandle): ProtoMessageRetractionHandle {
355
+ return createProtoHandle(handle);
356
+ }
357
+
358
+ // =============================================================================
359
+ // Handle Set Conversions (TS -> Proto)
360
+ // =============================================================================
361
+
362
+ export function toProtoAttributeHandleSet(handles: AttributeHandleSet): ProtoAttributeHandleSet {
363
+ return {
364
+ attributeHandle: handles.map(h => createProtoHandle(h)),
365
+ };
366
+ }
367
+
368
+ export function toProtoFederateHandleSet(handles: FederateHandleSet): ProtoFederateHandleSet {
369
+ return {
370
+ federateHandle: handles.map(h => createProtoHandle(h)),
371
+ };
372
+ }
373
+
374
+ // =============================================================================
375
+ // Handle-Value Map Conversions (TS -> Proto)
376
+ // =============================================================================
377
+
378
+ export function toProtoAttributeHandleValueMap(
379
+ map: AttributeHandleValueMap
380
+ ): ProtoAttributeHandleValueMap {
381
+ return {
382
+ attributeHandleValue: map.map(entry => ({
383
+ attributeHandle: createProtoHandle(entry.attributeHandle),
384
+ value: entry.value,
385
+ })),
386
+ };
387
+ }
388
+
389
+ export function toProtoParameterHandleValueMap(
390
+ map: ParameterHandleValueMap
391
+ ): ProtoParameterHandleValueMap {
392
+ return {
393
+ parameterHandleValue: map.map(entry => ({
394
+ parameterHandle: createProtoHandle(entry.parameterHandle),
395
+ value: entry.value,
396
+ })),
397
+ };
398
+ }
399
+
400
+ // =============================================================================
401
+ // FOM Module Conversions (TS -> Proto)
402
+ // =============================================================================
403
+
404
+ export function toProtoFomModule(module: FomModule): ProtoFomModule {
405
+ switch (module.type) {
406
+ case "inline":
407
+ // Convert inline XML string to UTF-8 bytes and use file format
408
+ const encoder = new TextEncoder();
409
+ const content = encoder.encode(module.content);
410
+ return {
411
+ compressedModule: undefined,
412
+ url: undefined,
413
+ file: { name: "fom.xml", content },
414
+ };
415
+ case "file":
416
+ return {
417
+ compressedModule: undefined,
418
+ url: undefined,
419
+ file: { name: module.name, content: module.content },
420
+ };
421
+ case "url":
422
+ return { compressedModule: undefined, url: module.url, file: undefined };
423
+ }
424
+ }
425
+
426
+ export function toProtoFomModuleSet(modules: FomModuleSet): ProtoFomModuleSet {
427
+ return {
428
+ fomModule: modules.map(toProtoFomModule),
429
+ };
430
+ }
431
+
432
+ // =============================================================================
433
+ // Configuration Conversions (TS -> Proto)
434
+ // =============================================================================
435
+
436
+ export function toProtoRtiConfiguration(config: RtiConfiguration): ProtoRtiConfiguration {
437
+ return {
438
+ configurationName: config.configurationName ?? "",
439
+ rtiAddress: config.rtiAddress ?? "",
440
+ additionalSettings: config.additionalSettings ?? "",
441
+ };
442
+ }
443
+
444
+ export function toProtoCredentials(credentials: Credentials): ProtoCredentials {
445
+ return {
446
+ type: credentials.type,
447
+ data: credentials.data,
448
+ };
449
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * HLA Encoding Helpers
3
+ *
4
+ * IEEE 1516.2 encodings for HLAinteger64Time and HLAinteger64Interval.
5
+ * These are 8-byte, big-endian, two's-complement integers.
6
+ */
7
+
8
+ const INTEGER_64_SIZE = 8;
9
+
10
+ function assertLength(data: Uint8Array, expected: number, label: string): void {
11
+ if (data.length !== expected) {
12
+ throw new Error(`${label}: expected ${expected} bytes, got ${data.length}`);
13
+ }
14
+ }
15
+
16
+ /**
17
+ * Encode a BigInt as HLAinteger64Time (IEEE 1516.2).
18
+ */
19
+ export function encodeHLAinteger64Time(value: bigint): Uint8Array {
20
+ const buffer = new Uint8Array(INTEGER_64_SIZE);
21
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
22
+ view.setBigInt64(0, value, false);
23
+ return buffer;
24
+ }
25
+
26
+ /**
27
+ * Decode an HLAinteger64Time (IEEE 1516.2) into a BigInt.
28
+ */
29
+ export function decodeHLAinteger64Time(data: Uint8Array): bigint {
30
+ assertLength(data, INTEGER_64_SIZE, "HLAinteger64Time");
31
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
32
+ return view.getBigInt64(0, false);
33
+ }
34
+
35
+ /**
36
+ * Encode a BigInt as HLAinteger64Interval (IEEE 1516.2).
37
+ */
38
+ export function encodeHLAinteger64Interval(value: bigint): Uint8Array {
39
+ const buffer = new Uint8Array(INTEGER_64_SIZE);
40
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
41
+ view.setBigInt64(0, value, false);
42
+ return buffer;
43
+ }
44
+
45
+ /**
46
+ * Decode an HLAinteger64Interval (IEEE 1516.2) into a BigInt.
47
+ */
48
+ export function decodeHLAinteger64Interval(data: Uint8Array): bigint {
49
+ assertLength(data, INTEGER_64_SIZE, "HLAinteger64Interval");
50
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
51
+ return view.getBigInt64(0, false);
52
+ }