diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json
index 2c716d31..6f02abb8 100755
--- a/src/core/config/Categories.json
+++ b/src/core/config/Categories.json
@@ -54,7 +54,7 @@
"From MessagePack",
"To Braille",
"From Braille",
- "LV Decode"
+ "Parse TLV"
]
},
{
diff --git a/src/core/lib/LengthValue.mjs b/src/core/lib/TLVParser.mjs
similarity index 74%
rename from src/core/lib/LengthValue.mjs
rename to src/core/lib/TLVParser.mjs
index 3ec0c5e5..9e9395ff 100644
--- a/src/core/lib/LengthValue.mjs
+++ b/src/core/lib/TLVParser.mjs
@@ -1,5 +1,8 @@
/**
+ * Parser for Type-length-value data.
+ *
* @author gchq77703 []
+ * @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
@@ -11,12 +14,15 @@ const defaults = {
};
/**
- * Length Value library
+ * TLVParser library
*/
-export default class LengthValue {
+export default class TLVParser {
/**
- * LengthValue constructor
+ * TLVParser constructor
+ *
+ * @param {byteArray} input
+ * @param {Object} options
*/
constructor(input, options) {
this.input = input;
@@ -24,7 +30,7 @@ export default class LengthValue {
}
/**
- * @returns {Number}
+ * @returns {number}
*/
getLength() {
if (this.basicEncodingRules) {
@@ -48,13 +54,14 @@ export default class LengthValue {
}
/**
- * @param {Number} length
- * @returns {Number[]}
+ * @param {number} length
+ * @returns {number[]}
*/
getValue(length) {
const value = [];
for (let i = 0; i < length; i++) {
+ if (this.location > this.input.length) return value;
value.push(this.input[this.location]);
this.location++;
}
@@ -63,7 +70,7 @@ export default class LengthValue {
}
/**
- * @returns {Boolean}
+ * @returns {boolean}
*/
atEnd() {
return this.input.length <= this.location;
diff --git a/src/core/operations/LVDecode.mjs b/src/core/operations/LVDecode.mjs
deleted file mode 100644
index 63af65f6..00000000
--- a/src/core/operations/LVDecode.mjs
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * @author gchq77703 []
- * @copyright Crown Copyright 2018
- * @license Apache-2.0
- */
-
-import Operation from "../Operation";
-import LengthValue from "../lib/LengthValue";
-
-/**
- * From LV Decode operation
- */
-class LVDecode extends Operation {
-
- /**
- * LVDecode constructor
- */
- constructor() {
- super();
-
- this.name = "LV Decode";
- this.module = "Default";
- this.description = "Converts a Length-Value (LV) encoded string into a JSON object. Can optionally include a Key
/ Type
entry.";
- this.infoURL = "https://wikipedia.org/wiki/KLV";
- this.inputType = "byteArray";
- this.outputType = "JSON";
- this.args = [
- {
- name: "Bytes in Key Value",
- type: "option",
- value: [
- "0 Bytes (No Key)",
- "1 Byte",
- "2 Bytes",
- "4 Bytes"
- ]
- },
- {
- name: "Bytes in Length Value",
- type: "option",
- value: [
- "1 Byte",
- "2 Bytes",
- "4 Bytes"
- ]
- },
- {
- name: "Use Basic Encoding Rules",
- type: "boolean"
- }
- ];
- }
-
- /**
- * @param {byteArray} input
- * @param {Object[]} args
- * @returns {string}
- */
- run(input, args) {
- const bytesInKey = parseInt(args[0].split(" ")[0], 10);
- const bytesInLength = parseInt(args[1].split(" ")[0], 10);
- const basicEncodingRules = args[2];
-
- const lv = new LengthValue(input, { bytesInLength, basicEncodingRules });
-
- const data = [];
-
- while (!lv.atEnd()) {
- const key = bytesInKey ? lv.getValue(bytesInKey) : undefined;
- const length = lv.getLength();
- const value = lv.getValue(length);
-
- data.push({ key, length, value });
- }
-
- return data;
- }
-
-}
-
-export default LVDecode;
diff --git a/src/core/operations/ParseTLV.mjs b/src/core/operations/ParseTLV.mjs
new file mode 100644
index 00000000..a87144a8
--- /dev/null
+++ b/src/core/operations/ParseTLV.mjs
@@ -0,0 +1,76 @@
+/**
+ * @author gchq77703 []
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import TLVParser from "../lib/TLVParser";
+import OperationError from "../errors/OperationError";
+
+/**
+ * Parse TLV operation
+ */
+class ParseTLV extends Operation {
+
+ /**
+ * ParseTLV constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Parse TLV";
+ this.module = "Default";
+ this.description = "Converts a Type-Length-Value (TLV) encoded string into a JSON object. Can optionally include a Key
/ Type
entry.
Tags: Key-Length-Value, KLV, Length-Value, LV";
+ this.infoURL = "https://wikipedia.org/wiki/Type-length-value";
+ this.inputType = "byteArray";
+ this.outputType = "JSON";
+ this.args = [
+ {
+ name: "Type/Key size",
+ type: "number",
+ value: 1
+ },
+ {
+ name: "Length size",
+ type: "number",
+ value: 1
+ },
+ {
+ name: "Use BER",
+ type: "boolean",
+ value: false
+ }
+ ];
+ }
+
+ /**
+ * @param {byteArray} input
+ * @param {Object[]} args
+ * @returns {string}
+ */
+ run(input, args) {
+ const [bytesInKey, bytesInLength, basicEncodingRules] = args;
+
+ if (bytesInKey <= 0 && bytesInLength <= 0)
+ throw new OperationError("Type or Length size must be greater than 0");
+
+ const tlv = new TLVParser(input, { bytesInLength, basicEncodingRules });
+
+ const data = [];
+
+ while (!tlv.atEnd()) {
+ const key = bytesInKey ? tlv.getValue(bytesInKey) : undefined;
+ const length = tlv.getLength();
+ const value = tlv.getValue(length);
+
+ data.push({ key, length, value });
+ }
+
+ return data;
+ }
+
+}
+
+export default ParseTLV;
diff --git a/test/index.mjs b/test/index.mjs
index 89f4c44e..9bb93a60 100644
--- a/test/index.mjs
+++ b/test/index.mjs
@@ -71,7 +71,7 @@ import "./tests/operations/SymmetricDifference";
import "./tests/operations/ToGeohash.mjs";
import "./tests/operations/TranslateDateTimeFormat";
import "./tests/operations/Magic";
-import "./tests/operations/LVDecode";
+import "./tests/operations/ParseTLV";
let allTestsPassing = true;
const testStatusCounts = {
diff --git a/test/tests/operations/LVDecode.mjs b/test/tests/operations/LVDecode.mjs
deleted file mode 100644
index 4fd7fc83..00000000
--- a/test/tests/operations/LVDecode.mjs
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * LV Decoder tests.
- *
- * @author gchq77703 []
- * @copyright Crown Copyright 2018
- * @license Apache-2.0
- */
-
-import TestRegister from "../../TestRegister";
-
-TestRegister.addTests([
- {
- name: "LVDecode: LengthValue",
- input: "\x05\x48\x6f\x75\x73\x65\x04\x72\x6f\x6f\x6d\x04\x64\x6f\x6f\x72",
- expectedOutput: JSON.stringify([{"length": 5, "value": [72, 111, 117, 115, 101]}, {"length": 4, "value": [114, 111, 111, 109]}, {"length": 4, "value": [100, 111, 111, 114]}]),
- recipeConfig: [
- {
- "op": "LV Decode",
- "args": ["0 Bytes (No Key)", "1 Byte", false]
- }
- ]
- },
- {
- name: "LVDecode: LengthValue with BER",
- input: "\x05\x48\x6f\x75\x73\x65\x04\x72\x6f\x6f\x6d\x04\x64\x6f\x6f\x72",
- expectedOutput: JSON.stringify([{"length": 5, "value": [72, 111, 117, 115, 101]}, {"length": 4, "value": [114, 111, 111, 109]}, {"length": 4, "value": [100, 111, 111, 114]}]),
- recipeConfig: [
- {
- "op": "LV Decode",
- "args": ["0 Bytes (No Key)", "4 Bytes", false] // length value is patently wrong, should be ignored by BER.
- }
- ]
- },
- {
- name: "LVDecode: KeyLengthValue",
- input: "\x04\x05\x48\x6f\x75\x73\x65\x05\x04\x72\x6f\x6f\x6d\x42\x04\x64\x6f\x6f\x72",
- expectedOutput: JSON.stringify([{"key":[4],"length":5,"value":[72,111,117,115,101]},{"key":[5],"length":4,"value":[114,111,111,109]},{"key":[66],"length":4,"value":[100,111,111,114]}]),
- recipeConfig: [
- {
- "op": "LV Decode",
- "args": ["1 Byte", "1 Byte", false]
- }
- ]
- },
- {
- name: "LVDecode: KeyLengthValue with BER",
- input: "\x04\x05\x48\x6f\x75\x73\x65\x05\x04\x72\x6f\x6f\x6d\x42\x04\x64\x6f\x6f\x72",
- expectedOutput: JSON.stringify([{"key":[4],"length":5,"value":[72,111,117,115,101]},{"key":[5],"length":4,"value":[114,111,111,109]},{"key":[66],"length":4,"value":[100,111,111,114]}]),
- recipeConfig: [
- {
- "op": "LV Decode",
- "args": ["1 Byte", "4 Byte", true] // length value is patently wrong, should be ignored by BER.
- }
- ]
- }
-]);
diff --git a/test/tests/operations/ParseTLV.mjs b/test/tests/operations/ParseTLV.mjs
new file mode 100644
index 00000000..43cc02d7
--- /dev/null
+++ b/test/tests/operations/ParseTLV.mjs
@@ -0,0 +1,56 @@
+/**
+ * Parse TLV tests.
+ *
+ * @author gchq77703 []
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import TestRegister from "../../TestRegister";
+
+TestRegister.addTests([
+ {
+ name: "Parse TLV: LengthValue",
+ input: "\x05\x48\x6f\x75\x73\x65\x04\x72\x6f\x6f\x6d\x04\x64\x6f\x6f\x72",
+ expectedOutput: JSON.stringify([{"length": 5, "value": [72, 111, 117, 115, 101]}, {"length": 4, "value": [114, 111, 111, 109]}, {"length": 4, "value": [100, 111, 111, 114]}], null, 4),
+ recipeConfig: [
+ {
+ "op": "Parse TLV",
+ "args": [0, 1, false]
+ }
+ ]
+ },
+ {
+ name: "Parse TLV: LengthValue with BER",
+ input: "\x05\x48\x6f\x75\x73\x65\x04\x72\x6f\x6f\x6d\x04\x64\x6f\x6f\x72",
+ expectedOutput: JSON.stringify([{"length": 5, "value": [72, 111, 117, 115, 101]}, {"length": 4, "value": [114, 111, 111, 109]}, {"length": 4, "value": [100, 111, 111, 114]}], null, 4),
+ recipeConfig: [
+ {
+ "op": "Parse TLV",
+ "args": [0, 4, true] // length value is patently wrong, should be ignored by BER.
+ }
+ ]
+ },
+ {
+ name: "Parse TLV: KeyLengthValue",
+ input: "\x04\x05\x48\x6f\x75\x73\x65\x05\x04\x72\x6f\x6f\x6d\x42\x04\x64\x6f\x6f\x72",
+ expectedOutput: JSON.stringify([{"key": [4], "length": 5, "value": [72, 111, 117, 115, 101]}, {"key": [5], "length": 4, "value": [114, 111, 111, 109]}, {"key": [66], "length": 4, "value": [100, 111, 111, 114]}], null, 4),
+ recipeConfig: [
+ {
+ "op": "Parse TLV",
+ "args": [1, 1, false]
+ }
+ ]
+ },
+ {
+ name: "Parse TLV: KeyLengthValue with BER",
+ input: "\x04\x05\x48\x6f\x75\x73\x65\x05\x04\x72\x6f\x6f\x6d\x42\x04\x64\x6f\x6f\x72",
+ expectedOutput: JSON.stringify([{"key": [4], "length": 5, "value": [72, 111, 117, 115, 101]}, {"key": [5], "length": 4, "value": [114, 111, 111, 109]}, {"key": [66], "length": 4, "value": [100, 111, 111, 114]}], null, 4),
+ recipeConfig: [
+ {
+ "op": "Parse TLV",
+ "args": [1, 4, true] // length value is patently wrong, should be ignored by BER.
+ }
+ ]
+ }
+]);