44#include < napi.h>
55#include < string>
66
7+ #include " Hash.hpp"
78#include " IndexItem.hpp"
89#include " Packet.hpp"
10+ #include " Timestamp.hpp"
911#include " TypeSubtype.hpp"
10- # include " xxhash/xxhash.h "
12+
1113namespace nbs {
1214
1315 Napi::Object Decoder::Init (Napi::Env& env, Napi::Object& exports) {
14- Napi::Function func =
15- DefineClass (env,
16- " Decoder" ,
17- {
18- InstanceMethod<&Decoder::GetAvailableTypes>(
19- " getAvailableTypes" ,
20- static_cast <napi_property_attributes>(napi_writable | napi_configurable)),
21- InstanceMethod<&Decoder::GetTimestampRange>(
22- " getTimestampRange" ,
23- static_cast <napi_property_attributes>(napi_writable | napi_configurable)),
24- InstanceMethod<&Decoder::GetPackets>(
25- " getPackets" ,
26- static_cast <napi_property_attributes>(napi_writable | napi_configurable)),
27- InstanceMethod<&Decoder::NextTimestamp>(
28- " nextTimestamp" ,
29- static_cast <napi_property_attributes>(napi_writable | napi_configurable)),
30- });
16+ Napi::Function func = DefineClass (
17+ env,
18+ " Decoder" ,
19+ {
20+ InstanceMethod<&Decoder::GetAvailableTypes>(
21+ " getAvailableTypes" ,
22+ napi_property_attributes (napi_writable | napi_configurable)),
23+ InstanceMethod<&Decoder::GetTimestampRange>(
24+ " getTimestampRange" ,
25+ napi_property_attributes (napi_writable | napi_configurable)),
26+ InstanceMethod<&Decoder::GetPackets>(" getPackets" ,
27+ napi_property_attributes (napi_writable | napi_configurable)),
28+ InstanceMethod<&Decoder::NextTimestamp>(" nextTimestamp" ,
29+ napi_property_attributes (napi_writable | napi_configurable)),
30+ InstanceMethod<&Decoder::Close>(" close" , napi_property_attributes (napi_writable | napi_configurable)),
31+ });
3132
3233 Napi::FunctionReference* constructor = new Napi::FunctionReference ();
3334
@@ -115,7 +116,7 @@ namespace nbs {
115116 for (size_t i = 0 ; i < availableTypes.size (); i++) {
116117 auto jsType = Napi::Object::New (env);
117118
118- jsType.Set (" type" , this -> HashToJsValue (availableTypes[i].type , env));
119+ jsType.Set (" type" , hash::ToJsValue (availableTypes[i].type , env));
119120 jsType.Set (" subtype" , Napi::Number::New (env, availableTypes[i].subtype ));
120121
121122 jsTypes[i] = jsType;
@@ -147,8 +148,8 @@ namespace nbs {
147148 auto jsRange = Napi::Array::New (env, 2 );
148149
149150 size_t i = 0 ;
150- jsRange[i + 0 ] = this -> TimestampToJsValue (range.first , env);
151- jsRange[i + 1 ] = this -> TimestampToJsValue (range.second , env);
151+ jsRange[i + 0 ] = timestamp::ToJsValue (range.first , env);
152+ jsRange[i + 1 ] = timestamp::ToJsValue (range.second , env);
152153
153154 return jsRange;
154155 }
@@ -158,7 +159,7 @@ namespace nbs {
158159
159160 uint64_t timestamp = 0 ;
160161 try {
161- timestamp = this -> TimestampFromJsValue (info[0 ], env);
162+ timestamp = timestamp::FromJsValue (info[0 ], env);
162163 }
163164 catch (const std::exception& ex) {
164165 Napi::TypeError::New (env, std::string (" invalid type for argument `timestamp`: " ) + ex.what ())
@@ -220,7 +221,7 @@ namespace nbs {
220221 auto index_timestamp = this ->index .nextTimestamp (timestamp, types, steps);
221222
222223 // Convert timestamp back to Napi format and return.
223- auto new_timestamp = this -> TimestampToJsValue (index_timestamp, env).As <Napi::Number>();
224+ auto new_timestamp = timestamp::ToJsValue (index_timestamp, env).As <Napi::Number>();
224225 return new_timestamp;
225226 }
226227
@@ -230,7 +231,7 @@ namespace nbs {
230231 uint64_t timestamp = 0 ;
231232
232233 try {
233- timestamp = this -> TimestampFromJsValue (info[0 ], env);
234+ timestamp = timestamp::FromJsValue (info[0 ], env);
234235 }
235236 catch (const std::exception& ex) {
236237 Napi::TypeError::New (env, std::string (" invalid type for argument `timestamp`: " ) + ex.what ())
@@ -267,25 +268,11 @@ namespace nbs {
267268 return env.Undefined ();
268269 }
269270
270- auto packets = this ->GetMatchingPackets (timestamp, types);
271-
271+ auto packets = this ->GetMatchingPackets (timestamp, types);
272272 auto jsPackets = Napi::Array::New (env, packets.size ());
273273
274274 for (size_t i = 0 ; i < packets.size (); i++) {
275- auto jsPacket = Napi::Object::New (env);
276-
277- jsPacket.Set (" timestamp" , this ->TimestampToJsValue (packets[i].timestamp , env));
278- jsPacket.Set (" type" , HashToJsValue (packets[i].type , env));
279- jsPacket.Set (" subtype" , Napi::Number::New (env, packets[i].subtype ));
280-
281- if (packets[i].payload == nullptr ) {
282- jsPacket.Set (" payload" , env.Undefined ());
283- }
284- else {
285- jsPacket.Set (" payload" , Napi::Buffer<uint8_t >::Copy (env, packets[i].payload , packets[i].length ));
286- }
287-
288- jsPackets[i] = jsPacket;
275+ jsPackets[i] = Packet::ToJsValue (packets[i], env);
289276 }
290277
291278 return jsPackets;
@@ -348,42 +335,6 @@ namespace nbs {
348335 return packet;
349336 }
350337
351- uint64_t Decoder::HashFromJsValue (const Napi::Value& jsHash, const Napi::Env& env) {
352- uint64_t hash = 0 ;
353-
354- // If we have a string, apply XXHash to get the hash
355- if (jsHash.IsString ()) {
356- std::string s = jsHash.As <Napi::String>().Utf8Value ();
357- hash = XXH64 (s.c_str (), s.size (), 0x4e55436c );
358- }
359- // Otherwise try to interpret it as a buffer that contains the hash
360- else if (jsHash.IsTypedArray ()) {
361- Napi::TypedArray typedArray = jsHash.As <Napi::TypedArray>();
362- Napi::ArrayBuffer buffer = typedArray.ArrayBuffer ();
363-
364- uint8_t * data = reinterpret_cast <uint8_t *>(buffer.Data ());
365- uint8_t * start = data + typedArray.ByteOffset ();
366- uint8_t * end = start + typedArray.ByteLength ();
367-
368- if (std::distance (start, end) == 8 ) {
369- std::memcpy (&hash, start, 8 );
370- }
371- else {
372- throw std::runtime_error (" provided Buffer length is not 8" );
373- }
374- }
375- else {
376- throw std::runtime_error (" expected a string or Buffer" );
377- }
378-
379- return hash;
380- }
381-
382- Napi::Value Decoder::HashToJsValue (const uint64_t & hash, const Napi::Env& env) {
383- return Napi::Buffer<uint8_t >::Copy (env, reinterpret_cast <const uint8_t *>(&hash), sizeof (uint64_t ))
384- .As <Napi::Value>();
385- }
386-
387338 TypeSubtype Decoder::TypeSubtypeFromJsValue (const Napi::Value& jsTypeSubtype, const Napi::Env& env) {
388339 if (!jsTypeSubtype.IsObject ()) {
389340 throw std::runtime_error (" expected object" );
@@ -398,7 +349,7 @@ namespace nbs {
398349 uint64_t type = 0 ;
399350
400351 try {
401- type = this -> HashFromJsValue (typeSubtype.Get (" type" ), env);
352+ type = hash::FromJsValue (typeSubtype.Get (" type" ), env);
402353 }
403354 catch (const std::exception& ex) {
404355 throw std::runtime_error (" invalid `.type`: " + std::string (ex.what ()));
@@ -416,44 +367,10 @@ namespace nbs {
416367 return {type, subtype};
417368 }
418369
419- uint64_t Decoder::TimestampFromJsValue (const Napi::Value& jsTimestamp, const Napi::Env& env) {
420- uint64_t timestamp = 0 ;
421-
422- if (jsTimestamp.IsNumber ()) {
423- timestamp = jsTimestamp.As <Napi::Number>().Int64Value ();
424- }
425- else if (jsTimestamp.IsBigInt ()) {
426- bool lossless = true ;
427- timestamp = jsTimestamp.As <Napi::BigInt>().Uint64Value (&lossless);
370+ void Decoder::Close (const Napi::CallbackInfo& info) {
371+ for (auto & map : memoryMaps) {
372+ map.unmap ();
428373 }
429- else if (jsTimestamp.IsObject ()) {
430- auto ts = jsTimestamp.As <Napi::Object>();
431-
432- if (!ts.Has (" seconds" ) || !ts.Has (" nanos" )) {
433- throw std::runtime_error (" expected object with `seconds` and `nanos` keys" );
434- }
435-
436- if (!ts.Get (" seconds" ).IsNumber () || !ts.Get (" nanos" ).IsNumber ()) {
437- throw std::runtime_error (" `seconds` and `nanos` must be numbers" );
438- }
439-
440- uint64_t seconds = ts.Get (" seconds" ).As <Napi::Number>().Int64Value ();
441- uint64_t nanos = ts.Get (" nanos" ).As <Napi::Number>().Int64Value ();
442-
443- timestamp = seconds * 1e9 + nanos;
444- }
445- else {
446- throw std::runtime_error (" expected positive number or BigInt or timestamp object" );
447- }
448-
449- return timestamp;
450- }
451-
452- Napi::Value Decoder::TimestampToJsValue (const uint64_t & timestamp, const Napi::Env& env) {
453- Napi::Object jsTimestamp = Napi::Object::New (env);
454- jsTimestamp.Set (" seconds" , Napi::Number::New (env, timestamp / 1000000000L ));
455- jsTimestamp.Set (" nanos" , Napi::Number::New (env, timestamp % 1000000000L ));
456- return jsTimestamp;
457374 }
458375
459376} // namespace nbs
0 commit comments