103 lines
2.9 KiB
TypeScript
103 lines
2.9 KiB
TypeScript
import type { CellValue } from "@/lib/dataGrid/cellValue";
|
|
|
|
export interface ExportRowsDiagnostics {
|
|
rowCount: number;
|
|
cellCount: number;
|
|
nullCellCount: number;
|
|
stringCellCount: number;
|
|
numberCellCount: number;
|
|
booleanCellCount: number;
|
|
totalValueChars: number;
|
|
totalValueUtf8Bytes: number;
|
|
maxValueChars: number;
|
|
maxValueUtf8Bytes: number;
|
|
cellsAtLeast1MiB: number;
|
|
cellsAtLeast10MiB: number;
|
|
rowsAtLeast1MiB: number;
|
|
minCellsPerRow: number;
|
|
maxCellsPerRow: number;
|
|
}
|
|
|
|
const MEBIBYTE = 1024 * 1024;
|
|
|
|
function utf8ByteLength(value: string): number {
|
|
let bytes = 0;
|
|
for (let index = 0; index < value.length; index += 1) {
|
|
const code = value.charCodeAt(index);
|
|
if (code <= 0x7f) bytes += 1;
|
|
else if (code <= 0x7ff) bytes += 2;
|
|
else if (code >= 0xd800 && code <= 0xdbff && index + 1 < value.length) {
|
|
const next = value.charCodeAt(index + 1);
|
|
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
bytes += 4;
|
|
index += 1;
|
|
} else bytes += 3;
|
|
} else bytes += 3;
|
|
}
|
|
return bytes;
|
|
}
|
|
|
|
export function summarizeExportRows(rows: readonly (readonly CellValue[])[]): ExportRowsDiagnostics {
|
|
let cellCount = 0;
|
|
let nullCellCount = 0;
|
|
let stringCellCount = 0;
|
|
let numberCellCount = 0;
|
|
let booleanCellCount = 0;
|
|
let totalValueChars = 0;
|
|
let totalValueUtf8Bytes = 0;
|
|
let maxValueChars = 0;
|
|
let maxValueUtf8Bytes = 0;
|
|
let cellsAtLeast1MiB = 0;
|
|
let cellsAtLeast10MiB = 0;
|
|
let rowsAtLeast1MiB = 0;
|
|
let minCellsPerRow = rows.length === 0 ? 0 : Number.POSITIVE_INFINITY;
|
|
let maxCellsPerRow = 0;
|
|
|
|
for (const row of rows) {
|
|
minCellsPerRow = Math.min(minCellsPerRow, row.length);
|
|
maxCellsPerRow = Math.max(maxCellsPerRow, row.length);
|
|
let rowHasLargeCell = false;
|
|
for (const value of row) {
|
|
cellCount += 1;
|
|
if (value === null) {
|
|
nullCellCount += 1;
|
|
continue;
|
|
}
|
|
if (typeof value === "string") stringCellCount += 1;
|
|
else if (typeof value === "number") numberCellCount += 1;
|
|
else booleanCellCount += 1;
|
|
|
|
const text = String(value);
|
|
const utf8Bytes = utf8ByteLength(text);
|
|
totalValueChars += text.length;
|
|
totalValueUtf8Bytes += utf8Bytes;
|
|
maxValueChars = Math.max(maxValueChars, text.length);
|
|
maxValueUtf8Bytes = Math.max(maxValueUtf8Bytes, utf8Bytes);
|
|
if (utf8Bytes >= MEBIBYTE) {
|
|
cellsAtLeast1MiB += 1;
|
|
rowHasLargeCell = true;
|
|
}
|
|
if (utf8Bytes >= 10 * MEBIBYTE) cellsAtLeast10MiB += 1;
|
|
}
|
|
if (rowHasLargeCell) rowsAtLeast1MiB += 1;
|
|
}
|
|
|
|
return {
|
|
rowCount: rows.length,
|
|
cellCount,
|
|
nullCellCount,
|
|
stringCellCount,
|
|
numberCellCount,
|
|
booleanCellCount,
|
|
totalValueChars,
|
|
totalValueUtf8Bytes,
|
|
maxValueChars,
|
|
maxValueUtf8Bytes,
|
|
cellsAtLeast1MiB,
|
|
cellsAtLeast10MiB,
|
|
rowsAtLeast1MiB,
|
|
minCellsPerRow: Number.isFinite(minCellsPerRow) ? minCellsPerRow : 0,
|
|
maxCellsPerRow,
|
|
};
|
|
}
|