@openhps/protobuf 1.0.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.
Files changed (137) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +165 -0
  3. package/dist/cjs/InternalProtobufDeserializer.js +152 -0
  4. package/dist/cjs/InternalProtobufDeserializer.js.map +1 -0
  5. package/dist/cjs/InternalProtobufSerializer.js +137 -0
  6. package/dist/cjs/InternalProtobufSerializer.js.map +1 -0
  7. package/dist/cjs/ProtobufSerializer.js +136 -0
  8. package/dist/cjs/ProtobufSerializer.js.map +1 -0
  9. package/dist/cjs/bin/generator.js +107 -0
  10. package/dist/cjs/bin/generator.js.map +1 -0
  11. package/dist/cjs/decorators/index.js +4 -0
  12. package/dist/cjs/decorators/index.js.map +1 -0
  13. package/dist/cjs/decorators/options.js +3 -0
  14. package/dist/cjs/decorators/options.js.map +1 -0
  15. package/dist/cjs/generator/ObjectGenerator.js +316 -0
  16. package/dist/cjs/generator/ObjectGenerator.js.map +1 -0
  17. package/dist/cjs/generator/ProjectGenerator.js +120 -0
  18. package/dist/cjs/generator/ProjectGenerator.js.map +1 -0
  19. package/dist/cjs/generator/ProtobufGenerator.js +31 -0
  20. package/dist/cjs/generator/ProtobufGenerator.js.map +1 -0
  21. package/dist/cjs/generator/ServiceGenerator.js +14 -0
  22. package/dist/cjs/generator/ServiceGenerator.js.map +1 -0
  23. package/dist/cjs/generator/constants.js +21 -0
  24. package/dist/cjs/generator/constants.js.map +1 -0
  25. package/dist/cjs/generator/index.js +7 -0
  26. package/dist/cjs/generator/index.js.map +1 -0
  27. package/dist/cjs/generator/types.js +3 -0
  28. package/dist/cjs/generator/types.js.map +1 -0
  29. package/dist/cjs/index.js +6 -0
  30. package/dist/cjs/index.js.map +1 -0
  31. package/dist/esm/InternalProtobufDeserializer.js +147 -0
  32. package/dist/esm/InternalProtobufDeserializer.js.map +1 -0
  33. package/dist/esm/InternalProtobufSerializer.js +132 -0
  34. package/dist/esm/InternalProtobufSerializer.js.map +1 -0
  35. package/dist/esm/ProtobufSerializer.js +131 -0
  36. package/dist/esm/ProtobufSerializer.js.map +1 -0
  37. package/dist/esm/bin/generator.js +104 -0
  38. package/dist/esm/bin/generator.js.map +1 -0
  39. package/dist/esm/decorators/index.js +2 -0
  40. package/dist/esm/decorators/index.js.map +1 -0
  41. package/dist/esm/decorators/options.js +2 -0
  42. package/dist/esm/decorators/options.js.map +1 -0
  43. package/dist/esm/generator/ObjectGenerator.js +311 -0
  44. package/dist/esm/generator/ObjectGenerator.js.map +1 -0
  45. package/dist/esm/generator/ProjectGenerator.js +115 -0
  46. package/dist/esm/generator/ProjectGenerator.js.map +1 -0
  47. package/dist/esm/generator/ProtobufGenerator.js +27 -0
  48. package/dist/esm/generator/ProtobufGenerator.js.map +1 -0
  49. package/dist/esm/generator/ServiceGenerator.js +10 -0
  50. package/dist/esm/generator/ServiceGenerator.js.map +1 -0
  51. package/dist/esm/generator/constants.js +18 -0
  52. package/dist/esm/generator/constants.js.map +1 -0
  53. package/dist/esm/generator/index.js +4 -0
  54. package/dist/esm/generator/index.js.map +1 -0
  55. package/dist/esm/generator/types.js +2 -0
  56. package/dist/esm/generator/types.js.map +1 -0
  57. package/dist/esm/index.js +3 -0
  58. package/dist/esm/index.js.map +1 -0
  59. package/dist/esm5/InternalProtobufDeserializer.js +147 -0
  60. package/dist/esm5/InternalProtobufDeserializer.js.map +1 -0
  61. package/dist/esm5/InternalProtobufSerializer.js +132 -0
  62. package/dist/esm5/InternalProtobufSerializer.js.map +1 -0
  63. package/dist/esm5/ProtobufSerializer.js +131 -0
  64. package/dist/esm5/ProtobufSerializer.js.map +1 -0
  65. package/dist/esm5/bin/generator.js +104 -0
  66. package/dist/esm5/bin/generator.js.map +1 -0
  67. package/dist/esm5/decorators/index.js +2 -0
  68. package/dist/esm5/decorators/index.js.map +1 -0
  69. package/dist/esm5/decorators/options.js +2 -0
  70. package/dist/esm5/decorators/options.js.map +1 -0
  71. package/dist/esm5/generator/ObjectGenerator.js +311 -0
  72. package/dist/esm5/generator/ObjectGenerator.js.map +1 -0
  73. package/dist/esm5/generator/ProjectGenerator.js +115 -0
  74. package/dist/esm5/generator/ProjectGenerator.js.map +1 -0
  75. package/dist/esm5/generator/ProtobufGenerator.js +27 -0
  76. package/dist/esm5/generator/ProtobufGenerator.js.map +1 -0
  77. package/dist/esm5/generator/ServiceGenerator.js +10 -0
  78. package/dist/esm5/generator/ServiceGenerator.js.map +1 -0
  79. package/dist/esm5/generator/constants.js +18 -0
  80. package/dist/esm5/generator/constants.js.map +1 -0
  81. package/dist/esm5/generator/index.js +4 -0
  82. package/dist/esm5/generator/index.js.map +1 -0
  83. package/dist/esm5/generator/types.js +2 -0
  84. package/dist/esm5/generator/types.js.map +1 -0
  85. package/dist/esm5/index.js +3 -0
  86. package/dist/esm5/index.js.map +1 -0
  87. package/dist/types/InternalProtobufDeserializer.d.ts +9 -0
  88. package/dist/types/InternalProtobufDeserializer.d.ts.map +1 -0
  89. package/dist/types/InternalProtobufSerializer.d.ts +23 -0
  90. package/dist/types/InternalProtobufSerializer.d.ts.map +1 -0
  91. package/dist/types/ProtobufSerializer.d.ts +32 -0
  92. package/dist/types/ProtobufSerializer.d.ts.map +1 -0
  93. package/dist/types/bin/generator.d.ts +3 -0
  94. package/dist/types/bin/generator.d.ts.map +1 -0
  95. package/dist/types/decorators/index.d.ts +2 -0
  96. package/dist/types/decorators/index.d.ts.map +1 -0
  97. package/dist/types/decorators/options.d.ts +30 -0
  98. package/dist/types/decorators/options.d.ts.map +1 -0
  99. package/dist/types/generator/ObjectGenerator.d.ts +22 -0
  100. package/dist/types/generator/ObjectGenerator.d.ts.map +1 -0
  101. package/dist/types/generator/ProjectGenerator.d.ts +17 -0
  102. package/dist/types/generator/ProjectGenerator.d.ts.map +1 -0
  103. package/dist/types/generator/ProtobufGenerator.d.ts +26 -0
  104. package/dist/types/generator/ProtobufGenerator.d.ts.map +1 -0
  105. package/dist/types/generator/ServiceGenerator.d.ts +7 -0
  106. package/dist/types/generator/ServiceGenerator.d.ts.map +1 -0
  107. package/dist/types/generator/constants.d.ts +3 -0
  108. package/dist/types/generator/constants.d.ts.map +1 -0
  109. package/dist/types/generator/index.d.ts +4 -0
  110. package/dist/types/generator/index.d.ts.map +1 -0
  111. package/dist/types/generator/types.d.ts +5 -0
  112. package/dist/types/generator/types.d.ts.map +1 -0
  113. package/dist/types/index.d.ts +3 -0
  114. package/dist/types/index.d.ts.map +1 -0
  115. package/dist/web/openhps-protobuf.es.js +15165 -0
  116. package/dist/web/openhps-protobuf.es.js.map +1 -0
  117. package/dist/web/openhps-protobuf.es.min.js +2 -0
  118. package/dist/web/openhps-protobuf.es.min.js.map +1 -0
  119. package/dist/web/openhps-protobuf.js +16722 -0
  120. package/dist/web/openhps-protobuf.js.map +1 -0
  121. package/dist/web/openhps-protobuf.min.js +2 -0
  122. package/dist/web/openhps-protobuf.min.js.map +1 -0
  123. package/package.json +96 -0
  124. package/src/InternalProtobufDeserializer.ts +245 -0
  125. package/src/InternalProtobufSerializer.ts +212 -0
  126. package/src/ProtobufSerializer.ts +168 -0
  127. package/src/bin/generator.ts +131 -0
  128. package/src/decorators/index.ts +1 -0
  129. package/src/decorators/options.ts +30 -0
  130. package/src/generator/ObjectGenerator.ts +377 -0
  131. package/src/generator/ProjectGenerator.ts +130 -0
  132. package/src/generator/ProtobufGenerator.ts +49 -0
  133. package/src/generator/ServiceGenerator.ts +11 -0
  134. package/src/generator/constants.ts +19 -0
  135. package/src/generator/index.ts +3 -0
  136. package/src/generator/types.ts +4 -0
  137. package/src/index.ts +2 -0
