rclnodejs 1.5.2 → 1.7.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/index.js +79 -3
- package/lib/action/client.js +55 -9
- package/lib/action/deferred.js +8 -2
- package/lib/action/server.js +10 -1
- package/lib/action/uuid.js +4 -1
- package/lib/client.js +152 -3
- package/lib/clock.js +4 -1
- package/lib/context.js +12 -2
- package/lib/duration.js +37 -12
- package/lib/errors.js +571 -0
- package/lib/event_handler.js +21 -4
- package/lib/interface_loader.js +52 -12
- package/lib/lifecycle.js +8 -2
- package/lib/logging.js +12 -3
- package/lib/message_serialization.js +179 -0
- package/lib/native_loader.js +9 -4
- package/lib/node.js +283 -47
- package/lib/parameter.js +176 -45
- package/lib/parameter_client.js +506 -0
- package/lib/parameter_watcher.js +309 -0
- package/lib/qos.js +22 -5
- package/lib/rate.js +6 -1
- package/lib/serialization.js +7 -2
- package/lib/subscription.js +16 -1
- package/lib/time.js +136 -21
- package/lib/time_source.js +13 -4
- package/lib/utils.js +313 -0
- package/lib/validator.js +11 -12
- package/package.json +2 -7
- package/prebuilds/linux-arm64/humble-jammy-arm64-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/jazzy-noble-arm64-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/kilted-noble-arm64-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/humble-jammy-x64-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/jazzy-noble-x64-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/kilted-noble-x64-rclnodejs.node +0 -0
- package/rosidl_convertor/idl_convertor.js +3 -2
- package/rosidl_gen/generate_worker.js +1 -1
- package/rosidl_gen/idl_generator.js +11 -24
- package/rosidl_gen/index.js +1 -1
- package/rosidl_gen/templates/action-template.js +68 -0
- package/rosidl_gen/templates/message-template.js +1113 -0
- package/rosidl_gen/templates/service-event-template.js +31 -0
- package/rosidl_gen/templates/service-template.js +44 -0
- package/rosidl_parser/rosidl_parser.js +2 -2
- package/third_party/ref-napi/lib/ref.js +0 -45
- package/types/base.d.ts +3 -0
- package/types/client.d.ts +36 -0
- package/types/errors.d.ts +447 -0
- package/types/index.d.ts +17 -0
- package/types/interfaces.d.ts +1910 -1
- package/types/node.d.ts +56 -1
- package/types/parameter_client.d.ts +252 -0
- package/types/parameter_watcher.d.ts +104 -0
- package/rosidl_gen/templates/CMakeLists.dot +0 -40
- package/rosidl_gen/templates/action.dot +0 -50
- package/rosidl_gen/templates/message.dot +0 -851
- package/rosidl_gen/templates/package.dot +0 -16
- package/rosidl_gen/templates/service.dot +0 -26
- package/rosidl_gen/templates/service_event.dot +0 -10
|
@@ -0,0 +1,1113 @@
|
|
|
1
|
+
// Copyright (c) 2025, The Robot Web Tools Contributors
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Generate JavaScript message class code using native template literals
|
|
19
|
+
* This replaces the doT template engine with pure JavaScript
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// Helper functions (same as in message.dot template)
|
|
23
|
+
function getPrimitiveNameByType(type) {
|
|
24
|
+
if (type.type === 'bool') {
|
|
25
|
+
return 'Bool';
|
|
26
|
+
} else if (type.type === 'int8') {
|
|
27
|
+
return 'Int8';
|
|
28
|
+
} else if (type.type === 'uint8') {
|
|
29
|
+
return 'UInt8';
|
|
30
|
+
} else if (type.type === 'int16') {
|
|
31
|
+
return 'Int16';
|
|
32
|
+
} else if (type.type === 'uint16') {
|
|
33
|
+
return 'UInt16';
|
|
34
|
+
} else if (type.type === 'int32') {
|
|
35
|
+
return 'Int32';
|
|
36
|
+
} else if (type.type === 'uint32') {
|
|
37
|
+
return 'UInt32';
|
|
38
|
+
} else if (type.type === 'int64') {
|
|
39
|
+
return 'Int64';
|
|
40
|
+
} else if (type.type === 'uint64') {
|
|
41
|
+
return 'UInt64';
|
|
42
|
+
} else if (type.type === 'float64') {
|
|
43
|
+
return 'Float64';
|
|
44
|
+
} else if (type.type === 'float32') {
|
|
45
|
+
return 'Float32';
|
|
46
|
+
} else if (type.type === 'char') {
|
|
47
|
+
return 'Char';
|
|
48
|
+
} else if (type.type === 'byte') {
|
|
49
|
+
return 'Byte';
|
|
50
|
+
} else if (type.type === 'string' || type.type === 'wstring') {
|
|
51
|
+
return 'String';
|
|
52
|
+
} else {
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getTypedArrayName(type) {
|
|
58
|
+
const t = type.type.toLowerCase();
|
|
59
|
+
let typedArrayName = null;
|
|
60
|
+
|
|
61
|
+
switch (t) {
|
|
62
|
+
case 'byte':
|
|
63
|
+
case 'octet':
|
|
64
|
+
case 'uint8':
|
|
65
|
+
typedArrayName = 'Uint8Array';
|
|
66
|
+
break;
|
|
67
|
+
case 'char':
|
|
68
|
+
case 'int8':
|
|
69
|
+
typedArrayName = 'Int8Array';
|
|
70
|
+
break;
|
|
71
|
+
case 'int16':
|
|
72
|
+
case 'short':
|
|
73
|
+
typedArrayName = 'Int16Array';
|
|
74
|
+
break;
|
|
75
|
+
case 'uint16':
|
|
76
|
+
case 'unsigned short':
|
|
77
|
+
typedArrayName = 'Uint16Array';
|
|
78
|
+
break;
|
|
79
|
+
case 'int32':
|
|
80
|
+
case 'long':
|
|
81
|
+
typedArrayName = 'Int32Array';
|
|
82
|
+
break;
|
|
83
|
+
case 'uint32':
|
|
84
|
+
case 'unsigned long':
|
|
85
|
+
typedArrayName = 'Uint32Array';
|
|
86
|
+
break;
|
|
87
|
+
case 'float':
|
|
88
|
+
case 'float32':
|
|
89
|
+
typedArrayName = 'Float32Array';
|
|
90
|
+
break;
|
|
91
|
+
case 'double':
|
|
92
|
+
case 'float64':
|
|
93
|
+
typedArrayName = 'Float64Array';
|
|
94
|
+
break;
|
|
95
|
+
default:
|
|
96
|
+
typedArrayName = '';
|
|
97
|
+
}
|
|
98
|
+
return typedArrayName;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function getTypedArrayElementName(type) {
|
|
102
|
+
const t = type.type.toLowerCase();
|
|
103
|
+
if (t === 'int8') {
|
|
104
|
+
return 'int8';
|
|
105
|
+
} else if (t === 'uint8') {
|
|
106
|
+
return 'uint8';
|
|
107
|
+
} else if (t === 'int16') {
|
|
108
|
+
return 'int16';
|
|
109
|
+
} else if (t === 'uint16') {
|
|
110
|
+
return 'uint16';
|
|
111
|
+
} else if (t === 'int32') {
|
|
112
|
+
return 'int32';
|
|
113
|
+
} else if (t === 'uint32') {
|
|
114
|
+
return 'uint32';
|
|
115
|
+
} else if (t === 'float64') {
|
|
116
|
+
return 'double';
|
|
117
|
+
} else if (t === 'float32') {
|
|
118
|
+
return 'float';
|
|
119
|
+
} else if (t === 'char') {
|
|
120
|
+
return 'int8';
|
|
121
|
+
} else if (t === 'byte') {
|
|
122
|
+
return 'uint8';
|
|
123
|
+
} else {
|
|
124
|
+
return '';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const primitiveBaseType = [
|
|
129
|
+
'Bool',
|
|
130
|
+
'Int8',
|
|
131
|
+
'UInt8',
|
|
132
|
+
'Int16',
|
|
133
|
+
'UInt16',
|
|
134
|
+
'Int32',
|
|
135
|
+
'UInt32',
|
|
136
|
+
'Int64',
|
|
137
|
+
'UInt64',
|
|
138
|
+
'Float64',
|
|
139
|
+
'Float32',
|
|
140
|
+
'Char',
|
|
141
|
+
'Byte',
|
|
142
|
+
'String',
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
const typedArrayType = [
|
|
146
|
+
'int8',
|
|
147
|
+
'uint8',
|
|
148
|
+
'int16',
|
|
149
|
+
'uint16',
|
|
150
|
+
'int32',
|
|
151
|
+
'uint32',
|
|
152
|
+
'float64',
|
|
153
|
+
'float32',
|
|
154
|
+
'char',
|
|
155
|
+
'byte',
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
function isPrimitivePackage(baseType) {
|
|
159
|
+
return primitiveBaseType.indexOf(baseType.type) !== -1;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function isTypedArrayType(type) {
|
|
163
|
+
return typedArrayType.indexOf(type.type.toLowerCase()) !== -1;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function isBigInt(type) {
|
|
167
|
+
return ['int64', 'uint64'].indexOf(type.type.toLowerCase()) !== -1;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function getWrapperNameByType(type) {
|
|
171
|
+
if (type.isPrimitiveType) {
|
|
172
|
+
return getPrimitiveNameByType(type) + 'Wrapper';
|
|
173
|
+
} else {
|
|
174
|
+
return type.type + 'Wrapper';
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function getModulePathByType(type, messageInfo) {
|
|
179
|
+
if (type.isPrimitiveType) {
|
|
180
|
+
return 'std_msgs__msg__' + getPrimitiveNameByType(type) + '.js';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (
|
|
184
|
+
messageInfo &&
|
|
185
|
+
messageInfo.subFolder === 'action' &&
|
|
186
|
+
messageInfo.pkgName === type.pkgName &&
|
|
187
|
+
(type.type.endsWith('_Goal') ||
|
|
188
|
+
type.type.endsWith('_Result') ||
|
|
189
|
+
type.type.endsWith('_Feedback'))
|
|
190
|
+
) {
|
|
191
|
+
return type.pkgName + '__action__' + type.type + '.js';
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* We should use '__msg__' to require "service_msgs/msg/ServiceEventInfo.msg" for service event message. */
|
|
195
|
+
if (
|
|
196
|
+
messageInfo &&
|
|
197
|
+
messageInfo.isServiceEvent &&
|
|
198
|
+
type.type !== 'ServiceEventInfo'
|
|
199
|
+
) {
|
|
200
|
+
return type.pkgName + `__${messageInfo.subFolder}__` + type.type + '.js';
|
|
201
|
+
}
|
|
202
|
+
return type.pkgName + '__msg__' + type.type + '.js';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function getPackageNameByType(type) {
|
|
206
|
+
if (type.isPrimitiveType) {
|
|
207
|
+
return 'std_msgs';
|
|
208
|
+
} else {
|
|
209
|
+
return type.pkgName;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function extractMemberNames(fields) {
|
|
214
|
+
let memberNames = [];
|
|
215
|
+
fields.forEach((field) => {
|
|
216
|
+
memberNames.push(field.name);
|
|
217
|
+
});
|
|
218
|
+
return JSON.stringify(memberNames);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Main template generation function
|
|
223
|
+
* @param {Object} data - Template data
|
|
224
|
+
* @param {Object} data.spec - Message specification
|
|
225
|
+
* @param {Object} data.messageInfo - Message information (pkgName, subFolder, interfaceName, isServiceEvent)
|
|
226
|
+
* @param {string} data.json - JSON string of spec
|
|
227
|
+
* @param {boolean} data.isDebug - Debug flag
|
|
228
|
+
* @returns {string} Generated JavaScript code
|
|
229
|
+
*/
|
|
230
|
+
function generateMessage(data) {
|
|
231
|
+
const spec = data.spec;
|
|
232
|
+
const messageInfo = data.messageInfo;
|
|
233
|
+
const json = data.json;
|
|
234
|
+
const isDebug = data.isDebug;
|
|
235
|
+
|
|
236
|
+
// Initialize variables
|
|
237
|
+
const objectWrapper = spec.msgName + 'Wrapper';
|
|
238
|
+
const arrayWrapper = spec.msgName + 'ArrayWrapper';
|
|
239
|
+
const refObjectType = spec.msgName + 'RefStruct';
|
|
240
|
+
const refObjectArrayType = spec.msgName + 'RefStructArray';
|
|
241
|
+
const refArrayType = spec.msgName + 'RefArray';
|
|
242
|
+
const compactMsgDefJSON = JSON.stringify(JSON.parse(json));
|
|
243
|
+
|
|
244
|
+
// Add dummy field if empty (following rosidl_generator_c style)
|
|
245
|
+
if (spec.fields.length === 0) {
|
|
246
|
+
spec.isEmpty = true;
|
|
247
|
+
spec.fields.push({
|
|
248
|
+
type: {
|
|
249
|
+
isArray: false,
|
|
250
|
+
pkgName: null,
|
|
251
|
+
type: 'bool',
|
|
252
|
+
isDynamicArray: false,
|
|
253
|
+
stringUpperBound: null,
|
|
254
|
+
isUpperBound: false,
|
|
255
|
+
isPrimitiveType: true,
|
|
256
|
+
isFixedSizeArray: false,
|
|
257
|
+
arraySize: null,
|
|
258
|
+
},
|
|
259
|
+
name: '_dummy',
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Check if will use TypedArray
|
|
264
|
+
const willUseTypedArray = isTypedArrayType(spec.baseType);
|
|
265
|
+
const currentTypedArray = getTypedArrayName(spec.baseType);
|
|
266
|
+
const currentTypedArrayElementType = getTypedArrayElementName(spec.baseType);
|
|
267
|
+
|
|
268
|
+
// Track required modules
|
|
269
|
+
let existedModules = [];
|
|
270
|
+
function shouldRequire(baseType, fieldType) {
|
|
271
|
+
let requiredModule = `${getPackageNameByType(fieldType)}/${getModulePathByType(fieldType, messageInfo)}`;
|
|
272
|
+
let shouldReq =
|
|
273
|
+
!isPrimitivePackage(baseType) &&
|
|
274
|
+
(fieldType.isArray ||
|
|
275
|
+
!fieldType.isPrimitiveType ||
|
|
276
|
+
fieldType.type === 'string');
|
|
277
|
+
|
|
278
|
+
if (shouldReq && existedModules.indexOf(requiredModule) === -1) {
|
|
279
|
+
existedModules.push(requiredModule);
|
|
280
|
+
return true;
|
|
281
|
+
} else {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Start generating the code
|
|
287
|
+
return `// This file is automatically generated by rclnodejs
|
|
288
|
+
//
|
|
289
|
+
// *** DO NOT EDIT directly
|
|
290
|
+
//
|
|
291
|
+
|
|
292
|
+
'use strict';
|
|
293
|
+
|
|
294
|
+
${willUseTypedArray ? "const rclnodejs = require('../../lib/native_loader.js');" : ''}
|
|
295
|
+
const ref = require('../../third_party/ref-napi');
|
|
296
|
+
const StructType = require('@rclnodejs/ref-struct-di')(ref);
|
|
297
|
+
const ArrayType = require('@rclnodejs/ref-array-di')(ref);
|
|
298
|
+
const primitiveTypes = require('../../rosidl_gen/primitive_types.js');
|
|
299
|
+
const deallocator = require('../../rosidl_gen/deallocator.js');
|
|
300
|
+
const translator = require('../../rosidl_gen/message_translator.js');
|
|
301
|
+
|
|
302
|
+
${spec.fields
|
|
303
|
+
.map((field) => {
|
|
304
|
+
if (shouldRequire(spec.baseType, field.type)) {
|
|
305
|
+
return `const ${getWrapperNameByType(field.type)} = require('../../generated/${getPackageNameByType(field.type)}/${getModulePathByType(field.type, messageInfo)}');`;
|
|
306
|
+
}
|
|
307
|
+
return '';
|
|
308
|
+
})
|
|
309
|
+
.filter((line) => line)
|
|
310
|
+
.join('\n')}
|
|
311
|
+
|
|
312
|
+
${
|
|
313
|
+
spec.msgName === 'String'
|
|
314
|
+
? `const ${refObjectType} = primitiveTypes.string;`
|
|
315
|
+
: `const ${refObjectType} = StructType({
|
|
316
|
+
${spec.fields
|
|
317
|
+
.map((field) => {
|
|
318
|
+
if (field.type.isPrimitiveType && !field.type.isArray) {
|
|
319
|
+
return ` ${field.name}: primitiveTypes.${field.type.type},`;
|
|
320
|
+
} else if (
|
|
321
|
+
field.type.isPrimitiveType &&
|
|
322
|
+
field.type.isArray &&
|
|
323
|
+
field.type.isFixedSizeArray
|
|
324
|
+
) {
|
|
325
|
+
return ` ${field.name}: ArrayType(primitiveTypes.${field.type.type}, ${field.type.arraySize}),`;
|
|
326
|
+
} else if (
|
|
327
|
+
!field.type.isPrimitiveType &&
|
|
328
|
+
field.type.isArray &&
|
|
329
|
+
field.type.isFixedSizeArray
|
|
330
|
+
) {
|
|
331
|
+
return ` ${field.name}: ArrayType(${getWrapperNameByType(field.type)}.refObjectType, ${field.type.arraySize}),`;
|
|
332
|
+
} else if (field.type.isArray) {
|
|
333
|
+
return ` ${field.name}: ${getWrapperNameByType(field.type)}.refObjectArrayType,`;
|
|
334
|
+
} else {
|
|
335
|
+
return ` ${field.name}: ${getWrapperNameByType(field.type)}.refObjectType,`;
|
|
336
|
+
}
|
|
337
|
+
})
|
|
338
|
+
.join('\n')}
|
|
339
|
+
});`
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const ${refArrayType} = ArrayType(${refObjectType});
|
|
343
|
+
const ${refObjectArrayType} = StructType({
|
|
344
|
+
${
|
|
345
|
+
willUseTypedArray
|
|
346
|
+
? ` data: ref.refType(ref.types.${currentTypedArrayElementType}),`
|
|
347
|
+
: ` data: ${refArrayType},`
|
|
348
|
+
}
|
|
349
|
+
size: ref.types.size_t,
|
|
350
|
+
capacity: ref.types.size_t
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
${generateWrapperClass()}
|
|
354
|
+
|
|
355
|
+
${generateArrayWrapperClass()}
|
|
356
|
+
|
|
357
|
+
${generateConstants()}
|
|
358
|
+
|
|
359
|
+
module.exports = ${objectWrapper};
|
|
360
|
+
|
|
361
|
+
${isDebug ? `/*\n * The following is the original spec object coming from parser:\n${json}\n*/` : ''}
|
|
362
|
+
`;
|
|
363
|
+
|
|
364
|
+
// Helper function to generate the wrapper class
|
|
365
|
+
function generateWrapperClass() {
|
|
366
|
+
return `class ${objectWrapper} {
|
|
367
|
+
constructor(other) {
|
|
368
|
+
this._initialize();
|
|
369
|
+
this._setDefaults();
|
|
370
|
+
|
|
371
|
+
${
|
|
372
|
+
spec.fields
|
|
373
|
+
.map(
|
|
374
|
+
(field) => ` if (typeof other === 'object' && other._refObject) {
|
|
375
|
+
this._refObject = new ${refObjectType}(other._refObject.toObject());
|
|
376
|
+
${
|
|
377
|
+
field.type.isArray
|
|
378
|
+
? ` this._wrapperFields.${field.name} = ${getWrapperNameByType(field.type)}.createArray();
|
|
379
|
+
this._wrapperFields.${field.name}.copy(other._wrapperFields.${field.name});
|
|
380
|
+
${field.type.isPrimitiveType && !isTypedArrayType(field.type) ? ` this.${field.name} = other.${field.name};` : ''}`
|
|
381
|
+
: !field.type.isPrimitiveType ||
|
|
382
|
+
(field.type.type === 'string' && spec.msgName !== 'String')
|
|
383
|
+
? ` this._wrapperFields.${field.name} = new ${getWrapperNameByType(field.type)}(other._wrapperFields.${field.name});`
|
|
384
|
+
: ''
|
|
385
|
+
}`
|
|
386
|
+
)
|
|
387
|
+
.filter((line) => line.trim())
|
|
388
|
+
.join('\n')[0] || ''
|
|
389
|
+
} if (typeof other === 'object' && other._refObject) {
|
|
390
|
+
this._refObject = new ${refObjectType}(other._refObject.toObject());
|
|
391
|
+
${spec.fields
|
|
392
|
+
.map((field) => {
|
|
393
|
+
if (field.type.isArray) {
|
|
394
|
+
return ` this._wrapperFields.${field.name} = ${getWrapperNameByType(field.type)}.createArray();
|
|
395
|
+
this._wrapperFields.${field.name}.copy(other._wrapperFields.${field.name});
|
|
396
|
+
${field.type.isPrimitiveType && !isTypedArrayType(field.type) ? ` this.${field.name} = other.${field.name};` : ''}`;
|
|
397
|
+
} else if (
|
|
398
|
+
!field.type.isPrimitiveType ||
|
|
399
|
+
(field.type.type === 'string' && spec.msgName !== 'String')
|
|
400
|
+
) {
|
|
401
|
+
return ` this._wrapperFields.${field.name} = new ${getWrapperNameByType(field.type)}(other._wrapperFields.${field.name});`;
|
|
402
|
+
}
|
|
403
|
+
return '';
|
|
404
|
+
})
|
|
405
|
+
.filter((line) => line)
|
|
406
|
+
.join('\n')}
|
|
407
|
+
} else if (typeof other !== 'undefined') {
|
|
408
|
+
translator.constructFromPlanObject(this, other);
|
|
409
|
+
}
|
|
410
|
+
this.freeze(/*own=*/false);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
_setDefaults() {
|
|
414
|
+
${spec.fields
|
|
415
|
+
.map((field) => {
|
|
416
|
+
if (
|
|
417
|
+
field.type.isPrimitiveType &&
|
|
418
|
+
!field.type.isArray &&
|
|
419
|
+
field.default_value
|
|
420
|
+
) {
|
|
421
|
+
if (field.type.type === 'string' || field.type.type === 'wstring') {
|
|
422
|
+
return ` this._refObject.${field.name} = "${field.default_value.replace(/"/g, '\\"')}";`;
|
|
423
|
+
} else {
|
|
424
|
+
return ` this._refObject.${field.name} = ${field.default_value};`;
|
|
425
|
+
}
|
|
426
|
+
} else if (
|
|
427
|
+
field.type.isPrimitiveType &&
|
|
428
|
+
!isTypedArrayType(field.type) &&
|
|
429
|
+
field.default_value
|
|
430
|
+
) {
|
|
431
|
+
if (isBigInt(field.type)) {
|
|
432
|
+
return ` this._${field.name}Array = ${JSON.stringify(field.default_value)}.map(num => BigInt(num));`;
|
|
433
|
+
} else {
|
|
434
|
+
return ` this._${field.name}Array = ${JSON.stringify(field.default_value)};`;
|
|
435
|
+
}
|
|
436
|
+
} else if (
|
|
437
|
+
field.type.isPrimitiveType &&
|
|
438
|
+
isTypedArrayType(field.type) &&
|
|
439
|
+
field.default_value
|
|
440
|
+
) {
|
|
441
|
+
return ` this._wrapperFields.${field.name}.fill(${getTypedArrayName(field.type)}.from(${JSON.stringify(field.default_value)}));`;
|
|
442
|
+
}
|
|
443
|
+
return '';
|
|
444
|
+
})
|
|
445
|
+
.filter((line) => line)
|
|
446
|
+
.join('\n')}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
_initialize() {
|
|
450
|
+
this._wrapperFields = {};
|
|
451
|
+
this._refObject = new ${refObjectType}();
|
|
452
|
+
${spec.fields
|
|
453
|
+
.map((field) => {
|
|
454
|
+
if (field.type.isArray) {
|
|
455
|
+
let result = ` this._wrapperFields.${field.name} = ${getWrapperNameByType(field.type)}.createArray();`;
|
|
456
|
+
if (field.type.type === 'string' && field.type.isFixedSizeArray) {
|
|
457
|
+
result += `\n for (let i = 0; i < ${field.type.arraySize}; i++) {
|
|
458
|
+
primitiveTypes.initString(this._refObject.${field.name}[i]);
|
|
459
|
+
}`;
|
|
460
|
+
}
|
|
461
|
+
if (
|
|
462
|
+
field.type.isArray &&
|
|
463
|
+
field.type.isPrimitiveType &&
|
|
464
|
+
!isTypedArrayType(field.type)
|
|
465
|
+
) {
|
|
466
|
+
result += `\n this._${field.name}Array = [];`;
|
|
467
|
+
}
|
|
468
|
+
return result;
|
|
469
|
+
} else if (
|
|
470
|
+
!field.type.isPrimitiveType ||
|
|
471
|
+
(field.type.type === 'string' && spec.msgName !== 'String')
|
|
472
|
+
) {
|
|
473
|
+
return ` this._wrapperFields.${field.name} = new ${getWrapperNameByType(field.type)}();`;
|
|
474
|
+
} else if (spec.msgName === 'String') {
|
|
475
|
+
return ` primitiveTypes.initString(this._refObject);`;
|
|
476
|
+
}
|
|
477
|
+
return '';
|
|
478
|
+
})
|
|
479
|
+
.filter((line) => line)
|
|
480
|
+
.join('\n')}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
static createFromRefObject(refObject) {
|
|
484
|
+
let self = new ${objectWrapper}();
|
|
485
|
+
self.copyRefObject(refObject);
|
|
486
|
+
return self;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
static createArray() {
|
|
490
|
+
return new ${arrayWrapper}();
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
static get ArrayType() {
|
|
494
|
+
return ${arrayWrapper};
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
static get refObjectArrayType() {
|
|
498
|
+
return ${refObjectArrayType};
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
static get refObjectType() {
|
|
502
|
+
return ${refObjectType};
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
toRawROS() {
|
|
506
|
+
this.freeze(/*own=*/true);
|
|
507
|
+
return this._refObject.ref();
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
freeze(own) {
|
|
511
|
+
${generateFreezeMethod()}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
serialize() {
|
|
515
|
+
this.freeze(/*own=*/false);
|
|
516
|
+
return this._refObject.ref();
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
deserialize(refObject) {
|
|
520
|
+
${spec.fields
|
|
521
|
+
.map((field) => {
|
|
522
|
+
if (
|
|
523
|
+
field.type.isArray &&
|
|
524
|
+
field.type.isPrimitiveType &&
|
|
525
|
+
field.type.isFixedSizeArray &&
|
|
526
|
+
isTypedArrayType(field.type)
|
|
527
|
+
) {
|
|
528
|
+
return ` this._wrapperFields.${field.name}.fill(refObject.${field.name}.toArray());`;
|
|
529
|
+
} else if (
|
|
530
|
+
field.type.isArray &&
|
|
531
|
+
field.type.isPrimitiveType &&
|
|
532
|
+
field.type.isFixedSizeArray &&
|
|
533
|
+
!isTypedArrayType(field.type)
|
|
534
|
+
) {
|
|
535
|
+
if (field.type.type === 'string') {
|
|
536
|
+
return ` for (let index = 0; index < ${field.type.arraySize}; index++) {
|
|
537
|
+
this._${field.name}Array[index] = refObject.${field.name}[index].data;
|
|
538
|
+
}`;
|
|
539
|
+
} else {
|
|
540
|
+
return ` this._${field.name}Array = refObject.${field.name}.toArray();`;
|
|
541
|
+
}
|
|
542
|
+
} else if (
|
|
543
|
+
field.type.isArray &&
|
|
544
|
+
field.type.isPrimitiveType &&
|
|
545
|
+
!isTypedArrayType(field.type)
|
|
546
|
+
) {
|
|
547
|
+
return ` refObject.${field.name}.data.length = refObject.${field.name}.size;
|
|
548
|
+
for (let index = 0; index < refObject.${field.name}.size; index++) {
|
|
549
|
+
this._${field.name}Array[index] = refObject.${field.name}.data[index].data;
|
|
550
|
+
}`;
|
|
551
|
+
} else if (
|
|
552
|
+
field.type.isArray &&
|
|
553
|
+
!field.type.isPrimitiveType &&
|
|
554
|
+
field.type.isFixedSizeArray
|
|
555
|
+
) {
|
|
556
|
+
return ` this._refObject.${field.name} = refObject.${field.name};
|
|
557
|
+
this._wrapperFields.${field.name}.size = ${field.type.arraySize}
|
|
558
|
+
for (let i = 0; i < ${field.type.arraySize}; i++) {
|
|
559
|
+
this._wrapperFields.${field.name}.data[i].copyRefObject(refObject.${field.name}[i]);
|
|
560
|
+
}`;
|
|
561
|
+
} else if (field.type.isArray || !field.type.isPrimitiveType) {
|
|
562
|
+
return ` this._wrapperFields.${field.name}.copyRefObject(refObject.${field.name});`;
|
|
563
|
+
} else if (field.type.type === 'string' && spec.msgName !== 'String') {
|
|
564
|
+
return ` this._wrapperFields.${field.name}.data = refObject.${field.name}.data;`;
|
|
565
|
+
} else if (field.type.isPrimitiveType) {
|
|
566
|
+
return ` this._refObject.${field.name} = refObject.${field.name};`;
|
|
567
|
+
}
|
|
568
|
+
return '';
|
|
569
|
+
})
|
|
570
|
+
.filter((line) => line)
|
|
571
|
+
.join('\n')}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
toPlainObject(enableTypedArray) {
|
|
575
|
+
return translator.toPlainObject(this, enableTypedArray);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
static freeStruct(refObject) {
|
|
579
|
+
${generateFreeStructMethod()}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
static destroyRawROS(msg) {
|
|
583
|
+
${objectWrapper}.freeStruct(msg.refObject);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
static type() {
|
|
587
|
+
return {pkgName: '${messageInfo.pkgName}', subFolder: '${messageInfo.subFolder}', interfaceName: '${messageInfo.interfaceName}'};
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
static isPrimitive() {
|
|
591
|
+
return ${isPrimitivePackage(spec.baseType)};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
static get isROSArray() {
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
get refObject() {
|
|
599
|
+
return this._refObject;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
${generateGettersSetters()}
|
|
603
|
+
|
|
604
|
+
copyRefObject(refObject) {
|
|
605
|
+
this._refObject = new ${refObjectType}(refObject.toObject());
|
|
606
|
+
|
|
607
|
+
${spec.fields
|
|
608
|
+
.map((field) => {
|
|
609
|
+
if (
|
|
610
|
+
field.type.isArray &&
|
|
611
|
+
field.type.isPrimitiveType &&
|
|
612
|
+
!isTypedArrayType(field.type)
|
|
613
|
+
) {
|
|
614
|
+
return ` refObject.${field.name}.data.length = refObject.${field.name}.size;
|
|
615
|
+
for (let index = 0; index < refObject.${field.name}.size; index++) {
|
|
616
|
+
this._${field.name}Array[index] = refObject.${field.name}.data[index].data;
|
|
617
|
+
}`;
|
|
618
|
+
} else if (
|
|
619
|
+
field.type.isArray &&
|
|
620
|
+
field.type.isPrimitiveType &&
|
|
621
|
+
field.type.isFixedSizeArray
|
|
622
|
+
) {
|
|
623
|
+
return ` this._wrapperFields.${field.name}.fill(refObject.${field.name}.toArray());`;
|
|
624
|
+
} else if (
|
|
625
|
+
field.type.isArray &&
|
|
626
|
+
!field.type.isPrimitiveType &&
|
|
627
|
+
field.type.isFixedSizeArray
|
|
628
|
+
) {
|
|
629
|
+
return ` this._refObject.${field.name} = refObject.${field.name};
|
|
630
|
+
this._wrapperFields.${field.name}.size = ${field.type.arraySize}
|
|
631
|
+
for (let i = 0; i < ${field.type.arraySize}; i++) {
|
|
632
|
+
this._wrapperFields.${field.name}.data[i].copyRefObject(refObject.${field.name}[i]);
|
|
633
|
+
}`;
|
|
634
|
+
} else if (
|
|
635
|
+
!field.type.isPrimitiveType ||
|
|
636
|
+
field.type.isArray ||
|
|
637
|
+
(field.type.type === 'string' && spec.msgName !== 'String')
|
|
638
|
+
) {
|
|
639
|
+
return ` this._wrapperFields.${field.name}.copyRefObject(this._refObject.${field.name});`;
|
|
640
|
+
}
|
|
641
|
+
return '';
|
|
642
|
+
})
|
|
643
|
+
.filter((line) => line)
|
|
644
|
+
.join('\n')}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
copy(other) {
|
|
648
|
+
this._refObject = new ${refObjectType}(other._refObject.toObject());
|
|
649
|
+
|
|
650
|
+
${spec.fields
|
|
651
|
+
.map((field) => {
|
|
652
|
+
if (
|
|
653
|
+
field.type.isArray &&
|
|
654
|
+
field.type.isPrimitiveType &&
|
|
655
|
+
!isTypedArrayType(field.type)
|
|
656
|
+
) {
|
|
657
|
+
return ` this._${field.name}Array = other._${field.name}Array.slice();`;
|
|
658
|
+
} else if (
|
|
659
|
+
!field.type.isPrimitiveType ||
|
|
660
|
+
field.type.isArray ||
|
|
661
|
+
(field.type.type === 'string' && spec.msgName !== 'String')
|
|
662
|
+
) {
|
|
663
|
+
return ` this._wrapperFields.${field.name}.copy(other._wrapperFields.${field.name});`;
|
|
664
|
+
}
|
|
665
|
+
return '';
|
|
666
|
+
})
|
|
667
|
+
.filter((line) => line)
|
|
668
|
+
.join('\n')}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
static get classType() {
|
|
672
|
+
return ${objectWrapper};
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
static get ROSMessageDef() {
|
|
676
|
+
return ${compactMsgDefJSON};
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
hasMember(name) {
|
|
680
|
+
let memberNames = ${extractMemberNames(spec.fields)};
|
|
681
|
+
return memberNames.indexOf(name) !== -1;
|
|
682
|
+
}
|
|
683
|
+
}`;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// Helper function to generate freeze method
|
|
687
|
+
function generateFreezeMethod() {
|
|
688
|
+
return spec.fields
|
|
689
|
+
.map((field) => {
|
|
690
|
+
if (
|
|
691
|
+
field.type.isArray &&
|
|
692
|
+
field.type.isPrimitiveType &&
|
|
693
|
+
!isTypedArrayType(field.type) &&
|
|
694
|
+
field.type.isFixedSizeArray
|
|
695
|
+
) {
|
|
696
|
+
if (field.type.type === 'string') {
|
|
697
|
+
return ` for (let i = 0; i < ${field.type.arraySize}; i++) {
|
|
698
|
+
if (own) {
|
|
699
|
+
primitiveTypes.initString(this._refObject.${field.name}[i].ref(), own);
|
|
700
|
+
} else {
|
|
701
|
+
if (this._${field.name}Array.length === ${field.type.arraySize}) {
|
|
702
|
+
const value = this._${field.name}Array[i];
|
|
703
|
+
this._refObject.${field.name}[i].data = value;
|
|
704
|
+
this._refObject.${field.name}[i].size = Buffer.byteLength(value);
|
|
705
|
+
this._refObject.${field.name}[i].capacity = Buffer.byteLength(value) + 1;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}`;
|
|
709
|
+
} else if (isBigInt(field.type)) {
|
|
710
|
+
return ` this._refObject.${field.name} = this._${field.name}Array.map(num => num.toString());`;
|
|
711
|
+
} else {
|
|
712
|
+
return ` this._refObject.${field.name} = this._${field.name}Array;`;
|
|
713
|
+
}
|
|
714
|
+
} else if (
|
|
715
|
+
field.type.isArray &&
|
|
716
|
+
field.type.isPrimitiveType &&
|
|
717
|
+
isTypedArrayType(field.type) &&
|
|
718
|
+
field.type.isFixedSizeArray
|
|
719
|
+
) {
|
|
720
|
+
return ` this._refObject.${field.name} = Array.from(this._wrapperFields.${field.name}.data);`;
|
|
721
|
+
} else if (
|
|
722
|
+
field.type.isArray &&
|
|
723
|
+
field.type.isPrimitiveType &&
|
|
724
|
+
!isTypedArrayType(field.type)
|
|
725
|
+
) {
|
|
726
|
+
return ` if (own) {
|
|
727
|
+
this._wrapperFields.${field.name}.fill([]);
|
|
728
|
+
} else {
|
|
729
|
+
this._wrapperFields.${field.name}.fill(this._${field.name}Array);
|
|
730
|
+
}
|
|
731
|
+
this._wrapperFields.${field.name}.freeze(own);
|
|
732
|
+
this._refObject.${field.name} = this._wrapperFields.${field.name}.refObject;`;
|
|
733
|
+
} else if (
|
|
734
|
+
field.type.isArray &&
|
|
735
|
+
field.type.isPrimitiveType &&
|
|
736
|
+
isTypedArrayType(field.type)
|
|
737
|
+
) {
|
|
738
|
+
return ` if (own) {
|
|
739
|
+
this._wrapperFields.${field.name}.fill(${getTypedArrayName(field.type)}.from([]));
|
|
740
|
+
}
|
|
741
|
+
this._wrapperFields.${field.name}.freeze(own);
|
|
742
|
+
this._refObject.${field.name} = this._wrapperFields.${field.name}.refObject;`;
|
|
743
|
+
} else if (
|
|
744
|
+
field.type.isArray &&
|
|
745
|
+
!field.type.isPrimitiveType &&
|
|
746
|
+
field.type.isFixedSizeArray
|
|
747
|
+
) {
|
|
748
|
+
return ` for (let i = 0; i < ${field.type.arraySize}; i++) {
|
|
749
|
+
if (this._wrapperFields.${field.name}.data[i]) {
|
|
750
|
+
this._wrapperFields.${field.name}.data[i].freeze(own);
|
|
751
|
+
this._refObject.${field.name}[i] = this._wrapperFields.${field.name}.data[i].refObject;
|
|
752
|
+
}
|
|
753
|
+
}`;
|
|
754
|
+
} else if (field.type.isArray || !field.type.isPrimitiveType) {
|
|
755
|
+
let result = '';
|
|
756
|
+
if (field.type.isArray) {
|
|
757
|
+
result += ` if (own) {
|
|
758
|
+
this._wrapperFields.${field.name}.fill([]);
|
|
759
|
+
}
|
|
760
|
+
`;
|
|
761
|
+
}
|
|
762
|
+
result += ` this._wrapperFields.${field.name}.freeze(own);
|
|
763
|
+
this._refObject.${field.name} = this._wrapperFields.${field.name}.refObject;`;
|
|
764
|
+
return result;
|
|
765
|
+
} else if (field.type.type === 'string' && spec.msgName !== 'String') {
|
|
766
|
+
return ` if (own) {
|
|
767
|
+
this._wrapperFields.${field.name}.freeze(own);
|
|
768
|
+
}
|
|
769
|
+
this._refObject.${field.name} = this._wrapperFields.${field.name}.refObject;`;
|
|
770
|
+
} else if (spec.msgName === 'String') {
|
|
771
|
+
return ` if (own) {
|
|
772
|
+
primitiveTypes.initString(this._refObject.ref(), own);
|
|
773
|
+
}`;
|
|
774
|
+
}
|
|
775
|
+
return '';
|
|
776
|
+
})
|
|
777
|
+
.filter((line) => line)
|
|
778
|
+
.join('\n');
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Helper function to generate freeStruct method
|
|
782
|
+
function generateFreeStructMethod() {
|
|
783
|
+
return spec.fields
|
|
784
|
+
.map((field) => {
|
|
785
|
+
if (field.type.isArray && !field.type.isFixedSizeArray) {
|
|
786
|
+
return ` if (refObject.${field.name}.size != 0) {
|
|
787
|
+
${getWrapperNameByType(field.type)}.ArrayType.freeArray(refObject.${field.name});
|
|
788
|
+
if (!${getWrapperNameByType(field.type)}.ArrayType.useTypedArray) {
|
|
789
|
+
deallocator.freeStructMember(refObject.${field.name}, ${getWrapperNameByType(field.type)}.refObjectArrayType, 'data');
|
|
790
|
+
}
|
|
791
|
+
}`;
|
|
792
|
+
} else if (
|
|
793
|
+
field.type.isArray &&
|
|
794
|
+
!field.type.isPrimitiveType &&
|
|
795
|
+
field.type.isFixedSizeArray
|
|
796
|
+
) {
|
|
797
|
+
return ` for (let i = 0; i < ${field.type.arraySize}; i++) {
|
|
798
|
+
${getWrapperNameByType(field.type)}.freeStruct(refObject.${field.name}[i]);
|
|
799
|
+
}`;
|
|
800
|
+
} else if (
|
|
801
|
+
field.type.isArray &&
|
|
802
|
+
field.type.type === 'string' &&
|
|
803
|
+
field.type.isFixedSizeArray
|
|
804
|
+
) {
|
|
805
|
+
return ` for (let i = 0; i < ${field.type.arraySize}; i++) {
|
|
806
|
+
${getWrapperNameByType(field.type)}.freeStruct(refObject.${field.name}[i]);
|
|
807
|
+
}`;
|
|
808
|
+
} else if (
|
|
809
|
+
!field.type.isPrimitiveType ||
|
|
810
|
+
(field.type.type === 'string' && spec.msgName !== 'String')
|
|
811
|
+
) {
|
|
812
|
+
return ` ${getWrapperNameByType(field.type)}.freeStruct(refObject.${field.name});`;
|
|
813
|
+
} else if (spec.msgName === 'String') {
|
|
814
|
+
return ` deallocator.freeStructMember(refObject, ${getWrapperNameByType(field.type)}.refObjectType, '${field.name}');`;
|
|
815
|
+
}
|
|
816
|
+
return '';
|
|
817
|
+
})
|
|
818
|
+
.filter((line) => line)
|
|
819
|
+
.join('\n');
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Helper function to generate getters and setters
|
|
823
|
+
function generateGettersSetters() {
|
|
824
|
+
return spec.fields
|
|
825
|
+
.map(
|
|
826
|
+
(field) => ` get ${field.name}() {
|
|
827
|
+
${generateGetter(field)}
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
set ${field.name}(value) {
|
|
831
|
+
${generateSetter(field)}
|
|
832
|
+
}`
|
|
833
|
+
)
|
|
834
|
+
.join('\n\n');
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
function generateGetter(field) {
|
|
838
|
+
if (field.type.isArray && field.type.type === 'Constants') {
|
|
839
|
+
return ` return [];`;
|
|
840
|
+
} else if (field.type.isArray && isTypedArrayType(field.type)) {
|
|
841
|
+
return ` return this._wrapperFields['${field.name}'].data;`;
|
|
842
|
+
} else if (field.type.isArray && field.type.isPrimitiveType) {
|
|
843
|
+
return ` return this._${field.name}Array;`;
|
|
844
|
+
} else if (field.type.isArray && !field.type.isPrimitiveType) {
|
|
845
|
+
return ` return this._wrapperFields.${field.name};`;
|
|
846
|
+
} else if (!field.type.isPrimitiveType && !field.type.isArray) {
|
|
847
|
+
return ` return this._wrapperFields.${field.name};`;
|
|
848
|
+
} else if (
|
|
849
|
+
!field.type.isArray &&
|
|
850
|
+
field.type.type === 'string' &&
|
|
851
|
+
spec.msgName !== 'String'
|
|
852
|
+
) {
|
|
853
|
+
return ` return this._wrapperFields.${field.name}.data;`;
|
|
854
|
+
} else if (isBigInt(field.type)) {
|
|
855
|
+
return ` return BigInt(this._refObject.${field.name});`;
|
|
856
|
+
} else {
|
|
857
|
+
return ` return this._refObject.${field.name};`;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
function generateSetter(field) {
|
|
862
|
+
let result = '';
|
|
863
|
+
|
|
864
|
+
if (field.type.isArray && field.type.isFixedSizeArray) {
|
|
865
|
+
result += ` if (value.length !== ${field.type.arraySize}) {
|
|
866
|
+
throw new RangeError('The length of the array must be ${field.type.arraySize}.');
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
`;
|
|
870
|
+
}
|
|
871
|
+
if (field.type.isArray && field.type.isUpperBound) {
|
|
872
|
+
result += ` if (value.length > ${field.type.arraySize}) {
|
|
873
|
+
throw new RangeError('The length of array ${field.name} must be <= ${field.type.arraySize}.');
|
|
874
|
+
}
|
|
875
|
+
`;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
if (field.type.isArray && isTypedArrayType(field.type)) {
|
|
879
|
+
result += ` this._wrapperFields['${field.name}'].fill(value);`;
|
|
880
|
+
} else if (field.type.isArray && field.type.isPrimitiveType) {
|
|
881
|
+
result += ` this._${field.name}Array = value;`;
|
|
882
|
+
} else if (field.type.isArray && !field.type.isPrimitiveType) {
|
|
883
|
+
result += ` this._wrapperFields.${field.name}.fill(value);`;
|
|
884
|
+
} else if (!field.type.isPrimitiveType && !field.type.isArray) {
|
|
885
|
+
result += ` if (value instanceof ${getWrapperNameByType(field.type)}) {
|
|
886
|
+
this._wrapperFields.${field.name}.copy(value);
|
|
887
|
+
} else {
|
|
888
|
+
this._wrapperFields.${field.name}.copy(new ${getWrapperNameByType(field.type)}(value));
|
|
889
|
+
}`;
|
|
890
|
+
} else if (
|
|
891
|
+
!field.type.isArray &&
|
|
892
|
+
field.type.type === 'string' &&
|
|
893
|
+
spec.msgName !== 'String'
|
|
894
|
+
) {
|
|
895
|
+
result += ` this._wrapperFields.${field.name}.data = value;`;
|
|
896
|
+
} else if (isBigInt(field.type)) {
|
|
897
|
+
result += ` if (typeof value !== "bigint") {
|
|
898
|
+
throw new TypeError('${field.name} must be type of bigint');
|
|
899
|
+
}
|
|
900
|
+
this._refObject.${field.name} = value.toString();`;
|
|
901
|
+
} else {
|
|
902
|
+
if (spec.msgName === 'String') {
|
|
903
|
+
result += ` this._refObject.size = Buffer.byteLength(value);
|
|
904
|
+
this._refObject.capacity = Buffer.byteLength(value) + 1;
|
|
905
|
+
`;
|
|
906
|
+
}
|
|
907
|
+
result += ` this._refObject.${field.name} = value;`;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
return result;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// Helper function to generate array wrapper class
|
|
914
|
+
function generateArrayWrapperClass() {
|
|
915
|
+
return `class ${arrayWrapper} {
|
|
916
|
+
constructor(size = 0) {
|
|
917
|
+
this._resize(size);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
toRawROS() {
|
|
921
|
+
return this._refObject.ref();
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
fill(values) {
|
|
925
|
+
${
|
|
926
|
+
willUseTypedArray
|
|
927
|
+
? ` if (Array.isArray(values)) {
|
|
928
|
+
this._wrappers = new ${currentTypedArray}(values);
|
|
929
|
+
} else {
|
|
930
|
+
this._wrappers = values;
|
|
931
|
+
}`
|
|
932
|
+
: isPrimitivePackage(spec.baseType)
|
|
933
|
+
? ` const length = values.length;
|
|
934
|
+
this._resize(length);
|
|
935
|
+
for (let i = 0; i < length; ++i) {
|
|
936
|
+
let wrapper = new ${objectWrapper}();
|
|
937
|
+
wrapper.data = values[i];
|
|
938
|
+
this._wrappers[i] = wrapper;
|
|
939
|
+
}`
|
|
940
|
+
: ` const length = values.length;
|
|
941
|
+
this._resize(length);
|
|
942
|
+
values.forEach((value, index) => {
|
|
943
|
+
if (value instanceof ${objectWrapper}) {
|
|
944
|
+
this._wrappers[index].copy(value);
|
|
945
|
+
} else {
|
|
946
|
+
this._wrappers[index] = new ${objectWrapper}(value);
|
|
947
|
+
}
|
|
948
|
+
});`
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
freeze(own) {
|
|
953
|
+
${
|
|
954
|
+
!willUseTypedArray
|
|
955
|
+
? ` this._wrappers.forEach((wrapper, index) => {
|
|
956
|
+
wrapper.freeze(own);
|
|
957
|
+
this._refArray[index] = wrapper.refObject;
|
|
958
|
+
});
|
|
959
|
+
`
|
|
960
|
+
: ''
|
|
961
|
+
}
|
|
962
|
+
this._refObject.size = this._wrappers.length;
|
|
963
|
+
this._refObject.capacity = this._wrappers.length;
|
|
964
|
+
|
|
965
|
+
if (this._refObject.capacity === 0) {
|
|
966
|
+
this._refObject.data = null
|
|
967
|
+
} else {
|
|
968
|
+
${
|
|
969
|
+
willUseTypedArray
|
|
970
|
+
? ` const buffer = Buffer.from(new Uint8Array(this._wrappers.buffer));
|
|
971
|
+
this._refObject.data = buffer;`
|
|
972
|
+
: ` this._refObject.data = this._refArray.buffer;`
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
get refObject() {
|
|
978
|
+
return this._refObject;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
get data() {
|
|
982
|
+
return this._wrappers;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
get size() {
|
|
986
|
+
return this._wrappers.length;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
set size(value) {
|
|
990
|
+
if (typeof value != 'number') {
|
|
991
|
+
throw new TypeError('Invalid argument: should provide a number to ${arrayWrapper}.size setter');
|
|
992
|
+
}
|
|
993
|
+
return this._resize(value);
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
get capacity() {
|
|
997
|
+
return this._wrappers.length;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
set capacity(value) {
|
|
1001
|
+
if (typeof value != 'number') {
|
|
1002
|
+
throw new TypeError('Invalid argument: should provide a number to ${arrayWrapper}.capacity setter');
|
|
1003
|
+
}
|
|
1004
|
+
return this._resize(value);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
_resize(size) {
|
|
1008
|
+
if (size < 0) {
|
|
1009
|
+
throw new RangeError('Invalid argument: should provide a positive number');
|
|
1010
|
+
}
|
|
1011
|
+
${
|
|
1012
|
+
willUseTypedArray
|
|
1013
|
+
? ` this._refArray = undefined;`
|
|
1014
|
+
: ` this._refArray = new ${refArrayType}(size);`
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
this._refObject = new ${refObjectArrayType}();
|
|
1018
|
+
this._refObject.size = size;
|
|
1019
|
+
this._refObject.capacity = size;
|
|
1020
|
+
|
|
1021
|
+
${
|
|
1022
|
+
willUseTypedArray
|
|
1023
|
+
? ` this._wrappers = new ${currentTypedArray}(size);`
|
|
1024
|
+
: ` this._wrappers = new Array();
|
|
1025
|
+
for (let i = 0; i < size; i++) {
|
|
1026
|
+
this._wrappers.push(new ${objectWrapper}());
|
|
1027
|
+
}`
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
copyRefObject(refObject) {
|
|
1032
|
+
this._refObject = refObject;
|
|
1033
|
+
|
|
1034
|
+
${
|
|
1035
|
+
willUseTypedArray
|
|
1036
|
+
? ` const byteLen = refObject.size * ref.types.${currentTypedArrayElementType}.size;
|
|
1037
|
+
const arrayBuffer = refObject.data.length !== 0 ?
|
|
1038
|
+
rclnodejs.createArrayBufferFromAddress(refObject.data.hexAddress(), byteLen) :
|
|
1039
|
+
Buffer.alloc(0);
|
|
1040
|
+
this._wrappers = new ${currentTypedArray}(arrayBuffer);`
|
|
1041
|
+
: ` let refObjectArray = this._refObject.data;
|
|
1042
|
+
refObjectArray.length = this._refObject.size;
|
|
1043
|
+
this._resize(this._refObject.size);
|
|
1044
|
+
for (let index = 0; index < this._refObject.size; index++) {
|
|
1045
|
+
this._wrappers[index].copyRefObject(refObjectArray[index]);
|
|
1046
|
+
}`
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
copy(other) {
|
|
1051
|
+
if (! (other instanceof ${arrayWrapper})) {
|
|
1052
|
+
throw new TypeError('Invalid argument: should provide "${arrayWrapper}".');
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
this._resize(other.size);
|
|
1056
|
+
${
|
|
1057
|
+
willUseTypedArray
|
|
1058
|
+
? ` this._wrappers = other._wrappers.slice();`
|
|
1059
|
+
: ` other._wrappers.forEach((wrapper, index) => {
|
|
1060
|
+
this._wrappers[index].copy(wrapper);
|
|
1061
|
+
});`
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
static freeArray(refObject) {
|
|
1066
|
+
${
|
|
1067
|
+
!willUseTypedArray
|
|
1068
|
+
? ` let refObjectArray = refObject.data;
|
|
1069
|
+
refObjectArray.length = refObject.size;
|
|
1070
|
+
for (let index = 0; index < refObject.size; index++) {
|
|
1071
|
+
${objectWrapper}.freeStruct(refObjectArray[index]);
|
|
1072
|
+
}`
|
|
1073
|
+
: ''
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
static get elementType() {
|
|
1078
|
+
return ${objectWrapper};
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
static get isROSArray() {
|
|
1082
|
+
return true;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
static get useTypedArray() {
|
|
1086
|
+
return ${willUseTypedArray};
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
get classType() {
|
|
1090
|
+
return ${arrayWrapper};
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
toPlainObject(enableTypedArray) {
|
|
1094
|
+
return translator.toPlainObject(this, enableTypedArray);
|
|
1095
|
+
}
|
|
1096
|
+
}`;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// Helper function to generate constants
|
|
1100
|
+
function generateConstants() {
|
|
1101
|
+
if (spec.constants && spec.constants.length > 0) {
|
|
1102
|
+
return spec.constants
|
|
1103
|
+
.map((c) => {
|
|
1104
|
+
const value = c.type === 'string' ? `"${c.value}"` : c.value;
|
|
1105
|
+
return `Object.defineProperty(${objectWrapper}, "${c.name}", {value: ${value}, writable: false, enumerable: true, configurable: true});`;
|
|
1106
|
+
})
|
|
1107
|
+
.join('\n');
|
|
1108
|
+
}
|
|
1109
|
+
return '';
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
module.exports = generateMessage;
|