UNPKG

ais-web

Version:

Compact AIS decoder in TypeScript for browser and web apps

90 lines (89 loc) 3.28 kB
"use strict"; // bitUtils.ts /** * Utility functions for AIS bitfield encoding and decoding. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.encodeBitField = encodeBitField; exports.to6BitAscii = to6BitAscii; exports.from6BitAscii = from6BitAscii; exports.parseBitField = parseBitField; const AIS_6BIT_CHAR_CODES = { '@': 0, 'A': 1, 'B': 2, 'C': 3, 'D': 4, 'E': 5, 'F': 6, 'G': 7, 'H': 8, 'I': 9, 'J': 10, 'K': 11, 'L': 12, 'M': 13, 'N': 14, 'O': 15, 'P': 16, 'Q': 17, 'R': 18, 'S': 19, 'T': 20, 'U': 21, 'V': 22, 'W': 23, 'X': 24, 'Y': 25, 'Z': 26, '[': 27, '\\': 28, ']': 29, '^': 30, '_': 31, ' ': 32, '!': 33, '"': 34, '#': 35, '$': 36, '%': 37, '&': 38, '\'': 39, '(': 40, ')': 41, '*': 42, '+': 43, ',': 44, '-': 45, '.': 46, '/': 47, '0': 48, '1': 49, '2': 50, '3': 51, '4': 52, '5': 53, '6': 54, '7': 55, '8': 56, '9': 57, ':': 58, ';': 59, '<': 60, '=': 61, '>': 62, '?': 63, }; function encodeBitField(fields) { var _a; let bits = ''; for (const field of fields) { if (field.ascii) { // Ensure uppercase and pad with '@' (code 0) to required length in characters let str = String(field.value).toUpperCase().padEnd(field.length / 6, '@'); for (const ch of str) { const code = (_a = AIS_6BIT_CHAR_CODES[ch]) !== null && _a !== void 0 ? _a : 0; // fallback to '@' if unknown bits += code.toString(2).padStart(6, '0'); } } else { let val = Number(field.value); if (field.signed) { const max = 1 << (field.length - 1); if (val < 0) val = (1 << field.length) + val; else if (val >= max) val = max - 1; } bits += val.toString(2).padStart(field.length, '0'); } } return bits; } function to6BitAscii(bits) { const chunks = bits.match(/.{1,6}/g) || []; return chunks.map(b => { const val = parseInt(b.padEnd(6, '0'), 2); return String.fromCharCode(val + 48 + (val > 39 ? 8 : 0)); }).join(''); } function from6BitAscii(payload, fillBits) { let bits = ''; for (const ch of payload) { const val = ch.charCodeAt(0); let sixbit = val - 48; if (sixbit > 39) sixbit -= 8; bits += sixbit.toString(2).padStart(6, '0'); } return bits.slice(0, bits.length - fillBits); } function parseBitField(bits, fields) { const result = {}; for (const field of fields) { const segment = bits.slice(field.start, field.start + field.length); if (field.ascii) { let str = ''; for (let i = 0; i < segment.length; i += 6) { const val = parseInt(segment.slice(i, i + 6), 2); str += String.fromCharCode(val + 64); } result[field.key] = str.trim().replace(/@+$/, ''); } else { let val = parseInt(segment, 2); if (field.signed) { const max = 1 << (field.length - 1); if (val >= max) val -= (1 << field.length); } result[field.key] = val; } } return result; }