@@ -0,0 +1,168 @@
1
+ import { Constructor, DataSerializer, DataSerializerConfig, DataSerializerUtils } from '@openhps/core';
2
+ import * as path from 'path';
3
+ import * as protobuf from 'protobufjs';
4
+ import * as fs from 'fs';
5
+ import { ProjectGenerator } from './generator';
6
+ import { InternalProtobufDeserializer } from './InternalProtobufDeserializer';
7
+ import { InternalProtobufSerializer } from './InternalProtobufSerializer';
8
+
9
+ export class ProtobufSerializer extends DataSerializer {
10
+ protected static wrapperMessage: protobuf.Type;
11
+ protected static options: ProtobufSerializerConfig = {
12
+ serializer: new InternalProtobufSerializer(),
13
+ deserializer: new InternalProtobufDeserializer(),
14
+ types: new Map(),
15
+ };
16
+ protected static root: protobuf.Root;
17
+
18
+ private static getFiles(directory: string, files: string[] = []): string[] {
19
+ if (!fs.statSync(directory).isDirectory()) {
20
+ return [];
21
+ }
22
+ const fileList = fs.readdirSync(path.normalize(directory));
23
+ for (const file of fileList) {
24
+ const name = `${directory}/${file}`;
25
+ if (fs.statSync(name).isDirectory()) {
26
+ this.getFiles(name, files);
27
+ } else if (name.endsWith('.proto')) {
28
+ files.push(path.normalize(name));
29
+ }
30
+ }
31
+ return files;
32
+ }
33
+
34
+ /**
35
+ * Initialize the protocol buffer serializer
36
+ * @param {string} [directory] Directory of generated protocol messages. Default will generate on the fly
37
+ * @returns {Promise<void>} Promise once initialized
38
+ */
39
+ static initialize(directory?: string): Promise<void> {
40
+ return new Promise((resolve, reject) => {
41
+ ProtobufSerializer.root = new protobuf.Root();
42
+ Promise.resolve(
43
+ !directory ? (ProjectGenerator.buildProject(path.resolve('tmp')) as any) : Promise.resolve(),
44
+ )
45
+ .then(() => {
46
+ const files = this.getFiles(path.resolve(directory ?? 'tmp'));
47
+ const loadPromise: Promise<void> = new Promise((resolve) => {
48
+ ProtobufSerializer.root
49
+ .load(files, {
50
+ keepCase: true,
51
+ })
52
+ .then(() => {
53
+ files.forEach((file) => {
54
+ const className = path.parse(file).name;
55
+ const knownType = this.knownTypes.get(className);
56
+ if (knownType) {
57
+ const objectMeta = DataSerializerUtils.getOwnMetadata(
58
+ this.knownTypes.get(className),
59
+ );
60
+ const rootMeta = DataSerializerUtils.getRootMetadata(
61
+ this.knownTypes.get(className),
62
+ );
63
+ const MessageType = ProtobufSerializer.root.lookupType(className);
64
+ let enumNumber = undefined;
65
+ const enumMapping: Map<number, string> = new Map();
66
+ try {
67
+ const typeEnum = ProtobufSerializer.root.lookupEnum(
68
+ `${rootMeta.classType.name}Type`,
69
+ );
70
+ Object.keys(typeEnum.values).forEach((key, id) => {
71
+ if (id === 0) {
72
+ return; // Unspecified
73
+ }
74
+ const otherClassName = typeEnum.valuesOptions[key]['(className)'];
75
+ if (otherClassName === className) {
76
+ enumNumber = typeEnum.values[key];
77
+ }
78
+ enumMapping.set(
79
+ typeEnum.values[key],
80
+ typeEnum.valuesOptions[key]['(className)'],
81
+ );
82
+ });
83
+ } catch (ex) {
84
+ // Ignore :')
85
+ }
86
+ objectMeta.protobuf = {
87
+ messageType: MessageType,
88
+ messageTypeEnum: enumNumber,
89
+ enumMapping,
90
+ };
91
+ this.options.types.set(className, MessageType);
92
+ }
93
+ });
94
+ resolve();
95
+ })
96
+ .catch((error) => {
97
+ return reject(error);
98
+ });
99
+ });
100
+
101
+ this.wrapperMessage = new protobuf.Type('WrapperMessage');
102
+ this.wrapperMessage.add(new protobuf.Field('data', 1, 'google.protobuf.Any'));
103
+ this.wrapperMessage.addJSON(protobuf.common['google/protobuf/any.proto'].nested);
104
+ return loadPromise;
105
+ })
106
+ .then(() => {
107
+ console.log(ProtobufSerializer.root.toJSON());
108
+ resolve();
109
+ })
110
+ .catch(reject);
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Serialize data
116
+ * @param {any} data Data to serialize
117
+ * @param {DataSerializerConfig} [config] Data serializer configuration
118
+ * @returns {Uint8Array} Serialized buffer
119
+ */
120
+ static serialize<T>(data: T, config?: DataSerializerConfig): Uint8Array {
121
+ const serializedData = super.serialize(data, {
122
+ ...this.options,
123
+ ...config,
124
+ });
125
+ const MessageType = this.options.types.get(data.constructor.name) as protobuf.Type;
126
+ const message = MessageType.fromObject(serializedData);
127
+ const wrapper = this.wrapperMessage.create({
128
+ data: {
129
+ type_url: data.constructor.name,
130
+ value: MessageType.encode(message).finish(),
131
+ },
132
+ });
133
+ return this.wrapperMessage.encode(wrapper).finish();
134
+ }
135
+
136
+ /**
137
+ * Deserialize data
138
+ * @param serializedData Data to deserialze
139
+ * @param dataType Optional data type to specify deserialization type
140
+ * @param config Data serializer configuration
141
+ */
142
+ static deserialize<T>(
143
+ serializedData: Uint8Array | any,
144
+ dataType?: Constructor<T>,
145
+ config?: DataSerializerConfig,
146
+ ): T {
147
+ const decodedData: any = this.wrapperMessage.decode(serializedData);
148
+ const typeURL = decodedData.data.type_url;
149
+ const MessageType = this.options.types.get(typeURL) as protobuf.Type;
150
+ const decodedMessage = MessageType.decode(decodedData.data.value);
151
+ const finalType = dataType ?? (this.knownTypes.get(typeURL) as Constructor<T>);
152
+ return this.options.deserializer.convertSingleValue(
153
+ decodedMessage,
154
+ DataSerializerUtils.ensureTypeDescriptor(finalType),
155
+ DataSerializer.knownTypes,
156
+ undefined,
157
+ undefined,
158
+ {
159
+ ...config,
160
+ ...this.options,
161
+ },
162
+ );
163
+ }
164
+ }
165
+
166
+ export interface ProtobufSerializerConfig extends DataSerializerConfig {
167
+ types: Map<string, protobuf.Type>;
168
+ }
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+
3
+ import chalk from 'chalk';
4
+ import { ProjectGenerator } from '../generator/';
5
+ import '@openhps/rf';
6
+ import * as path from 'path';
7
+ import { input } from '@inquirer/prompts';
8
+ import * as yargs from 'yargs';
9
+ import {
10
+ Absolute3DPosition,
11
+ Accuracy1D,
12
+ AngleUnit,
13
+ DataFrame,
14
+ DataObject,
15
+ DataSerializer,
16
+ LengthUnit,
17
+ LinearVelocity,
18
+ LinearVelocityUnit,
19
+ Orientation,
20
+ RelativeDistance,
21
+ } from '@openhps/core';
22
+ import { ProtobufSerializer } from '../ProtobufSerializer';
23
+ import { expect } from 'chai';
24
+
25
+ const args: [K: string] = yargs.argv as any;
26
+ const data = {
27
+ directory: path.normalize('tmp'),
28
+ };
29
+
30
+ /**
31
+ * Main CLI entry
32
+ */
33
+ function main() {
34
+ console.log(chalk.redBright('OpenHPS Protocol Buffer Generator'));
35
+
36
+ if (args['help'] || args['?']) {
37
+ console.log('Command line arguments:');
38
+ console.log('-d <dir>\t\tSpecify the output directory to create the protocol buffer messages.');
39
+ console.log('-v\t\tVerbose logging.');
40
+ process.exit();
41
+ }
42
+
43
+ Promise.resolve(
44
+ args['d'] ??
45
+ input({
46
+ message: 'Enter the output directory',
47
+ }),
48
+ ).then((directory) => {
49
+ data.directory = directory;
50
+ prepare();
51
+ generate();
52
+ });
53
+ }
54
+
55
+ /**
56
+ *
57
+ */
58
+ function prepare() {
59
+ console.log('Detected serializable packages:');
60
+ ProjectGenerator.getPackages().map((module) => {
61
+ console.log(`\t${module}`);
62
+ });
63
+ }
64
+
65
+ /**
66
+ *
67
+ */
68
+ function generate() {
69
+ ProjectGenerator.buildProject(data.directory, {
70
+ logLevel: args['v'] ? 3 : 2,
71
+ useAnyType: args['any'] !== undefined,
72
+ })
73
+ .then((count) => {
74
+ console.log(chalk.green(`${count} protocol buffer messages created!`));
75
+ return test();
76
+ })
77
+ .then(() => {
78
+ process.exit();
79
+ })
80
+ .catch((ex: Error) => {
81
+ console.error(chalk.red(ex.stack));
82
+ process.exit(-1);
83
+ });
84
+ }
85
+
86
+ /**
87
+ *
88
+ */
89
+ function test(): Promise<void> {
90
+ return new Promise((resolve, reject) => {
91
+ console.log(`Performing a self-test of the protocol buffer messages ...`);
92
+ // Load data
93
+ ProtobufSerializer.initialize(data.directory)
94
+ .then(() => {
95
+ // Generic example
96
+ const frame = new DataFrame();
97
+ const object = new DataObject('test', 'Test Object');
98
+ object.setPosition(new Absolute3DPosition(1, 2, 3, LengthUnit.METER));
99
+ object.position.orientation = Orientation.fromEuler({
100
+ yaw: 50,
101
+ roll: 10,
102
+ pitch: 10,
103
+ unit: AngleUnit.DEGREE,
104
+ });
105
+ object.position.velocity.linear = new LinearVelocity(
106
+ 1,
107
+ 0,
108
+ 0,
109
+ LinearVelocityUnit.METER_PER_SECOND,
110
+ ).setAccuracy(new Accuracy1D(1, LinearVelocityUnit.CENTIMETER_PER_SECOND));
111
+ object.position.orientation.accuracy = new Accuracy1D(10, AngleUnit.DEGREE);
112
+ object.addRelativePosition(new RelativeDistance('test2', 10, LengthUnit.METER));
113
+ frame.source = object;
114
+ frame.addObject(new DataObject('test2', 'Test Object 2'));
115
+ const buffer = ProtobufSerializer.serialize(frame);
116
+ const deserialized: DataFrame = ProtobufSerializer.deserialize(buffer);
117
+ expect(deserialized).to.not.be.undefined;
118
+ const compare1 = JSON.stringify(DataSerializer.serialize(deserialized), null, 2);
119
+ const compare2 = JSON.stringify(DataSerializer.serialize(frame), null, 2);
120
+ // console.log(compare1);
121
+ // console.log('\n');
122
+ // console.log(compare2);
123
+ expect(compare1).to.eql(compare2);
124
+ console.log(chalk.green(`Basic serialization and deserialization test completed!`));
125
+ resolve();
126
+ })
127
+ .catch(reject);
128
+ });
129
+ }
130
+
131
+ main();
@@ -0,0 +1 @@
1
+ import './options';
@@ -0,0 +1,30 @@
1
+ import { SerializableObjectOptions, MemberOptionsBase, ObjectMetadata, Serializable } from '@openhps/core';
2
+ import { Type } from 'protobufjs';
3
+
4
+ export type { SerializableObjectOptions, MemberOptionsBase, ObjectMetadata };
5
+
6
+ declare module '@openhps/core/dist/types/data/decorators/options' {
7
+ export interface MemberOptionsBase {
8
+ protobuf?: {
9
+ optional?: boolean;
10
+ name?: string;
11
+ };
12
+ }
13
+ }
14
+
15
+ declare module '@openhps/core/dist/types/data/decorators/metadata' {
16
+ export interface ObjectMetadata {
17
+ protobuf?: {
18
+ messageType?: Type;
19
+ messageTypeEnum?: number;
20
+ enumMapping?: Map<number, string>;
21
+ generator?: {
22
+ subTypes?: Serializable<any>[];
23
+ subModules?: Set<string>;
24
+ type?: Serializable<any>;
25
+ dataMembers?: Map<string, ObjectMemberMetadata & { subMembers?: Map<string, ObjectMemberMetadata> }>;
26
+ allowOverride?: boolean;
27
+ };
28
+ };
29
+ }
30
+ }