MCPcopy Index your code
hub / github.com/ChartGPU/ChartGPU / createDataStore

Function createDataStore

src/data/createDataStore.ts:91–331  ·  view source on GitHub ↗
(device: GPUDevice)

Source from the content-addressed store, hash-verified

89}
90
91export function createDataStore(device: GPUDevice): DataStore {
92 const series = new Map<number, SeriesEntry>();
93 let disposed = false;
94
95 // Type guard (avoid relying on Array.isArray narrowing for readonly tuples in strict TS configs).
96 const isTupleDataPoint = (p: DataPoint): p is DataPointTuple => Array.isArray(p);
97
98 const packDataPointsWithXOffset = (points: ReadonlyArray<DataPoint>, xOffset: number): Float32Array => {
99 if (!points || points.length === 0) return new Float32Array(0);
100
101 const buffer = new ArrayBuffer(points.length * 2 * 4);
102 const f32 = new Float32Array(buffer);
103
104 // Hot path: keep logic minimal (validation happens elsewhere in option resolution).
105 for (let i = 0; i < points.length; i++) {
106 const p = points[i]!;
107 const x = isTupleDataPoint(p) ? p[0] : p.x;
108 const y = isTupleDataPoint(p) ? p[1] : p.y;
109
110 // Subtracting before the Float32 cast preserves sub-ULP deltas for large x magnitudes.
111 f32[i * 2 + 0] = x - xOffset;
112 f32[i * 2 + 1] = y;
113 }
114
115 return f32;
116 };
117
118 const assertNotDisposed = (): void => {
119 if (disposed) {
120 throw new Error('DataStore is disposed.');
121 }
122 };
123
124 const getSeriesEntry = (index: number): SeriesEntry => {
125 assertNotDisposed();
126 const entry = series.get(index);
127 if (!entry) {
128 throw new Error(`Series ${index} has no data. Call setSeries(${index}, data) first.`);
129 }
130 return entry;
131 };
132
133 const setSeries = (index: number, data: ReadonlyArray<DataPoint>, options?: Readonly<{ xOffset?: number }>): void => {
134 assertNotDisposed();
135
136 const xOffset = options?.xOffset ?? 0;
137 const packed = xOffset === 0 ? packDataPoints(data) : packDataPointsWithXOffset(data, xOffset);
138 const pointCount = data.length;
139 const hash32 = hashFloat32ArrayBits(packed);
140
141 const requiredBytes = roundUpToMultipleOf4(packed.byteLength);
142 const targetBytes = Math.max(MIN_BUFFER_BYTES, requiredBytes);
143
144 const existing = series.get(index);
145 const unchanged = existing && existing.pointCount === pointCount && existing.hash32 === hash32;
146 if (unchanged) return;
147
148 let buffer = existing?.buffer ?? null;

Callers 2

createRenderCoordinatorFunction · 0.90

Calls

no outgoing calls

Tested by

no test coverage detected