@loaders.gl/netcdf 4.2.0-alpha.4 → 4.2.0-alpha.5

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.
@@ -1,161 +1,225 @@
1
1
  import { readType, num2str } from "./read-type.js";
2
+ // Grammar constants
2
3
  const ZERO = 0;
3
4
  const NC_DIMENSION = 10;
4
5
  const NC_VARIABLE = 11;
5
6
  const NC_ATTRIBUTE = 12;
6
7
  const NC_UNLIMITED = 0;
8
+ /**
9
+ * Read the header of the file
10
+ * @param buffer - Buffer for the file data
11
+ * @param version - Version of the file
12
+ * @return - Header
13
+ */
7
14
  export function readNetCDFHeader(buffer, version) {
8
- const recordDimensionLength = buffer.readUint32();
9
- const dimList = readDimensionsList(buffer);
10
- const attributes = readAttributesList(buffer);
11
- const variableList = readVariablesList(buffer, dimList.recordId, version);
12
- const header = {
13
- version,
14
- recordDimension: {
15
- length: recordDimensionLength,
16
- id: dimList.recordId,
17
- name: dimList.recordName,
18
- recordStep: variableList.recordStep
19
- },
20
- dimensions: dimList.dimensions,
21
- variables: variableList.variables,
22
- attributes
23
- };
24
- return header;
15
+ // Length of record dimension
16
+ // sum of the varSize's of all the record variables.
17
+ const recordDimensionLength = buffer.readUint32();
18
+ // List of dimensions
19
+ const dimList = readDimensionsList(buffer);
20
+ // List of global attributes
21
+ const attributes = readAttributesList(buffer);
22
+ // List of variables
23
+ const variableList = readVariablesList(buffer, dimList.recordId, version);
24
+ const header = {
25
+ version,
26
+ recordDimension: {
27
+ length: recordDimensionLength,
28
+ id: dimList.recordId, // id of the unlimited dimension
29
+ name: dimList.recordName, // name of the unlimited dimension
30
+ recordStep: variableList.recordStep
31
+ },
32
+ dimensions: dimList.dimensions,
33
+ variables: variableList.variables,
34
+ attributes
35
+ };
36
+ return header;
25
37
  }
