1<?php 2 3// Protocol Buffers - Google's data interchange format 4// Copyright 2008 Google Inc. All rights reserved. 5// 6// Use of this source code is governed by a BSD-style 7// license that can be found in the LICENSE file or at 8// https://developers.google.com/open-source/licenses/bsd 9 10namespace Google\Protobuf\Internal; 11 12use Google\Protobuf\Internal\Descriptor; 13use Google\Protobuf\Internal\FileDescriptor; 14use Google\Protobuf\Internal\FileDescriptorSet; 15use Google\Protobuf\Internal\MessageBuilderContext; 16use Google\Protobuf\Internal\EnumBuilderContext; 17 18class DescriptorPool 19{ 20 private static $pool; 21 // Map from message names to sub-maps, which are maps from field numbers to 22 // field descriptors. 23 private $class_to_desc = []; 24 private $class_to_enum_desc = []; 25 private $proto_to_class = []; 26 27 public static function getGeneratedPool() 28 { 29 if (!isset(self::$pool)) { 30 self::$pool = new DescriptorPool(); 31 } 32 return self::$pool; 33 } 34 35 public function internalAddGeneratedFile($data, $use_nested = false) 36 { 37 $files = new FileDescriptorSet(); 38 $files->mergeFromString($data); 39 40 foreach($files->getFile() as $file_proto) { 41 $file = FileDescriptor::buildFromProto($file_proto); 42 43 foreach ($file->getMessageType() as $desc) { 44 $this->addDescriptor($desc); 45 } 46 unset($desc); 47 48 foreach ($file->getEnumType() as $desc) { 49 $this->addEnumDescriptor($desc); 50 } 51 unset($desc); 52 53 foreach ($file->getMessageType() as $desc) { 54 $this->crossLink($desc); 55 } 56 unset($desc); 57 } 58 } 59 60 public function addMessage($name, $klass) 61 { 62 return new MessageBuilderContext($name, $klass, $this); 63 } 64 65 public function addEnum($name, $klass) 66 { 67 return new EnumBuilderContext($name, $klass, $this); 68 } 69 70 public function addDescriptor($descriptor) 71 { 72 $this->proto_to_class[$descriptor->getFullName()] = 73 $descriptor->getClass(); 74 $this->class_to_desc[$descriptor->getClass()] = $descriptor; 75 $this->class_to_desc[$descriptor->getLegacyClass()] = $descriptor; 76 $this->class_to_desc[$descriptor->getPreviouslyUnreservedClass()] = $descriptor; 77 foreach ($descriptor->getNestedType() as $nested_type) { 78 $this->addDescriptor($nested_type); 79 } 80 foreach ($descriptor->getEnumType() as $enum_type) { 81 $this->addEnumDescriptor($enum_type); 82 } 83 } 84 85 public function addEnumDescriptor($descriptor) 86 { 87 $this->proto_to_class[$descriptor->getFullName()] = 88 $descriptor->getClass(); 89 $this->class_to_enum_desc[$descriptor->getClass()] = $descriptor; 90 $this->class_to_enum_desc[$descriptor->getLegacyClass()] = $descriptor; 91 } 92 93 public function getDescriptorByClassName($klass) 94 { 95 if (isset($this->class_to_desc[$klass])) { 96 return $this->class_to_desc[$klass]; 97 } else { 98 return null; 99 } 100 } 101 102 public function getEnumDescriptorByClassName($klass) 103 { 104 if (isset($this->class_to_enum_desc[$klass])) { 105 return $this->class_to_enum_desc[$klass]; 106 } else { 107 return null; 108 } 109 } 110 111 public function getDescriptorByProtoName($proto) 112 { 113 if (isset($this->proto_to_class[$proto])) { 114 $klass = $this->proto_to_class[$proto]; 115 return $this->class_to_desc[$klass]; 116 } else { 117 return null; 118 } 119 } 120 121 public function getEnumDescriptorByProtoName($proto) 122 { 123 $klass = $this->proto_to_class[$proto]; 124 return $this->class_to_enum_desc[$klass]; 125 } 126 127 private function crossLink(Descriptor $desc) 128 { 129 foreach ($desc->getField() as $field) { 130 switch ($field->getType()) { 131 case GPBType::MESSAGE: 132 $proto = $field->getMessageType(); 133 if ($proto[0] == '.') { 134 $proto = substr($proto, 1); 135 } 136 $subdesc = $this->getDescriptorByProtoName($proto); 137 if (is_null($subdesc)) { 138 trigger_error( 139 'proto not added: ' . $proto 140 . " for " . $desc->getFullName(), E_USER_ERROR); 141 } 142 $field->setMessageType($subdesc); 143 break; 144 case GPBType::ENUM: 145 $proto = $field->getEnumType(); 146 if ($proto[0] == '.') { 147 $proto = substr($proto, 1); 148 } 149 $field->setEnumType( 150 $this->getEnumDescriptorByProtoName($proto)); 151 break; 152 default: 153 break; 154 } 155 } 156 unset($field); 157 158 foreach ($desc->getNestedType() as $nested_type) { 159 $this->crossLink($nested_type); 160 } 161 unset($nested_type); 162 } 163 164 public function finish() 165 { 166 foreach ($this->class_to_desc as $klass => $desc) { 167 $this->crossLink($desc); 168 } 169 unset($desc); 170 } 171} 172