From f525cf6bff0ead31f671268b64882d0a8eef465b Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 12 Feb 2024 11:32:48 +1100 Subject: [PATCH 01/19] Add `index` property and `getPacketByIndex` --- nbsdecoder.d.ts | 27 ++++++++++++++++++++ src/Decoder.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ src/Decoder.hpp | 6 +++++ src/Index.hpp | 13 ++++++++++ 4 files changed, 114 insertions(+) diff --git a/nbsdecoder.d.ts b/nbsdecoder.d.ts index 4cc186c..0282a9d 100644 --- a/nbsdecoder.d.ts +++ b/nbsdecoder.d.ts @@ -61,6 +61,14 @@ export interface NbsTypeSubtypeBuffer extends NbsTypeSubtype { type: Buffer; } +/** + * The valid timestamps for a type subtype + */ +export interface TypeIndex { + typeSubType: NbsTypeSubtype; + timestamps: NbsTimestamp[]; +} + /** * A decoder that can be used to read packets from NBS files */ @@ -73,6 +81,13 @@ export declare class NbsDecoder { */ public constructor(paths: string[]); + /** + * The index data of this decoder. + * + * Contains the a list of packet timestamps for each typeSubType in the loaded nbs files. + */ + public readonly index: TypeIndex[]; + /** Get a list of all the types present in the loaded nbs files */ public getAvailableTypes(): NbsTypeSubtypeBuffer[]; @@ -114,6 +129,18 @@ export declare class NbsDecoder { types: NbsTypeSubtype[] ): NbsPacket[]; + /** + * Get the packet of the given type at the given index in the loaded nbs file. + * + * Returns either the packet at the index with the given type, or `undefined` if the given + * index is outside the range of packets for the type. Use `.index` to check the number + * of packets of each type. + * + * @param index The index of the requested packet + * @param type The type of the requested packet + */ + public getPacketByIndex(index: number, type: NbsTypeSubtype): NbsPacket | undefined; + /** * Get the timestamp to seek to such that all messages of the given types are stepped by (n) steps * diff --git a/src/Decoder.cpp b/src/Decoder.cpp index b4b8704..c01d671 100755 --- a/src/Decoder.cpp +++ b/src/Decoder.cpp @@ -25,9 +25,12 @@ namespace nbs { napi_property_attributes(napi_writable | napi_configurable)), InstanceMethod<&Decoder::GetPackets>("getPackets", napi_property_attributes(napi_writable | napi_configurable)), + InstanceMethod<&Decoder::GetPacketByIndex>("getPacketByIndex", + napi_property_attributes(napi_writable | napi_configurable)), InstanceMethod<&Decoder::NextTimestamp>("nextTimestamp", napi_property_attributes(napi_writable | napi_configurable)), InstanceMethod<&Decoder::Close>("close", napi_property_attributes(napi_writable | napi_configurable)), + InstanceAccessor<&Decoder::GetIndices>("index"), }); Napi::FunctionReference* constructor = new Napi::FunctionReference(); @@ -106,6 +109,39 @@ namespace nbs { } } + Napi::Value Decoder::GetIndices(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + + auto type_iterators = this->index.getAllTypeIterators(); + auto indices = Napi::Array::New(env, type_iterators.size()); + + uint index = 0; + + for (const auto& [typeSubtype, iterators] : type_iterators) { + + auto typeIndices = Napi::Object::New(env); + + auto jsType = Napi::Object::New(env); + jsType.Set("type", hash::ToJsValue(typeSubtype.type, env)); + jsType.Set("subtype", Napi::Number::New(env, typeSubtype.subtype)); + + auto timestamps = Napi::Array::New(env, std::distance(iterators.first, iterators.second)); + + uint timestampIndex = 0; + for (auto it = iterators.first; it != iterators.second; it++) { + auto index = *it; + timestamps[timestampIndex++] = timestamp::ToJsValue(index.item.timestamp, env); + } + + typeIndices.Set("typeSubType", jsType); + typeIndices.Set("timestamps", timestamps); + + indices[index++] = typeIndices; + } + + return indices; + } + Napi::Value Decoder::GetAvailableTypes(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); @@ -278,6 +314,38 @@ namespace nbs { return jsPackets; } + Napi::Value Decoder::GetPacketByIndex(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + + uint64_t index = 0; + auto jsIndex = info[0]; + if (jsIndex.IsNumber()) { + index = jsIndex.As().Int64Value(); + } else { + Napi::TypeError::New(env, "expected positive number for `index`"); + return env.Undefined(); + } + + TypeSubtype type; + try { + type = this->TypeSubtypeFromJsValue(info[1], env); + } catch (const std::exception& ex) { + Napi::TypeError::New(env, "invalid type for `type`: " + std::string(ex.what())); + return env.Undefined(); + } + + auto typeIterator = this->index.getIteratorForType(type); + auto packetLocation = typeIterator.first + index; + + // If the index is out of range return undefined + if (packetLocation > typeIterator.second) { + return env.Undefined(); + } + + auto packet = this->Read(*packetLocation); + return Packet::ToJsValue(packet, env); + } + std::vector Decoder::GetMatchingPackets(const uint64_t& timestamp, const std::vector& types) { std::vector packets; diff --git a/src/Decoder.hpp b/src/Decoder.hpp index 5232b5f..87f89f5 100755 --- a/src/Decoder.hpp +++ b/src/Decoder.hpp @@ -18,6 +18,9 @@ namespace nbs { /// Constructor: takes a list of file paths from JS and constructs a Decoder Decoder(const Napi::CallbackInfo& info); + /// Create the object representing the index file + Napi::Value GetIndices(const Napi::CallbackInfo& info); + /// Get a list of the available types in the nbs files of this decoder /// Returns a JS array of type subtype objects Napi::Value GetAvailableTypes(const Napi::CallbackInfo& info); @@ -30,6 +33,9 @@ namespace nbs { /// Returns a JS array of packet objects Napi::Value GetPackets(const Napi::CallbackInfo& info); + /// Get the packet at the given index of the given type subtype + Napi::Value GetPacketByIndex(const Napi::CallbackInfo& info); + Napi::Value NextTimestamp(const Napi::CallbackInfo& info); /** diff --git a/src/Index.hpp b/src/Index.hpp index 7210232..612fb8a 100755 --- a/src/Index.hpp +++ b/src/Index.hpp @@ -11,6 +11,8 @@ #include "zstr/zstr.hpp" namespace nbs { + using IndexIterator = std::vector::iterator; + class Index { public: /// Empty default constructor @@ -78,6 +80,17 @@ namespace nbs { } } + /// Get all iterators for all type subtype pairs in the index + std::vector>> getAllTypeIterators() { + std::vector>> result; + + for (const auto& pair : this->typeMap) { + result.push_back(pair); + } + + return result; + } + /// Get the iterator range (begin, end) for the given type and subtype in the index std::pair::iterator, std::vector::iterator> getIteratorForType( const TypeSubtype& type) { From cc2275669d56f1eb895dc37aa63c679297dc8726 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 12 Feb 2024 14:54:29 +1100 Subject: [PATCH 02/19] Minor fixes + add tests --- src/Decoder.cpp | 6 ++-- tests/test_decoder.js | 69 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/Decoder.cpp b/src/Decoder.cpp index c01d671..9b97aff 100755 --- a/src/Decoder.cpp +++ b/src/Decoder.cpp @@ -322,7 +322,7 @@ namespace nbs { if (jsIndex.IsNumber()) { index = jsIndex.As().Int64Value(); } else { - Napi::TypeError::New(env, "expected positive number for `index`"); + Napi::TypeError::New(env, "invalid type for argument `index`: expected integer").ThrowAsJavaScriptException(); return env.Undefined(); } @@ -330,7 +330,7 @@ namespace nbs { try { type = this->TypeSubtypeFromJsValue(info[1], env); } catch (const std::exception& ex) { - Napi::TypeError::New(env, "invalid type for `type`: " + std::string(ex.what())); + Napi::TypeError::New(env, "invalid type for argument `type`: " + std::string(ex.what())).ThrowAsJavaScriptException(); return env.Undefined(); } @@ -338,7 +338,7 @@ namespace nbs { auto packetLocation = typeIterator.first + index; // If the index is out of range return undefined - if (packetLocation > typeIterator.second) { + if (packetLocation >= typeIterator.second) { return env.Undefined(); } diff --git a/tests/test_decoder.js b/tests/test_decoder.js index 0157fd2..35fa3ce 100755 --- a/tests/test_decoder.js +++ b/tests/test_decoder.js @@ -438,6 +438,75 @@ test('NbsDecoder.getPackets() returns the last packet of each type when given a }); }); +test('NbsDecoder.getPacketByIndex() throws for invalid arguments', () => { + assert.throws( + () => { + decoder.getPacketByIndex(); + }, + /invalid type for argument `index`: expected integer/, + 'NbsDecoder.getPacketByIndex throws for missing `index` argument', + ); + + assert.throws( + () => { + decoder.getPacketByIndex(true); + }, + /invalid type for argument `index`: expected integer/, + 'NbsDecoder.getPacketByIndex throws for incorrect `index` argument type', + ); + + assert.throws( + () => { + decoder.getPacketByIndex(0); + }, + /invalid type for argument `type`: expected object/, + 'NbsDecoder.getPacketByIndex throws for missing `type` argument', + ) + + assert.throws( + () => { + decoder.getPacketByIndex(0, {}); + }, + /invalid type for argument `type`: expected object with `type` and `subtype` keys/, + 'NbsDecoder.getPacketByIndex throws for invalid `type` argument', + ) +}); + +test('NbsDecoder.getPacketByIndex() returns the correct packets in the valid range', () => { + + const packet0 = decoder.getPacketByIndex(0, { type: pingType, subtype: 0}); + const packet1 = decoder.getPacketByIndex(1, { type: pingType, subtype: 0}); + const packetLast = decoder.getPacketByIndex(299, { type: pingType, subtype: 0}); + + assert.equal(packet0, { + timestamp: { seconds: 1000, nanos: 0 }, + type: pingType, + subtype: 0, + payload: Buffer.from('ping.0', 'utf8'), + }); + + assert.equal(packet1, { + timestamp: { seconds: 1003, nanos: 0 }, + type: pingType, + subtype: 0, + payload: Buffer.from('ping.1', 'utf8'), + }); + + assert.equal(packetLast, { + timestamp: { seconds: 1897, nanos: 0 }, + type: pingType, + subtype: 0, + payload: Buffer.from('ping.699', 'utf8'), + }); +}); + +test('NbsDecoder.getPacketByIndex() returns undefined for indexes greater than the valid range', () => { + assert.equal(decoder.getPacketByIndex(300, { type: pingType, subtype: 0}), undefined); + assert.equal(decoder.getPacketByIndex(300, { type: pongType, subtype: 0}), undefined); + assert.equal(decoder.getPacketByIndex(150, { type: pangType, subtype: 100}), undefined); + assert.equal(decoder.getPacketByIndex(150, { type: pangType, subtype: 200}), undefined); +}); + const multiTypeNextTimestampArray = [ { type: pongType, subtype: 0 }, { type: pingType, subtype: 0 }, From 2eb5ac45b51ce8b63c99dd1f2656adfa53e77979 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 12 Feb 2024 15:05:22 +1100 Subject: [PATCH 03/19] Add more tests + formatting --- nbsdecoder.d.ts | 8 +++---- tests/test_decoder.js | 55 ++++++++++++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/nbsdecoder.d.ts b/nbsdecoder.d.ts index 0282a9d..62ec2c5 100644 --- a/nbsdecoder.d.ts +++ b/nbsdecoder.d.ts @@ -82,8 +82,8 @@ export declare class NbsDecoder { public constructor(paths: string[]); /** - * The index data of this decoder. - * + * The index data of this decoder. + * * Contains the a list of packet timestamps for each typeSubType in the loaded nbs files. */ public readonly index: TypeIndex[]; @@ -131,11 +131,11 @@ export declare class NbsDecoder { /** * Get the packet of the given type at the given index in the loaded nbs file. - * + * * Returns either the packet at the index with the given type, or `undefined` if the given * index is outside the range of packets for the type. Use `.index` to check the number * of packets of each type. - * + * * @param index The index of the requested packet * @param type The type of the requested packet */ diff --git a/tests/test_decoder.js b/tests/test_decoder.js index 35fa3ce..fa3ac70 100755 --- a/tests/test_decoder.js +++ b/tests/test_decoder.js @@ -79,6 +79,34 @@ test('NbsDecoder constructor throws for invalid arguments', () => { ); }); +test('NbsDecoder.index contains the correct number of timestamps', () => { + const pingIndices = decoder.index.find((index) => pingType.equals(index.typeSubType.type)); + assert.equal(pingIndices.timestamps.length, 300); + + const pongIndices = decoder.index.find((index) => pongType.equals(index.typeSubType.type)); + assert.equal(pongIndices.timestamps.length, 300); + + const pang100Indices = decoder.index.find( + (index) => pangType.equals(index.typeSubType.type) && index.typeSubType.subtype === 100 + ); + assert.equal(pang100Indices.timestamps.length, 150); + + const pang200Indices = decoder.index.find( + (index) => pangType.equals(index.typeSubType.type) && index.typeSubType.subtype === 200 + ); + assert.equal(pang200Indices.timestamps.length, 150); +}); + +test('NbsDecoder.index contains the correct packet timestamps', () => { + const pingIndices = decoder.index.find((index) => pingType.equals(index.typeSubType.type)); + + assert.equal(pingIndices.timestamps[0], { seconds: 1000, nanos: 0 }); + assert.equal(pingIndices.timestamps[1], { seconds: 1003, nanos: 0 }); + + const lastIndex = pingIndices.timestamps.length - 1; + assert.equal(pingIndices.timestamps[lastIndex], { seconds: 1897, nanos: 0 }); +}); + test('NbsDecoder.getAvailableTypes() returns a list of all the types available in the nbs files', () => { const types = decoder.getAvailableTypes(); @@ -444,7 +472,7 @@ test('NbsDecoder.getPacketByIndex() throws for invalid arguments', () => { decoder.getPacketByIndex(); }, /invalid type for argument `index`: expected integer/, - 'NbsDecoder.getPacketByIndex throws for missing `index` argument', + 'NbsDecoder.getPacketByIndex throws for missing `index` argument' ); assert.throws( @@ -452,7 +480,7 @@ test('NbsDecoder.getPacketByIndex() throws for invalid arguments', () => { decoder.getPacketByIndex(true); }, /invalid type for argument `index`: expected integer/, - 'NbsDecoder.getPacketByIndex throws for incorrect `index` argument type', + 'NbsDecoder.getPacketByIndex throws for incorrect `index` argument type' ); assert.throws( @@ -460,23 +488,22 @@ test('NbsDecoder.getPacketByIndex() throws for invalid arguments', () => { decoder.getPacketByIndex(0); }, /invalid type for argument `type`: expected object/, - 'NbsDecoder.getPacketByIndex throws for missing `type` argument', - ) + 'NbsDecoder.getPacketByIndex throws for missing `type` argument' + ); assert.throws( () => { decoder.getPacketByIndex(0, {}); }, /invalid type for argument `type`: expected object with `type` and `subtype` keys/, - 'NbsDecoder.getPacketByIndex throws for invalid `type` argument', - ) + 'NbsDecoder.getPacketByIndex throws for invalid `type` argument' + ); }); test('NbsDecoder.getPacketByIndex() returns the correct packets in the valid range', () => { - - const packet0 = decoder.getPacketByIndex(0, { type: pingType, subtype: 0}); - const packet1 = decoder.getPacketByIndex(1, { type: pingType, subtype: 0}); - const packetLast = decoder.getPacketByIndex(299, { type: pingType, subtype: 0}); + const packet0 = decoder.getPacketByIndex(0, { type: pingType, subtype: 0 }); + const packet1 = decoder.getPacketByIndex(1, { type: pingType, subtype: 0 }); + const packetLast = decoder.getPacketByIndex(299, { type: pingType, subtype: 0 }); assert.equal(packet0, { timestamp: { seconds: 1000, nanos: 0 }, @@ -501,10 +528,10 @@ test('NbsDecoder.getPacketByIndex() returns the correct packets in the valid ran }); test('NbsDecoder.getPacketByIndex() returns undefined for indexes greater than the valid range', () => { - assert.equal(decoder.getPacketByIndex(300, { type: pingType, subtype: 0}), undefined); - assert.equal(decoder.getPacketByIndex(300, { type: pongType, subtype: 0}), undefined); - assert.equal(decoder.getPacketByIndex(150, { type: pangType, subtype: 100}), undefined); - assert.equal(decoder.getPacketByIndex(150, { type: pangType, subtype: 200}), undefined); + assert.equal(decoder.getPacketByIndex(300, { type: pingType, subtype: 0 }), undefined); + assert.equal(decoder.getPacketByIndex(300, { type: pongType, subtype: 0 }), undefined); + assert.equal(decoder.getPacketByIndex(150, { type: pangType, subtype: 100 }), undefined); + assert.equal(decoder.getPacketByIndex(150, { type: pangType, subtype: 200 }), undefined); }); const multiTypeNextTimestampArray = [ From 4095b6b26d2e6e24cccb60e30cf41302353b2962 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 12 Feb 2024 15:12:19 +1100 Subject: [PATCH 04/19] Formatting --- src/Decoder.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Decoder.cpp b/src/Decoder.cpp index 9b97aff..8a21fb6 100755 --- a/src/Decoder.cpp +++ b/src/Decoder.cpp @@ -26,7 +26,7 @@ namespace nbs { InstanceMethod<&Decoder::GetPackets>("getPackets", napi_property_attributes(napi_writable | napi_configurable)), InstanceMethod<&Decoder::GetPacketByIndex>("getPacketByIndex", - napi_property_attributes(napi_writable | napi_configurable)), + napi_property_attributes(napi_writable | napi_configurable)), InstanceMethod<&Decoder::NextTimestamp>("nextTimestamp", napi_property_attributes(napi_writable | napi_configurable)), InstanceMethod<&Decoder::Close>("close", napi_property_attributes(napi_writable | napi_configurable)), @@ -113,7 +113,7 @@ namespace nbs { Napi::Env env = info.Env(); auto type_iterators = this->index.getAllTypeIterators(); - auto indices = Napi::Array::New(env, type_iterators.size()); + auto indices = Napi::Array::New(env, type_iterators.size()); uint index = 0; @@ -129,7 +129,7 @@ namespace nbs { uint timestampIndex = 0; for (auto it = iterators.first; it != iterators.second; it++) { - auto index = *it; + auto index = *it; timestamps[timestampIndex++] = timestamp::ToJsValue(index.item.timestamp, env); } @@ -318,23 +318,27 @@ namespace nbs { Napi::Env env = info.Env(); uint64_t index = 0; - auto jsIndex = info[0]; + auto jsIndex = info[0]; if (jsIndex.IsNumber()) { index = jsIndex.As().Int64Value(); - } else { - Napi::TypeError::New(env, "invalid type for argument `index`: expected integer").ThrowAsJavaScriptException(); + } + else { + Napi::TypeError::New(env, "invalid type for argument `index`: expected integer") + .ThrowAsJavaScriptException(); return env.Undefined(); } TypeSubtype type; try { type = this->TypeSubtypeFromJsValue(info[1], env); - } catch (const std::exception& ex) { - Napi::TypeError::New(env, "invalid type for argument `type`: " + std::string(ex.what())).ThrowAsJavaScriptException(); + } + catch (const std::exception& ex) { + Napi::TypeError::New(env, "invalid type for argument `type`: " + std::string(ex.what())) + .ThrowAsJavaScriptException(); return env.Undefined(); } - auto typeIterator = this->index.getIteratorForType(type); + auto typeIterator = this->index.getIteratorForType(type); auto packetLocation = typeIterator.first + index; // If the index is out of range return undefined From 7652ef8fc115f1a568ebf16d7ea1614abcdfbfa4 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 12 Feb 2024 15:25:42 +1100 Subject: [PATCH 05/19] Update workflows --- .github/workflows/node.js.yml | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 0512fda..1d6d77a 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -9,24 +9,43 @@ on: pull_request: branches: [main] +# Ensure that only one instance of the workflow is run at a time for each branch/tag. +# Jobs currently running on the branch/tag will be cancelled when new commits are pushed. +# See https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#concurrency. +concurrency: + # `github.workflow` is the workflow name, `github.ref` is the current branch/tag identifier + group: ${{ format('{0}:{1}', github.workflow, github.ref) }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + jobs: - build-and-test: + build: runs-on: ${{ matrix.os }} + continue-on-error: true strategy: matrix: - os: [ubuntu-latest, windows-2019, macos-latest] + os: [ubuntu-latest, windows-latest, macos-latest] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - node-version: [14.x, 16.x, 18.x] + node-version: [12.x, 14.x, 16.x, 18.x, 20.x] steps: - - uses: actions/checkout@v3 + - name: Checkout Code + uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'yarn' - - run: yarn install - - run: yarn test + - name: Install node-gyp + run: npm install -g node-gyp + + - name: Install dependencies + run: yarn ci + + - name: Build + run: yarn build + + - name: Run tests + run: yarn test From c697ca652a6fdbe4b1470cbd477d2d303bcede1b Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 12 Feb 2024 15:27:15 +1100 Subject: [PATCH 06/19] oop --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 1d6d77a..87ba280 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -42,7 +42,7 @@ jobs: run: npm install -g node-gyp - name: Install dependencies - run: yarn ci + run: yarn - name: Build run: yarn build From 88b184e9a7f04d262c194b9a9aa983ff85d99bf9 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 12 Feb 2024 15:31:57 +1100 Subject: [PATCH 07/19] Remove old node --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 87ba280..56222f8 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -26,7 +26,7 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macos-latest] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - node-version: [12.x, 14.x, 16.x, 18.x, 20.x] + node-version: [14.x, 16.x, 18.x, 20.x] steps: - name: Checkout Code From 1b7b781bf2bf9be019736d4721e7523615f689e9 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 12 Feb 2024 15:45:59 +1100 Subject: [PATCH 08/19] Maybe fix --- .github/workflows/node.js.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 56222f8..64b6a16 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -26,7 +26,7 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macos-latest] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - node-version: [14.x, 16.x, 18.x, 20.x] + node-version: [18.x, 20.x, 21.x] steps: - name: Checkout Code @@ -39,7 +39,7 @@ jobs: cache: 'yarn' - name: Install node-gyp - run: npm install -g node-gyp + run: npm install -g node-gyp@10.0.1 - name: Install dependencies run: yarn diff --git a/package.json b/package.json index 6c50e74..82c14f7 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "nbsdecoder.js", "types": "nbsdecoder.d.ts", "engines": { - "node": ">=14.14.0" + "node": ">=18.17.0" }, "files": [ "nbsdecoder.js", From 87ca2fc1b08844b3598db909a03bb35988e86b96 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 12 Feb 2024 15:52:20 +1100 Subject: [PATCH 09/19] More build fixes --- .github/workflows/formatting.yml | 4 ++-- src/Decoder.cpp | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index 7ec141d..de4be4c 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -15,10 +15,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Use Node.js 16 + - name: Use Node.js 21 uses: actions/setup-node@v3 with: - node-version: '16.x' + node-version: '21.x' cache: 'yarn' - run: yarn install diff --git a/src/Decoder.cpp b/src/Decoder.cpp index 8a21fb6..21c3105 100755 --- a/src/Decoder.cpp +++ b/src/Decoder.cpp @@ -115,19 +115,21 @@ namespace nbs { auto type_iterators = this->index.getAllTypeIterators(); auto indices = Napi::Array::New(env, type_iterators.size()); - uint index = 0; + uint64_t index = 0; - for (const auto& [typeSubtype, iterators] : type_iterators) { + for (const auto& typeIterator : type_iterators) { + auto typeSubType = typeIterator.first; + auto iterators = typeIterator.second; auto typeIndices = Napi::Object::New(env); auto jsType = Napi::Object::New(env); - jsType.Set("type", hash::ToJsValue(typeSubtype.type, env)); - jsType.Set("subtype", Napi::Number::New(env, typeSubtype.subtype)); + jsType.Set("type", hash::ToJsValue(typeSubType.type, env)); + jsType.Set("subtype", Napi::Number::New(env, typeSubType.subtype)); auto timestamps = Napi::Array::New(env, std::distance(iterators.first, iterators.second)); - uint timestampIndex = 0; + uint64_t timestampIndex = 0; for (auto it = iterators.first; it != iterators.second; it++) { auto index = *it; timestamps[timestampIndex++] = timestamp::ToJsValue(index.item.timestamp, env); From 911f6c02c1dbd3f3807d17ad5f35c0f68783313e Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 12 Feb 2024 16:05:44 +1100 Subject: [PATCH 10/19] Update node versions and workflows --- .github/workflows/formatting.yml | 4 ++-- .github/workflows/node.js.yml | 33 +++++++++++++++++++++++++------- package.json | 2 +- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index 7ec141d..de4be4c 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -15,10 +15,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Use Node.js 16 + - name: Use Node.js 21 uses: actions/setup-node@v3 with: - node-version: '16.x' + node-version: '21.x' cache: 'yarn' - run: yarn install diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 0512fda..64b6a16 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -9,24 +9,43 @@ on: pull_request: branches: [main] +# Ensure that only one instance of the workflow is run at a time for each branch/tag. +# Jobs currently running on the branch/tag will be cancelled when new commits are pushed. +# See https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#concurrency. +concurrency: + # `github.workflow` is the workflow name, `github.ref` is the current branch/tag identifier + group: ${{ format('{0}:{1}', github.workflow, github.ref) }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + jobs: - build-and-test: + build: runs-on: ${{ matrix.os }} + continue-on-error: true strategy: matrix: - os: [ubuntu-latest, windows-2019, macos-latest] + os: [ubuntu-latest, windows-latest, macos-latest] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - node-version: [14.x, 16.x, 18.x] + node-version: [18.x, 20.x, 21.x] steps: - - uses: actions/checkout@v3 + - name: Checkout Code + uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'yarn' - - run: yarn install - - run: yarn test + - name: Install node-gyp + run: npm install -g node-gyp@10.0.1 + + - name: Install dependencies + run: yarn + + - name: Build + run: yarn build + + - name: Run tests + run: yarn test diff --git a/package.json b/package.json index 6c50e74..82c14f7 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "nbsdecoder.js", "types": "nbsdecoder.d.ts", "engines": { - "node": ">=14.14.0" + "node": ">=18.17.0" }, "files": [ "nbsdecoder.js", From dc00c944ab28e1751477843dbeb5bbb1387cfd06 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Thu, 15 Feb 2024 10:33:55 +1100 Subject: [PATCH 11/19] Change to node 20 for formatting --- .github/workflows/formatting.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index de4be4c..1f89dbb 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -15,10 +15,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Use Node.js 21 + - name: Install Node.js uses: actions/setup-node@v3 with: - node-version: '21.x' + node-version: '20.x' cache: 'yarn' - run: yarn install From d1266c93b56f10413fe2293349da04f1d008b275 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Thu, 15 Feb 2024 10:37:28 +1100 Subject: [PATCH 12/19] Update npm publish node version --- .github/workflows/publish-to-npm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-to-npm.yml b/.github/workflows/publish-to-npm.yml index 8a81fe7..a2e8279 100644 --- a/.github/workflows/publish-to-npm.yml +++ b/.github/workflows/publish-to-npm.yml @@ -15,7 +15,7 @@ jobs: # Installs Node and sets up up the .npmrc file to publish to npm - uses: actions/setup-node@v3 with: - node-version: '16.x' + node-version: '20.x' registry-url: 'https://registry.npmjs.org' cache: 'yarn' From 65cc0ba52ea120cd3638971d7cb4cdfd52111c28 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Thu, 15 Feb 2024 14:29:07 +1100 Subject: [PATCH 13/19] Apply suggestions to get index --- src/Decoder.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Decoder.cpp b/src/Decoder.cpp index 21c3105..25472cb 100755 --- a/src/Decoder.cpp +++ b/src/Decoder.cpp @@ -340,15 +340,15 @@ namespace nbs { return env.Undefined(); } - auto typeIterator = this->index.getIteratorForType(type); - auto packetLocation = typeIterator.first + index; + auto typeIterator = this->index.getIteratorForType(type); // If the index is out of range return undefined - if (packetLocation >= typeIterator.second) { + if (std::distance(typeIterator.first, typeIterator.second) < index) { return env.Undefined(); } - auto packet = this->Read(*packetLocation); + auto packetLocation = std::next(typeIterator.first, index); + auto packet = this->Read(*packetLocation); return Packet::ToJsValue(packet, env); } From 3cbb935e7e2fa3e954981b14016eeb1be38ab44f Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Thu, 15 Feb 2024 16:25:06 +1100 Subject: [PATCH 14/19] Replace `.index` property with `getTypeIndex` --- nbsdecoder.d.ts | 6 +++--- src/Decoder.cpp | 48 +++++++++++++++++-------------------------- src/Decoder.hpp | 6 +++--- src/Index.hpp | 8 +++++--- tests/test_decoder.js | 39 ++++++++++++++++++----------------- 5 files changed, 50 insertions(+), 57 deletions(-) diff --git a/nbsdecoder.d.ts b/nbsdecoder.d.ts index 62ec2c5..3e1c269 100644 --- a/nbsdecoder.d.ts +++ b/nbsdecoder.d.ts @@ -82,11 +82,11 @@ export declare class NbsDecoder { public constructor(paths: string[]); /** - * The index data of this decoder. + * Get all the timestamps of a specified message type subtype. * - * Contains the a list of packet timestamps for each typeSubType in the loaded nbs files. + * @param type A type subtype object to get the timestamps for */ - public readonly index: TypeIndex[]; + public getTypeIndex(type: NbsTypeSubtype): NbsTimestamp[]; /** Get a list of all the types present in the loaded nbs files */ public getAvailableTypes(): NbsTypeSubtypeBuffer[]; diff --git a/src/Decoder.cpp b/src/Decoder.cpp index 25472cb..a3f3f1f 100755 --- a/src/Decoder.cpp +++ b/src/Decoder.cpp @@ -23,6 +23,8 @@ namespace nbs { InstanceMethod<&Decoder::GetTimestampRange>( "getTimestampRange", napi_property_attributes(napi_writable | napi_configurable)), + InstanceMethod<&Decoder::GetTypeIndex>("getTypeIndex", + napi_property_attributes(napi_writable | napi_configurable)), InstanceMethod<&Decoder::GetPackets>("getPackets", napi_property_attributes(napi_writable | napi_configurable)), InstanceMethod<&Decoder::GetPacketByIndex>("getPacketByIndex", @@ -30,7 +32,6 @@ namespace nbs { InstanceMethod<&Decoder::NextTimestamp>("nextTimestamp", napi_property_attributes(napi_writable | napi_configurable)), InstanceMethod<&Decoder::Close>("close", napi_property_attributes(napi_writable | napi_configurable)), - InstanceAccessor<&Decoder::GetIndices>("index"), }); Napi::FunctionReference* constructor = new Napi::FunctionReference(); @@ -109,39 +110,28 @@ namespace nbs { } } - Napi::Value Decoder::GetIndices(const Napi::CallbackInfo& info) { + Napi::Value Decoder::GetTypeIndex(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - auto type_iterators = this->index.getAllTypeIterators(); - auto indices = Napi::Array::New(env, type_iterators.size()); - - uint64_t index = 0; - - for (const auto& typeIterator : type_iterators) { - auto typeSubType = typeIterator.first; - auto iterators = typeIterator.second; - - auto typeIndices = Napi::Object::New(env); - - auto jsType = Napi::Object::New(env); - jsType.Set("type", hash::ToJsValue(typeSubType.type, env)); - jsType.Set("subtype", Napi::Number::New(env, typeSubType.subtype)); - - auto timestamps = Napi::Array::New(env, std::distance(iterators.first, iterators.second)); - - uint64_t timestampIndex = 0; - for (auto it = iterators.first; it != iterators.second; it++) { - auto index = *it; - timestamps[timestampIndex++] = timestamp::ToJsValue(index.item.timestamp, env); - } + TypeSubtype type; + try { + type = this->TypeSubtypeFromJsValue(info[0], env); + } + catch (const std::exception& ex) { + Napi::TypeError::New(env, "invalid type for argument `type`: " + std::string(ex.what())) + .ThrowAsJavaScriptException(); + return env.Undefined(); + } - typeIndices.Set("typeSubType", jsType); - typeIndices.Set("timestamps", timestamps); + auto typeIterator = this->index.getIteratorForType(type); + auto timestamps = Napi::Array::New(env, std::distance(typeIterator.first, typeIterator.second)); - indices[index++] = typeIndices; + uint64_t idx = 0; + for (auto it = typeIterator.first; it != typeIterator.second; it++) { + timestamps[idx++] = timestamp::ToJsValue(it->item.timestamp, env); } - return indices; + return timestamps; } Napi::Value Decoder::GetAvailableTypes(const Napi::CallbackInfo& info) { @@ -343,7 +333,7 @@ namespace nbs { auto typeIterator = this->index.getIteratorForType(type); // If the index is out of range return undefined - if (std::distance(typeIterator.first, typeIterator.second) < index) { + if (std::distance(typeIterator.first, typeIterator.second) <= index) { return env.Undefined(); } diff --git a/src/Decoder.hpp b/src/Decoder.hpp index 87f89f5..a89694b 100755 --- a/src/Decoder.hpp +++ b/src/Decoder.hpp @@ -18,13 +18,13 @@ namespace nbs { /// Constructor: takes a list of file paths from JS and constructs a Decoder Decoder(const Napi::CallbackInfo& info); - /// Create the object representing the index file - Napi::Value GetIndices(const Napi::CallbackInfo& info); - /// Get a list of the available types in the nbs files of this decoder /// Returns a JS array of type subtype objects Napi::Value GetAvailableTypes(const Napi::CallbackInfo& info); + /// Get the timestamps for a specified type subtype + Napi::Value GetTypeIndex(const Napi::CallbackInfo& info); + /// Get a list of the available types in the nbs files of this decoder /// Returns a JS array with two elements: the start timestamp object and the end timestamp object Napi::Value GetTimestampRange(const Napi::CallbackInfo& info); diff --git a/src/Index.hpp b/src/Index.hpp index 612fb8a..91ab712 100755 --- a/src/Index.hpp +++ b/src/Index.hpp @@ -92,9 +92,11 @@ namespace nbs { } /// Get the iterator range (begin, end) for the given type and subtype in the index - std::pair::iterator, std::vector::iterator> getIteratorForType( - const TypeSubtype& type) { - return this->typeMap[type]; + std::pair getIteratorForType(const TypeSubtype& type) { + // Check that the type actually exists, otherwise the type map will add the given type + // with an empty iterator + auto typeExists = (this->typeMap.count(type) > 0); + return typeExists ? this->typeMap[type] : std::make_pair((nbs::IndexIterator) 0, (nbs::IndexIterator) 0); } /// Get a list of iterator ranges (begin, end) for the given list of type and subtype in the index diff --git a/tests/test_decoder.js b/tests/test_decoder.js index fa3ac70..0cf4419 100755 --- a/tests/test_decoder.js +++ b/tests/test_decoder.js @@ -79,32 +79,33 @@ test('NbsDecoder constructor throws for invalid arguments', () => { ); }); -test('NbsDecoder.index contains the correct number of timestamps', () => { - const pingIndices = decoder.index.find((index) => pingType.equals(index.typeSubType.type)); - assert.equal(pingIndices.timestamps.length, 300); +test('NbsDecoder.getTypeIndex returns the correct number of timestamps', () => { + const pingIndices = decoder.getTypeIndex({ type: pingType, subtype: 0 }); + assert.equal(pingIndices.length, 300); - const pongIndices = decoder.index.find((index) => pongType.equals(index.typeSubType.type)); - assert.equal(pongIndices.timestamps.length, 300); + const pongIndices = decoder.getTypeIndex({ type: pongType, subtype: 0 }); + assert.equal(pongIndices.length, 300); - const pang100Indices = decoder.index.find( - (index) => pangType.equals(index.typeSubType.type) && index.typeSubType.subtype === 100 - ); - assert.equal(pang100Indices.timestamps.length, 150); + const pang100Indices = decoder.getTypeIndex({ type: pangType, subtype: 100 }); + assert.equal(pang100Indices.length, 150); - const pang200Indices = decoder.index.find( - (index) => pangType.equals(index.typeSubType.type) && index.typeSubType.subtype === 200 - ); - assert.equal(pang200Indices.timestamps.length, 150); + const pang200Indices = decoder.getTypeIndex({ type: pangType, subtype: 200 }); + assert.equal(pang200Indices.length, 150); +}); + +test('NbsDecoder.getTypeIndex returns an empty array for types not in the decoder', () => { + const fakePacketIndices = decoder.getTypeIndex({ type: 'fakeIndex', subtype: 0 }); + assert.equal(fakePacketIndices.length, 0); }); -test('NbsDecoder.index contains the correct packet timestamps', () => { - const pingIndices = decoder.index.find((index) => pingType.equals(index.typeSubType.type)); +test('NbsDecoder.getTypeIndex the correct packet timestamps', () => { + const pingIndices = decoder.getTypeIndex({ type: pingType, subtype: 0 }); - assert.equal(pingIndices.timestamps[0], { seconds: 1000, nanos: 0 }); - assert.equal(pingIndices.timestamps[1], { seconds: 1003, nanos: 0 }); + assert.equal(pingIndices[0], { seconds: 1000, nanos: 0 }); + assert.equal(pingIndices[1], { seconds: 1003, nanos: 0 }); - const lastIndex = pingIndices.timestamps.length - 1; - assert.equal(pingIndices.timestamps[lastIndex], { seconds: 1897, nanos: 0 }); + const lastIndex = pingIndices.length - 1; + assert.equal(pingIndices[lastIndex], { seconds: 1897, nanos: 0 }); }); test('NbsDecoder.getAvailableTypes() returns a list of all the types available in the nbs files', () => { From e8be2eda01acef79bff23cc63a0e153b91b9f804 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 19 Feb 2024 14:39:25 +1100 Subject: [PATCH 15/19] Apply review suggestions --- nbsdecoder.d.ts | 21 +++++++++------------ src/Decoder.cpp | 24 ++++++++++++++---------- src/Decoder.hpp | 2 +- src/Index.hpp | 16 ++++------------ tests/test_decoder.js | 22 +++++++++++++--------- 5 files changed, 41 insertions(+), 44 deletions(-) diff --git a/nbsdecoder.d.ts b/nbsdecoder.d.ts index 3e1c269..f945247 100644 --- a/nbsdecoder.d.ts +++ b/nbsdecoder.d.ts @@ -61,9 +61,7 @@ export interface NbsTypeSubtypeBuffer extends NbsTypeSubtype { type: Buffer; } -/** - * The valid timestamps for a type subtype - */ +/** The timestamps for a type subtype */ export interface TypeIndex { typeSubType: NbsTypeSubtype; timestamps: NbsTimestamp[]; @@ -84,9 +82,9 @@ export declare class NbsDecoder { /** * Get all the timestamps of a specified message type subtype. * - * @param type A type subtype object to get the timestamps for + * @param typeSubtype A type subtype object to get the timestamps for */ - public getTypeIndex(type: NbsTypeSubtype): NbsTimestamp[]; + public getTypeIndex(typeSubtype: NbsTypeSubtype): NbsTimestamp[]; /** Get a list of all the types present in the loaded nbs files */ public getAvailableTypes(): NbsTypeSubtypeBuffer[]; @@ -97,9 +95,9 @@ export declare class NbsDecoder { /** * Get the timestamp range (start, end) for all packets of the given type in the loaded nbs files * - * @param type A type subtype object to get the timestamp range for + * @param typeSubtype A type subtype object to get the timestamp range for */ - public getTimestampRange(type: NbsTypeSubtype): [NbsTimestamp, NbsTimestamp]; + public getTimestampRange(typeSubtype: NbsTypeSubtype): [NbsTimestamp, NbsTimestamp]; /** * Get the packets at or before the given timestamp for all types in the loaded nbs files @@ -133,13 +131,12 @@ export declare class NbsDecoder { * Get the packet of the given type at the given index in the loaded nbs file. * * Returns either the packet at the index with the given type, or `undefined` if the given - * index is outside the range of packets for the type. Use `.index` to check the number - * of packets of each type. + * index is outside the range of packets for the type. * - * @param index The index of the requested packet - * @param type The type of the requested packet + * @param index The index of the requested packet + * @param typeSubtype The type of the requested packet */ - public getPacketByIndex(index: number, type: NbsTypeSubtype): NbsPacket | undefined; + public getPacketByIndex(index: number, typeSubtype: NbsTypeSubtype): NbsPacket | undefined; /** * Get the timestamp to seek to such that all messages of the given types are stepped by (n) steps diff --git a/src/Decoder.cpp b/src/Decoder.cpp index a3f3f1f..d2eebda 100755 --- a/src/Decoder.cpp +++ b/src/Decoder.cpp @@ -113,17 +113,17 @@ namespace nbs { Napi::Value Decoder::GetTypeIndex(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - TypeSubtype type; + TypeSubtype typeSubtype; try { - type = this->TypeSubtypeFromJsValue(info[0], env); + typeSubtype = this->TypeSubtypeFromJsValue(info[0], env); } catch (const std::exception& ex) { - Napi::TypeError::New(env, "invalid type for argument `type`: " + std::string(ex.what())) + Napi::TypeError::New(env, "invalid type for argument `typeSubtype`: " + std::string(ex.what())) .ThrowAsJavaScriptException(); return env.Undefined(); } - auto typeIterator = this->index.getIteratorForType(type); + auto typeIterator = this->index.getIteratorForType(typeSubtype); auto timestamps = Napi::Array::New(env, std::distance(typeIterator.first, typeIterator.second)); uint64_t idx = 0; @@ -309,8 +309,8 @@ namespace nbs { Napi::Value Decoder::GetPacketByIndex(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - uint64_t index = 0; - auto jsIndex = info[0]; + int64_t index = 0; + auto jsIndex = info[0]; if (jsIndex.IsNumber()) { index = jsIndex.As().Int64Value(); } @@ -320,17 +320,21 @@ namespace nbs { return env.Undefined(); } - TypeSubtype type; + if (index < 0) { + return env.Undefined(); + } + + TypeSubtype typeSubtype; try { - type = this->TypeSubtypeFromJsValue(info[1], env); + typeSubtype = this->TypeSubtypeFromJsValue(info[1], env); } catch (const std::exception& ex) { - Napi::TypeError::New(env, "invalid type for argument `type`: " + std::string(ex.what())) + Napi::TypeError::New(env, "invalid type for argument `typeSubtype`: " + std::string(ex.what())) .ThrowAsJavaScriptException(); return env.Undefined(); } - auto typeIterator = this->index.getIteratorForType(type); + auto typeIterator = this->index.getIteratorForType(typeSubtype); // If the index is out of range return undefined if (std::distance(typeIterator.first, typeIterator.second) <= index) { diff --git a/src/Decoder.hpp b/src/Decoder.hpp index a89694b..fd0abe4 100755 --- a/src/Decoder.hpp +++ b/src/Decoder.hpp @@ -22,7 +22,7 @@ namespace nbs { /// Returns a JS array of type subtype objects Napi::Value GetAvailableTypes(const Napi::CallbackInfo& info); - /// Get the timestamps for a specified type subtype + /// Get all the timestamps of a specified message type subtype from the index Napi::Value GetTypeIndex(const Napi::CallbackInfo& info); /// Get a list of the available types in the nbs files of this decoder diff --git a/src/Index.hpp b/src/Index.hpp index 91ab712..c2e1fef 100755 --- a/src/Index.hpp +++ b/src/Index.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -80,23 +81,14 @@ namespace nbs { } } - /// Get all iterators for all type subtype pairs in the index - std::vector>> getAllTypeIterators() { - std::vector>> result; - - for (const auto& pair : this->typeMap) { - result.push_back(pair); - } - - return result; - } - /// Get the iterator range (begin, end) for the given type and subtype in the index std::pair getIteratorForType(const TypeSubtype& type) { // Check that the type actually exists, otherwise the type map will add the given type // with an empty iterator auto typeExists = (this->typeMap.count(type) > 0); - return typeExists ? this->typeMap[type] : std::make_pair((nbs::IndexIterator) 0, (nbs::IndexIterator) 0); + if (typeExists) { + return this->typeMap[type]; + } } /// Get a list of iterator ranges (begin, end) for the given list of type and subtype in the index diff --git a/tests/test_decoder.js b/tests/test_decoder.js index 0cf4419..d1a87b3 100755 --- a/tests/test_decoder.js +++ b/tests/test_decoder.js @@ -79,7 +79,7 @@ test('NbsDecoder constructor throws for invalid arguments', () => { ); }); -test('NbsDecoder.getTypeIndex returns the correct number of timestamps', () => { +test('NbsDecoder.getTypeIndex() returns the correct index for the given type subtype', () => { const pingIndices = decoder.getTypeIndex({ type: pingType, subtype: 0 }); assert.equal(pingIndices.length, 300); @@ -93,12 +93,12 @@ test('NbsDecoder.getTypeIndex returns the correct number of timestamps', () => { assert.equal(pang200Indices.length, 150); }); -test('NbsDecoder.getTypeIndex returns an empty array for types not in the decoder', () => { +test('NbsDecoder.getTypeIndex() returns an empty array for types not in the decoder', () => { const fakePacketIndices = decoder.getTypeIndex({ type: 'fakeIndex', subtype: 0 }); assert.equal(fakePacketIndices.length, 0); }); -test('NbsDecoder.getTypeIndex the correct packet timestamps', () => { +test('NbsDecoder.getTypeIndex() returns the correct index with the correct packet timestamps', () => { const pingIndices = decoder.getTypeIndex({ type: pingType, subtype: 0 }); assert.equal(pingIndices[0], { seconds: 1000, nanos: 0 }); @@ -473,7 +473,7 @@ test('NbsDecoder.getPacketByIndex() throws for invalid arguments', () => { decoder.getPacketByIndex(); }, /invalid type for argument `index`: expected integer/, - 'NbsDecoder.getPacketByIndex throws for missing `index` argument' + 'NbsDecoder.getPacketByIndex() throws for missing `index` argument' ); assert.throws( @@ -481,7 +481,7 @@ test('NbsDecoder.getPacketByIndex() throws for invalid arguments', () => { decoder.getPacketByIndex(true); }, /invalid type for argument `index`: expected integer/, - 'NbsDecoder.getPacketByIndex throws for incorrect `index` argument type' + 'NbsDecoder.getPacketByIndex() throws for incorrect `index` argument type' ); assert.throws( @@ -489,7 +489,7 @@ test('NbsDecoder.getPacketByIndex() throws for invalid arguments', () => { decoder.getPacketByIndex(0); }, /invalid type for argument `type`: expected object/, - 'NbsDecoder.getPacketByIndex throws for missing `type` argument' + 'NbsDecoder.getPacketByIndex() throws for missing `type` argument' ); assert.throws( @@ -497,11 +497,11 @@ test('NbsDecoder.getPacketByIndex() throws for invalid arguments', () => { decoder.getPacketByIndex(0, {}); }, /invalid type for argument `type`: expected object with `type` and `subtype` keys/, - 'NbsDecoder.getPacketByIndex throws for invalid `type` argument' + 'NbsDecoder.getPacketByIndex() throws for invalid `type` argument' ); }); -test('NbsDecoder.getPacketByIndex() returns the correct packets in the valid range', () => { +test('NbsDecoder.getPacketByIndex() returns the correct packet for a valid index', () => { const packet0 = decoder.getPacketByIndex(0, { type: pingType, subtype: 0 }); const packet1 = decoder.getPacketByIndex(1, { type: pingType, subtype: 0 }); const packetLast = decoder.getPacketByIndex(299, { type: pingType, subtype: 0 }); @@ -528,7 +528,11 @@ test('NbsDecoder.getPacketByIndex() returns the correct packets in the valid ran }); }); -test('NbsDecoder.getPacketByIndex() returns undefined for indexes greater than the valid range', () => { +test('NbsDecoder.getPacketByIndex() returns undefined for indices outside the valid range', () => { + // Negative indices + assert.equal(decoder.getPacketByIndex(-1, { type: pingType, subtype: 0 }), undefined); + + // Indices one above the max assert.equal(decoder.getPacketByIndex(300, { type: pingType, subtype: 0 }), undefined); assert.equal(decoder.getPacketByIndex(300, { type: pongType, subtype: 0 }), undefined); assert.equal(decoder.getPacketByIndex(150, { type: pangType, subtype: 100 }), undefined); From e06b497f7ec96f27ef1a353fcb14805c87dd2674 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 19 Feb 2024 14:39:36 +1100 Subject: [PATCH 16/19] Maybe fix builds --- src/Index.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Index.hpp b/src/Index.hpp index c2e1fef..2dc8737 100755 --- a/src/Index.hpp +++ b/src/Index.hpp @@ -85,10 +85,11 @@ namespace nbs { std::pair getIteratorForType(const TypeSubtype& type) { // Check that the type actually exists, otherwise the type map will add the given type // with an empty iterator - auto typeExists = (this->typeMap.count(type) > 0); - if (typeExists) { + auto typeExists = (this->typeMap.find(type) != this->typeMap.end()); + if (typeExists == true) { return this->typeMap[type]; } + return std::make_pair((std::vector::iterator) 0, (std::vector::iterator) 0); } /// Get a list of iterator ranges (begin, end) for the given list of type and subtype in the index From ef499e3b1920bfd8728f3f083dca7631bfad555b Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 19 Feb 2024 14:41:07 +1100 Subject: [PATCH 17/19] Fix test error messages --- tests/test_decoder.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_decoder.js b/tests/test_decoder.js index d1a87b3..df940a1 100755 --- a/tests/test_decoder.js +++ b/tests/test_decoder.js @@ -488,7 +488,7 @@ test('NbsDecoder.getPacketByIndex() throws for invalid arguments', () => { () => { decoder.getPacketByIndex(0); }, - /invalid type for argument `type`: expected object/, + /invalid type for argument `typeSubtype`: expected object/, 'NbsDecoder.getPacketByIndex() throws for missing `type` argument' ); @@ -496,7 +496,7 @@ test('NbsDecoder.getPacketByIndex() throws for invalid arguments', () => { () => { decoder.getPacketByIndex(0, {}); }, - /invalid type for argument `type`: expected object with `type` and `subtype` keys/, + /invalid type for argument `typeSubtype`: expected object with `type` and `subtype` keys/, 'NbsDecoder.getPacketByIndex() throws for invalid `type` argument' ); }); From aad6e9ff4d1354028877991204dbb269ff66817a Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Mon, 19 Feb 2024 14:50:17 +1100 Subject: [PATCH 18/19] Maybe fix again --- src/Index.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Index.hpp b/src/Index.hpp index 2dc8737..dffa7cb 100755 --- a/src/Index.hpp +++ b/src/Index.hpp @@ -89,7 +89,7 @@ namespace nbs { if (typeExists == true) { return this->typeMap[type]; } - return std::make_pair((std::vector::iterator) 0, (std::vector::iterator) 0); + return {}; } /// Get a list of iterator ranges (begin, end) for the given list of type and subtype in the index From 056a9060c287d9f5c058ce27fd977e8f517b3b97 Mon Sep 17 00:00:00 2001 From: Adrian Wann Date: Tue, 20 Feb 2024 10:07:18 +1100 Subject: [PATCH 19/19] Remove unused import --- src/Index.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Index.hpp b/src/Index.hpp index dffa7cb..19b6400 100755 --- a/src/Index.hpp +++ b/src/Index.hpp @@ -3,7 +3,6 @@ #include #include -#include #include #include