From ffec80a04d430e84b7aaf8dd571a611538a711f1 Mon Sep 17 00:00:00 2001 From: Krmjn09 Date: Thu, 26 Jun 2025 19:20:31 +0530 Subject: [PATCH 1/9] $file.readBuffer to read the data from disk --- demo/node/rntuple_test.js | 5 +++-- modules/rntuple.mjs | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/demo/node/rntuple_test.js b/demo/node/rntuple_test.js index a16a02c42..67fe2190c 100644 --- a/demo/node/rntuple_test.js +++ b/demo/node/rntuple_test.js @@ -4,10 +4,11 @@ import { readHeaderFooter } from 'jsroot/rntuple'; console.log(`JSROOT version ${version}`); +// let file = await openFile('https://jsroot.gsi.de/files/tmp/ntpl001_staff.root'); -let file = await openFile('https://jsroot.gsi.de/files/tmp/ntpl001_staff.root'); +let file = await openFile('./simple.root'); -let rntuple = await file.readObject('Staff'); +let rntuple = await file.readObject('myNtuple'); await readHeaderFooter(rntuple); diff --git a/modules/rntuple.mjs b/modules/rntuple.mjs index 9d82bfc00..ee19f1b25 100644 --- a/modules/rntuple.mjs +++ b/modules/rntuple.mjs @@ -495,6 +495,15 @@ const numRecordCluster = reader.readU32(); this.pageLocations = clusterPageLocations; } +deserializePage(blob) { + const reader = new RBufferReader(blob); + console.log('Deserializing first 10 double values from data page ') + for (let i = 0; i < 10; ++i) { + const val = reader.readF64(); + console.log(val); + } +} + } @@ -527,7 +536,7 @@ async function readHeaderFooter(tuple) { tuple.builder.deserializeHeader(header_blob); tuple.builder.deserializeFooter(footer_blob); - + // Deserialize the Page List Envelope const group = tuple.builder.clusterGroups?.[0]; if (!group || !group.pageListLocator) throw new Error('No valid cluster group or page list locator found'); @@ -545,7 +554,30 @@ async function readHeaderFooter(tuple) { throw new Error(`Unzipped page list is not a DataView, got ${Object.prototype.toString.call(unzipped_blob)}`); tuple.builder.deserializePageList(unzipped_blob); - return true; + + // Read the first page data + const firstPage = tuple.builder?.pageLocations?.[0]?.[0]?.pages?.[0]; + if (!firstPage || !firstPage.locator) + throw new Error('No valid first page found in pageLocations'); + + const pageOffset = Number(firstPage.locator.offset), + pageSize = Number(firstPage.locator.size), + uncompressedPageSize = 8000; + console.log('Compressed size :', pageSize); + + return tuple.$file.readBuffer([pageOffset, pageSize]).then(compressedPage => { + if (!(compressedPage instanceof DataView)) + throw new Error('Compressed page readBuffer did not return a DataView'); + + return R__unzip(compressedPage, uncompressedPageSize).then(unzippedPage => { + if (!(unzippedPage instanceof DataView)) + throw new Error('Unzipped page is not a DataView'); + + tuple.builder.deserializePage(unzippedPage); + + return true; + }); + }); }); }); }); From f6dfc7b4f680febcd7e6ecb4f30590ff6b8dc8d7 Mon Sep 17 00:00:00 2001 From: Krmjn09 Date: Fri, 27 Jun 2025 13:55:33 +0530 Subject: [PATCH 2/9] Added rntuple_test.jsin .yml --- .github/workflows/jsroot-ci.yml | 4 +++ demo/node/rntuple_test.js | 7 +++-- modules/rntuple.mjs | 53 +++++++++++++++++---------------- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/.github/workflows/jsroot-ci.yml b/.github/workflows/jsroot-ci.yml index e6a394eda..91248eeb4 100644 --- a/.github/workflows/jsroot-ci.yml +++ b/.github/workflows/jsroot-ci.yml @@ -63,6 +63,7 @@ jobs: node demo/node/file_proxy.js multi ./hsimple.root node demo/node/file_proxy.js buffer ./hsimple.root node demo/node/buffer_test.js + node demo/node/rntuple_test.js tests_ubuntu: runs-on: ubuntu-latest @@ -176,6 +177,8 @@ jobs: node demo/node/file_proxy.js multi ./hsimple.root node demo/node/file_proxy.js buffer ./hsimple.root node demo/node/buffer_test.js + node demo/node/rntuple_test.js + build-windows: runs-on: windows-latest @@ -223,4 +226,5 @@ jobs: node demo/node/file_proxy.js multi ./hsimple.root node demo/node/file_proxy.js buffer ./hsimple.root node demo/node/buffer_test.js + node demo/node/rntuple_test.js diff --git a/demo/node/rntuple_test.js b/demo/node/rntuple_test.js index 67fe2190c..1a78cab6a 100644 --- a/demo/node/rntuple_test.js +++ b/demo/node/rntuple_test.js @@ -4,11 +4,12 @@ import { readHeaderFooter } from 'jsroot/rntuple'; console.log(`JSROOT version ${version}`); -// let file = await openFile('https://jsroot.gsi.de/files/tmp/ntpl001_staff.root'); +const file = await openFile('https://jsroot.gsi.de/files/tmp/ntpl001_staff.root'), +rntuple = await file.readObject('Staff'); -let file = await openFile('./simple.root'); +// let file = await openFile('./simple.root'); -let rntuple = await file.readObject('myNtuple'); +// let rntuple = await file.readObject('myNtuple'); await readHeaderFooter(rntuple); diff --git a/modules/rntuple.mjs b/modules/rntuple.mjs index ee19f1b25..ee8f4362c 100644 --- a/modules/rntuple.mjs +++ b/modules/rntuple.mjs @@ -495,14 +495,16 @@ const numRecordCluster = reader.readU32(); this.pageLocations = clusterPageLocations; } -deserializePage(blob) { - const reader = new RBufferReader(blob); - console.log('Deserializing first 10 double values from data page ') - for (let i = 0; i < 10; ++i) { - const val = reader.readF64(); - console.log(val); - } -} + +// Example Of Deserializing Page Content +// deserializePage(blob) { +// const reader = new RBufferReader(blob); +// console.log('Deserializing first 10 double values from data page ') +// for (let i = 0; i < 10; ++i) { +// const val = reader.readF64(); +// console.log(val); +// } +// } } @@ -554,30 +556,31 @@ async function readHeaderFooter(tuple) { throw new Error(`Unzipped page list is not a DataView, got ${Object.prototype.toString.call(unzipped_blob)}`); tuple.builder.deserializePageList(unzipped_blob); + return true; // Read the first page data - const firstPage = tuple.builder?.pageLocations?.[0]?.[0]?.pages?.[0]; - if (!firstPage || !firstPage.locator) - throw new Error('No valid first page found in pageLocations'); + // const firstPage = tuple.builder?.pageLocations?.[0]?.[0]?.pages?.[0]; + // if (!firstPage || !firstPage.locator) + // throw new Error('No valid first page found in pageLocations'); - const pageOffset = Number(firstPage.locator.offset), - pageSize = Number(firstPage.locator.size), - uncompressedPageSize = 8000; - console.log('Compressed size :', pageSize); + // const pageOffset = Number(firstPage.locator.offset), + // pageSize = Number(firstPage.locator.size), + // uncompressedPageSize = 8000; + // console.log('Compressed size :', pageSize); - return tuple.$file.readBuffer([pageOffset, pageSize]).then(compressedPage => { - if (!(compressedPage instanceof DataView)) - throw new Error('Compressed page readBuffer did not return a DataView'); + // return tuple.$file.readBuffer([pageOffset, pageSize]).then(compressedPage => { + // if (!(compressedPage instanceof DataView)) + // throw new Error('Compressed page readBuffer did not return a DataView'); - return R__unzip(compressedPage, uncompressedPageSize).then(unzippedPage => { - if (!(unzippedPage instanceof DataView)) - throw new Error('Unzipped page is not a DataView'); + // return R__unzip(compressedPage, uncompressedPageSize).then(unzippedPage => { + // if (!(unzippedPage instanceof DataView)) + // throw new Error('Unzipped page is not a DataView'); - tuple.builder.deserializePage(unzippedPage); + // tuple.builder.deserializePage(unzippedPage); - return true; - }); - }); + // return true; + // }); + // }); }); }); }); From 14cdddbb4575bcf6bed84bba21b0ebb87c19e1ae Mon Sep 17 00:00:00 2001 From: Krmjn09 Date: Fri, 27 Jun 2025 15:50:11 +0530 Subject: [PATCH 3/9] Added the simple.root --- demo/node/rntuple_test.js | 8 ++++---- demo/node/simple.root | Bin 0 -> 8511 bytes 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 demo/node/simple.root diff --git a/demo/node/rntuple_test.js b/demo/node/rntuple_test.js index 1a78cab6a..9ac5792bd 100644 --- a/demo/node/rntuple_test.js +++ b/demo/node/rntuple_test.js @@ -4,12 +4,12 @@ import { readHeaderFooter } from 'jsroot/rntuple'; console.log(`JSROOT version ${version}`); -const file = await openFile('https://jsroot.gsi.de/files/tmp/ntpl001_staff.root'), -rntuple = await file.readObject('Staff'); +// const file = await openFile('https://jsroot.gsi.de/files/tmp/ntpl001_staff.root'), +// rntuple = await file.readObject('Staff'); -// let file = await openFile('./simple.root'); +const file = await openFile('./simple.root'), -// let rntuple = await file.readObject('myNtuple'); +rntuple = await file.readObject('myNtuple'); await readHeaderFooter(rntuple); diff --git a/demo/node/simple.root b/demo/node/simple.root new file mode 100644 index 0000000000000000000000000000000000000000..3f90a9da175cdca3229c136c5c5adeae7a1ff73d GIT binary patch literal 8511 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 O_w%bnE#l6d2>c(FB@wy+ literal 0 HcmV?d00001 From ff2e65900b1d65898d3335703fe837685b1f0334 Mon Sep 17 00:00:00 2001 From: Krmjn09 Date: Fri, 27 Jun 2025 15:50:32 +0530 Subject: [PATCH 4/9] uncommented the code --- modules/rntuple.mjs | 52 ++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/modules/rntuple.mjs b/modules/rntuple.mjs index ee8f4362c..0cf415522 100644 --- a/modules/rntuple.mjs +++ b/modules/rntuple.mjs @@ -497,14 +497,14 @@ const numRecordCluster = reader.readU32(); } // Example Of Deserializing Page Content -// deserializePage(blob) { -// const reader = new RBufferReader(blob); -// console.log('Deserializing first 10 double values from data page ') -// for (let i = 0; i < 10; ++i) { -// const val = reader.readF64(); -// console.log(val); -// } -// } +deserializePage(blob) { + const reader = new RBufferReader(blob); + console.log('Deserializing first 10 double values from data page ') + for (let i = 0; i < 10; ++i) { + const val = reader.readF64(); + console.log(val); + } +} } @@ -556,31 +556,31 @@ async function readHeaderFooter(tuple) { throw new Error(`Unzipped page list is not a DataView, got ${Object.prototype.toString.call(unzipped_blob)}`); tuple.builder.deserializePageList(unzipped_blob); - return true; + // Read the first page data - // const firstPage = tuple.builder?.pageLocations?.[0]?.[0]?.pages?.[0]; - // if (!firstPage || !firstPage.locator) - // throw new Error('No valid first page found in pageLocations'); + const firstPage = tuple.builder?.pageLocations?.[0]?.[0]?.pages?.[0]; + if (!firstPage || !firstPage.locator) + throw new Error('No valid first page found in pageLocations'); - // const pageOffset = Number(firstPage.locator.offset), - // pageSize = Number(firstPage.locator.size), - // uncompressedPageSize = 8000; - // console.log('Compressed size :', pageSize); + const pageOffset = Number(firstPage.locator.offset), + pageSize = Number(firstPage.locator.size), + uncompressedPageSize = 8000; + console.log('Compressed size :', pageSize); - // return tuple.$file.readBuffer([pageOffset, pageSize]).then(compressedPage => { - // if (!(compressedPage instanceof DataView)) - // throw new Error('Compressed page readBuffer did not return a DataView'); + return tuple.$file.readBuffer([pageOffset, pageSize]).then(compressedPage => { + if (!(compressedPage instanceof DataView)) + throw new Error('Compressed page readBuffer did not return a DataView'); - // return R__unzip(compressedPage, uncompressedPageSize).then(unzippedPage => { - // if (!(unzippedPage instanceof DataView)) - // throw new Error('Unzipped page is not a DataView'); + return R__unzip(compressedPage, uncompressedPageSize).then(unzippedPage => { + if (!(unzippedPage instanceof DataView)) + throw new Error('Unzipped page is not a DataView'); - // tuple.builder.deserializePage(unzippedPage); + tuple.builder.deserializePage(unzippedPage); - // return true; - // }); - // }); + return true; + }); + }); }); }); }); From 13f45a5842e462b291f5bf13c08bf6cf651fbf77 Mon Sep 17 00:00:00 2001 From: Krmjn09 Date: Fri, 27 Jun 2025 15:51:42 +0530 Subject: [PATCH 5/9] removed warnings --- modules/rntuple.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rntuple.mjs b/modules/rntuple.mjs index 0cf415522..67ada3b4d 100644 --- a/modules/rntuple.mjs +++ b/modules/rntuple.mjs @@ -499,7 +499,7 @@ const numRecordCluster = reader.readU32(); // Example Of Deserializing Page Content deserializePage(blob) { const reader = new RBufferReader(blob); - console.log('Deserializing first 10 double values from data page ') + console.log('Deserializing first 10 double values from data page '); for (let i = 0; i < 10; ++i) { const val = reader.readF64(); console.log(val); From a46c75b93593db69caa29fd3657e9a94d26e3773 Mon Sep 17 00:00:00 2001 From: Krmjn09 Date: Mon, 30 Jun 2025 14:18:52 +0530 Subject: [PATCH 6/9] Column Validation --- demo/node/rntuple_test.js | 8 ++++++-- modules/rntuple.mjs | 12 ++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/demo/node/rntuple_test.js b/demo/node/rntuple_test.js index 9ac5792bd..ffc968a3e 100644 --- a/demo/node/rntuple_test.js +++ b/demo/node/rntuple_test.js @@ -1,14 +1,18 @@ import { version, openFile } from 'jsroot'; import { readHeaderFooter } from 'jsroot/rntuple'; - +import path from 'path'; +import { fileURLToPath } from 'url'; console.log(`JSROOT version ${version}`); // const file = await openFile('https://jsroot.gsi.de/files/tmp/ntpl001_staff.root'), // rntuple = await file.readObject('Staff'); -const file = await openFile('./simple.root'), +const __filename = fileURLToPath(import.meta.url), +__dirname = path.dirname(__filename), +rootFilePath = path.join(__dirname, 'simple.root'), +file = await openFile(rootFilePath), rntuple = await file.readObject('myNtuple'); await readHeaderFooter(rntuple); diff --git a/modules/rntuple.mjs b/modules/rntuple.mjs index 67ada3b4d..3b07e6e7f 100644 --- a/modules/rntuple.mjs +++ b/modules/rntuple.mjs @@ -538,6 +538,18 @@ async function readHeaderFooter(tuple) { tuple.builder.deserializeHeader(header_blob); tuple.builder.deserializeFooter(footer_blob); + + // Column Validation +const firstColumn = tuple.builder.columnDescriptors?.[0]; +if (!firstColumn) + throw new Error(' No column descriptor found'); + +if (firstColumn.coltype !== 13) + throw new Error(` Expected column type 7 (kReal64), got ${firstColumn.coltype}`); + +const field = tuple.builder.fieldDescriptors?.[firstColumn.fieldId]; +console.log(`Field: ${field?.name ?? 'undefined'} | Type: ${field?.typeName ?? 'unknown'}`); + // Deserialize the Page List Envelope const group = tuple.builder.clusterGroups?.[0]; if (!group || !group.pageListLocator) From c0068baddc56b219439a57b588e1a7510db3aca8 Mon Sep 17 00:00:00 2001 From: Krmjn09 Date: Mon, 30 Jun 2025 14:35:35 +0530 Subject: [PATCH 7/9] simple method to pass simple.root --- .github/workflows/jsroot-ci.yml | 7 ++++--- demo/node/rntuple_test.js | 9 +-------- modules/rntuple.mjs | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/.github/workflows/jsroot-ci.yml b/.github/workflows/jsroot-ci.yml index 91248eeb4..1bbe109be 100644 --- a/.github/workflows/jsroot-ci.yml +++ b/.github/workflows/jsroot-ci.yml @@ -63,7 +63,7 @@ jobs: node demo/node/file_proxy.js multi ./hsimple.root node demo/node/file_proxy.js buffer ./hsimple.root node demo/node/buffer_test.js - node demo/node/rntuple_test.js + cd demo/node; node rntuple_test.js; cd ../.. tests_ubuntu: runs-on: ubuntu-latest @@ -177,7 +177,7 @@ jobs: node demo/node/file_proxy.js multi ./hsimple.root node demo/node/file_proxy.js buffer ./hsimple.root node demo/node/buffer_test.js - node demo/node/rntuple_test.js + cd demo/node; node rntuple_test.js; cd ../.. build-windows: @@ -226,5 +226,6 @@ jobs: node demo/node/file_proxy.js multi ./hsimple.root node demo/node/file_proxy.js buffer ./hsimple.root node demo/node/buffer_test.js - node demo/node/rntuple_test.js + cd demo/node; node rntuple_test.js; cd ../.. + diff --git a/demo/node/rntuple_test.js b/demo/node/rntuple_test.js index ffc968a3e..c7706001f 100644 --- a/demo/node/rntuple_test.js +++ b/demo/node/rntuple_test.js @@ -1,18 +1,11 @@ import { version, openFile } from 'jsroot'; import { readHeaderFooter } from 'jsroot/rntuple'; -import path from 'path'; -import { fileURLToPath } from 'url'; console.log(`JSROOT version ${version}`); // const file = await openFile('https://jsroot.gsi.de/files/tmp/ntpl001_staff.root'), // rntuple = await file.readObject('Staff'); - -const __filename = fileURLToPath(import.meta.url), -__dirname = path.dirname(__filename), - -rootFilePath = path.join(__dirname, 'simple.root'), -file = await openFile(rootFilePath), +const file = await openFile('simple.root'), rntuple = await file.readObject('myNtuple'); await readHeaderFooter(rntuple); diff --git a/modules/rntuple.mjs b/modules/rntuple.mjs index 3b07e6e7f..023e99aba 100644 --- a/modules/rntuple.mjs +++ b/modules/rntuple.mjs @@ -545,7 +545,7 @@ if (!firstColumn) throw new Error(' No column descriptor found'); if (firstColumn.coltype !== 13) - throw new Error(` Expected column type 7 (kReal64), got ${firstColumn.coltype}`); + throw new Error(` Expected column type 13 (kReal64), got ${firstColumn.coltype}`); const field = tuple.builder.fieldDescriptors?.[firstColumn.fieldId]; console.log(`Field: ${field?.name ?? 'undefined'} | Type: ${field?.typeName ?? 'unknown'}`); From f688eddce842ecbf382ae5e54c836306be26c3ca Mon Sep 17 00:00:00 2001 From: Krmjn09 Date: Mon, 30 Jun 2025 15:00:30 +0530 Subject: [PATCH 8/9] Calculating the uncompressed Size --- modules/rntuple.mjs | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/modules/rntuple.mjs b/modules/rntuple.mjs index 023e99aba..7f18ecf91 100644 --- a/modules/rntuple.mjs +++ b/modules/rntuple.mjs @@ -540,15 +540,34 @@ async function readHeaderFooter(tuple) { tuple.builder.deserializeFooter(footer_blob); // Column Validation -const firstColumn = tuple.builder.columnDescriptors?.[0]; -if (!firstColumn) - throw new Error(' No column descriptor found'); + const firstColumn = tuple.builder.columnDescriptors?.[0]; + if (!firstColumn) + throw new Error(' No column descriptor found'); + + if (firstColumn.coltype !== 13) + throw new Error(` Expected column type 13 (kReal64), got ${firstColumn.coltype}`); + const field = tuple.builder.fieldDescriptors?.[firstColumn.fieldId]; + console.log(`Field: ${field?.name ?? 'undefined'} | Type: ${field?.typeName ?? 'unknown'}`); + + // Returns the size in bytes of one value based on its type + function getElementSize(typeName) { + switch (typeName) { + case 'double': return 8; + case 'float': return 4; + case 'int32_t': + case 'uint32_t': return 4; + case 'int64_t': + case 'uint64_t': return 8; + case 'int16_t': + case 'uint16_t': return 2; + case 'bool': + case 'uint8_t': + case 'int8_t': return 1; + default: + throw new Error(`Unknown type for uncompressed page size: ${typeName}`); + } + } -if (firstColumn.coltype !== 13) - throw new Error(` Expected column type 13 (kReal64), got ${firstColumn.coltype}`); - -const field = tuple.builder.fieldDescriptors?.[firstColumn.fieldId]; -console.log(`Field: ${field?.name ?? 'undefined'} | Type: ${field?.typeName ?? 'unknown'}`); // Deserialize the Page List Envelope const group = tuple.builder.clusterGroups?.[0]; @@ -577,7 +596,13 @@ console.log(`Field: ${field?.name ?? 'undefined'} | Type: ${field?.typeName ?? ' const pageOffset = Number(firstPage.locator.offset), pageSize = Number(firstPage.locator.size), - uncompressedPageSize = 8000; + + // Calculate the uncompressed page size in bytes using element type size and number of elements + elementSize = getElementSize(field?.typeName ?? ''), + numElements = Number(firstPage.numElements), + uncompressedPageSize = elementSize * numElements; + console.log(`Uncompressed page size: ${uncompressedPageSize}`); + console.log('Compressed size :', pageSize); return tuple.$file.readBuffer([pageOffset, pageSize]).then(compressedPage => { From 9a75e5fcff20fcf70d91c18379f6d150cca6d018 Mon Sep 17 00:00:00 2001 From: Krmjn09 Date: Mon, 30 Jun 2025 16:04:14 +0530 Subject: [PATCH 9/9] suggeted changes --- modules/rntuple.mjs | 49 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/modules/rntuple.mjs b/modules/rntuple.mjs index 7f18ecf91..2e08d9355 100644 --- a/modules/rntuple.mjs +++ b/modules/rntuple.mjs @@ -497,13 +497,20 @@ const numRecordCluster = reader.readU32(); } // Example Of Deserializing Page Content -deserializePage(blob) { - const reader = new RBufferReader(blob); - console.log('Deserializing first 10 double values from data page '); - for (let i = 0; i < 10; ++i) { - const val = reader.readF64(); - console.log(val); - } +deserializePage(blob, columnDescriptor, fieldDescriptor) { + const reader = new RBufferReader(blob); + + // Validate the column type before decoding + if (columnDescriptor.coltype !== 13) + throw new Error(`Expected column type 13 (kReal64), got ${columnDescriptor.coltype}`); + + console.log(`Field: ${fieldDescriptor?.fieldName ?? 'undefined'} | Type: ${fieldDescriptor?.typeName ?? 'unknown'}`); + console.log('Deserializing first 10 double values from data page'); + + for (let i = 0; i < 10; ++i) { + const val = reader.readF64(); + console.log(val); + } } @@ -539,15 +546,12 @@ async function readHeaderFooter(tuple) { tuple.builder.deserializeFooter(footer_blob); - // Column Validation + // Extract first column and corresponding field const firstColumn = tuple.builder.columnDescriptors?.[0]; if (!firstColumn) - throw new Error(' No column descriptor found'); - - if (firstColumn.coltype !== 13) - throw new Error(` Expected column type 13 (kReal64), got ${firstColumn.coltype}`); - const field = tuple.builder.fieldDescriptors?.[firstColumn.fieldId]; - console.log(`Field: ${field?.name ?? 'undefined'} | Type: ${field?.typeName ?? 'unknown'}`); + throw new Error('No column descriptor found'); + + const field = tuple.builder.fieldDescriptors?.[firstColumn.fieldId]; // Returns the size in bytes of one value based on its type function getElementSize(typeName) { @@ -589,21 +593,19 @@ async function readHeaderFooter(tuple) { tuple.builder.deserializePageList(unzipped_blob); - // Read the first page data + // Access first page metadata const firstPage = tuple.builder?.pageLocations?.[0]?.[0]?.pages?.[0]; if (!firstPage || !firstPage.locator) throw new Error('No valid first page found in pageLocations'); const pageOffset = Number(firstPage.locator.offset), pageSize = Number(firstPage.locator.size), + elementSize = getElementSize(field?.typeName ?? ''), + numElements = Number(firstPage.numElements), + uncompressedPageSize = elementSize * numElements; - // Calculate the uncompressed page size in bytes using element type size and number of elements - elementSize = getElementSize(field?.typeName ?? ''), - numElements = Number(firstPage.numElements), - uncompressedPageSize = elementSize * numElements; - console.log(`Uncompressed page size: ${uncompressedPageSize}`); - - console.log('Compressed size :', pageSize); + console.log(`Uncompressed page size: ${uncompressedPageSize}`); + console.log(`Compressed page size: ${pageSize}`); return tuple.$file.readBuffer([pageOffset, pageSize]).then(compressedPage => { if (!(compressedPage instanceof DataView)) @@ -613,8 +615,7 @@ async function readHeaderFooter(tuple) { if (!(unzippedPage instanceof DataView)) throw new Error('Unzipped page is not a DataView'); - tuple.builder.deserializePage(unzippedPage); - + tuple.builder.deserializePage(unzippedPage, firstColumn, field); return true; }); });