blob: 419bbf4dca17026ff579caad4b1113195c0b89bc [file] [log] [blame]
avm9996399bb77c2020-01-27 03:15:08 +01001<?php
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc. All rights reserved.
5// https://developers.google.com/protocol-buffers/
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are
9// met:
10//
11// * Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13// * Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following disclaimer
15// in the documentation and/or other materials provided with the
16// distribution.
17// * Neither the name of Google Inc. nor the names of its
18// contributors may be used to endorse or promote products derived from
19// this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33namespace Google\Protobuf\Internal;
34
35use Google\Protobuf\Internal\Descriptor;
36use Google\Protobuf\Internal\FileDescriptor;
37use Google\Protobuf\Internal\FileDescriptorSet;
38use Google\Protobuf\Internal\MessageBuilderContext;
39use Google\Protobuf\Internal\EnumBuilderContext;
40
41class DescriptorPool
42{
43 private static $pool;
44 // Map from message names to sub-maps, which are maps from field numbers to
45 // field descriptors.
46 private $class_to_desc = [];
47 private $class_to_enum_desc = [];
48 private $proto_to_class = [];
49
50 public static function getGeneratedPool()
51 {
52 if (!isset(self::$pool)) {
53 self::$pool = new DescriptorPool();
54 }
55 return self::$pool;
56 }
57
58 public function internalAddGeneratedFile($data, $use_nested = false)
59 {
60 $files = new FileDescriptorSet();
61 $files->mergeFromString($data);
62 $file = FileDescriptor::buildFromProto($files->getFile()[0]);
63
64 foreach ($file->getMessageType() as $desc) {
65 $this->addDescriptor($desc);
66 }
67 unset($desc);
68
69 foreach ($file->getEnumType() as $desc) {
70 $this->addEnumDescriptor($desc);
71 }
72 unset($desc);
73
74 foreach ($file->getMessageType() as $desc) {
75 $this->crossLink($desc);
76 }
77 unset($desc);
78 }
79
80 public function addMessage($name, $klass)
81 {
82 return new MessageBuilderContext($name, $klass, $this);
83 }
84
85 public function addEnum($name, $klass)
86 {
87 return new EnumBuilderContext($name, $klass, $this);
88 }
89
90 public function addDescriptor($descriptor)
91 {
92 $this->proto_to_class[$descriptor->getFullName()] =
93 $descriptor->getClass();
94 $this->class_to_desc[$descriptor->getClass()] = $descriptor;
95 $this->class_to_desc[$descriptor->getLegacyClass()] = $descriptor;
96 foreach ($descriptor->getNestedType() as $nested_type) {
97 $this->addDescriptor($nested_type);
98 }
99 foreach ($descriptor->getEnumType() as $enum_type) {
100 $this->addEnumDescriptor($enum_type);
101 }
102 }
103
104 public function addEnumDescriptor($descriptor)
105 {
106 $this->proto_to_class[$descriptor->getFullName()] =
107 $descriptor->getClass();
108 $this->class_to_enum_desc[$descriptor->getClass()] = $descriptor;
109 $this->class_to_enum_desc[$descriptor->getLegacyClass()] = $descriptor;
110 }
111
112 public function getDescriptorByClassName($klass)
113 {
114 if (isset($this->class_to_desc[$klass])) {
115 return $this->class_to_desc[$klass];
116 } else {
117 return null;
118 }
119 }
120
121 public function getEnumDescriptorByClassName($klass)
122 {
123 if (isset($this->class_to_enum_desc[$klass])) {
124 return $this->class_to_enum_desc[$klass];
125 } else {
126 return null;
127 }
128 }
129
130 public function getDescriptorByProtoName($proto)
131 {
132 if (isset($this->proto_to_class[$proto])) {
133 $klass = $this->proto_to_class[$proto];
134 return $this->class_to_desc[$klass];
135 } else {
136 return null;
137 }
138 }
139
140 public function getEnumDescriptorByProtoName($proto)
141 {
142 $klass = $this->proto_to_class[$proto];
143 return $this->class_to_enum_desc[$klass];
144 }
145
146 private function crossLink(Descriptor $desc)
147 {
148 foreach ($desc->getField() as $field) {
149 switch ($field->getType()) {
150 case GPBType::MESSAGE:
151 $proto = $field->getMessageType();
152 $field->setMessageType(
153 $this->getDescriptorByProtoName($proto));
154 break;
155 case GPBType::ENUM:
156 $proto = $field->getEnumType();
157 $field->setEnumType(
158 $this->getEnumDescriptorByProtoName($proto));
159 break;
160 default:
161 break;
162 }
163 }
164 unset($field);
165
166 foreach ($desc->getNestedType() as $nested_type) {
167 $this->crossLink($nested_type);
168 }
169 unset($nested_type);
170 }
171
172 public function finish()
173 {
174 foreach ($this->class_to_desc as $klass => $desc) {
175 $this->crossLink($desc);
176 }
177 unset($desc);
178 }
179}