@aircast-4g/mavlink 1.1.6 → 1.1.8

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.
@@ -8,6 +8,34 @@ function isTestTypes(msg) {
8
8
 
9
9
  // Auto-generated decoder and parser for test dialect
10
10
  // Generated from MAVLink XML definitions
11
+ // Embedded MAVLink CRC implementation
12
+ const CRC_EXTRA = {
13
+ 17000: 0
14
+ };
15
+ class MAVLinkCRC {
16
+ static calculate(data, crcExtra) {
17
+ let crc = 0xffff;
18
+ // Process all message bytes using MCRF4XX algorithm
19
+ for (let i = 0; i < data.length; i++) {
20
+ let tmp = data[i] ^ (crc & 0xff);
21
+ tmp = (tmp ^ (tmp << 4)) & 0xff;
22
+ crc = ((crc >> 8) ^ (tmp << 8) ^ (tmp << 3) ^ (tmp >> 4)) & 0xffff;
23
+ }
24
+ // Add CRC_EXTRA byte using the same algorithm
25
+ let tmp = crcExtra ^ (crc & 0xff);
26
+ tmp = (tmp ^ (tmp << 4)) & 0xff;
27
+ crc = ((crc >> 8) ^ (tmp << 8) ^ (tmp << 3) ^ (tmp >> 4)) & 0xffff;
28
+ return crc;
29
+ }
30
+ static validate(data, messageId, receivedChecksum) {
31
+ const crcExtra = CRC_EXTRA[messageId];
32
+ if (crcExtra === undefined) {
33
+ return false;
34
+ }
35
+ const calculatedChecksum = this.calculate(data, crcExtra);
36
+ return calculatedChecksum === receivedChecksum;
37
+ }
38
+ }
11
39
  // Base dialect parser class
12
40
  class DialectParser {
13
41
  constructor(dialectName) {
@@ -95,9 +123,11 @@ class DialectParser {
95
123
  frameOffset += 13;
96
124
  }
97
125
  }
98
- frame.crc_ok = true; // Simplified - not doing CRC validation
126
+ // Validate CRC using proper MAVLink algorithm
127
+ const headerAndPayload = data.slice(offset + 1, offset + frameOffset - offset - 2);
128
+ frame.crc_ok = MAVLinkCRC.validate(headerAndPayload, frame.message_id, frame.checksum);
99
129
  frame.protocol_version = isV2 ? 2 : 1;
100
- return { frame, bytesConsumed: frameOffset - offset };
130
+ return { frame: frame, bytesConsumed: frameOffset - offset };
101
131
  }
102
132
  resetBuffer() {
103
133
  this.buffer = new Uint8Array(0);
@@ -118,7 +148,7 @@ class DialectParser {
118
148
  },
119
149
  protocol_version: protocolVersion,
120
150
  checksum: frame.checksum,
121
- crc_ok: frame.crc_ok !== false,
151
+ crc_ok: frame.crc_ok ?? true,
122
152
  signature: frame.signature,
123
153
  dialect: this.dialectName
124
154
  };
@@ -134,7 +164,7 @@ class DialectParser {
134
164
  payload,
135
165
  protocol_version: protocolVersion,
136
166
  checksum: frame.checksum,
137
- crc_ok: frame.crc_ok !== false,
167
+ crc_ok: frame.crc_ok ?? true,
138
168
  signature: frame.signature,
139
169
  dialect: this.dialectName
140
170
  };
@@ -186,18 +216,37 @@ class DialectParser {
186
216
  const isArray = field.arrayLength !== undefined;
187
217
  const arrayLength = field.arrayLength || 1;
188
218
  if (isArray && arrayLength > 1) {
189
- const values = [];
190
- let totalBytes = 0;
191
219
  // Strip array notation from type to avoid double processing
192
220
  let baseType = field.type;
193
221
  if (baseType.includes('[') && baseType.includes(']')) {
194
222
  baseType = baseType.substring(0, baseType.indexOf('['));
195
223
  }
224
+ // Special handling for char arrays - return as string
225
+ if (baseType === 'char') {
226
+ const chars = [];
227
+ let totalBytes = 0;
228
+ for (let i = 0; i < arrayLength; i++) {
229
+ if (offset + totalBytes >= view.byteLength)
230
+ break;
231
+ const charCode = view.getUint8(offset + totalBytes);
232
+ if (charCode === 0)
233
+ break; // Null terminator
234
+ chars.push(String.fromCharCode(charCode));
235
+ totalBytes += 1;
236
+ }
237
+ // Return string value and total bytes for the array
238
+ return { value: chars.join(''), bytesRead: arrayLength }; // Always consume full array size
239
+ }
240
+ // Handle other array types
241
+ const values = [];
242
+ let totalBytes = 0;
196
243
  for (let i = 0; i < arrayLength; i++) {
197
244
  if (offset + totalBytes >= view.byteLength)
198
245
  break;
199
246
  const { value, bytesRead } = this.decodeSingleValue(view, offset + totalBytes, baseType);
200
- values.push(value);
247
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint' || typeof value === 'boolean') {
248
+ values.push(value);
249
+ }
201
250
  totalBytes += bytesRead;
202
251
  }
203
252
  return { value: values, bytesRead: totalBytes };
@@ -214,7 +263,7 @@ class DialectParser {
214
263
  case 'int8_t':
215
264
  return { value: view.getInt8(offset), bytesRead: 1 };
216
265
  case 'uint16_t':
217
- return { value: view.getUint16(offset, true), bytesRead: 2 };
266
+ return { value: view.getUint16(offset, false), bytesRead: 2 };
218
267
  case 'int16_t':
219
268
  return { value: view.getInt16(offset, true), bytesRead: 2 };
220
269
  case 'uint32_t':
@@ -254,7 +303,9 @@ class DialectParser {
254
303
  if (offset + totalBytes >= view.byteLength)
255
304
  break;
256
305
  const { value, bytesRead } = this.decodeSingleValue(view, offset + totalBytes, baseType);
257
- values.push(value);
306
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint' || typeof value === 'boolean') {
307
+ values.push(value);
308
+ }
258
309
  totalBytes += bytesRead;
259
310
  }
260
311
  return { value: values, bytesRead: totalBytes };
@@ -278,6 +329,347 @@ class DialectParser {
278
329
  supportsMessage(messageId) {
279
330
  return this.messageDefinitions.has(messageId);
280
331
  }
332
+ // Serialization methods for outgoing commands
333
+ serializeMessage(message) {
334
+ const messageDef = Array.from(this.messageDefinitions.values())
335
+ .find(def => def.name === message.message_name);
336
+ if (!messageDef) {
337
+ throw new Error(`Unknown message type: ${message.message_name}`);
338
+ }
339
+ // Extract fields from either flat structure or payload structure
340
+ const messageFields = this.extractMessageFields(message, messageDef.fields);
341
+ // Complete the message with all defined fields (including extension fields with defaults)
342
+ const completeMessage = this.completeMessageWithDefaults(messageFields, messageDef.fields);
343
+ const payload = this.serializePayload(completeMessage, messageDef.fields);
344
+ return this.createMAVLinkFrame(message, messageDef.id, payload);
345
+ }
346
+ // Extract message fields from payload structure (payload format required)
347
+ extractMessageFields(message, fieldDefinitions) {
348
+ // Require payload structure
349
+ if (!message.payload || typeof message.payload !== 'object') {
350
+ throw new Error(`Message must have a 'payload' object containing the message fields. Expected format: { message_name: '...', system_id: 1, component_id: 1, sequence: 0, payload: { ...fields } }`);
351
+ }
352
+ return message.payload;
353
+ }
354
+ // Helper method to complete message with all defined fields
355
+ completeMessageWithDefaults(message, fields) {
356
+ const completeMessage = { ...message };
357
+ for (const field of fields) {
358
+ if (completeMessage[field.name] === undefined) {
359
+ completeMessage[field.name] = this.getDefaultValueForField(field);
360
+ }
361
+ }
362
+ return completeMessage;
363
+ }
364
+ // Get default value for a field based on its definition
365
+ getDefaultValueForField(field) {
366
+ const isArray = field.arrayLength !== undefined && field.arrayLength > 1;
367
+ if (isArray) {
368
+ return [];
369
+ }
370
+ let baseType = field.type;
371
+ if (baseType.includes('[') && baseType.includes(']')) {
372
+ baseType = baseType.substring(0, baseType.indexOf('['));
373
+ }
374
+ switch (baseType) {
375
+ case 'uint8_t':
376
+ case 'int8_t':
377
+ case 'uint16_t':
378
+ case 'int16_t':
379
+ case 'uint32_t':
380
+ case 'int32_t':
381
+ case 'float':
382
+ case 'double':
383
+ return 0;
384
+ case 'uint64_t':
385
+ case 'int64_t':
386
+ return 0n;
387
+ case 'char':
388
+ return field.type.includes('[') ? '' : '\0';
389
+ default:
390
+ return 0;
391
+ }
392
+ }
393
+ serializePayload(message, fields) {
394
+ // Calculate total payload size
395
+ let totalSize = 0;
396
+ for (const field of fields) {
397
+ totalSize += this.getFieldSize(field);
398
+ }
399
+ const buffer = new ArrayBuffer(totalSize);
400
+ const view = new DataView(buffer);
401
+ let offset = 0;
402
+ for (const field of fields) {
403
+ const value = message[field.name];
404
+ const bytesWritten = this.serializeField(view, offset, field, value);
405
+ offset += bytesWritten;
406
+ }
407
+ // Implement MAVLink payload trimming: remove trailing zero bytes from extension fields only
408
+ // This is required for proper handling of extension fields
409
+ const fullPayload = new Uint8Array(buffer);
410
+ // Calculate minimum payload size (core fields only)
411
+ let corePayloadSize = 0;
412
+ let extensionStartOffset = 0;
413
+ let hasExtensions = false;
414
+ message.message_name;
415
+ for (const field of fields) {
416
+ const fieldSize = this.getFieldSize(field);
417
+ // Check if this is an extension field using proper XML-based detection
418
+ const isExtensionField = field.extension === true;
419
+ if (isExtensionField) {
420
+ if (!hasExtensions) {
421
+ extensionStartOffset = corePayloadSize;
422
+ hasExtensions = true;
423
+ }
424
+ // Don't add extension field sizes to core payload size
425
+ }
426
+ else {
427
+ // This is a core field - always add to core payload size
428
+ corePayloadSize += fieldSize;
429
+ }
430
+ }
431
+ // If there are no extension fields, don't trim at all
432
+ if (!hasExtensions) {
433
+ return fullPayload;
434
+ }
435
+ // Find the last non-zero byte in extension fields only
436
+ let trimmedLength = fullPayload.length;
437
+ // If we have extensions, check if they contain any non-zero bytes
438
+ if (hasExtensions && extensionStartOffset < fullPayload.length) {
439
+ // Look for non-zero bytes in the extension section
440
+ let hasNonZeroExtensions = false;
441
+ for (let i = extensionStartOffset; i < fullPayload.length; i++) {
442
+ if (fullPayload[i] !== 0) {
443
+ hasNonZeroExtensions = true;
444
+ break;
445
+ }
446
+ }
447
+ if (!hasNonZeroExtensions) {
448
+ // All extension fields are zero, trim them all
449
+ trimmedLength = corePayloadSize;
450
+ }
451
+ else {
452
+ // Find the last non-zero byte in extension fields
453
+ for (let i = fullPayload.length - 1; i >= extensionStartOffset; i--) {
454
+ if (fullPayload[i] !== 0) {
455
+ trimmedLength = i + 1;
456
+ break;
457
+ }
458
+ }
459
+ }
460
+ }
461
+ // Never trim below the core payload size
462
+ if (trimmedLength < corePayloadSize) {
463
+ trimmedLength = corePayloadSize;
464
+ }
465
+ // Return trimmed payload if it's shorter than the original
466
+ if (trimmedLength < fullPayload.length) {
467
+ return fullPayload.slice(0, trimmedLength);
468
+ }
469
+ return fullPayload;
470
+ }
471
+ serializeField(view, offset, field, value) {
472
+ const isArray = field.arrayLength !== undefined;
473
+ const arrayLength = field.arrayLength || 1;
474
+ if (isArray && arrayLength > 1) {
475
+ let totalBytes = 0;
476
+ let baseType = field.type;
477
+ if (baseType.includes('[') && baseType.includes(']')) {
478
+ baseType = baseType.substring(0, baseType.indexOf('['));
479
+ }
480
+ // Special handling for char arrays - treat string as char array
481
+ if (baseType === 'char' && typeof value === 'string') {
482
+ const str = value;
483
+ for (let i = 0; i < arrayLength; i++) {
484
+ const charCode = i < str.length ? str.charCodeAt(i) : 0;
485
+ view.setUint8(offset + totalBytes, charCode);
486
+ totalBytes += 1;
487
+ }
488
+ return totalBytes;
489
+ }
490
+ // Handle other array types
491
+ const arrayValue = Array.isArray(value) ? value : [value];
492
+ for (let i = 0; i < arrayLength; i++) {
493
+ const itemValue = i < arrayValue.length ? arrayValue[i] : this.getDefaultValueForType(baseType);
494
+ const bytesWritten = this.serializeSingleValue(view, offset + totalBytes, baseType, itemValue);
495
+ totalBytes += bytesWritten;
496
+ }
497
+ return totalBytes;
498
+ }
499
+ else {
500
+ return this.serializeSingleValue(view, offset, field.type, value);
501
+ }
502
+ }
503
+ serializeSingleValue(view, offset, type, value) {
504
+ const actualValue = value ?? this.getDefaultValueForType(type);
505
+ switch (type) {
506
+ case 'uint8_t':
507
+ view.setUint8(offset, Number(actualValue));
508
+ return 1;
509
+ case 'int8_t':
510
+ view.setInt8(offset, Number(actualValue));
511
+ return 1;
512
+ case 'uint16_t':
513
+ view.setUint16(offset, Number(actualValue), false);
514
+ return 2;
515
+ case 'int16_t':
516
+ view.setInt16(offset, Number(actualValue), true);
517
+ return 2;
518
+ case 'uint32_t':
519
+ view.setUint32(offset, Number(actualValue), true);
520
+ return 4;
521
+ case 'int32_t':
522
+ view.setInt32(offset, Number(actualValue), true);
523
+ return 4;
524
+ case 'uint64_t':
525
+ view.setBigUint64(offset, typeof actualValue === 'bigint' ? actualValue : BigInt(Number(actualValue) || 0), true);
526
+ return 8;
527
+ case 'int64_t':
528
+ view.setBigInt64(offset, typeof actualValue === 'bigint' ? actualValue : BigInt(Number(actualValue) || 0), true);
529
+ return 8;
530
+ case 'float':
531
+ view.setFloat32(offset, Number(actualValue), true);
532
+ return 4;
533
+ case 'double':
534
+ view.setFloat64(offset, Number(actualValue), true);
535
+ return 8;
536
+ case 'char':
537
+ view.setUint8(offset, typeof actualValue === 'string' ? actualValue.charCodeAt(0) : Number(actualValue));
538
+ return 1;
539
+ default:
540
+ if (type.startsWith('char[') && type.endsWith(']')) {
541
+ const length = parseInt(type.slice(5, -1));
542
+ const str = String(actualValue);
543
+ for (let i = 0; i < length; i++) {
544
+ const charCode = i < str.length ? str.charCodeAt(i) : 0;
545
+ view.setUint8(offset + i, charCode);
546
+ }
547
+ return length;
548
+ }
549
+ view.setUint8(offset, Number(actualValue));
550
+ return 1;
551
+ }
552
+ }
553
+ getFieldSize(field) {
554
+ if (typeof field === 'string') {
555
+ // Legacy support for type string
556
+ if (field.includes('[') && field.includes(']')) {
557
+ const baseType = field.substring(0, field.indexOf('['));
558
+ const arrayLength = parseInt(field.substring(field.indexOf('[') + 1, field.indexOf(']')));
559
+ return this.getSingleFieldSize(baseType) * arrayLength;
560
+ }
561
+ return this.getSingleFieldSize(field);
562
+ }
563
+ // Handle FieldDefinition object
564
+ const type = field.type;
565
+ const arrayLength = field.arrayLength;
566
+ if (arrayLength && arrayLength > 1) {
567
+ return this.getSingleFieldSize(type) * arrayLength;
568
+ }
569
+ if (type.includes('[') && type.includes(']')) {
570
+ const baseType = type.substring(0, type.indexOf('['));
571
+ const parsedArrayLength = parseInt(type.substring(type.indexOf('[') + 1, type.indexOf(']')));
572
+ return this.getSingleFieldSize(baseType) * parsedArrayLength;
573
+ }
574
+ return this.getSingleFieldSize(type);
575
+ }
576
+ getSingleFieldSize(type) {
577
+ switch (type) {
578
+ case 'uint8_t':
579
+ case 'int8_t':
580
+ case 'char':
581
+ return 1;
582
+ case 'uint16_t':
583
+ case 'int16_t':
584
+ return 2;
585
+ case 'uint32_t':
586
+ case 'int32_t':
587
+ case 'float':
588
+ return 4;
589
+ case 'uint64_t':
590
+ case 'int64_t':
591
+ case 'double':
592
+ return 8;
593
+ default:
594
+ return 1;
595
+ }
596
+ }
597
+ getDefaultValueForType(type) {
598
+ switch (type) {
599
+ case 'uint8_t':
600
+ case 'int8_t':
601
+ case 'uint16_t':
602
+ case 'int16_t':
603
+ case 'uint32_t':
604
+ case 'int32_t':
605
+ case 'float':
606
+ case 'double':
607
+ return 0;
608
+ case 'uint64_t':
609
+ case 'int64_t':
610
+ return 0n;
611
+ case 'char':
612
+ return 0;
613
+ default:
614
+ return 0;
615
+ }
616
+ }
617
+ createMAVLinkFrame(message, messageId, payload) {
618
+ const systemId = typeof message.system_id === 'number' ? message.system_id : 1;
619
+ const componentId = typeof message.component_id === 'number' ? message.component_id : 1;
620
+ const sequence = typeof message.sequence === 'number' ? message.sequence : 0;
621
+ // Automatically determine protocol version based on message requirements
622
+ const needsV2 = messageId > 255; // v1 only supports 8-bit message IDs (0-255)
623
+ const userSpecifiedVersion = typeof message.protocol_version === 'number' ? message.protocol_version : null;
624
+ // Use user-specified version if provided, otherwise auto-detect
625
+ const protocolVersion = userSpecifiedVersion !== null ? userSpecifiedVersion : (needsV2 ? 2 : 1);
626
+ const isV2 = protocolVersion === 2;
627
+ const magic = isV2 ? 0xFD : 0xFE;
628
+ // Calculate frame size based on protocol version
629
+ const headerSize = isV2 ? 10 : 6; // v2 has extra fields
630
+ const frameSize = headerSize + payload.length + 2;
631
+ const buffer = new ArrayBuffer(frameSize);
632
+ const view = new DataView(buffer);
633
+ let offset = 0;
634
+ // Header
635
+ view.setUint8(offset++, magic);
636
+ view.setUint8(offset++, payload.length);
637
+ if (isV2) {
638
+ // MAVLink v2: magic(1) + len(1) + incompat_flags(1) + compat_flags(1) + seq(1) + sysid(1) + compid(1) + msgid(3) + payload + checksum(2)
639
+ view.setUint8(offset++, 0); // incompat_flags
640
+ view.setUint8(offset++, 0); // compat_flags
641
+ view.setUint8(offset++, sequence);
642
+ view.setUint8(offset++, systemId);
643
+ view.setUint8(offset++, componentId);
644
+ // 24-bit message ID in v2
645
+ view.setUint8(offset++, messageId & 0xFF);
646
+ view.setUint8(offset++, (messageId >> 8) & 0xFF);
647
+ view.setUint8(offset++, (messageId >> 16) & 0xFF);
648
+ }
649
+ else {
650
+ // MAVLink v1: magic(1) + len(1) + seq(1) + sysid(1) + compid(1) + msgid(1) + payload + checksum(2)
651
+ view.setUint8(offset++, sequence);
652
+ view.setUint8(offset++, systemId);
653
+ view.setUint8(offset++, componentId);
654
+ view.setUint8(offset++, messageId & 0xFF); // 8-bit message ID in v1
655
+ }
656
+ // Payload
657
+ const payloadView = new Uint8Array(buffer, offset, payload.length);
658
+ payloadView.set(payload);
659
+ offset += payload.length;
660
+ // Calculate proper MAVLink CRC with CRC_EXTRA
661
+ const crcExtra = CRC_EXTRA[messageId];
662
+ if (crcExtra === undefined) {
663
+ throw new Error("No CRC_EXTRA defined for message ID " + messageId);
664
+ }
665
+ // Get message data (exclude start byte and checksum)
666
+ const messageData = new Uint8Array(buffer, 1, offset - 1);
667
+ const checksum = MAVLinkCRC.calculate(messageData, crcExtra);
668
+ // Checksum (little endian)
669
+ view.setUint8(offset++, checksum & 0xFF);
670
+ view.setUint8(offset++, (checksum >> 8) & 0xFF);
671
+ return new Uint8Array(buffer);
672
+ }
281
673
  }
282
674
  const MESSAGE_DEFINITIONS = [
283
675
  {
@@ -290,7 +682,7 @@ const MESSAGE_DEFINITIONS = [
290
682
  },
291
683
  {
292
684
  name: 's',
293
- type: 'char[10]',
685
+ type: 'char',
294
686
  arrayLength: 10,
295
687
  },
296
688
  {
@@ -334,53 +726,53 @@ const MESSAGE_DEFINITIONS = [
334
726
  type: 'double',
335
727
  },
336
728
  {
337
- name: 'u8Array',
338
- type: 'uint8_t[3]',
729
+ name: 'u8_array',
730
+ type: 'uint8_t',
339
731
  arrayLength: 3,
340
732
  },
341
733
  {
342
- name: 'u16Array',
343
- type: 'uint16_t[3]',
734
+ name: 'u16_array',
735
+ type: 'uint16_t',
344
736
  arrayLength: 3,
345
737
  },
346
738
  {
347
- name: 'u32Array',
348
- type: 'uint32_t[3]',
739
+ name: 'u32_array',
740
+ type: 'uint32_t',
349
741
  arrayLength: 3,
350
742
  },
351
743
  {
352
- name: 'u64Array',
353
- type: 'uint64_t[3]',
744
+ name: 'u64_array',
745
+ type: 'uint64_t',
354
746
  arrayLength: 3,
355
747
  },
356
748
  {
357
- name: 's8Array',
358
- type: 'int8_t[3]',
749
+ name: 's8_array',
750
+ type: 'int8_t',
359
751
  arrayLength: 3,
360
752
  },
361
753
  {
362
- name: 's16Array',
363
- type: 'int16_t[3]',
754
+ name: 's16_array',
755
+ type: 'int16_t',
364
756
  arrayLength: 3,
365
757
  },
366
758
  {
367
- name: 's32Array',
368
- type: 'int32_t[3]',
759
+ name: 's32_array',
760
+ type: 'int32_t',
369
761
  arrayLength: 3,
370
762
  },
371
763
  {
372
- name: 's64Array',
373
- type: 'int64_t[3]',
764
+ name: 's64_array',
765
+ type: 'int64_t',
374
766
  arrayLength: 3,
375
767
  },
376
768
  {
377
- name: 'fArray',
378
- type: 'float[3]',
769
+ name: 'f_array',
770
+ type: 'float',
379
771
  arrayLength: 3,
380
772
  },
381
773
  {
382
- name: 'dArray',
383
- type: 'double[3]',
774
+ name: 'd_array',
775
+ type: 'double',
384
776
  arrayLength: 3,
385
777
  },
386
778
  ]
@@ -404,6 +796,43 @@ class TestParser extends DialectParser {
404
796
  }
405
797
  }
406
798
  }
799
+ // Dialect-specific serializer
800
+ class TestSerializer {
801
+ constructor() {
802
+ this.parser = new TestParser();
803
+ }
804
+ // Serialize a message to MAVLink bytes
805
+ serialize(message) {
806
+ return this.parser.serializeMessage(message);
807
+ }
808
+ // Complete a message with all defined fields (including extension fields with defaults)
809
+ // This is useful to see what the serializer would send without actually serializing
810
+ // Requires payload structure format
811
+ completeMessage(message) {
812
+ const messageDef = Array.from(this.parser['messageDefinitions'].values())
813
+ .find(def => def.name === message.message_name);
814
+ if (!messageDef) {
815
+ throw new Error(`Unknown message type: ${message.message_name}`);
816
+ }
817
+ // Extract fields from payload structure (throws error if not payload format)
818
+ const messageFields = this.parser['extractMessageFields'](message, messageDef.fields);
819
+ // Complete the message with defaults
820
+ const completedFields = this.parser['completeMessageWithDefaults'](messageFields, messageDef.fields);
821
+ // Return in the payload structure format
822
+ return {
823
+ ...message,
824
+ payload: completedFields
825
+ };
826
+ }
827
+ // Get supported message names for this dialect
828
+ getSupportedMessages() {
829
+ return Array.from(this.parser['messageDefinitions'].values()).map(def => def.name);
830
+ }
831
+ // Check if a message is supported by this dialect
832
+ supportsMessage(messageName) {
833
+ return Array.from(this.parser['messageDefinitions'].values()).some(def => def.name === messageName);
834
+ }
835
+ }
407
836
 
408
- export { TestParser, isTestTypes };
837
+ export { TestParser, TestSerializer, isTestTypes };
409
838
  //# sourceMappingURL=index.js.map