38
+ /**
39
+ * Read list of dimensions
40
+ * @ignore
41
+ * @param {IOBuffer} buffer - Buffer for the file data
42
+ */
26
43
  function readDimensionsList(buffer) {
27
- const dimList = buffer.readUint32();
28
- if (dimList === ZERO) {
29
- if (buffer.readUint32() !== ZERO) {
30
- throw new Error('NetCDF: wrong empty tag for list of dimensions');
44
+ const dimList = buffer.readUint32();
45
+ if (dimList === ZERO) {
46
+ if (buffer.readUint32() !== ZERO) {
47
+ throw new Error('NetCDF: wrong empty tag for list of dimensions');
48
+ }
49
+ // TODO - is this empty dimension list supported / recoverable?
50
+ return {
51
+ recordId: 0,
52
+ recordName: '',
53
+ dimensions: []
54
+ };
31
55
  }
32
- return {
33
- recordId: 0,
34
- recordName: '',
35
- dimensions: []
36
- };
37
- }
38
- if (dimList !== NC_DIMENSION) {
39
- throw new Error('NetCDF: wrong tag for list of dimensions');
40
- }
41
- const dimensionSize = buffer.readUint32();
42
- const dimensions = new Array(dimensionSize);
43
- let recordId;
44
- let recordName;
45
- for (let dim = 0; dim < dimensionSize; dim++) {
46
- const name = readName(buffer);
47
- const size = buffer.readUint32();
48
- if (size === NC_UNLIMITED) {
49
- recordId = dim;
50
- recordName = name;
56
+ if (dimList !== NC_DIMENSION) {
57
+ throw new Error('NetCDF: wrong tag for list of dimensions');
58
+ }
59
+ // Length of dimensions
60
+ const dimensionSize = buffer.readUint32();
61
+ const dimensions = new Array(dimensionSize);
62
+ let recordId;
63
+ let recordName;
64
+ for (let dim = 0; dim < dimensionSize; dim++) {
65
+ // Read name
66
+ const name = readName(buffer);
67
+ // Read dimension size
68
+ const size = buffer.readUint32();
69
+ if (size === NC_UNLIMITED) {
70
+ // in netcdf 3 one field can be of size unlimmited
71
+ recordId = dim;
72
+ recordName = name;
73
+ }
74
+ dimensions[dim] = {
75
+ name,
76
+ size
77
+ };
51
78
  }
52
- dimensions[dim] = {
53
- name,
54
- size
79
+ return {
80
+ dimensions,
81
+ recordId,
82
+ recordName
55
83
  };
56
- }
57
- return {
58
- dimensions,
59
- recordId,
60
- recordName
61
- };
62
84
  }
85
+ /**
86
+ * List of attributes
87
+ * @ignore
88
+ * @param buffer - Buffer for the file data
89
+ * @return List of attributes with:
90
+ */
63
91
  function readAttributesList(buffer) {
64
- const gAttList = buffer.readUint32();
65
- if (gAttList === ZERO) {
66
- if (buffer.readUint32() !== ZERO) {
67
- throw new Error('NetCDF: wrong empty tag for list of attributes');
92
+ const gAttList = buffer.readUint32();
93
+ if (gAttList === ZERO) {
94
+ if (buffer.readUint32() !== ZERO) {
95
+ throw new Error('NetCDF: wrong empty tag for list of attributes');
96
+ }
97
+ return [];
68
98
  }
69
- return [];
70
- }
71
- if (gAttList !== NC_ATTRIBUTE) {
72
- throw new Error('NetCDF: wrong tag for list of attributes');
73
- }
74
- const attributeSize = buffer.readUint32();
75
- const attributes = new Array(attributeSize);
76
- for (let gAtt = 0; gAtt < attributeSize; gAtt++) {
77
- const name = readName(buffer);
78
- const type = buffer.readUint32();
79
- if (type < 1 || type > 6) {
80
- throw new Error(`NetCDF: non valid type ${type}`);
99
+ if (gAttList !== NC_ATTRIBUTE) {
100
+ throw new Error('NetCDF: wrong tag for list of attributes');
81
101
  }
82
- const size = buffer.readUint32();
83
- const value = readType(buffer, type, size);
84
- padding(buffer);
85
- attributes[gAtt] = {
86
- name,
87
- type: num2str(type),
88
- value
89
- };
90
- }
91
- return attributes;
102
+ // Length of attributes
103
+ const attributeSize = buffer.readUint32();
104
+ const attributes = new Array(attributeSize);
105
+ for (let gAtt = 0; gAtt < attributeSize; gAtt++) {
106
+ // Read name
107
+ const name = readName(buffer);
108
+ // Read type
109
+ const type = buffer.readUint32();
110
+ if (type < 1 || type > 6) {
111
+ throw new Error(`NetCDF: non valid type ${type}`);
112
+ }
113
+ // Read attribute
114
+ const size = buffer.readUint32();
115
+ const value = readType(buffer, type, size);
116
+ // Apply padding
117
+ padding(buffer);
118
+ attributes[gAtt] = {
119
+ name,
120
+ type: num2str(type),
121
+ value
122
+ };
123
+ }
124
+ return attributes;
92
125
  }
126
+ /**
127
+ * List of variables
128
+ * @param buffer - Buffer for the file data
129
+ * @param recordId - Id of the unlimited dimension (also called record dimension)
130
+ * This value may be undefined if there is no unlimited dimension
131
+ * @param {number} version - Version of the file
132
+ */
133
+ // eslint-disable-next-line max-statements, complexity
93
134
  function readVariablesList(buffer, recordId, version) {
94
- const varList = buffer.readUint32();
95
- let recordStep = 0;
96
- if (varList === ZERO) {
97
- if (buffer.readUint32() !== ZERO) {
98
- throw new Error('NetCDF: wrong empty tag for list of variables');
135
+ const varList = buffer.readUint32();
136
+ let recordStep = 0;
137
+ if (varList === ZERO) {
138
+ if (buffer.readUint32() !== ZERO) {
139
+ throw new Error('NetCDF: wrong empty tag for list of variables');
140
+ }
141
+ return {
142
+ recordStep,
143
+ variables: []
144
+ };
99
145
  }
100
- return {
101
- recordStep,
102
- variables: []
103
- };
104
- }
105
- if (varList !== NC_VARIABLE) {
106
- throw new Error('NetCDF: wrong tag for list of variables');
107
- }
108
- const variableSize = buffer.readUint32();
109
- const variables = new Array(variableSize);
110
- for (let v = 0; v < variableSize; v++) {
111
- const name = readName(buffer);
112
- const dimensionality = buffer.readUint32();
113
- const dimensionsIds = new Array(dimensionality);
114
- for (let dim = 0; dim < dimensionality; dim++) {
115
- dimensionsIds[dim] = buffer.readUint32();
116
- }
117
- const attributes = readAttributesList(buffer);
118
- const type = buffer.readUint32();
119
- if (type < 1 && type > 6) {
120
- throw new Error(`NetCDF: non valid type ${type}`);
146
+ if (varList !== NC_VARIABLE) {
147
+ throw new Error('NetCDF: wrong tag for list of variables');
121
148
  }
122
- const varSize = buffer.readUint32();
123
- let offset = buffer.readUint32();
124
- if (version === 2) {
125
- if (offset > 0) {
126
- throw new Error('NetCDF: offsets larger than 4GB not supported');
127
- }
128
- offset = buffer.readUint32();
149
+ // Length of variables
150
+ const variableSize = buffer.readUint32();
151
+ const variables = new Array(variableSize);
152
+ for (let v = 0; v < variableSize; v++) {
153
+ // Read name
154
+ const name = readName(buffer);
155
+ // Read dimensionality of the variable
156
+ const dimensionality = buffer.readUint32();
157
+ // Index into the list of dimensions
158
+ const dimensionsIds = new Array(dimensionality);
159
+ for (let dim = 0; dim < dimensionality; dim++) {
160
+ dimensionsIds[dim] = buffer.readUint32();
161
+ }
162
+ // Read variables size
163
+ const attributes = readAttributesList(buffer);
164
+ // Read type
165
+ const type = buffer.readUint32();
166
+ if (type < 1 && type > 6) {
167
+ throw new Error(`NetCDF: non valid type ${type}`);
168
+ }
169
+ // Read variable size
170
+ // The 32-bit varSize field is not large enough to contain the size of variables that require
171
+ // more than 2^32 - 4 bytes, so 2^32 - 1 is used in the varSize field for such variables.
172
+ const varSize = buffer.readUint32();
173
+ // Read offset
174
+ let offset = buffer.readUint32();
175
+ if (version === 2) {
176
+ if (offset > 0) {
177
+ throw new Error('NetCDF: offsets larger than 4GB not supported');
178
+ }
179
+ offset = buffer.readUint32();
180
+ }
181
+ let record = false;
182
+ // Count amount of record variables
183
+ if (typeof recordId !== 'undefined' && dimensionsIds[0] === recordId) {
184
+ recordStep += varSize;
185
+ record = true;
186
+ }
187
+ variables[v] = {
188
+ name,
189
+ dimensions: dimensionsIds,
190
+ attributes,
191
+ type: num2str(type),
192
+ size: varSize,
193
+ offset,
194
+ record
195
+ };
129
196
  }
130
- let record = false;
131
- if (typeof recordId !== 'undefined' && dimensionsIds[0] === recordId) {
132
- recordStep += varSize;
133
- record = true;
134
- }
135
- variables[v] = {
136
- name,
137
- dimensions: dimensionsIds,
138
- attributes,
139
- type: num2str(type),
140
- size: varSize,
141
- offset,
142
- record
197
+ return {
198
+ variables,
199
+ recordStep
143
200
  };
144
- }
145
- return {
146
- variables,
147
- recordStep
148
- };
149
201
  }
202
+ // HELPERS
203
+ /**
204
+ * Reads the name
205
+ * @param buffer - Buffer for the file data
206
+ * @return Name
207
+ */
150
208
  export function readName(buffer) {
151
- const nameLength = buffer.readUint32();
152
- const name = buffer.readChars(nameLength);
153
- padding(buffer);
154
- return name;
209
+ // Read name
210
+ const nameLength = buffer.readUint32();
211
+ const name = buffer.readChars(nameLength);
212
+ // validate name
213
+ // TODO
214
+ // Apply padding
215
+ padding(buffer);
216
+ return name;
155
217
  }
218
+ /**
219
+ * Moves 1, 2, or 3 bytes to next 4-byte boundary
220
+ */
156
221
  function padding(buffer) {
157
- if (buffer.offset % 4 !== 0) {
158
- buffer.skip(4 - buffer.offset % 4);
159
- }
222
+ if (buffer.offset % 4 !== 0) {
223
+ buffer.skip(4 - (buffer.offset % 4));
224
+ }
160
225
  }
161
- //# sourceMappingURL=read-header.js.map
@@ -1,4 +1,4 @@
1
- import { IOBuffer } from '../iobuffer/iobuffer';
1
+ import { IOBuffer } from "../iobuffer/iobuffer.js";
2
2
  export declare const TYPES: {
3
3
  BYTE: number;
4
4
  CHAR: number;
@@ -1 +1 @@
1
- {"version":3,"file":"read-type.d.ts","sourceRoot":"","sources":["../../src/netcdfjs/read-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAE9C,eAAO,MAAM,KAAK;;;;;;;CAOjB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,QAAQ,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,UAAU,CAkBzC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB5C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB9C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB5C"}
1
+ {"version":3,"file":"read-type.d.ts","sourceRoot":"","sources":["../../src/netcdfjs/read-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,gCAA6B;AAE9C,eAAO,MAAM,KAAK;;;;;;;CAOjB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,QAAQ,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,UAAU,CAkBzC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB5C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB9C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB5C"}
@@ -1,97 +1,133 @@
1
1
  export const TYPES = {
2
- BYTE: 1,
3
- CHAR: 2,
4
- SHORT: 3,
5
- INT: 4,
6
- FLOAT: 5,
7
- DOUBLE: 6
2
+ BYTE: 1,
3
+ CHAR: 2,
4
+ SHORT: 3,
5
+ INT: 4,
6
+ FLOAT: 5,
7
+ DOUBLE: 6
8
8
  };
9
+ /**
10
+ * Given a type and a size reads the next element
11
+ * @param buffer - Buffer for the file data
12
+ * @param type - Type of the data to read
13
+ * @param size - Size of the element to read
14
+ * @return
15
+ */
9
16
  export function readType(buffer, type, size) {
10
- switch (type) {
11
- case TYPES.BYTE:
12
- return buffer.readBytes(size);
13
- case TYPES.CHAR:
14
- return trimNull(buffer.readChars(size));
15
- case TYPES.SHORT:
16
- return readNumber(size, buffer.readInt16.bind(buffer));
17
- case TYPES.INT:
18
- return readNumber(size, buffer.readInt32.bind(buffer));
19
- case TYPES.FLOAT:
20
- return readNumber(size, buffer.readFloat32.bind(buffer));
21
- case TYPES.DOUBLE:
22
- return readNumber(size, buffer.readFloat64.bind(buffer));
23
- default:
24
- throw new Error(`NetCDF: non valid type ${type}`);
25
- }
17
+ switch (type) {
18
+ case TYPES.BYTE:
19
+ return buffer.readBytes(size);
20
+ case TYPES.CHAR:
21
+ return trimNull(buffer.readChars(size));
22
+ case TYPES.SHORT:
23
+ return readNumber(size, buffer.readInt16.bind(buffer));
24
+ case TYPES.INT:
25
+ return readNumber(size, buffer.readInt32.bind(buffer));
26
+ case TYPES.FLOAT:
27
+ return readNumber(size, buffer.readFloat32.bind(buffer));
28
+ case TYPES.DOUBLE:
29
+ return readNumber(size, buffer.readFloat64.bind(buffer));
30
+ /* istanbul ignore next */
31
+ default:
32
+ throw new Error(`NetCDF: non valid type ${type}`);
33
+ }
26
34
  }
35
+ /**
36
+ * Parse a number into their respective type
37
+ * @param type - integer that represents the type
38
+ * @return parsed value of the type
39
+ */
27
40
  export function num2str(type) {
28
- switch (Number(type)) {
29
- case TYPES.BYTE:
30
- return 'byte';
31
- case TYPES.CHAR:
32
- return 'char';
33
- case TYPES.SHORT:
34
- return 'short';
35
- case TYPES.INT:
36
- return 'int';
37
- case TYPES.FLOAT:
38
- return 'float';
39
- case TYPES.DOUBLE:
40
- return 'double';
41
- default:
42
- return 'undefined';
43
- }
41
+ switch (Number(type)) {
42
+ case TYPES.BYTE:
43
+ return 'byte';
44
+ case TYPES.CHAR:
45
+ return 'char';
46
+ case TYPES.SHORT:
47
+ return 'short';
48
+ case TYPES.INT:
49
+ return 'int';
50
+ case TYPES.FLOAT:
51
+ return 'float';
52
+ case TYPES.DOUBLE:
53
+ return 'double';
54
+ /* istanbul ignore next */
55
+ default:
56
+ return 'undefined';
57
+ }
44
58
  }
59
+ /**
60
+ * Parse a number type identifier to his size in bytes
61
+ * @param type - integer that represents the type
62
+ * @return size of the type
63
+ */
45
64
  export function num2bytes(type) {
46
- switch (Number(type)) {
47
- case TYPES.BYTE:
48
- return 1;
49
- case TYPES.CHAR:
50
- return 1;
51
- case TYPES.SHORT:
52
- return 2;
53
- case TYPES.INT:
54
- return 4;
55
- case TYPES.FLOAT:
56
- return 4;
57
- case TYPES.DOUBLE:
58
- return 8;
59
- default:
60
- return -1;
61
- }
65
+ switch (Number(type)) {
66
+ case TYPES.BYTE:
67
+ return 1;
68
+ case TYPES.CHAR:
69
+ return 1;
70
+ case TYPES.SHORT:
71
+ return 2;
72
+ case TYPES.INT:
73
+ return 4;
74
+ case TYPES.FLOAT:
75
+ return 4;
76
+ case TYPES.DOUBLE:
77
+ return 8;
78
+ /* istanbul ignore next */
79
+ default:
80
+ return -1;
81
+ }
62
82
  }
83
+ /**
84
+ * Reverse search of num2str
85
+ * @param type string that represents the type
86
+ * @return parsed value of the type
87
+ */
63
88
  export function str2num(type) {
64
- switch (String(type)) {
65
- case 'byte':
66
- return TYPES.BYTE;
67
- case 'char':
68
- return TYPES.CHAR;
69
- case 'short':
70
- return TYPES.SHORT;
71
- case 'int':
72
- return TYPES.INT;
73
- case 'float':
74
- return TYPES.FLOAT;
75
- case 'double':
76
- return TYPES.DOUBLE;
77
- default:
78
- return -1;
79
- }
89
+ switch (String(type)) {
90
+ case 'byte':
91
+ return TYPES.BYTE;
92
+ case 'char':
93
+ return TYPES.CHAR;
94
+ case 'short':
95
+ return TYPES.SHORT;
96
+ case 'int':
97
+ return TYPES.INT;
98
+ case 'float':
99
+ return TYPES.FLOAT;
100
+ case 'double':
101
+ return TYPES.DOUBLE;
102
+ /* istanbul ignore next */
103
+ default:
104
+ return -1;
105
+ }
80
106
  }
107
+ /**
108
+ * Auxiliary function to read numeric data
109
+ * @param size - Size of the element to read
110
+ * @param bufferReader - Function to read next value
111
+ * @return
112
+ */
81
113
  function readNumber(size, bufferReader) {
82
- if (size !== 1) {
83
- const numbers = new Array(size);
84
- for (let i = 0; i < size; i++) {
85
- numbers[i] = bufferReader();
114
+ if (size !== 1) {
115
+ const numbers = new Array(size);
116
+ for (let i = 0; i < size; i++) {
117
+ numbers[i] = bufferReader();
118
+ }
119
+ return numbers;
86
120
  }
87
- return numbers;
88
- }
89
- return bufferReader();
121
+ return bufferReader();
90
122
  }
123
+ /**
124
+ * Removes null terminate value
125
+ * @param value - String to trim
126
+ * @return - Trimmed string
127
+ */
91
128
  function trimNull(value) {
92
- if (value.charCodeAt(value.length - 1) === 0) {
93
- return value.substring(0, value.length - 1);
94
- }
95
- return value;
129
+ if (value.charCodeAt(value.length - 1) === 0) {
130
+ return value.substring(0, value.length - 1);
131
+ }
132
+ return value;
96
133
  }
97
- //# sourceMappingURL=read-type.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loaders.gl/netcdf",
3
3
  "description": "Loader for NetCDF",
4
- "version": "4.2.0-alpha.4",
4
+ "version": "4.2.0-alpha.5",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "publishConfig": {
@@ -34,11 +34,15 @@
34
34
  "README.md"
35
35
  ],
36
36
  "scripts": {
37
- "pre-build": "npm run build-bundle && npm run build-bundle -- --env=dev",
38
- "build-bundle": "ocular-bundle ./src/index.ts"
37
+ "pre-build": "npm run build-bundle && npm run build-bundle-dev",
38
+ "build-bundle": "ocular-bundle ./bundle.ts --output=dist/dist.min.js",
39
+ "build-bundle-dev": "ocular-bundle ./bundle.ts --env=dev --output=dist/dist.dev.js"
39
40
  },
40
41
  "dependencies": {
41
- "@loaders.gl/loader-utils": "4.2.0-alpha.4"
42
+ "@loaders.gl/loader-utils": "4.2.0-alpha.5"
42
43
  },
43
- "gitHead": "6c52dee5c3f005648a394cc4aee7fc37005c8e83"
44
+ "peerDependencies": {
45
+ "@loaders.gl/core": "^4.0.0"
46
+ },
47
+ "gitHead": "32d95a81971f104e4dfeb88ab57065f05321a76a"
44
48
  }
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["NetCDFReader","NetCDFLoader"],"sources":["../src/index.ts"],"sourcesContent":["export {NetCDFReader} from './netcdfjs/netcdf-reader';\n\nexport {NetCDFLoader} from './netcdf-loader';\n"],"mappings":"SAAQA,YAAY;AAAA,SAEZC,YAAY"}