@airframes/acars-decoder 1.8.14 → 1.9.1

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.
package/dist/index.js CHANGED
@@ -131,11 +131,11 @@ var CoordinateUtils = class _CoordinateUtils {
131
131
  * @returns An object with latitude and longitude properties
132
132
  */
133
133
  static decodeStringCoordinates(stringCoords) {
134
- const firstChar = stringCoords.substring(0, 1);
135
- let middleChar = stringCoords.substring(6, 7);
134
+ const firstChar = stringCoords.charAt(0);
135
+ let middleChar = stringCoords.charAt(6);
136
136
  let longitudeChars = stringCoords.substring(7, 13);
137
- if (middleChar == " ") {
138
- middleChar = stringCoords.substring(7, 8);
137
+ if (middleChar === " ") {
138
+ middleChar = stringCoords.charAt(7);
139
139
  longitudeChars = stringCoords.substring(8, 14);
140
140
  }
141
141
  if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
@@ -153,24 +153,26 @@ var CoordinateUtils = class _CoordinateUtils {
153
153
  * @returns An object with latitude and longitude properties
154
154
  */
155
155
  static decodeStringCoordinatesDecimalMinutes(stringCoords) {
156
- const firstChar = stringCoords.substring(0, 1);
157
- let middleChar = stringCoords.substring(6, 7);
156
+ const firstChar = stringCoords.charAt(0);
157
+ let middleChar = stringCoords.charAt(6);
158
158
  let longitudeChars = stringCoords.substring(7, 13);
159
- if (middleChar == " ") {
160
- middleChar = stringCoords.substring(7, 8);
159
+ if (middleChar === " ") {
160
+ middleChar = stringCoords.charAt(7);
161
161
  longitudeChars = stringCoords.substring(8, 14);
162
162
  }
163
- const latDeg = Math.trunc(Number(stringCoords.substring(1, 6)) / 1e3);
164
- const latMin = Number(stringCoords.substring(1, 6)) % 1e3 / 10;
165
- const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
166
- const lonMin = Number(longitudeChars) % 1e3 / 10;
167
- if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
168
- return {
169
- latitude: (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar),
170
- longitude: (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar)
171
- };
163
+ if (firstChar !== "N" && firstChar !== "S" || middleChar !== "W" && middleChar !== "E") {
164
+ return void 0;
172
165
  }
173
- return void 0;
166
+ const latRaw = Number(stringCoords.substring(1, 6));
167
+ const lonRaw = Number(longitudeChars);
168
+ const latDeg = Math.trunc(latRaw / 1e3);
169
+ const latMin = latRaw % 1e3 / 10;
170
+ const lonDeg = Math.trunc(lonRaw / 1e3);
171
+ const lonMin = lonRaw % 1e3 / 10;
172
+ return {
173
+ latitude: (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar),
174
+ longitude: (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar)
175
+ };
174
176
  }
175
177
  static coordinateString(coords) {
176
178
  const latDir = coords.latitude > 0 ? "N" : "S";
@@ -201,25 +203,13 @@ var DateTimeUtils = class {
201
203
  // Expects a six digit date string and a four digit UTC time string
202
204
  // (DDMMYY) (HHMM)
203
205
  static UTCDateTimeToString(dateString, timeString) {
204
- let utcDate = /* @__PURE__ */ new Date();
205
- utcDate.setUTCDate(+dateString.substr(0, 2));
206
- utcDate.setUTCMonth(+dateString.substr(2, 2));
207
- if (dateString.length === 6) {
208
- utcDate.setUTCFullYear(2e3 + +dateString.substr(4, 2));
209
- }
210
- if (timeString.length === 6) {
211
- utcDate.setUTCHours(
212
- +timeString.substr(0, 2),
213
- +timeString.substr(2, 2),
214
- +timeString.substr(4, 2)
215
- );
216
- } else {
217
- utcDate.setUTCHours(
218
- +timeString.substr(0, 2),
219
- +timeString.substr(2, 2),
220
- 0
221
- );
222
- }
206
+ const day = +dateString.substr(0, 2);
207
+ const month = +dateString.substr(2, 2) - 1;
208
+ const year = dateString.length === 6 ? 2e3 + +dateString.substr(4, 2) : (/* @__PURE__ */ new Date()).getUTCFullYear();
209
+ const hours = +timeString.substr(0, 2);
210
+ const minutes = +timeString.substr(2, 2);
211
+ const seconds = timeString.length === 6 ? +timeString.substr(4, 2) : 0;
212
+ const utcDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
223
213
  return utcDate.toUTCString();
224
214
  }
225
215
  /**
@@ -564,7 +554,7 @@ var ResultFormatter = class {
564
554
  decodeResult.raw.fuel_remaining = value;
565
555
  decodeResult.formatted.items.push({
566
556
  type: "fuel_remaining",
567
- code: " FUEL_REM",
557
+ code: "FUEL_REM",
568
558
  label: "Fuel Remaining",
569
559
  value: decodeResult.raw.fuel_remaining.toString()
570
560
  });
@@ -623,7 +613,7 @@ var ResultFormatter = class {
623
613
  type: "message_checksum",
624
614
  code: "CHECKSUM",
625
615
  label: "Message Checksum",
626
- value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
616
+ value: "0x" + (decodeResult.raw.checksum >>> 0).toString(16).padStart(4, "0")
627
617
  });
628
618
  }
629
619
  static groundspeed(decodeResult, value) {
@@ -958,7 +948,7 @@ var ResultFormatter = class {
958
948
  type: "sequence",
959
949
  code: "SEQ",
960
950
  label: "Sequence Number",
961
- value: decodeResult.raw.sequence_number
951
+ value: decodeResult.raw.sequence_number.toString()
962
952
  });
963
953
  }
964
954
  static sequenceResponse(decodeResult, value) {
@@ -967,7 +957,7 @@ var ResultFormatter = class {
967
957
  type: "sequence",
968
958
  code: "SEQ_RESP",
969
959
  label: "Sequence Response",
970
- value: decodeResult.raw.sequence_response
960
+ value: decodeResult.raw.sequence_response.toString()
971
961
  });
972
962
  }
973
963
  static unknown(decodeResult, value, sep = ",") {
@@ -1073,6 +1063,7 @@ var DecoderPlugin = class {
1073
1063
  };
1074
1064
 
1075
1065
  // lib/plugins/CBand.ts
1066
+ var CBAND_HEADER = /^(?<msgno>[A-Z]\d{2}[A-Z])(?<airline>[A-Z0-9]{2})(?<number>[0-9]{4})/;
1076
1067
  var CBand = class extends DecoderPlugin {
1077
1068
  name = "c-band";
1078
1069
  qualifiers() {
@@ -1081,35 +1072,43 @@ var CBand = class extends DecoderPlugin {
1081
1072
  };
1082
1073
  }
1083
1074
  decode(message, options = {}) {
1084
- let decodeResult = this.defaultResult();
1075
+ const text = message.text;
1076
+ if (text.length < 10) {
1077
+ const result = this.defaultResult();
1078
+ result.decoder.name = this.name;
1079
+ result.message = message;
1080
+ return result;
1081
+ }
1082
+ const cband = CBAND_HEADER.exec(text);
1083
+ if (!cband?.groups) {
1084
+ const result = this.defaultResult();
1085
+ result.decoder.name = this.name;
1086
+ result.message = message;
1087
+ return result;
1088
+ }
1089
+ const decoded = this.decoder.decode(
1090
+ {
1091
+ label: message.label,
1092
+ sublabel: message.sublabel,
1093
+ text: text.substring(10)
1094
+ },
1095
+ options
1096
+ );
1097
+ const decodeResult = this.defaultResult();
1085
1098
  decodeResult.decoder.name = this.name;
1086
1099
  decodeResult.message = message;
1087
- let cband = message.text.match(
1088
- /^(?<msgno>[A-Z]\d{2}[A-Z])(?<airline>[A-Z0-9]{2})(?<number>[0-9]{4})/
1089
- );
1090
- if (cband?.groups) {
1091
- const messageText = message.text.substring(10);
1092
- const decoded = this.decoder.decode(
1093
- {
1094
- label: message.label,
1095
- sublabel: message.sublabel,
1096
- text: messageText
1097
- },
1098
- options
1100
+ if (decoded.decoded) {
1101
+ ResultFormatter.flightNumber(
1102
+ decodeResult,
1103
+ cband.groups.airline + Number(cband.groups.number)
1099
1104
  );
1100
- if (decoded.decoded) {
1101
- ResultFormatter.flightNumber(
1102
- decodeResult,
1103
- cband.groups.airline + Number(cband.groups.number)
1104
- );
1105
- decodeResult.decoded = true;
1106
- decodeResult.decoder.decodeLevel = decoded.decoder.decodeLevel;
1107
- decodeResult.decoder.name = this.name + "-" + decoded.decoder.name;
1108
- decodeResult.raw = { ...decodeResult.raw, ...decoded.raw };
1109
- decodeResult.formatted.description = decoded.formatted.description;
1110
- decodeResult.formatted.items.push(...decoded.formatted.items);
1111
- decodeResult.remaining = decoded.remaining;
1112
- }
1105
+ decodeResult.decoded = true;
1106
+ decodeResult.decoder.decodeLevel = decoded.decoder.decodeLevel;
1107
+ decodeResult.decoder.name = this.name + "-" + decoded.decoder.name;
1108
+ decodeResult.raw = { ...decodeResult.raw, ...decoded.raw };
1109
+ decodeResult.formatted.description = decoded.formatted.description;
1110
+ decodeResult.formatted.items.push(...decoded.formatted.items);
1111
+ decodeResult.remaining = decoded.remaining;
1113
1112
  }
1114
1113
  return decodeResult;
1115
1114
  }
@@ -1194,7 +1193,9 @@ var FlightPlanUtils = class _FlightPlanUtils {
1194
1193
  label: "Route Status",
1195
1194
  value: "Route Planned"
1196
1195
  });
1197
- decodeResult.raw.route_status = header;
1196
+ if (header.length > 2) {
1197
+ addRoute(decodeResult, header.substring(2));
1198
+ }
1198
1199
  } else if (header.startsWith("RI")) {
1199
1200
  decodeResult.raw.route_status = "RI";
1200
1201
  decodeResult.formatted.items.push({
@@ -1272,7 +1273,11 @@ function addCompanyRoute(decodeResult, value) {
1272
1273
  name = segments[0];
1273
1274
  } else {
1274
1275
  name = segments[0].slice(0, parens_idx);
1275
- runway = segments[0].slice(parens_idx + 1, segments[0].indexOf(")"));
1276
+ const close_paren_idx = segments[0].indexOf(")");
1277
+ runway = segments[0].slice(
1278
+ parens_idx + 1,
1279
+ close_paren_idx === -1 ? void 0 : close_paren_idx
1280
+ );
1276
1281
  }
1277
1282
  let waypoints;
1278
1283
  if (segments.length > 1) {
@@ -1292,6 +1297,11 @@ function addCompanyRoute(decodeResult, value) {
1292
1297
  }
1293
1298
 
1294
1299
  // lib/utils/arinc_702_helper.ts
1300
+ function asciiStringToBytes(data) {
1301
+ const bytes = new Uint8Array(data.length);
1302
+ for (let i = 0; i < data.length; i++) bytes[i] = data.charCodeAt(i) & 255;
1303
+ return bytes;
1304
+ }
1295
1305
  var Arinc702Helper = class _Arinc702Helper {
1296
1306
  /**
1297
1307
  * Decodes an ARINC 702 message
@@ -1810,7 +1820,7 @@ function processSummary(decodeResult, data) {
1810
1820
  }
1811
1821
  function crc16IbmSdlcRev(data) {
1812
1822
  let crc = 65535;
1813
- const bytes = Buffer.from(data, "ascii");
1823
+ const bytes = asciiStringToBytes(data);
1814
1824
  for (const byte of bytes) {
1815
1825
  crc ^= byte;
1816
1826
  for (let i = 0; i < 8; i++) {
@@ -1831,7 +1841,7 @@ function crc16IbmSdlcRev(data) {
1831
1841
  function crc16Genibus(data) {
1832
1842
  let crc = 65535;
1833
1843
  const polynomial = 4129;
1834
- const bytes = Buffer.from(data, "ascii");
1844
+ const bytes = asciiStringToBytes(data);
1835
1845
  for (const byte of bytes) {
1836
1846
  crc ^= byte << 8;
1837
1847
  for (let i = 0; i < 8; i++) {
@@ -1856,6 +1866,7 @@ function processMessageReference(decodeResult, data) {
1856
1866
  }
1857
1867
 
1858
1868
  // lib/plugins/ARINC_702.ts
1869
+ var NEWLINE_REGEX = /[\n\r]/g;
1859
1870
  var Arinc702 = class extends DecoderPlugin {
1860
1871
  name = "arinc-702";
1861
1872
  qualifiers() {
@@ -1867,7 +1878,7 @@ var Arinc702 = class extends DecoderPlugin {
1867
1878
  let decodeResult = this.defaultResult();
1868
1879
  decodeResult.decoder.name = this.name;
1869
1880
  decodeResult.message = message;
1870
- const msg = message.text.replace(/\n|\r/g, "");
1881
+ const msg = message.text.replace(NEWLINE_REGEX, "");
1871
1882
  let decoded = false;
1872
1883
  decoded = Arinc702Helper.decodeH1Message(decodeResult, msg);
1873
1884
  if (decoded) {
@@ -1934,6 +1945,12 @@ var Arinc702 = class extends DecoderPlugin {
1934
1945
  }
1935
1946
  };
1936
1947
 
1948
+ // lib/utils/acars_free_text.ts
1949
+ function formatAcarsFreeText(text) {
1950
+ if (!text) return "";
1951
+ return text.trim().replace(/\s+/g, " ");
1952
+ }
1953
+
1937
1954
  // lib/plugins/Label_5Z_Slash.ts
1938
1955
  var Label_5Z_Slash = class extends DecoderPlugin {
1939
1956
  name = "label-5z-slash";
@@ -1975,7 +1992,10 @@ var Label_5Z_Slash = class extends DecoderPlugin {
1975
1992
  decodeResult.formatted.description = "Airline Designated Downlink";
1976
1993
  const lines = message.text.split("\r\n");
1977
1994
  if (lines[0] === "/TXT") {
1978
- ResultFormatter.text(decodeResult, lines.slice(1).join("\r\n"));
1995
+ ResultFormatter.text(
1996
+ decodeResult,
1997
+ formatAcarsFreeText(lines.slice(1).join("\r\n"))
1998
+ );
1979
1999
  decodeResult.decoded = true;
1980
2000
  decodeResult.decoder.decodeLevel = "full";
1981
2001
  return decodeResult;
@@ -2517,6 +2537,111 @@ var Label_15_FST = class extends DecoderPlugin {
2517
2537
  }
2518
2538
  };
2519
2539
 
2540
+ // lib/plugins/Label_16_AUTPOS.ts
2541
+ var Label_16_AUTPOS = class extends DecoderPlugin {
2542
+ name = "label-16-autpos";
2543
+ qualifiers() {
2544
+ return {
2545
+ labels: ["16"],
2546
+ preambles: [""]
2547
+ };
2548
+ }
2549
+ decode(message) {
2550
+ let decodeResult = this.defaultResult();
2551
+ decodeResult.decoder.name = this.name;
2552
+ decodeResult.message = message;
2553
+ const regex = /^(\d{6})\/AUTPOS\/LLD (N|S)(\d{2})(\d{2})(\d{2}) (E|W)(\d{3})(\d{2})(\d{2})\s*\r?\n\/ALT (\d+)\/SAT ([*\-\d]{4})\r?\n\/WND ([*\d]{3})([\*\d]{3})\/TAT ([*\-\d]{4})\/TAS ([*\d]{3,4})\/CRZ ([*\d]{3,4})\r?\n\/FOB (\d{6})\r?\n\/DAT (\d{6})\/TIM (\d{6})/;
2554
+ const match = regex.exec(message.text);
2555
+ if (!match) {
2556
+ decodeResult.decoded = false;
2557
+ return decodeResult;
2558
+ }
2559
+ decodeResult.decoded = true;
2560
+ decodeResult.decoder.decodeLevel = "full";
2561
+ decodeResult.formatted.description = "Position Report";
2562
+ const [
2563
+ ,
2564
+ flight,
2565
+ latHem,
2566
+ latDeg,
2567
+ latMin,
2568
+ latSec,
2569
+ lonHem,
2570
+ lonDeg,
2571
+ lonMin,
2572
+ lonSec,
2573
+ altitude,
2574
+ sat,
2575
+ windDir,
2576
+ windSpd,
2577
+ tat,
2578
+ tas,
2579
+ crz,
2580
+ fob,
2581
+ dat,
2582
+ tim
2583
+ ] = match;
2584
+ ResultFormatter.day(decodeResult, parseInt(flight.slice(0, 2), 10));
2585
+ ResultFormatter.flightNumber(decodeResult, flight.slice(2));
2586
+ let latitude = CoordinateUtils.dmsToDecimalDegrees(
2587
+ parseInt(latDeg, 10),
2588
+ parseInt(latMin, 10),
2589
+ parseInt(latSec, 10)
2590
+ );
2591
+ if (latHem === "S") latitude = -latitude;
2592
+ let longitude = CoordinateUtils.dmsToDecimalDegrees(
2593
+ parseInt(lonDeg, 10),
2594
+ parseInt(lonMin, 10),
2595
+ parseInt(lonSec, 10)
2596
+ );
2597
+ if (lonHem === "W") longitude = -longitude;
2598
+ ResultFormatter.position(decodeResult, {
2599
+ latitude,
2600
+ longitude
2601
+ });
2602
+ const alt = parseInt(altitude, 10);
2603
+ ResultFormatter.altitude(decodeResult, alt);
2604
+ if (!windSpd.includes("*") && !windDir.includes("*")) {
2605
+ ResultFormatter.windData(decodeResult, [
2606
+ {
2607
+ waypoint: {
2608
+ name: "POSITION"
2609
+ },
2610
+ flightLevel: Math.round(alt / 100),
2611
+ windDirection: parseInt(windDir, 10),
2612
+ windSpeed: parseInt(windSpd, 10)
2613
+ }
2614
+ ]);
2615
+ }
2616
+ if (!tat.includes("*")) {
2617
+ ResultFormatter.totalAirTemp(decodeResult, tat);
2618
+ }
2619
+ if (!tas.includes("*")) {
2620
+ ResultFormatter.airspeed(decodeResult, parseInt(tas, 10));
2621
+ }
2622
+ if (!sat.includes("*")) {
2623
+ ResultFormatter.temperature(decodeResult, sat);
2624
+ }
2625
+ if (!crz.includes("*")) {
2626
+ ResultFormatter.mach(decodeResult, parseInt(crz, 10) / 1e3);
2627
+ }
2628
+ if (!fob.includes("*")) {
2629
+ ResultFormatter.currentFuel(decodeResult, parseInt(fob, 10));
2630
+ }
2631
+ if (!dat.includes("*") && !tim.includes("*")) {
2632
+ const yy = dat.slice(0, 2);
2633
+ const mm = dat.slice(2, 4);
2634
+ const dd = dat.slice(4, 6);
2635
+ const ddmmyy = `${dd}${mm}${yy}`;
2636
+ ResultFormatter.timestamp(
2637
+ decodeResult,
2638
+ DateTimeUtils.convertDateTimeToEpoch(tim, ddmmyy)
2639
+ );
2640
+ }
2641
+ return decodeResult;
2642
+ }
2643
+ };
2644
+
2520
2645
  // lib/plugins/Label_16_Honeywell.ts
2521
2646
  var Label_16_Honeywell = class extends DecoderPlugin {
2522
2647
  name = "label-16-honeywell";
@@ -3291,7 +3416,7 @@ var Label_2P_FM3 = class extends DecoderPlugin {
3291
3416
  const parts = message.text.split(",");
3292
3417
  if (parts.length === 7) {
3293
3418
  const header = parts[0].split("FM3 ");
3294
- if (header.length == 0) {
3419
+ if (header.length < 2) {
3295
3420
  ResultFormatter.unknown(decodeResult, message.text);
3296
3421
  decodeResult.decoded = false;
3297
3422
  decodeResult.decoder.decodeLevel = "none";
@@ -3362,7 +3487,7 @@ var Label_2P_FM4 = class extends DecoderPlugin {
3362
3487
  const parts = message.text.split(",");
3363
3488
  if (parts.length === 10) {
3364
3489
  const header = parts[0].split("FM4");
3365
- if (header.length == 0) {
3490
+ if (header.length < 2) {
3366
3491
  ResultFormatter.unknown(decodeResult, message.text);
3367
3492
  decodeResult.decoded = false;
3368
3493
  decodeResult.decoder.decodeLevel = "none";
@@ -3421,7 +3546,7 @@ var Label_2P_FM5 = class extends DecoderPlugin {
3421
3546
  const parts = message.text.split(",");
3422
3547
  if (parts.length === 12) {
3423
3548
  const header = parts[0].split("FM5 ");
3424
- if (header.length == 0) {
3549
+ if (header.length < 2) {
3425
3550
  ResultFormatter.unknown(decodeResult, message.text);
3426
3551
  decodeResult.decoded = false;
3427
3552
  decodeResult.decoder.decodeLevel = "none";
@@ -3844,7 +3969,8 @@ var Label_4A = class extends DecoderPlugin {
3844
3969
  ResultFormatter.arrivalAirport(decodeResult, fields[5]);
3845
3970
  ResultFormatter.unknownArr(decodeResult, fields.slice(8));
3846
3971
  } else if (fields.length === 6) {
3847
- if (fields[0].match(/^[NS]/)) {
3972
+ const f0 = fields[0];
3973
+ if (f0.length > 0 && (f0[0] === "N" || f0[0] === "S")) {
3848
3974
  ResultFormatter.position(
3849
3975
  decodeResult,
3850
3976
  CoordinateUtils.decodeStringCoordinates(fields[0].substring(0, 13))
@@ -4225,6 +4351,9 @@ var Label_4T_ETA = class extends DecoderPlugin {
4225
4351
  };
4226
4352
 
4227
4353
  // lib/plugins/Label_80.ts
4354
+ var POS_REGEX = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
4355
+ var WS_REGEX = /\s+/;
4356
+ var NEWLINE_REGEX2 = /\r?\n/;
4228
4357
  var Label_80 = class extends DecoderPlugin {
4229
4358
  name = "label-80";
4230
4359
  qualifiers() {
@@ -4238,7 +4367,7 @@ var Label_80 = class extends DecoderPlugin {
4238
4367
  message,
4239
4368
  "Airline Defined Position Report"
4240
4369
  );
4241
- const lines = message.text.split(/\r?\n/);
4370
+ const lines = message.text.split(NEWLINE_REGEX2);
4242
4371
  if (lines.length === 1 && lines[0].includes(",")) {
4243
4372
  this.parseCsvFormat(lines[0], decodeResult);
4244
4373
  } else {
@@ -4273,7 +4402,7 @@ var Label_80 = class extends DecoderPlugin {
4273
4402
  ResultFormatter.unknown(results, header, "/");
4274
4403
  return;
4275
4404
  }
4276
- const msgInfo = fields[0].split(/\s+/);
4405
+ const msgInfo = fields[0].split(WS_REGEX);
4277
4406
  if (msgInfo.length === 3) {
4278
4407
  ResultFormatter.unknownArr(results, msgInfo.slice(0, 2), " ");
4279
4408
  ResultFormatter.flightNumber(results, msgInfo[2]);
@@ -4281,14 +4410,14 @@ var Label_80 = class extends DecoderPlugin {
4281
4410
  ResultFormatter.unknown(results, header, "/");
4282
4411
  return;
4283
4412
  }
4284
- const otherInfo1 = fields[1].split(/\s+/);
4413
+ const otherInfo1 = fields[1].split(WS_REGEX);
4285
4414
  if (otherInfo1.length === 2) {
4286
4415
  ResultFormatter.day(results, parseInt(otherInfo1[0], 10));
4287
4416
  ResultFormatter.departureAirport(results, otherInfo1[1]);
4288
4417
  } else {
4289
4418
  ResultFormatter.unknownArr(results, otherInfo1, " ");
4290
4419
  }
4291
- const otherInfo2 = fields[2].split(/\s+/);
4420
+ const otherInfo2 = fields[2].split(WS_REGEX);
4292
4421
  if (otherInfo2.length === 2) {
4293
4422
  ResultFormatter.arrivalAirport(results, otherInfo2[0]);
4294
4423
  ResultFormatter.tail(results, otherInfo2[1].replace(".", ""));
@@ -4300,7 +4429,7 @@ var Label_80 = class extends DecoderPlugin {
4300
4429
  }
4301
4430
  }
4302
4431
  parseTags(part, results) {
4303
- const kvPair = part.split(/\s+/);
4432
+ const kvPair = part.split(WS_REGEX);
4304
4433
  if (kvPair.length < 2) {
4305
4434
  ResultFormatter.unknown(results, part, "/");
4306
4435
  return;
@@ -4308,9 +4437,8 @@ var Label_80 = class extends DecoderPlugin {
4308
4437
  const tag = kvPair[0];
4309
4438
  const val = kvPair.slice(1).join(" ");
4310
4439
  switch (tag) {
4311
- case "POS":
4312
- const posRegex = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
4313
- const posResult = val.match(posRegex);
4440
+ case "POS": {
4441
+ const posResult = POS_REGEX.exec(val);
4314
4442
  const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.latd === "S" ? -1 : 1);
4315
4443
  const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
4316
4444
  const position = {
@@ -4319,6 +4447,7 @@ var Label_80 = class extends DecoderPlugin {
4319
4447
  };
4320
4448
  ResultFormatter.position(results, position);
4321
4449
  break;
4450
+ }
4322
4451
  case "ALT":
4323
4452
  ResultFormatter.altitude(results, parseInt(val.replace("+", ""), 10));
4324
4453
  break;
@@ -4351,10 +4480,11 @@ var Label_80 = class extends DecoderPlugin {
4351
4480
  DateTimeUtils.convertHHMMSSToTod(val)
4352
4481
  );
4353
4482
  break;
4354
- case "ETA":
4483
+ case "ETA": {
4355
4484
  const hhmm = val.split(".")[0].replace(":", "");
4356
4485
  ResultFormatter.eta(results, DateTimeUtils.convertHHMMSSToTod(hhmm));
4357
4486
  break;
4487
+ }
4358
4488
  case "HDG":
4359
4489
  ResultFormatter.heading(results, parseInt(val, 10));
4360
4490
  break;
@@ -4378,7 +4508,7 @@ var Label_80 = class extends DecoderPlugin {
4378
4508
  if (csvParts.length !== 9) {
4379
4509
  return;
4380
4510
  }
4381
- const header = csvParts[0].trim().split(/\s+/);
4511
+ const header = csvParts[0].trim().split(WS_REGEX);
4382
4512
  ResultFormatter.unknown(results, header[0], " ");
4383
4513
  ResultFormatter.unknown(results, header[1], " ");
4384
4514
  ResultFormatter.position(
@@ -4401,6 +4531,9 @@ var Label_80 = class extends DecoderPlugin {
4401
4531
  };
4402
4532
 
4403
4533
  // lib/plugins/Label_83.ts
4534
+ var WS_REGEX2 = /\s+/;
4535
+ var ALL_WS_REGEX = /\s/g;
4536
+ var ALL_DOTS_REGEX = /\./g;
4404
4537
  var Label_83 = class extends DecoderPlugin {
4405
4538
  name = "label-83";
4406
4539
  qualifiers() {
@@ -4415,8 +4548,8 @@ var Label_83 = class extends DecoderPlugin {
4415
4548
  decodeResult.formatted.description = "Airline Defined";
4416
4549
  decodeResult.decoded = true;
4417
4550
  const text = message.text;
4418
- if (text.substring(0, 10) === "4DH3 ETAT2") {
4419
- const fields = text.split(/\s+/);
4551
+ if (text.startsWith("4DH3 ETAT2")) {
4552
+ const fields = text.split(WS_REGEX2);
4420
4553
  if (fields[2].length > 5) {
4421
4554
  decodeResult.raw.day = fields[2].substring(5);
4422
4555
  }
@@ -4424,15 +4557,15 @@ var Label_83 = class extends DecoderPlugin {
4424
4557
  const subfields = fields[3].split("/");
4425
4558
  ResultFormatter.departureAirport(decodeResult, subfields[0]);
4426
4559
  ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
4427
- ResultFormatter.tail(decodeResult, fields[4].replace(/\./g, ""));
4560
+ ResultFormatter.tail(decodeResult, fields[4].replace(ALL_DOTS_REGEX, ""));
4428
4561
  ResultFormatter.eta(
4429
4562
  decodeResult,
4430
4563
  DateTimeUtils.convertHHMMSSToTod(fields[6] + "00")
4431
4564
  );
4432
- } else if (text.substring(0, 5) === "001PR") {
4565
+ } else if (text.startsWith("001PR")) {
4433
4566
  decodeResult.raw.day = text.substring(5, 7);
4434
4567
  const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
4435
- text.substring(13, 28).replace(/\./g, "")
4568
+ text.substring(13, 28).replace(ALL_DOTS_REGEX, "")
4436
4569
  );
4437
4570
  if (position) {
4438
4571
  ResultFormatter.position(decodeResult, position);
@@ -4440,15 +4573,15 @@ var Label_83 = class extends DecoderPlugin {
4440
4573
  ResultFormatter.altitude(decodeResult, Number(text.substring(28, 33)));
4441
4574
  ResultFormatter.unknown(decodeResult, text.substring(33));
4442
4575
  } else {
4443
- const fields = text.replace(/\s/g, "").split(",");
4576
+ const fields = text.replace(ALL_WS_REGEX, "").split(",");
4444
4577
  if (fields.length === 9) {
4445
4578
  ResultFormatter.departureAirport(decodeResult, fields[0]);
4446
4579
  ResultFormatter.arrivalAirport(decodeResult, fields[1]);
4447
4580
  decodeResult.raw.day = fields[2].substring(0, 2);
4448
4581
  decodeResult.raw.time = fields[2].substring(2);
4449
4582
  ResultFormatter.position(decodeResult, {
4450
- latitude: Number(fields[3].replace(/\s/g, "")),
4451
- longitude: Number(fields[4].replace(/\s/g, ""))
4583
+ latitude: Number(fields[3]),
4584
+ longitude: Number(fields[4])
4452
4585
  });
4453
4586
  ResultFormatter.altitude(decodeResult, Number(fields[5]));
4454
4587
  ResultFormatter.groundspeed(decodeResult, Number(fields[6]));
@@ -4512,13 +4645,15 @@ var Label_B6_Forwardslash = class extends DecoderPlugin {
4512
4645
  };
4513
4646
  }
4514
4647
  decode(message, options = {}) {
4515
- const decodeResult = this.defaultResult();
4516
- decodeResult.decoder.name = this.name;
4517
- decodeResult.formatted.description = "CPDLC Message";
4518
- decodeResult.message = message;
4519
- if (options.debug) {
4520
- console.log("CPDLC: " + message);
4648
+ const decodeResult = this.initResult(message, "CPDLC Message");
4649
+ const body = message.text.substring(1);
4650
+ if (body.length > 0) {
4651
+ ResultFormatter.text(decodeResult, body);
4652
+ this.setDecodeLevel(decodeResult, true, "partial");
4653
+ } else {
4654
+ this.setDecodeLevel(decodeResult, false);
4521
4655
  }
4656
+ this.debug(options, "CPDLC body:", body);
4522
4657
  return decodeResult;
4523
4658
  }
4524
4659
  };
@@ -4668,6 +4803,7 @@ var Label_H1_ATIS = class extends DecoderPlugin {
4668
4803
  const checksum = match[6];
4669
4804
  ResultFormatter.flightNumber(decodeResult, flight);
4670
4805
  ResultFormatter.arrivalAirport(decodeResult, facility);
4806
+ ResultFormatter.sequenceNumber(decodeResult, parseInt(seq, 10));
4671
4807
  decodeResult.raw.atis_code = code;
4672
4808
  decodeResult.formatted.items.push({
4673
4809
  type: "atis",
@@ -4877,9 +5013,39 @@ var Label_H1_M_POS = class extends DecoderPlugin {
4877
5013
  }
4878
5014
  };
4879
5015
 
5016
+ // lib/utils/compression.ts
5017
+ var pako = __toESM(require("pako"));
5018
+ function inflateData(data, raw) {
5019
+ const chunks = [];
5020
+ const inflator = new pako.Inflate({ windowBits: raw ? -15 : 15 });
5021
+ inflator.onData = (chunk) => {
5022
+ chunks.push(chunk);
5023
+ };
5024
+ inflator.push(data, 2);
5025
+ if (chunks.length === 0) return void 0;
5026
+ if (chunks.length === 1) return chunks[0];
5027
+ const totalLen = chunks.reduce((sum, c) => sum + c.length, 0);
5028
+ const result = new Uint8Array(totalLen);
5029
+ let offset = 0;
5030
+ for (const chunk of chunks) {
5031
+ result.set(chunk, offset);
5032
+ offset += chunk.length;
5033
+ }
5034
+ return result;
5035
+ }
5036
+ function base64ToUint8Array(base64) {
5037
+ const cleaned = base64.replace(/-/g, "+").replace(/_/g, "/").replace(/[^A-Za-z0-9+/]/g, "");
5038
+ const padded = cleaned + "=".repeat((4 - cleaned.length % 4) % 4);
5039
+ const binary = atob(padded);
5040
+ const bytes = new Uint8Array(binary.length);
5041
+ for (let i = 0; i < binary.length; i++) {
5042
+ bytes[i] = binary.charCodeAt(i);
5043
+ }
5044
+ return bytes;
5045
+ }
5046
+
4880
5047
  // lib/plugins/Label_H1_OHMA.ts
4881
- var zlib = __toESM(require("minizlib"));
4882
- var import_node_buffer = require("buffer");
5048
+ var textDecoder = new TextDecoder();
4883
5049
  var Label_H1_OHMA = class extends DecoderPlugin {
4884
5050
  name = "label-h1-ohma";
4885
5051
  qualifiers() {
@@ -4895,12 +5061,12 @@ var Label_H1_OHMA = class extends DecoderPlugin {
4895
5061
  decodeResult.message = message;
4896
5062
  const data = message.text.split("OHMA")[1];
4897
5063
  try {
4898
- const compressedBuffer = import_node_buffer.Buffer.from(data, "base64");
4899
- const decompress = new zlib.Inflate({});
4900
- decompress.write(compressedBuffer);
4901
- decompress.flush(zlib.constants.Z_SYNC_FLUSH);
4902
- const result = decompress.read();
4903
- const jsonText = result?.toString() || "";
5064
+ const compressedBuffer = base64ToUint8Array(data);
5065
+ const result = inflateData(compressedBuffer, false);
5066
+ if (!result || result.length === 0) {
5067
+ throw new Error("Decompression produced no output");
5068
+ }
5069
+ const jsonText = textDecoder.decode(result);
4904
5070
  let formattedMsg;
4905
5071
  let jsonMessage;
4906
5072
  try {
@@ -5305,10 +5471,47 @@ var Label_HX = class extends DecoderPlugin {
5305
5471
  }
5306
5472
  };
5307
5473
 
5474
+ // lib/utils/ascii85.ts
5475
+ function ascii85Decode(input) {
5476
+ let str = input;
5477
+ if (str.startsWith("<~")) str = str.slice(2);
5478
+ if (str.endsWith("~>")) str = str.slice(0, -2);
5479
+ str = str.replace(/\s/g, "");
5480
+ if (str.length === 0) return new Uint8Array(0);
5481
+ const output = [];
5482
+ let i = 0;
5483
+ while (i < str.length) {
5484
+ if (str[i] === "z") {
5485
+ output.push(0, 0, 0, 0);
5486
+ i++;
5487
+ continue;
5488
+ }
5489
+ const remaining = str.length - i;
5490
+ const chunkLen = Math.min(5, remaining);
5491
+ if (chunkLen === 1) break;
5492
+ let padded = str.slice(i, i + chunkLen);
5493
+ while (padded.length < 5) padded += "u";
5494
+ let value = 0;
5495
+ for (let j = 0; j < 5; j++) {
5496
+ const digit = padded.charCodeAt(j) - 33;
5497
+ if (digit < 0 || digit > 84) return null;
5498
+ value = value * 85 + digit;
5499
+ }
5500
+ if (chunkLen === 5 && value > 4294967295) return null;
5501
+ const v = value >>> 0;
5502
+ const numBytes = chunkLen === 5 ? 4 : chunkLen - 1;
5503
+ if (numBytes >= 1) output.push(v >>> 24 & 255);
5504
+ if (numBytes >= 2) output.push(v >>> 16 & 255);
5505
+ if (numBytes >= 3) output.push(v >>> 8 & 255);
5506
+ if (numBytes >= 4) output.push(v & 255);
5507
+ i += chunkLen;
5508
+ }
5509
+ return new Uint8Array(output);
5510
+ }
5511
+
5308
5512
  // lib/utils/miam.ts
5309
- var Base85 = __toESM(require("base85"));
5310
- var zlib2 = __toESM(require("minizlib"));
5311
- var import_node_buffer2 = require("buffer");
5513
+ var textDecoder2 = new TextDecoder();
5514
+ var textEncoder = new TextEncoder();
5312
5515
  var MIAMVersion = /* @__PURE__ */ ((MIAMVersion2) => {
5313
5516
  MIAMVersion2[MIAMVersion2["V1"] = 1] = "V1";
5314
5517
  MIAMVersion2[MIAMVersion2["V2"] = 2] = "V2";
@@ -5395,7 +5598,7 @@ var MIAMCoreUtils = class {
5395
5598
  error: "Empty MIAM message header"
5396
5599
  };
5397
5600
  }
5398
- let hdr = Base85.decode("<~" + rawHdr + "~>", "ascii85");
5601
+ let hdr = ascii85Decode("<~" + rawHdr + "~>");
5399
5602
  if (!hdr || hdr.length < hpad) {
5400
5603
  return {
5401
5604
  decoded: false,
@@ -5407,17 +5610,24 @@ var MIAMCoreUtils = class {
5407
5610
  if (rawBody.length > 0) {
5408
5611
  if ("0123".indexOf(bpad) >= 0) {
5409
5612
  const bpadValue = parseInt(bpad);
5410
- body = Base85.decode("<~" + rawBody + "~>", "ascii85") || void 0;
5411
- if (body && body.length >= bpadValue) {
5613
+ const decoded = ascii85Decode("<~" + rawBody + "~>");
5614
+ if (decoded === null) {
5615
+ return {
5616
+ decoded: false,
5617
+ error: "Ascii85 decode failed for MIAM message body"
5618
+ };
5619
+ }
5620
+ body = decoded;
5621
+ if (body.length >= bpadValue) {
5412
5622
  body = body.subarray(0, body.length - bpadValue);
5413
5623
  }
5414
5624
  } else if (bpad === "-") {
5415
- body = import_node_buffer2.Buffer.from(rawBody);
5625
+ body = textEncoder.encode(rawBody);
5416
5626
  }
5417
5627
  }
5418
5628
  hdr = hdr.subarray(0, hdr.length - hpad);
5419
- const version = hdr.readUInt8(0) & 15;
5420
- const pduType = hdr.readUInt8(0) >> 4 & 15;
5629
+ const version = hdr[0] & 15;
5630
+ const pduType = hdr[0] >> 4 & 15;
5421
5631
  if (isMIAMVersion(version) && isMIAMCorePdu(pduType)) {
5422
5632
  const versionPduHandler = this.VersionPduHandlerTable[version][pduType];
5423
5633
  return versionPduHandler(hdr, body);
@@ -5714,7 +5924,7 @@ var MIAMCoreUtils = class {
5714
5924
  ];
5715
5925
  let crc = (seed || 0) & 65535;
5716
5926
  for (let i = 0; i < buf.length; i++) {
5717
- crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 8 ^ buf.readUInt8(i)) >>> 0 & 255]) >>> 0;
5927
+ crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 8 ^ buf[i]) >>> 0 & 255]) >>> 0;
5718
5928
  }
5719
5929
  return crc & 65535;
5720
5930
  }
@@ -5979,7 +6189,7 @@ var MIAMCoreUtils = class {
5979
6189
  ];
5980
6190
  let crc = seed || 0;
5981
6191
  for (let i = 0; i < buf.length; i++) {
5982
- crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 24 ^ buf.readUInt8(i)) >>> 0]) >>> 0;
6192
+ crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 24 ^ buf[i]) >>> 0]) >>> 0;
5983
6193
  }
