UNPKG

open-epsilon

Version:

empty-epsilon / open-sound-control bidirectional proxy

135 lines 7.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageTranslator = void 0; const empty_epsilon_js_1 = require("empty-epsilon-js"); const ee_schema_1 = require("./ee-schema"); const naming = require("naming"); function translatePrimitiveType(pt) { return pt.charAt(0); } function translateType(pt) { return pt instanceof Array ? pt.map(translatePrimitiveType).join('') : translatePrimitiveType(pt); } function enumAddresItemToArgument(addressItem, enumObj, enumName) { const name = naming(addressItem, 'pascal'); if (typeof enumObj[name] === 'undefined') { throw new Error(`bad ${enumName} name ${name}`); } return '"' + name + '"'; } function addressItemToArgument(addressItem, argumentSchema) { switch (argumentSchema) { case "float": return Number.parseFloat(addressItem).toFixed(2); case "integer": case "bool": return addressItem; case "ESystem": return enumAddresItemToArgument(addressItem, empty_epsilon_js_1.ESystem, "ESystem"); case "EMissileWeapons": return enumAddresItemToArgument(addressItem, empty_epsilon_js_1.EMissileWeapons, "EMissileWeapons"); default: throw new Error(`unknown type: ${argumentSchema}`); } } function addressArrToArguments(addressParts, argumentsSchema) { return argumentsSchema.map((t, i) => addressItemToArgument(addressParts[i], t)); } class MessageTranslator { constructor(apiModel, namespace) { this.apiModel = apiModel; this.namespace = namespace; this.translateOscMessageToGameCommand = (message) => { const addressArr = message.address.split('/'); const oscArgs = message.args instanceof Array ? message.args : [message.args]; const vals = addressArr.concat(oscArgs.map(arg => '' + (arg.value == undefined ? arg : arg.value))); // console.info(`handling command: ${vals.join('/')}`); this.assertNamespaceAddress(addressArr); let addrIdx = 2; let path = []; let currentType = this.apiModel.global; while (addrIdx < addressArr.length) { if (ee_schema_1.isPrimitiveOrArrayOfPrimitiveType(currentType)) { throw new Error(`reached a primitive result ${currentType} before address is finished ${message.address}`); } else { const symbolName = addressArr[addrIdx++]; const symbol = currentType[symbolName]; if (symbol) { // the +1 makes us not use getters that exhaust the entire address. the last part needs to be a setter. if (symbol && symbol.get && addrIdx < addressArr.length - symbol.get.arguments.length) { currentType = symbol.get.type; const lastArdIdx = addrIdx + symbol.get.arguments.length; path.push(`${symbol.get.methodName}(${addressArrToArguments(addressArr.slice(addrIdx, lastArdIdx), symbol.get.arguments).join(',')})`); addrIdx = lastArdIdx; } else if (symbol && symbol.set && addrIdx <= vals.length - symbol.set.arguments.length) { // last one is a setter, its arguments are taken from the vals array const lastArdIdx = addrIdx + symbol.set.arguments.length; path.push(symbol.set.methodName); const setter = path.join(':'); const values = addressArrToArguments(vals.slice(addrIdx, lastArdIdx), symbol.set.arguments); const numOfStaticValues = addressArr.length - addrIdx; return { template: `${setter}(${values.map((v, idx) => idx >= numOfStaticValues ? `{${idx - numOfStaticValues}}` : v).join(', ')})`, values: values.slice(numOfStaticValues) }; } else { throw new Error(`reached a symbol with no matching methods '${symbolName}' in ${vals}`); } } else { throw new Error(`reached an unknown symbol '${symbolName}' in ${message.address}`); } } } throw new Error(`reached a non-primitive result ${currentType} but address is finished ${message.address}`); }; this.translateAddressToGameQuery = (address) => { const addressArr = address.split('/'); this.assertNamespaceAddress(addressArr); let addrIdx = 2; let path = []; let currentType = this.apiModel.global; while (addrIdx < addressArr.length) { if (ee_schema_1.isPrimitiveOrArrayOfPrimitiveType(currentType)) { throw new Error(`reached a primitive result ${currentType} before address is finished ${address}`); } else { const symbolName = addressArr[addrIdx++]; const symbol = currentType[symbolName]; if (symbol && symbol.get && addrIdx <= addressArr.length - symbol.get.arguments.length) { currentType = symbol.get.type; const lastArdIdx = addrIdx + symbol.get.arguments.length; path.push(`${symbol.get.methodName}(${addressArrToArguments(addressArr.slice(addrIdx, lastArdIdx), symbol.get.arguments).join(',')})`); addrIdx = lastArdIdx; } else { throw new Error(`reached an unknown symbol '${symbolName}' in ${address}`); } } } if (ee_schema_1.isPrimitiveOrArrayOfPrimitiveType(currentType)) { return { address: address, expr: path.join(':'), type: translateType(currentType) }; } else { throw new Error(`reached a non-primitive result ${currentType} but address is finished ${address}`); } }; if (~namespace.indexOf('/')) { throw new Error(`namespace '${namespace}' contains address delimiter '/'`); } } assertNamespaceAddress(addressArr) { // assert address begins with namespace if (addressArr[0] !== '' || addressArr[1] !== this.namespace) { throw new Error(`ilegal address prefix ${addressArr.join('/')}`); } } } exports.MessageTranslator = MessageTranslator; //# sourceMappingURL=translate.js.map