• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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