1// Copyright 2021 The Pigweed Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); you may not 4// use this file except in compliance with the License. You may obtain a copy of 5// the License at 6// 7// https://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, WITHOUT 11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12// License for the specific language governing permissions and limitations under 13// the License. 14 15/** Tools for compiling and importing Javascript protos on the fly. */ 16 17import { Message } from 'google-protobuf'; 18import { 19 DescriptorProto, 20 FileDescriptorSet, 21} from 'google-protobuf/google/protobuf/descriptor_pb'; 22 23export type MessageCreator = new () => Message; 24interface MessageMap { 25 [key: string | number]: MessageCreator; 26} 27interface MessageDescriptorMap { 28 [key: string | number]: DescriptorProto; 29} 30export interface ModuleMap { 31 [key: string | number]: any; 32} 33 34/** 35 * A wrapper class of protocol buffer modules to provide convenience methods. 36 */ 37export class ProtoCollection { 38 private readonly messages: MessageMap = {}; 39 private readonly messageDescriptors: MessageDescriptorMap = {}; 40 41 constructor( 42 readonly fileDescriptorSet: FileDescriptorSet, 43 modules: ModuleMap, 44 ) { 45 this.mapMessages(fileDescriptorSet, modules); 46 } 47 48 /** 49 * Creates a map between message identifier "{packageName}.{messageName}" 50 * and the Message class and also the associated DescriptorProto. 51 */ 52 private mapMessages(set: FileDescriptorSet, mods: ModuleMap): void { 53 for (const fileDescriptor of set.getFileList()) { 54 const mod = mods[fileDescriptor.getName()]; 55 for (const messageType of fileDescriptor.getMessageTypeList()) { 56 const fullName = 57 fileDescriptor.getPackage() + '.' + messageType.getName(); 58 const message = mod[messageType.getName()]; 59 this.messages[fullName] = message; 60 this.messageDescriptors[fullName] = messageType; 61 } 62 } 63 } 64 65 /** 66 * Finds the Message class referenced by the identifier. 67 * 68 * @param identifier String identifier of the form 69 * "{packageName}.{messageName}" i.e: "pw.rpc.test.NewMessage". 70 */ 71 getMessageCreator(identifier: string): MessageCreator | undefined { 72 return this.messages[identifier]; 73 } 74 75 /** 76 * Finds the DescriptorProto referenced by the identifier. 77 * 78 * @param identifier String identifier of the form 79 * "{packageName}.{messageName}" i.e: "pw.rpc.test.NewMessage". 80 */ 81 getDescriptorProto(identifier: string): DescriptorProto | undefined { 82 return this.messageDescriptors[identifier]; 83 } 84} 85