5984
6194
  return crc;
5985
6195
  }
@@ -6016,7 +6226,7 @@ var MIAMCoreUtils = class {
6016
6226
  let msgNum = 0;
6017
6227
  let ackOptions = 0;
6018
6228
  if (version === 1 /* V1 */) {
6019
- pduSize = hdr.readUInt8(1) << 16 | hdr.readUInt8(2) << 8 | hdr.readUInt8(3);
6229
+ pduSize = hdr[1] << 16 | hdr[2] << 8 | hdr[3];
6020
6230
  const msgSize = hdr.length + (body === void 0 ? 0 : body.length);
6021
6231
  if (pduSize > msgSize) {
6022
6232
  pduIsComplete = false;
@@ -6025,17 +6235,17 @@ var MIAMCoreUtils = class {
6025
6235
  );
6026
6236
  }
6027
6237
  hdr = hdr.subarray(4);
6028
- tail = hdr.subarray(0, 7).toString("ascii");
6238
+ tail = textDecoder2.decode(hdr.subarray(0, 7));
6029
6239
  hdr = hdr.subarray(7);
6030
6240
  } else if (version === 2 /* V2 */) {
6031
6241
  hdr = hdr.subarray(1);
6032
6242
  }
6033
- msgNum = hdr.readUInt8(0) >> 1 & 127;
6034
- ackOptions = hdr.readUInt8(0) & 1;
6243
+ msgNum = hdr[0] >> 1 & 127;
6244
+ ackOptions = hdr[0] & 1;
6035
6245
  hdr = hdr.subarray(1);
6036
- pduCompression = (hdr.readUInt8(0) << 2 | hdr.readUInt8(1) >> 6 & 3) & 7;
6037
- pduEncoding = hdr.readUInt8(1) >> 4 & 3;
6038
- pduAppType = hdr.readUInt8(1) & 15;
6246
+ pduCompression = (hdr[0] << 2 | hdr[1] >> 6 & 3) & 7;
6247
+ pduEncoding = hdr[1] >> 4 & 3;
6248
+ pduAppType = hdr[1] & 15;
6039
6249
  hdr = hdr.subarray(2);
6040
6250
  let appIdLen;
6041
6251
  if (isMIAMCoreApp(pduAppType)) {
@@ -6061,12 +6271,12 @@ var MIAMCoreUtils = class {
6061
6271
  error: "Header too short for v" + version + " appType: " + pduAppType
6062
6272
  };
6063
6273
  }
6064
- pduAppId = hdr.subarray(0, appIdLen).toString("ascii");
6274
+ pduAppId = textDecoder2.decode(hdr.subarray(0, appIdLen));
6065
6275
  hdr = hdr.subarray(appIdLen);
6066
6276
  if (crcLen === 4) {
6067
- pduCrc = hdr.readUInt8(0) << 24 | hdr.readUInt8(1) << 16 | hdr.readUInt8(2) << 8 | hdr.readUInt8(3);
6277
+ pduCrc = hdr[0] << 24 | hdr[1] << 16 | hdr[2] << 8 | hdr[3];
6068
6278
  } else if (crcLen === 2) {
6069
- pduCrc = hdr.readUInt8(0) << 8 | hdr.readUInt8(1);
6279
+ pduCrc = hdr[0] << 8 | hdr[1];
6070
6280
  }
6071
6281
  hdr = hdr.subarray(crcLen);
6072
6282
  if (body !== void 0 && body.length > 0) {
@@ -6074,10 +6284,12 @@ var MIAMCoreUtils = class {
6074
6284
  pduCompression
6075
6285
  ) >= 0) {
6076
6286
  try {
6077
- const decompress = new zlib2.InflateRaw({});
6078
- decompress.write(body);
6079
- decompress.flush(zlib2.constants.Z_SYNC_FLUSH);
6080
- pduData = decompress.read();
6287
+ const inflated = inflateData(body, true);
6288
+ if (inflated === void 0) {
6289
+ pduErrors.push("Inflation produced no output for body");
6290
+ } else {
6291
+ pduData = inflated;
6292
+ }
6081
6293
  } catch (e) {
6082
6294
  pduErrors.push("Inflation failed for body: " + e);
6083
6295
  }
@@ -6135,12 +6347,12 @@ var MIAMCoreUtils = class {
6135
6347
  label,
6136
6348
  ...sublabel ? { sublabel } : {},
6137
6349
  ...mfi ? { mfi } : {},
6138
- ...pduData ? { text: pduData.toString("ascii") } : {}
6350
+ ...pduData ? { text: textDecoder2.decode(pduData) } : {}
6139
6351
  };
6140
6352
  } else {
6141
6353
  pdu.non_acars = {
6142
6354
  appId: pduAppId,
6143
- ...pduData ? { text: pduData.toString("ascii") } : {}
6355
+ ...pduData ? { text: textDecoder2.decode(pduData) } : {}
6144
6356
  };
6145
6357
  }
6146
6358
  return {
@@ -6516,6 +6728,7 @@ var pluginClasses = [
6516
6728
  Label_13Through18_Slash,
6517
6729
  Label_15,
6518
6730
  Label_15_FST,
6731
+ Label_16_AUTPOS,
6519
6732
  Label_16_Honeywell,
6520
6733
  Label_16_N_Space,
6521
6734
  Label_16_POSA1,
@@ -6575,10 +6788,12 @@ var MessageDecoder = class {
6575
6788
  name;
6576
6789
  plugins;
6577
6790
  debug;
6578
- /** Maps a label string to the plugins registered for it, preserving registration order. */
6579
- labelIndex = /* @__PURE__ */ new Map();
6580
- /** Plugins that match all labels (qualifier label '*'). */
6581
- wildcardPlugins = [];
6791
+ /** Maps a label string to the candidate entries (wildcard + label-specific) in registration order. */
6792
+ candidatesByLabel = /* @__PURE__ */ new Map();
6793
+ /** Wildcard entries (plugins that register the '*' label). */
6794
+ wildcardEntries = [];
6795
+ /** Membership set for wildcard entries to dedupe when a plugin also registers a specific label. */
6796
+ wildcardSet = /* @__PURE__ */ new Set();
6582
6797
  constructor() {
6583
6798
  this.name = "acars-decoder-typescript";
6584
6799
  this.plugins = [];
@@ -6590,40 +6805,41 @@ var MessageDecoder = class {
6590
6805
  registerPlugin(plugin) {
6591
6806
  this.plugins.push(plugin);
6592
6807
  const qualifiers = plugin.qualifiers();
6808
+ const entry = {
6809
+ plugin,
6810
+ preambles: qualifiers.preambles && qualifiers.preambles.length > 0 ? qualifiers.preambles : void 0
6811
+ };
6593
6812
  for (const label of qualifiers.labels) {
6594
6813
  if (label === "*") {
6595
- this.wildcardPlugins.push(plugin);
6814
+ if (!this.wildcardSet.has(plugin)) {
6815
+ this.wildcardEntries.push(entry);
6816
+ this.wildcardSet.add(plugin);
6817
+ const wildcardInsertIndex = this.wildcardEntries.length - 1;
6818
+ for (const bucket of this.candidatesByLabel.values()) {
6819
+ bucket.splice(wildcardInsertIndex, 0, entry);
6820
+ }
6821
+ }
6596
6822
  } else {
6597
- let bucket = this.labelIndex.get(label);
6823
+ let bucket = this.candidatesByLabel.get(label);
6598
6824
  if (!bucket) {
6599
- bucket = [];
6600
- this.labelIndex.set(label, bucket);
6825
+ bucket = this.wildcardEntries.slice();
6826
+ this.candidatesByLabel.set(label, bucket);
6827
+ }
6828
+ if (!this.wildcardSet.has(plugin)) {
6829
+ bucket.push(entry);
6601
6830
  }
6602
- bucket.push(plugin);
6603
6831
  }
6604
6832
  }
6605
6833
  return true;
6606
6834
  }
6607
6835
  decode(message, options = {}) {
6608
- const labelPlugins = this.labelIndex.get(message.label) ?? [];
6609
- const seen = /* @__PURE__ */ new Set();
6610
- const candidates = [];
6611
- for (const plugin of [...this.wildcardPlugins, ...labelPlugins]) {
6612
- if (!seen.has(plugin)) {
6613
- seen.add(plugin);
6614
- candidates.push(plugin);
6615
- }
6616
- }
6617
- const usablePlugins = candidates.filter((plugin) => {
6618
- const preambles = plugin.qualifiers().preambles;
6619
- if (!preambles || preambles.length === 0) {
6620
- return true;
6621
- }
6622
- return preambles.some((p) => message.text.startsWith(p));
6623
- });
6836
+ const text = message.text;
6837
+ const candidates = this.candidatesByLabel.get(message.label) ?? this.wildcardEntries;
6624
6838
  if (options.debug) {
6625
6839
  console.log("Usable plugins");
6626
- console.log(usablePlugins);
6840
+ console.log(
6841
+ candidates.filter((e) => this.matchesPreambles(text, e.preambles)).map((e) => e.plugin)
6842
+ );
6627
6843
  }
6628
6844
  let result = {
6629
6845
  decoded: false,
@@ -6635,7 +6851,7 @@ var MessageDecoder = class {
6635
6851
  },
6636
6852
  message,
6637
6853
  remaining: {
6638
- text: message.text
6854
+ text
6639
6855
  },
6640
6856
  raw: {},
6641
6857
  formatted: {
@@ -6643,10 +6859,14 @@ var MessageDecoder = class {
6643
6859
  items: []
6644
6860
  }
6645
6861
  };
6646
- for (let i = 0; i < usablePlugins.length; i++) {
6647
- const plugin = usablePlugins[i];
6648
- result = plugin.decode(message, options);
6649
- if (result.decoded) {
6862
+ for (let i = 0; i < candidates.length; i++) {
6863
+ const entry = candidates[i];
6864
+ if (!this.matchesPreambles(text, entry.preambles)) {
6865
+ continue;
6866
+ }
6867
+ const pluginResult = entry.plugin.decode(message, options);
6868
+ if (pluginResult.decoded) {
6869
+ result = pluginResult;
6650
6870
  break;
6651
6871
  }
6652
6872
  }
@@ -6656,6 +6876,17 @@ var MessageDecoder = class {
6656
6876
  }
6657
6877
  return result;
6658
6878
  }
6879
+ matchesPreambles(text, preambles) {
6880
+ if (!preambles) {
6881
+ return true;
6882
+ }
6883
+ for (let i = 0; i < preambles.length; i++) {
6884
+ if (text.startsWith(preambles[i])) {
6885
+ return true;
6886
+ }
6887
+ }
6888
+ return false;
6889
+ }
6659
6890
  };
6660
6891
  // Annotate the CommonJS export names for ESM import in node:
6661
6892
  0 && (module.exports = {