@graphty/graph-io 0.3.18 → 0.3.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -2
- package/dist/chunks/{escape-D-gZWO26.js → escape-B-tkk_Cl.js} +74 -16
- package/dist/chunks/escape-B-tkk_Cl.js.map +1 -0
- package/dist/chunks/{writer-GAdltGmC.js → export-Bh60Dv-n.js} +7 -252
- package/dist/chunks/export-Bh60Dv-n.js.map +1 -0
- package/dist/chunks/exporter-BGrsWamJ.js +736 -0
- package/dist/chunks/exporter-BGrsWamJ.js.map +1 -0
- package/dist/chunks/exporter-DIeGJXAZ.js +834 -0
- package/dist/chunks/exporter-DIeGJXAZ.js.map +1 -0
- package/dist/chunks/{importer-Br_QeAeE.js → importer-BWY2FFc5.js} +28 -6
- package/dist/chunks/importer-BWY2FFc5.js.map +1 -0
- package/dist/chunks/importer-BaQpCEcJ.js +2194 -0
- package/dist/chunks/importer-BaQpCEcJ.js.map +1 -0
- package/dist/chunks/importer-DD-xv9_Y.js +1471 -0
- package/dist/chunks/importer-DD-xv9_Y.js.map +1 -0
- package/dist/chunks/{importer-aNJfe0qu.js → importer-DEcKhsmQ.js} +2 -2
- package/dist/chunks/{importer-aNJfe0qu.js.map → importer-DEcKhsmQ.js.map} +1 -1
- package/dist/chunks/{importer-DHagxvDD.js → importer-DIrbbnAf.js} +6 -4
- package/dist/chunks/{importer-DHagxvDD.js.map → importer-DIrbbnAf.js.map} +1 -1
- package/dist/chunks/importer-D_e7e7LX.js +3055 -0
- package/dist/chunks/importer-D_e7e7LX.js.map +1 -0
- package/dist/chunks/{importer-Du5crN9l.js → importer-Wv4C4gaF.js} +278 -82
- package/dist/chunks/importer-Wv4C4gaF.js.map +1 -0
- package/dist/chunks/importer-vi3bSdtw.js +1713 -0
- package/dist/chunks/importer-vi3bSdtw.js.map +1 -0
- package/dist/chunks/{importer-d0uQxFp6.js → importer-zGLo8Dg_.js} +6 -4
- package/dist/chunks/{importer-d0uQxFp6.js.map → importer-zGLo8Dg_.js.map} +1 -1
- package/dist/chunks/json-elements-DDS8N2Dd.js +779 -0
- package/dist/chunks/json-elements-DDS8N2Dd.js.map +1 -0
- package/dist/chunks/{records-Bk9jgodz.js → records-dbRkxwaq.js} +2 -2
- package/dist/chunks/{records-Bk9jgodz.js.map → records-dbRkxwaq.js.map} +1 -1
- package/dist/chunks/{report-BOk0p5y8.js → report-B1z4WT9e.js} +143 -111
- package/dist/chunks/{report-BOk0p5y8.js.map → report-B1z4WT9e.js.map} +1 -1
- package/dist/chunks/weights-Dzba96G3.js +176 -0
- package/dist/chunks/weights-Dzba96G3.js.map +1 -0
- package/dist/chunks/writer-C7flM-Ih.js +77 -0
- package/dist/chunks/writer-C7flM-Ih.js.map +1 -0
- package/dist/csv.js +6 -4
- package/dist/csv.js.map +1 -1
- package/dist/cx.d.ts +1 -0
- package/dist/cx.js +6 -0
- package/dist/cx.js.map +1 -0
- package/dist/cx2.d.ts +1 -0
- package/dist/cx2.js +10 -0
- package/dist/cx2.js.map +1 -0
- package/dist/cys.d.ts +1 -0
- package/dist/cys.js +6 -0
- package/dist/cys.js.map +1 -0
- package/dist/dot.js +1 -1
- package/dist/gexf.js +16 -4
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +13 -14
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +302 -399
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +1 -1
- package/dist/json.js +1 -1
- package/dist/neo4j.js +6 -4
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.js +1 -1
- package/dist/pajek.js +1 -1
- package/dist/src/common/cell-budget.d.ts +84 -0
- package/dist/src/common/cell-budget.d.ts.map +1 -0
- package/dist/src/common/cell-budget.js +138 -0
- package/dist/src/common/cell-budget.js.map +1 -0
- package/dist/src/common/input.d.ts +10 -0
- package/dist/src/common/input.d.ts.map +1 -1
- package/dist/src/common/input.js +39 -0
- package/dist/src/common/input.js.map +1 -1
- package/dist/src/common/json-elements.d.ts +286 -0
- package/dist/src/common/json-elements.d.ts.map +1 -0
- package/dist/src/common/json-elements.js +926 -0
- package/dist/src/common/json-elements.js.map +1 -0
- package/dist/src/common/options.d.ts +6 -0
- package/dist/src/common/options.d.ts.map +1 -1
- package/dist/src/common/options.js +1 -1
- package/dist/src/common/options.js.map +1 -1
- package/dist/src/common/xml.d.ts +37 -3
- package/dist/src/common/xml.d.ts.map +1 -1
- package/dist/src/common/xml.js +86 -6
- package/dist/src/common/xml.js.map +1 -1
- package/dist/src/common/zip.d.ts +92 -0
- package/dist/src/common/zip.d.ts.map +1 -0
- package/dist/src/common/zip.js +399 -0
- package/dist/src/common/zip.js.map +1 -0
- package/dist/src/formats/cx/importer.d.ts +133 -0
- package/dist/src/formats/cx/importer.d.ts.map +1 -0
- package/dist/src/formats/cx/importer.js +2220 -0
- package/dist/src/formats/cx/importer.js.map +1 -0
- package/dist/src/formats/cx/index.d.ts +7 -0
- package/dist/src/formats/cx/index.d.ts.map +1 -0
- package/dist/src/formats/cx/index.js +7 -0
- package/dist/src/formats/cx/index.js.map +1 -0
- package/dist/src/formats/cx2/exporter.d.ts +59 -0
- package/dist/src/formats/cx2/exporter.d.ts.map +1 -0
- package/dist/src/formats/cx2/exporter.js +864 -0
- package/dist/src/formats/cx2/exporter.js.map +1 -0
- package/dist/src/formats/cx2/importer.d.ts +169 -0
- package/dist/src/formats/cx2/importer.d.ts.map +1 -0
- package/dist/src/formats/cx2/importer.js +1652 -0
- package/dist/src/formats/cx2/importer.js.map +1 -0
- package/dist/src/formats/cx2/index.d.ts +7 -0
- package/dist/src/formats/cx2/index.d.ts.map +1 -0
- package/dist/src/formats/cx2/index.js +7 -0
- package/dist/src/formats/cx2/index.js.map +1 -0
- package/dist/src/formats/cys/constants.d.ts +68 -0
- package/dist/src/formats/cys/constants.d.ts.map +1 -0
- package/dist/src/formats/cys/constants.js +76 -0
- package/dist/src/formats/cys/constants.js.map +1 -0
- package/dist/src/formats/cys/importer.d.ts +38 -0
- package/dist/src/formats/cys/importer.d.ts.map +1 -0
- package/dist/src/formats/cys/importer.js +830 -0
- package/dist/src/formats/cys/importer.js.map +1 -0
- package/dist/src/formats/cys/index.d.ts +7 -0
- package/dist/src/formats/cys/index.d.ts.map +1 -0
- package/dist/src/formats/cys/index.js +7 -0
- package/dist/src/formats/cys/index.js.map +1 -0
- package/dist/src/formats/cys/session.d.ts +132 -0
- package/dist/src/formats/cys/session.d.ts.map +1 -0
- package/dist/src/formats/cys/session.js +315 -0
- package/dist/src/formats/cys/session.js.map +1 -0
- package/dist/src/formats/cys/tables.d.ts +90 -0
- package/dist/src/formats/cys/tables.d.ts.map +1 -0
- package/dist/src/formats/cys/tables.js +293 -0
- package/dist/src/formats/cys/tables.js.map +1 -0
- package/dist/src/formats/dot/exporter.d.ts +2 -0
- package/dist/src/formats/dot/exporter.d.ts.map +1 -1
- package/dist/src/formats/dot/exporter.js +12 -0
- package/dist/src/formats/dot/exporter.js.map +1 -1
- package/dist/src/formats/dot/importer.js +6 -2
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/gexf/exporter.d.ts +2 -0
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +6 -0
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/gexf/importer.d.ts +0 -2
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +1 -3
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gexf/index.d.ts +1 -1
- package/dist/src/formats/gexf/index.js +2 -2
- package/dist/src/formats/gexf/index.js.map +1 -1
- package/dist/src/formats/gml/exporter.d.ts +0 -8
- package/dist/src/formats/gml/exporter.d.ts.map +1 -1
- package/dist/src/formats/gml/exporter.js +8 -18
- package/dist/src/formats/gml/exporter.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +6 -104
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/xgmml/columns.d.ts +152 -0
- package/dist/src/formats/xgmml/columns.d.ts.map +1 -0
- package/dist/src/formats/xgmml/columns.js +593 -0
- package/dist/src/formats/xgmml/columns.js.map +1 -0
- package/dist/src/formats/xgmml/constants.d.ts +196 -0
- package/dist/src/formats/xgmml/constants.d.ts.map +1 -0
- package/dist/src/formats/xgmml/constants.js +197 -0
- package/dist/src/formats/xgmml/constants.js.map +1 -0
- package/dist/src/formats/xgmml/document.d.ts +361 -0
- package/dist/src/formats/xgmml/document.d.ts.map +1 -0
- package/dist/src/formats/xgmml/document.js +695 -0
- package/dist/src/formats/xgmml/document.js.map +1 -0
- package/dist/src/formats/xgmml/emit.d.ts +341 -0
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -0
- package/dist/src/formats/xgmml/emit.js +1275 -0
- package/dist/src/formats/xgmml/emit.js.map +1 -0
- package/dist/src/formats/xgmml/exporter.d.ts +24 -0
- package/dist/src/formats/xgmml/exporter.d.ts.map +1 -0
- package/dist/src/formats/xgmml/exporter.js +999 -0
- package/dist/src/formats/xgmml/exporter.js.map +1 -0
- package/dist/src/formats/xgmml/importer.d.ts +58 -0
- package/dist/src/formats/xgmml/importer.d.ts.map +1 -0
- package/dist/src/formats/xgmml/importer.js +360 -0
- package/dist/src/formats/xgmml/importer.js.map +1 -0
- package/dist/src/formats/xgmml/index.d.ts +8 -0
- package/dist/src/formats/xgmml/index.d.ts.map +1 -0
- package/dist/src/formats/xgmml/index.js +8 -0
- package/dist/src/formats/xgmml/index.js.map +1 -0
- package/dist/src/formats/xgmml/values.d.ts +60 -0
- package/dist/src/formats/xgmml/values.d.ts.map +1 -0
- package/dist/src/formats/xgmml/values.js +148 -0
- package/dist/src/formats/xgmml/values.js.map +1 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/registry.d.ts +7 -0
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +30 -10
- package/dist/src/registry.js.map +1 -1
- package/dist/src/sniff.d.ts +1 -1
- package/dist/src/sniff.d.ts.map +1 -1
- package/dist/src/sniff.js +4 -0
- package/dist/src/sniff.js.map +1 -1
- package/dist/xgmml.d.ts +1 -0
- package/dist/xgmml.js +9 -0
- package/dist/xgmml.js.map +1 -0
- package/package.json +25 -2
- package/src/common/cell-budget.ts +170 -0
- package/src/common/input.ts +40 -0
- package/src/common/json-elements.ts +1147 -0
- package/src/common/options.ts +1 -1
- package/src/common/xml.ts +127 -6
- package/src/common/zip.ts +472 -0
- package/src/formats/cx/importer.ts +2733 -0
- package/src/formats/cx/index.ts +7 -0
- package/src/formats/cx2/exporter.ts +1036 -0
- package/src/formats/cx2/importer.ts +2187 -0
- package/src/formats/cx2/index.ts +7 -0
- package/src/formats/cys/constants.ts +99 -0
- package/src/formats/cys/importer.ts +1100 -0
- package/src/formats/cys/index.ts +7 -0
- package/src/formats/cys/session.ts +428 -0
- package/src/formats/cys/tables.ts +400 -0
- package/src/formats/dot/exporter.ts +17 -0
- package/src/formats/dot/importer.ts +6 -2
- package/src/formats/gexf/exporter.ts +11 -0
- package/src/formats/gexf/importer.ts +1 -2
- package/src/formats/gexf/index.ts +1 -1
- package/src/formats/gml/exporter.ts +8 -19
- package/src/formats/json/importer.ts +6 -105
- package/src/formats/xgmml/columns.ts +747 -0
- package/src/formats/xgmml/constants.ts +265 -0
- package/src/formats/xgmml/document.ts +975 -0
- package/src/formats/xgmml/emit.ts +1563 -0
- package/src/formats/xgmml/exporter.ts +1215 -0
- package/src/formats/xgmml/importer.ts +491 -0
- package/src/formats/xgmml/index.ts +8 -0
- package/src/formats/xgmml/values.ts +183 -0
- package/src/index.ts +19 -0
- package/src/registry.ts +46 -15
- package/src/sniff.ts +18 -1
- package/dist/chunks/escape-D-gZWO26.js.map +0 -1
- package/dist/chunks/importer-Br_QeAeE.js.map +0 -1
- package/dist/chunks/importer-Du5crN9l.js.map +0 -1
- package/dist/chunks/writer-GAdltGmC.js.map +0 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A memory guard for the builder importGraph() fills. graph-format stores every attribute as a dense
|
|
3
|
+
* column, one slot per node (or edge) whether or not that element has a value, so a file whose nodes
|
|
4
|
+
* each carry a differently named attribute holds n values but allocates n x n slots: a few hundred
|
|
5
|
+
* kilobytes of input can need gigabytes. The guard counts the slots that hold no value and stops the
|
|
6
|
+
* import once they pass a limit. A dense file has almost no empty slots, so it is never stopped
|
|
7
|
+
* however large it is.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
type ColumnDecl,
|
|
12
|
+
type ColumnHandle,
|
|
13
|
+
GraphBuilder,
|
|
14
|
+
type GraphBuilderOptions,
|
|
15
|
+
GraphFormatError,
|
|
16
|
+
type NodeId,
|
|
17
|
+
} from "@graphty/graph-format";
|
|
18
|
+
|
|
19
|
+
import { describe } from "./options.js";
|
|
20
|
+
import { ImportReportBuilder } from "./report.js";
|
|
21
|
+
|
|
22
|
+
/** The issue code of an import stopped for allocating too many empty attribute slots. */
|
|
23
|
+
export const TOO_MANY_EMPTY_CELLS_CODE = "E_TOO_MANY_EMPTY_CELLS";
|
|
24
|
+
|
|
25
|
+
/** The default limit: 2^24 empty slots, about 130 MB of f64 columns. */
|
|
26
|
+
const DEFAULT_MAX_EMPTY_CELLS = 2 ** 24;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Resolve the maxEmptyCells option.
|
|
30
|
+
* @param value - the caller's value
|
|
31
|
+
* @returns a non-negative integer or Infinity
|
|
32
|
+
* @throws GraphFormatError E_UNSUPPORTED for anything else
|
|
33
|
+
*/
|
|
34
|
+
export function maxEmptyCellsOption(value: unknown): number {
|
|
35
|
+
if (value === undefined) {
|
|
36
|
+
return DEFAULT_MAX_EMPTY_CELLS;
|
|
37
|
+
}
|
|
38
|
+
if (typeof value === "number" && value >= 0 && (Number.isInteger(value) || value === Infinity)) {
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
throw new GraphFormatError(
|
|
42
|
+
"E_UNSUPPORTED",
|
|
43
|
+
`option maxEmptyCells: ${describe(value)} is not a non-negative integer or Infinity`,
|
|
44
|
+
{ option: "maxEmptyCells", found: value },
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** A GraphBuilder that throws an ImportError once its attribute columns hold too many empty slots. */
|
|
49
|
+
export class CellBudgetBuilder extends GraphBuilder {
|
|
50
|
+
private readonly nodeColumns = new Set<number>();
|
|
51
|
+
private readonly edgeColumns = new Set<number>();
|
|
52
|
+
private values = 0;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create a builder with a limit.
|
|
56
|
+
* @param options - the builder options
|
|
57
|
+
* @param format - the format being read, for the error's report
|
|
58
|
+
* @param maxEmptyCells - the most empty slots allowed
|
|
59
|
+
*/
|
|
60
|
+
constructor(
|
|
61
|
+
options: GraphBuilderOptions,
|
|
62
|
+
private readonly format: string,
|
|
63
|
+
private readonly maxEmptyCells: number,
|
|
64
|
+
) {
|
|
65
|
+
super(options);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Add a node, then check the limit (its row adds a slot to every node column).
|
|
70
|
+
* @param id - the node id
|
|
71
|
+
* @returns the node index
|
|
72
|
+
*/
|
|
73
|
+
override addNode(id: NodeId): number {
|
|
74
|
+
const index = super.addNode(id);
|
|
75
|
+
this.checkBudget();
|
|
76
|
+
return index;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Add an edge, then check the limit (its row adds a slot to every edge column).
|
|
81
|
+
* @param source - source id
|
|
82
|
+
* @param target - target id
|
|
83
|
+
* @param weight - the weight
|
|
84
|
+
* @returns the edge index
|
|
85
|
+
*/
|
|
86
|
+
override addEdge(source: NodeId, target: NodeId, weight?: number): number {
|
|
87
|
+
const edge = super.addEdge(source, target, weight);
|
|
88
|
+
this.checkBudget();
|
|
89
|
+
return edge;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Declare a node column, then check the limit.
|
|
94
|
+
* @param decl - the declaration
|
|
95
|
+
* @returns the column handle
|
|
96
|
+
*/
|
|
97
|
+
override declareNodeColumn(decl: ColumnDecl): ColumnHandle {
|
|
98
|
+
const handle = super.declareNodeColumn(decl);
|
|
99
|
+
this.nodeColumns.add(handle);
|
|
100
|
+
this.checkBudget();
|
|
101
|
+
return handle;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Declare an edge column, then check the limit.
|
|
106
|
+
* @param decl - the declaration
|
|
107
|
+
* @returns the column handle
|
|
108
|
+
*/
|
|
109
|
+
override declareEdgeColumn(decl: ColumnDecl): ColumnHandle {
|
|
110
|
+
const handle = super.declareEdgeColumn(decl);
|
|
111
|
+
this.edgeColumns.add(handle);
|
|
112
|
+
this.checkBudget();
|
|
113
|
+
return handle;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Set a node cell (a new name declares a column), then check the limit.
|
|
118
|
+
* @param column - the handle or name
|
|
119
|
+
* @param index - the node index
|
|
120
|
+
* @param value - the value
|
|
121
|
+
*/
|
|
122
|
+
override setNodeValue(column: ColumnHandle | string, index: number, value: unknown): void {
|
|
123
|
+
super.setNodeValue(column, index, value);
|
|
124
|
+
this.nodeColumns.add(typeof column === "string" ? this.nodeColumn(column) : column);
|
|
125
|
+
this.count(value);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Set an edge cell (a new name declares a column), then check the limit.
|
|
130
|
+
* @param column - the handle or name
|
|
131
|
+
* @param edge - the edge index
|
|
132
|
+
* @param value - the value
|
|
133
|
+
*/
|
|
134
|
+
override setEdgeValue(column: ColumnHandle | string, edge: number, value: unknown): void {
|
|
135
|
+
super.setEdgeValue(column, edge, value);
|
|
136
|
+
this.edgeColumns.add(typeof column === "string" ? this.edgeColumn(column) : column);
|
|
137
|
+
this.count(value);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Count a written value and check the budget.
|
|
142
|
+
* @param value - the value; null and undefined unset a slot and do not count
|
|
143
|
+
*/
|
|
144
|
+
private count(value: unknown): void {
|
|
145
|
+
if (value !== null && value !== undefined) {
|
|
146
|
+
this.values++;
|
|
147
|
+
}
|
|
148
|
+
this.checkBudget();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Throw when the columns' slots minus the values written pass the limit.
|
|
153
|
+
* @throws ImportError E_TOO_MANY_EMPTY_CELLS
|
|
154
|
+
*/
|
|
155
|
+
private checkBudget(): void {
|
|
156
|
+
const slots = this.nodeColumns.size * this.nodeBound + this.edgeColumns.size * this.edgeBound;
|
|
157
|
+
const empty = slots - this.values;
|
|
158
|
+
if (empty > this.maxEmptyCells) {
|
|
159
|
+
new ImportReportBuilder(this.format, Infinity).fail(
|
|
160
|
+
TOO_MANY_EMPTY_CELLS_CODE,
|
|
161
|
+
`the attributes are too sparse: ${this.nodeColumns.size} node and ${this.edgeColumns.size} edge ` +
|
|
162
|
+
`attribute column(s) over ${this.nodeBound} node(s) and ${this.edgeBound} edge(s) would ` +
|
|
163
|
+
`allocate more than ${this.maxEmptyCells} slots that hold no value; pass a larger ` +
|
|
164
|
+
`maxEmptyCells (or Infinity) to read the file anyway`,
|
|
165
|
+
undefined,
|
|
166
|
+
{ emptyCells: empty, maxEmptyCells: this.maxEmptyCells },
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
package/src/common/input.ts
CHANGED
|
@@ -529,6 +529,46 @@ async function* streamChunks(
|
|
|
529
529
|
}
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
+
/**
|
|
533
|
+
* Read the whole input as bytes, for a binary format (a zip): nothing is decoded. The signal is
|
|
534
|
+
* checked before every chunk and progress reported after it; a stream is cancelled when the read
|
|
535
|
+
* stops early.
|
|
536
|
+
* @param input - the input
|
|
537
|
+
* @param options - cancellation and progress (the encoding is ignored)
|
|
538
|
+
* @returns the bytes, or null when the input is text (a string, or a chunk that is a string),
|
|
539
|
+
* which a binary format cannot read
|
|
540
|
+
*/
|
|
541
|
+
export async function readBytes(input: ImportInput, options: ReadOptions = {}): Promise<Uint8Array | null> {
|
|
542
|
+
const signal = options.signal ?? null;
|
|
543
|
+
throwIfAborted(signal);
|
|
544
|
+
if (typeof input === "string") {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
if (input instanceof Uint8Array) {
|
|
548
|
+
options.onProgress?.(input.byteLength, input.byteLength);
|
|
549
|
+
return input;
|
|
550
|
+
}
|
|
551
|
+
const parts: Uint8Array[] = [];
|
|
552
|
+
let done = 0;
|
|
553
|
+
for await (const chunk of isReadableStream(input) ? streamChunks(input, signal) : input) {
|
|
554
|
+
throwIfAborted(signal);
|
|
555
|
+
if (typeof chunk === "string") {
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
if (!(chunk instanceof Uint8Array)) {
|
|
559
|
+
throw new GraphFormatError("E_UNSUPPORTED", "an input chunk must be a string or a Uint8Array", {
|
|
560
|
+
reason: "chunk type",
|
|
561
|
+
found: typeof chunk,
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
parts.push(chunk);
|
|
565
|
+
done += chunk.byteLength;
|
|
566
|
+
options.onProgress?.(done);
|
|
567
|
+
}
|
|
568
|
+
options.onProgress?.(done, done);
|
|
569
|
+
return parts.length === 0 ? new Uint8Array(0) : concatBytes(parts);
|
|
570
|
+
}
|
|
571
|
+
|
|
532
572
|
/**
|
|
533
573
|
* Read the whole input as one string (the GML / DOT / JSON path, design section 8.4).
|
|
534
574
|
* @param input - the input
|