serverless-offline-msk
Version:
A serverless offline plugin that enables AWS MSK events
235 lines (212 loc) • 5.67 kB
JavaScript
/* eslint-disable max-lines */
// format string parser
;
var aFrom = require("es5-ext/array/from")
, ensureString = require("es5-ext/object/validate-stringifiable-value")
, primitiveSet = require("es5-ext/object/primitive-set")
, typeChars = require("./lib/type-chars");
var digitChars = primitiveSet.apply(null, aFrom("0123456789"))
, flagChars = primitiveSet.apply(null, aFrom("#0-+ 'I"))
, lengthChars = primitiveSet.apply(null, aFrom("hlLzjt"));
var formatString, char, index, state, literalStart, literals, placeholders
, afterEscapeLiteralIndexes;
var literalEnd, placeholder, currentTokenStart;
var states = {
literal: function () {
if (char === "%") {
literalEnd = index;
placeholder = {};
state = "parameterStart";
}
++index;
},
parameterStart: function () {
if (hasOwnProperty.call(digitChars, char)) {
if (char === "0") {
state = "flagsStart";
} else {
currentTokenStart = index;
++index;
state = "parameter";
}
} else if (char === "%") {
afterEscapeLiteralIndexes.push(
literals.push(formatString.slice(literalStart, literalEnd) + "%")
);
literalStart = ++index;
state = "literal";
} else {
state = "flagsStart";
}
},
parameter: function () {
if (hasOwnProperty.call(digitChars, char)) {
++index;
} else if (char === "$") {
placeholder.parameter = Number(formatString.slice(currentTokenStart, index));
++index;
state = "flagsStart";
} else {
index = currentTokenStart;
state = "widthStart";
}
},
flagsStart: function () {
if (hasOwnProperty.call(flagChars, char)) {
currentTokenStart = index;
++index;
state = "flags";
} else {
state = "widthStart";
}
},
flags: function () {
if (hasOwnProperty.call(flagChars, char)) {
++index;
} else {
placeholder.flags = formatString.slice(currentTokenStart, index);
state = "widthStart";
}
},
widthStart: function () {
if (char === "*") {
++index;
if (placeholder.parameter) {
// Invalid configuration
state = "literal";
} else {
placeholder.width = char;
state = "precisionStart";
}
} else if (hasOwnProperty.call(digitChars, char)) {
currentTokenStart = index;
++index;
state = "width";
} else {
state = "precisionStart";
}
},
width: function () {
if (hasOwnProperty.call(digitChars, char)) {
++index;
} else {
placeholder.width = Number(formatString.slice(currentTokenStart, index));
state = "precisionStart";
}
},
precisionStart: function () {
if (char === ".") {
++index;
state = "precisionValueStart";
} else {
state = "lengthStart";
}
},
precisionValueStart: function () {
if (char === "*") {
++index;
if (placeholder.parameter) {
// Invalid configuration
state = "literal";
} else {
placeholder.precision = char;
state = "lengthStart";
}
} else if (hasOwnProperty.call(digitChars, char)) {
currentTokenStart = index;
++index;
state = "precision";
} else {
state = "literal";
}
},
precision: function () {
if (hasOwnProperty.call(digitChars, char)) {
++index;
} else {
placeholder.precision = Number(formatString.slice(currentTokenStart, index));
state = "lengthStart";
}
},
lengthStart: function () {
if (
hasOwnProperty.call(lengthChars, char) &&
hasOwnProperty.call(typeChars, formatString[index + 1])
) {
++index;
placeholder.length = char;
state = "length";
} else {
state = "type";
}
},
length: function () {
if (
((placeholder.length === "h" && char === "h") ||
(placeholder.length === "l" && char === "l")) &&
hasOwnProperty.call(typeChars, formatString[index + 1])
) {
++index;
placeholder.length += char;
}
state = "type";
},
type: function () {
if (hasOwnProperty.call(typeChars, char)) {
placeholder.type = char;
literals.push(formatString.slice(literalStart, literalEnd));
literalStart = ++index;
placeholder.content = formatString.slice(literalEnd, index);
placeholders.push(placeholder);
}
state = "literal";
}
};
var checkParameterIndexing = function () {
var placeholderParameters = [];
placeholders.forEach(function (placeholderItem) {
if (placeholderItem.parameter) placeholderParameters.push(placeholderItem.parameter);
});
if (!placeholderParameters.length) return true;
if (placeholderParameters.length !== placeholders.length) return false;
var currentParameter = 0;
return placeholderParameters
.sort(function (parameter1, parameter2) { return parameter1 - parameter2; })
.every(function (parameter) {
if (parameter !== currentParameter && parameter !== currentParameter + 1) return false;
currentParameter = parameter;
return true;
});
};
module.exports = function (input) {
formatString = ensureString(input);
state = "literal";
index = 0;
literalStart = 0;
literals = [];
placeholders = [];
afterEscapeLiteralIndexes = [];
var length = input.length;
// eslint-disable-next-line no-unmodified-loop-condition
while (index < length) {
char = input[index];
states[state]();
}
literals.push(formatString.slice(literalStart, length));
if (afterEscapeLiteralIndexes.length) {
for (
var i = afterEscapeLiteralIndexes.length - 1, literalIndex;
(literalIndex = afterEscapeLiteralIndexes[i]);
--i
) {
literals[literalIndex - 1] += literals[literalIndex];
delete literals[literalIndex];
}
literals = literals.filter(function (literal) { return typeof literal === "string"; });
}
return {
literals: literals,
placeholders: placeholders,
isParameterIndexingValid: checkParameterIndexing(placeholders)
};
};