@lazarusa/netcdf4-wasm-test 0.2.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 netcdf4-wasm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,386 @@
1
+ # netcdf4-wasm
2
+
3
+ NetCDF4 library compiled to WebAssembly with JavaScript/TypeScript bindings.
4
+
5
+ ## Overview
6
+
7
+ This project provides a complete WebAssembly port of the NetCDF4 C library, enabling NetCDF file operations in browser and Node.js environments. It includes:
8
+
9
+ - Complete NetCDF4 C library compiled to WASM using Emscripten
10
+ - High-level TypeScript/JavaScript API
11
+ - Support for reading and writing NetCDF4 files
12
+ - Comprehensive test suite
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install netcdf4-wasm
18
+ ```
19
+
20
+ ## Prerequisites
21
+
22
+ For building from source, you'll need:
23
+
24
+ - Emscripten SDK
25
+ - CMake
26
+ - Make
27
+ - wget or curl
28
+
29
+ Check dependencies:
30
+
31
+ ```bash
32
+ npm run check-deps
33
+ ```
34
+
35
+ Install Emscripten locally:
36
+
37
+ ```bash
38
+ npm run install-emscripten
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ The JavaScript API is modeled closely on the [netcdf4-python](https://unidata.github.io/netcdf4-python) API.
44
+
45
+ ### Basic Example
46
+
47
+ ```typescript
48
+ import { Dataset } from "netcdf4-wasm";
49
+ // or: import { NetCDF4 } from 'netcdf4-wasm';
50
+
51
+ async function example() {
52
+ // Create a new NetCDF file (similar to Python netCDF4.Dataset)
53
+ const nc = await Dataset("example.nc", "w", { format: "NETCDF4" });
54
+ // or: const nc = await NetCDF4.Dataset('example.nc', 'w', { format: 'NETCDF4' });
55
+
56
+ // Create dimensions
57
+ const lat = await nc.createDimension("lat", 73);
58
+ const lon = await nc.createDimension("lon", 144);
59
+ const time = await nc.createDimension("time", null); // unlimited dimension
60
+
61
+ // Create variables
62
+ const temp = await nc.createVariable("temperature", "f4", [
63
+ "time",
64
+ "lat",
65
+ "lon",
66
+ ]);
67
+ const times = await nc.createVariable("time", "f8", ["time"]);
68
+
69
+ // Set variable attributes
70
+ temp.units = "Kelvin";
71
+ temp.long_name = "surface temperature";
72
+ times.units = "hours since 0001-01-01 00:00:00.0";
73
+ times.calendar = "gregorian";
74
+
75
+ // Set global attributes
76
+ nc.setncattr("description", "bogus example script");
77
+ nc.setncattr("history", "Created " + new Date().toISOString());
78
+ nc.setncattr("source", "netCDF4-wasm example");
79
+
80
+ // Write data
81
+ const tempData = new Float64Array(73 * 144);
82
+ tempData.fill(288.0); // Fill with 288K
83
+ await temp.setValue(tempData);
84
+
85
+ // Close the file
86
+ await nc.close();
87
+ }
88
+ ```
89
+
90
+ ### Reading Files
91
+
92
+ ```typescript
93
+ import { Dataset } from "netcdf4-wasm";
94
+
95
+ async function readExample() {
96
+ // Open existing file for reading
97
+ const nc = await Dataset("data.nc", "r");
98
+
99
+ // Access dimensions
100
+ console.log("Dimensions:", Object.keys(nc.dimensions));
101
+ console.log("Time dimension size:", nc.dimensions.time.size);
102
+
103
+ // Access variables
104
+ console.log("Variables:", Object.keys(nc.variables));
105
+ const temp = nc.variables.temperature;
106
+
107
+ // Read variable attributes
108
+ console.log("Temperature units:", temp.units);
109
+ console.log("Temperature long name:", temp.long_name);
110
+
111
+ // Read data
112
+ const data = await temp.getValue();
113
+ console.log("Temperature data shape:", data.length);
114
+ console.log("First few values:", data.slice(0, 5));
115
+
116
+ // Access global attributes
117
+ console.log("Global attributes:", nc.ncattrs());
118
+ console.log("Description:", nc.getncattr("description"));
119
+
120
+ await nc.close();
121
+ }
122
+ ```
123
+
124
+ ### Alternative Constructor (Direct Instantiation)
125
+
126
+ ```typescript
127
+ import { NetCDF4 } from "netcdf4-wasm";
128
+
129
+ async function directExample() {
130
+ // Direct instantiation (requires manual initialization)
131
+ const nc = new NetCDF4("example.nc", "w", { format: "NETCDF4" });
132
+ await nc.initialize();
133
+
134
+ // Use same API as above...
135
+ const lat = await nc.createDimension("lat", 10);
136
+ const temp = await nc.createVariable("temperature", "f8", ["lat"]);
137
+
138
+ await nc.close();
139
+ }
140
+ ```
141
+
142
+ ### Working with Groups
143
+
144
+ ```typescript
145
+ async function groupExample() {
146
+ const nc = await Dataset("grouped.nc", "w", { format: "NETCDF4" });
147
+
148
+ // Create a group
149
+ const forecasts = nc.createGroup("forecasts");
150
+
151
+ // Create dimensions and variables in the group
152
+ const time = await forecasts.createDimension("time", 24);
153
+ const temp = await forecasts.createVariable("temperature", "f4", ["time"]);
154
+
155
+ // Set group attributes
156
+ forecasts.setncattr("description", "Forecast data");
157
+
158
+ await nc.close();
159
+ }
160
+ ```
161
+
162
+ ## API Reference
163
+
164
+ The API closely follows netcdf4-python conventions for ease of use by scientists familiar with Python.
165
+
166
+ ### Classes
167
+
168
+ #### `NetCDF4`
169
+
170
+ Main class for NetCDF file operations, similar to `netCDF4.Dataset` in Python.
171
+
172
+ **Constructor**
173
+
174
+ ```typescript
175
+ new NetCDF4(filename?: string, mode?: string, options?: NetCDF4WasmOptions)
176
+ ```
177
+
178
+ **Static Methods**
179
+
180
+ - `NetCDF4.Dataset(filename: string, mode?: string, options?: object): Promise<NetCDF4>` - Factory method (Python-like)
181
+
182
+ **Module Functions**
183
+
184
+ - `Dataset(filename: string, mode?: string, options?: object): Promise<NetCDF4>` - Convenience function (import directly)
185
+
186
+ **Properties**
187
+
188
+ - `dimensions: {[name: string]: Dimension}` - Dictionary of dimensions
189
+ - `variables: {[name: string]: Variable}` - Dictionary of variables
190
+ - `groups: {[name: string]: Group}` - Dictionary of groups
191
+ - `file_format: string` - File format (e.g., 'NETCDF4')
192
+ - `filepath: string` - Path to the file
193
+ - `isopen: boolean` - Whether file is currently open
194
+
195
+ **Methods**
196
+
197
+ _File Operations_
198
+
199
+ - `initialize(): Promise<void>` - Initialize the WASM module
200
+ - `close(): Promise<void>` - Close the file
201
+ - `sync(): Promise<void>` - Flush data to disk
202
+
203
+ _Structure Definition_
204
+
205
+ - `createDimension(name: string, size: number): Promise<Dimension>` - Create dimension
206
+ - `createVariable(name: string, datatype: string, dimensions: string[], options?: object): Promise<Variable>` - Create variable
207
+ - `createGroup(name: string): Group` - Create hierarchical group
208
+
209
+ _Attribute Access_
210
+
211
+ - `setncattr(name: string, value: any): void` - Set global attribute
212
+ - `getncattr(name: string): any` - Get global attribute
213
+ - `ncattrs(): string[]` - List all global attributes
214
+
215
+ #### `Variable`
216
+
217
+ Represents a NetCDF variable, similar to Python's Variable class.
218
+
219
+ **Properties**
220
+
221
+ - `name: string` - Variable name
222
+ - `datatype: string` - Data type ('f4', 'f8', 'i4', etc.)
223
+ - `dimensions: string[]` - Dimension names
224
+ - `units: string` - Units attribute (convenience property)
225
+ - `long_name: string` - Long name attribute (convenience property)
226
+ - `standard_name: string` - Standard name attribute (convenience property)
227
+
228
+ **Methods**
229
+
230
+ - `getValue(): Promise<Float64Array>` - Read variable data
231
+ - `setValue(data: Float64Array): Promise<void>` - Write variable data
232
+ - `setncattr(name: string, value: any): void` - Set variable attribute
233
+ - `getncattr(name: string): any` - Get variable attribute
234
+ - `ncattrs(): string[]` - List variable attributes
235
+
236
+ #### `Dimension`
237
+
238
+ Represents a NetCDF dimension.
239
+
240
+ **Properties**
241
+
242
+ - `name: string` - Dimension name
243
+ - `size: number` - Dimension size
244
+ - `isUnlimited: boolean` - Whether dimension is unlimited
245
+
246
+ **Methods**
247
+
248
+ - `__len__(): number` - Get dimension size (Python-like)
249
+
250
+ ### Constants
251
+
252
+ The `NC_CONSTANTS` object provides NetCDF constants:
253
+
254
+ ```typescript
255
+ NC_CONSTANTS.NC_NOERR; // No error
256
+ NC_CONSTANTS.NC_NOWRITE; // Read-only access
257
+ NC_CONSTANTS.NC_WRITE; // Write access
258
+ NC_CONSTANTS.NC_CLOBBER; // Overwrite existing file
259
+ NC_CONSTANTS.NC_NETCDF4; // NetCDF4 format
260
+ NC_CONSTANTS.NC_DOUBLE; // Double data type
261
+ NC_CONSTANTS.NC_UNLIMITED; // Unlimited dimension
262
+ ```
263
+
264
+ ## Building
265
+
266
+ ### Install dependencies
267
+
268
+ ```bash
269
+ npm install
270
+ ```
271
+
272
+ ### Check build dependencies
273
+
274
+ ```bash
275
+ npm run check-deps
276
+ ```
277
+
278
+ ### Build the project
279
+
280
+ ```bash
281
+ npm run build
282
+ ```
283
+
284
+ This will:
285
+
286
+ 1. Download and compile zlib, HDF5, and NetCDF4 C libraries
287
+ 2. Create the WASM module with Emscripten
288
+ 3. Compile TypeScript bindings
289
+
290
+ ### Clean build artifacts
291
+
292
+ ```bash
293
+ npm run clean
294
+ ```
295
+
296
+ ## Testing
297
+
298
+ Run tests:
299
+
300
+ ```bash
301
+ npm test
302
+ ```
303
+
304
+ Run tests with coverage:
305
+
306
+ ```bash
307
+ npm run test:coverage
308
+ ```
309
+
310
+ Watch mode:
311
+
312
+ ```bash
313
+ npm run test:watch
314
+ ```
315
+
316
+ ## Development
317
+
318
+ ### Project Structure
319
+
320
+ ```
321
+ netcdf4-wasm/
322
+ ├── src/ # TypeScript source code
323
+ │ ├── index.ts # Main API exports
324
+ │ ├── types.ts # Type definitions
325
+ │ ├── constants.ts # NetCDF constants
326
+ │ ├── netcdf4.ts # Main NetCDF4 class
327
+ │ ├── group.ts # Group class
328
+ │ ├── variable.ts # Variable class
329
+ │ ├── dimension.ts # Dimension class
330
+ │ ├── wasm-module.ts # WASM module loader
331
+ │ └── __tests__/ # Test files
332
+ ├── scripts/ # Build scripts
333
+ │ ├── build-wasm.sh # Main WASM build script
334
+ │ ├── check-dependencies.sh
335
+ │ └── install-emscripten.sh
336
+ ├── bindings/ # WASM bindings
337
+ │ ├── pre.js # Pre-run JavaScript
338
+ │ └── post.js # Post-run JavaScript
339
+ ├── build/ # Build artifacts (generated)
340
+ ├── dist/ # Distribution files (generated)
341
+ └── package.json
342
+ ```
343
+
344
+ ### Contributing
345
+
346
+ 1. Fork the repository
347
+ 2. Create a feature branch
348
+ 3. Make your changes
349
+ 4. Add tests for new functionality
350
+ 5. Run the test suite
351
+ 6. Submit a pull request
352
+
353
+ ## License
354
+
355
+ MIT License - see LICENSE file for details.
356
+
357
+ ## NetCDF4 Documentation
358
+
359
+ For more information about NetCDF4, visit: https://docs.unidata.ucar.edu/netcdf-c/current/
360
+
361
+ ## Troubleshooting
362
+
363
+ ### WASM Module Not Found
364
+
365
+ Make sure the WASM files are properly built and accessible:
366
+
367
+ ```bash
368
+ npm run build:wasm
369
+ ```
370
+
371
+ ### Emscripten Not Found
372
+
373
+ Install Emscripten:
374
+
375
+ ```bash
376
+ npm run install-emscripten
377
+ source build/emsdk/emsdk_env.sh
378
+ ```
379
+
380
+ ### Memory Issues
381
+
382
+ If you encounter memory-related errors, try increasing the initial memory:
383
+
384
+ ```typescript
385
+ const netcdf = new NetCDF4({ memoryInitialPages: 512 });
386
+ ```
@@ -0,0 +1,20 @@
1
+ export declare const NC_CONSTANTS: {
2
+ NC_NOERR: number;
3
+ NC_NOWRITE: number;
4
+ NC_WRITE: number;
5
+ NC_CLOBBER: number;
6
+ NC_NOCLOBBER: number;
7
+ NC_NETCDF4: number;
8
+ NC_BYTE: number;
9
+ NC_CHAR: number;
10
+ NC_SHORT: number;
11
+ NC_INT: number;
12
+ NC_FLOAT: number;
13
+ NC_DOUBLE: number;
14
+ NC_UNLIMITED: number;
15
+ NC_GLOBAL: number;
16
+ };
17
+ export declare const DATA_TYPE_MAP: {
18
+ [key: string]: number;
19
+ };
20
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;CAsBxB,CAAC;AAGF,eAAO,MAAM,aAAa,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAalD,CAAC"}
@@ -0,0 +1,37 @@
1
+ // NetCDF4 constants (populated from NetCDF4 headers)
2
+ export const NC_CONSTANTS = {
3
+ // Error codes
4
+ NC_NOERR: 0,
5
+ // File modes
6
+ NC_NOWRITE: 0,
7
+ NC_WRITE: 1,
8
+ NC_CLOBBER: 0,
9
+ NC_NOCLOBBER: 4,
10
+ NC_NETCDF4: 4096,
11
+ // Data types
12
+ NC_BYTE: 1,
13
+ NC_CHAR: 2,
14
+ NC_SHORT: 3,
15
+ NC_INT: 4,
16
+ NC_FLOAT: 5,
17
+ NC_DOUBLE: 6,
18
+ // Special values
19
+ NC_UNLIMITED: -1000, // Use special value to distinguish from 0
20
+ NC_GLOBAL: -1,
21
+ };
22
+ // Data type mapping from string names to NetCDF constants
23
+ export const DATA_TYPE_MAP = {
24
+ 'f8': NC_CONSTANTS.NC_DOUBLE,
25
+ 'f4': NC_CONSTANTS.NC_FLOAT,
26
+ 'i4': NC_CONSTANTS.NC_INT,
27
+ 'i2': NC_CONSTANTS.NC_SHORT,
28
+ 'i1': NC_CONSTANTS.NC_BYTE,
29
+ 'S1': NC_CONSTANTS.NC_CHAR,
30
+ 'double': NC_CONSTANTS.NC_DOUBLE,
31
+ 'float': NC_CONSTANTS.NC_FLOAT,
32
+ 'int': NC_CONSTANTS.NC_INT,
33
+ 'short': NC_CONSTANTS.NC_SHORT,
34
+ 'byte': NC_CONSTANTS.NC_BYTE,
35
+ 'char': NC_CONSTANTS.NC_CHAR
36
+ };
37
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,qDAAqD;AAErD,MAAM,CAAC,MAAM,YAAY,GAAG;IACxB,cAAc;IACd,QAAQ,EAAE,CAAC;IAEX,aAAa;IACb,UAAU,EAAE,CAAC;IACb,QAAQ,EAAE,CAAC;IACX,UAAU,EAAE,CAAC;IACb,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,IAAI;IAEhB,aAAa;IACb,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,CAAC;IACV,QAAQ,EAAE,CAAC;IACX,MAAM,EAAE,CAAC;IACT,QAAQ,EAAE,CAAC;IACX,SAAS,EAAE,CAAC;IAEZ,iBAAiB;IACjB,YAAY,EAAE,CAAC,IAAI,EAAE,0CAA0C;IAC/D,SAAS,EAAE,CAAC,CAAC;CAChB,CAAC;AAEF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,aAAa,GAA8B;IACpD,IAAI,EAAE,YAAY,CAAC,SAAS;IAC5B,IAAI,EAAE,YAAY,CAAC,QAAQ;IAC3B,IAAI,EAAE,YAAY,CAAC,MAAM;IACzB,IAAI,EAAE,YAAY,CAAC,QAAQ;IAC3B,IAAI,EAAE,YAAY,CAAC,OAAO;IAC1B,IAAI,EAAE,YAAY,CAAC,OAAO;IAC1B,QAAQ,EAAE,YAAY,CAAC,SAAS;IAChC,OAAO,EAAE,YAAY,CAAC,QAAQ;IAC9B,KAAK,EAAE,YAAY,CAAC,MAAM;IAC1B,OAAO,EAAE,YAAY,CAAC,QAAQ;IAC9B,MAAM,EAAE,YAAY,CAAC,OAAO;IAC5B,MAAM,EAAE,YAAY,CAAC,OAAO;CAC/B,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare class Dimension {
2
+ readonly name: string;
3
+ readonly size: number;
4
+ readonly isUnlimited: boolean;
5
+ constructor(name: string, size: number, isUnlimited?: boolean);
6
+ __len__(): number;
7
+ toString(): string;
8
+ }
9
+ //# sourceMappingURL=dimension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dimension.d.ts","sourceRoot":"","sources":["../src/dimension.ts"],"names":[],"mappings":"AAEA,qBAAa,SAAS;aAEE,IAAI,EAAE,MAAM;aACZ,IAAI,EAAE,MAAM;aACZ,WAAW,EAAE,OAAO;gBAFpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,GAAE,OAAe;IAGhD,OAAO,IAAI,MAAM;IAIjB,QAAQ,IAAI,MAAM;CAIrB"}
@@ -0,0 +1,19 @@
1
+ // Dimension class similar to netcdf4-python
2
+ export class Dimension {
3
+ name;
4
+ size;
5
+ isUnlimited;
6
+ constructor(name, size, isUnlimited = false) {
7
+ this.name = name;
8
+ this.size = size;
9
+ this.isUnlimited = isUnlimited;
10
+ }
11
+ __len__() {
12
+ return this.size;
13
+ }
14
+ toString() {
15
+ const sizeStr = this.isUnlimited ? 'unlimited' : this.size.toString();
16
+ return `<netCDF4.Dimension '${this.name}': size = ${sizeStr}>`;
17
+ }
18
+ }
19
+ //# sourceMappingURL=dimension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dimension.js","sourceRoot":"","sources":["../src/dimension.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAE5C,MAAM,OAAO,SAAS;IAEE;IACA;IACA;IAHpB,YACoB,IAAY,EACZ,IAAY,EACZ,cAAuB,KAAK;QAF5B,SAAI,GAAJ,IAAI,CAAQ;QACZ,SAAI,GAAJ,IAAI,CAAQ;QACZ,gBAAW,GAAX,WAAW,CAAiB;IAC7C,CAAC;IAEJ,OAAO;QACH,OAAO,IAAI,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,QAAQ;QACJ,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtE,OAAO,uBAAuB,IAAI,CAAC,IAAI,aAAa,OAAO,GAAG,CAAC;IACnE,CAAC;CACJ"}
@@ -0,0 +1,33 @@
1
+ import type { NetCDF4 } from './netcdf4.js';
2
+ import { Dimension } from './dimension.js';
3
+ import { Variable } from './variable.js';
4
+ import type { VariableOptions } from './types.js';
5
+ export declare class Group {
6
+ protected netcdf: NetCDF4;
7
+ readonly name: string;
8
+ protected groupId: number;
9
+ readonly dimensions: {
10
+ [name: string]: Dimension;
11
+ };
12
+ readonly variables: {
13
+ [name: string]: Variable;
14
+ };
15
+ readonly groups: {
16
+ [name: string]: Group;
17
+ };
18
+ private _attributes;
19
+ constructor(netcdf: NetCDF4, name: string, groupId: number);
20
+ setAttr(name: string, value: any): void;
21
+ getAttr(name: string): any;
22
+ attrs(): string[];
23
+ createDimension(name: string, size: number | null): Promise<Dimension>;
24
+ loadMockDimensions(): void;
25
+ createVariable(name: string, datatype: string, dimensions?: string[], options?: VariableOptions): Promise<Variable>;
26
+ createGroup(name: string): Group;
27
+ children(): {
28
+ [name: string]: Group;
29
+ };
30
+ get path(): string;
31
+ toString(): string;
32
+ }
33
+ //# sourceMappingURL=group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,qBAAa,KAAK;IAOV,SAAS,CAAC,MAAM,EAAE,OAAO;aACT,IAAI,EAAE,MAAM;IAC5B,SAAS,CAAC,OAAO,EAAE,MAAM;IAR7B,SAAgB,UAAU,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAM;IAC/D,SAAgB,SAAS,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAA;KAAE,CAAM;IAC7D,SAAgB,MAAM,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAM;IACvD,OAAO,CAAC,WAAW,CAA8B;gBAGnC,MAAM,EAAE,OAAO,EACT,IAAI,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM;IAI7B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAcvC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG;IAgB1B,KAAK,IAAI,MAAM,EAAE;IAIX,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC;IAuBrE,kBAAkB,IAAI,IAAI;IA8B3B,cAAc,CAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,GAAE,MAAM,EAAO,EACzB,OAAO,GAAE,eAAoB,GAC9B,OAAO,CAAC,QAAQ,CAAC;IAqCpB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK;IAQhC,QAAQ,IAAI;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE;IAKrC,IAAI,IAAI,IAAI,MAAM,CAGjB;IAED,QAAQ,IAAI,MAAM;CAGrB"}