15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol Buffers - Google's data interchange format
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2008 Google Inc.  All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/protobuf/
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: robinson@google.com (Will Robinson)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This module outputs pure-Python protocol message classes that will
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// largely be constructed at runtime via the metaclass in reflection.py.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In other words, our job is basically to output a Python equivalent
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the C++ *Descriptor objects, and fix up all circular references
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// within these objects.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that the runtime performance of protocol message classes created in
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this way is expected to be lousy.  The plan is to create an alternate
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// generator that outputs a Python/C extension module that lets
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// performance-minded Python code leverage the fast C++ implementation
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// directly.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/python/python_generator.h>
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor.pb.h>
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/common.h>
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <google/protobuf/stubs/stringprintf.h>
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/printer.h>
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor.h>
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/zero_copy_stream.h>
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/strutil.h>
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/substitute.h>
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace compiler {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace python {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// suffix stripped.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string StripProto(const string& filename) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* suffix = HasSuffixString(filename, ".protodevel")
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ? ".protodevel" : ".proto";
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StripSuffixString(filename, suffix);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the Python module name expected for a given .proto filename.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ModuleName(const string& filename) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string basename = StripProto(filename);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StripString(&basename, "-", '_');
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StripString(&basename, "/", '.');
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return basename + "_pb2";
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the name of all containing types for descriptor,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in order from outermost to innermost, followed by descriptor's
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// own name.  Each name is separated by |separator|.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename DescriptorT>
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const string& separator) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string name = descriptor.name();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (const Descriptor* current = descriptor.containing_type();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       current != NULL; current = current->containing_type()) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = current->name() + separator + name;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return name;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Name of the class attribute where we store the Python
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// descriptor.Descriptor instance for the generated class.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Must stay consistent with the _DESCRIPTOR_KEY constant
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in proto2/public/reflection.py.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDescriptorKey[] = "DESCRIPTOR";
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Does the file have top-level enums?
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochinline bool HasTopLevelEnums(const FileDescriptor *file) {
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return file->enum_type_count() > 0;
113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Should we generate generic services for this file?
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool HasGenericServices(const FileDescriptor *file) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return file->service_count() > 0 &&
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         file->options().py_generic_services();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints the common boilerplate needed at the top of every .py
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// file output by this generator.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintTopBoilerplate(
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io::Printer* printer, const FileDescriptor* file, bool descriptor_proto) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(robinson): Allow parameterization of Python version?
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "# source: $filename$\n"
131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "\n",
132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "filename", file->name());
133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (HasTopLevelEnums(file)) {
134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    printer->Print(
135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        "from google.protobuf.internal import enum_type_wrapper\n");
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  printer->Print(
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "from google.protobuf import descriptor as _descriptor\n"
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "from google.protobuf import message as _message\n"
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "from google.protobuf import reflection as _reflection\n"
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      );
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasGenericServices(file)) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        "from google.protobuf import service as _service\n"
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "from google.protobuf import service_reflection\n");
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Avoid circular imports if this module is descriptor_pb2.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!descriptor_proto) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "from google.protobuf import descriptor_pb2\n");
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "# @@protoc_insertion_point(imports)\n");
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("\n\n");
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a Python literal giving the default value for a field.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the field specifies no explicit default value, we'll return
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the default default value for the field type (zero for numbers,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// empty string for strings, empty list for repeated fields, and
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// None for non-repeated, composite fields).
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(robinson): Unify with code from
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// //compiler/cpp/internal/primitive_field.cc
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// //compiler/cpp/internal/enum_field.cc
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// //compiler/cpp/internal/string_field.cc
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string StringifyDefaultValue(const FieldDescriptor& field) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field.is_repeated()) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "[]";
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (field.cpp_type()) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_INT32:
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleItoa(field.default_value_int32());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_UINT32:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleItoa(field.default_value_uint32());
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_INT64:
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleItoa(field.default_value_int64());
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_UINT64:
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleItoa(field.default_value_uint64());
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_DOUBLE: {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double value = field.default_value_double();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (value == numeric_limits<double>::infinity()) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Python pre-2.6 on Windows does not parse "inf" correctly.  However,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // a numeric literal that is too big for a double will become infinity.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "1e10000";
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (value == -numeric_limits<double>::infinity()) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // See above.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "-1e10000";
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (value != value) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // infinity * 0 = nan
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "(1e10000 * 0)";
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SimpleDtoa(value);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_FLOAT: {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float value = field.default_value_float();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (value == numeric_limits<float>::infinity()) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Python pre-2.6 on Windows does not parse "inf" correctly.  However,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // a numeric literal that is too big for a double will become infinity.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "1e10000";
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (value == -numeric_limits<float>::infinity()) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // See above.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "-1e10000";
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (value != value) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // infinity - infinity = nan
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "(1e10000 * 0)";
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SimpleFtoa(value);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_BOOL:
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return field.default_value_bool() ? "True" : "False";
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_ENUM:
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleItoa(field.default_value_enum()->number());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_STRING:
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field.type() == FieldDescriptor::TYPE_STRING) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "unicode(\"" + CEscape(field.default_value_string()) +
222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                        "\", \"utf-8\")";
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "\"" + CEscape(field.default_value_string()) + "\"";
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      case FieldDescriptor::CPPTYPE_MESSAGE:
227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          return "None";
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (We could add a default case above but then we wouldn't get the nice
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // compiler warning when a new type is added.)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_LOG(FATAL) << "Not reached.";
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "";
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Generator::Generator() : file_(NULL) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Generator::~Generator() {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Generator::Generate(const FileDescriptor* file,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const string& parameter,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GeneratorContext* context,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         string* error) const {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Completely serialize all Generate() calls on this instance.  The
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread-safety constraints of the CodeGenerator interface aren't clear so
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // just be as conservative as possible.  It's easier to relax this later if
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we need to, but I doubt it will be an issue.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(kenton):  The proper thing to do would be to allocate any state on
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the stack and use that, so that the Generator class itself does not need
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   to have any mutable members.  Then it is implicitly thread-safe.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutexLock lock(&mutex_);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_ = file;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string module_name = ModuleName(file->name());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string filename = module_name;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StripString(&filename, ".", '/');
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filename += ".py";
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptorProto fdp;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_->CopyTo(&fdp);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fdp.SerializeToString(&file_descriptor_serialized_);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(output.get());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::Printer printer(output.get(), '$');
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_ = &printer;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintImports();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintFileDescriptor();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintTopLevelEnums();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintTopLevelExtensions();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintAllNestedEnumsInFile();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintMessageDescriptors();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FixForeignFieldsInDescriptors();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintMessages();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have to fix up the extensions after the message classes themselves,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since they need to call static RegisterExtension() methods on these
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // classes.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FixForeignFieldsInExtensions();
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Descriptor options may have custom extensions. These custom options
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // can only be successfully parsed after we register corresponding
290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // extensions. Therefore we parse all options again here to recognize
291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // custom options that may be unknown when we define the descriptors.
292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  FixAllDescriptorOptions();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasGenericServices(file)) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintServices();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer.Print(
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "# @@protoc_insertion_point(module_scope)\n");
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !printer.failed();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints Python imports for all modules imported by |file|.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintImports() const {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->dependency_count(); ++i) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string module_name = ModuleName(file_->dependency(i)->name());
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("import $module$\n", "module",
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    module_name);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("\n");
311ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Print public imports.
313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < file_->public_dependency_count(); ++i) {
314ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    string module_name = ModuleName(file_->public_dependency(i)->name());
315ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    printer_->Print("from $module$ import *\n", "module", module_name);
316ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
317ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  printer_->Print("\n");
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints the single file descriptor for this file.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintFileDescriptor() const {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> m;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["descriptor_name"] = kDescriptorKey;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["name"] = file_->name();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["package"] = file_->package();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char file_descriptor_template[] =
327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "$descriptor_name$ = _descriptor.FileDescriptor(\n"
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  name='$name$',\n"
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  package='$package$',\n";
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(m, file_descriptor_template);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Indent();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "serialized_pb='$value$'",
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "value", strings::CHexEscape(file_descriptor_serialized_));
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(falk): Also print options and fix the message_type, enum_type,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //             service and extension later in the generation.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Outdent();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(")\n");
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("\n");
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints descriptors and module-level constants for all top-level
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// enums defined in |file|.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintTopLevelEnums() const {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<pair<string, int> > top_level_enum_values;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->enum_type_count(); ++i) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintEnum(enum_descriptor);
351ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    printer_->Print("$name$ = "
352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)",
353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    "name", enum_descriptor.name(),
354ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    "descriptor_name",
355ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    ModuleLevelDescriptorName(enum_descriptor));
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("\n");
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < enum_descriptor.value_count(); ++j) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      top_level_enum_values.push_back(
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          make_pair(value_descriptor.name(), value_descriptor.number()));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < top_level_enum_values.size(); ++i) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("$name$ = $value$\n",
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "name", top_level_enum_values[i].first,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "value", SimpleItoa(top_level_enum_values[i].second));
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("\n");
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints all enums contained in all message types in |file|.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintAllNestedEnumsInFile() const {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->message_type_count(); ++i) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintNestedEnums(*file_->message_type(i));
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints a Python statement assigning the appropriate module-level
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// enum name to a Python EnumDescriptor object equivalent to
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// enum_descriptor.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> m;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["name"] = enum_descriptor.name();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["full_name"] = enum_descriptor.full_name();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["file"] = kDescriptorKey;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char enum_descriptor_template[] =
390ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "$descriptor_name$ = _descriptor.EnumDescriptor(\n"
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  name='$name$',\n"
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  full_name='$full_name$',\n"
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  filename=None,\n"
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  file=$file$,\n"
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  values=[\n";
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string options_string;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum_descriptor.options().SerializeToString(&options_string);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(m, enum_descriptor_template);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Indent();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Indent();
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < enum_descriptor.value_count(); ++i) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintEnumValueDescriptor(*enum_descriptor.value(i));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print(",\n");
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Outdent();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("],\n");
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("containing_type=None,\n");
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("options=$options_value$,\n",
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "options_value",
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  OptionsValue("EnumOptions", options_string));
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumDescriptorProto edp;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintSerializedPbInterval(enum_descriptor, edp);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Outdent();
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(")\n");
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("\n");
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Recursively prints enums in nested types within descriptor, then
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prints enums contained at the top level in descriptor.
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintNestedEnums(const Descriptor& descriptor) const {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor.nested_type_count(); ++i) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintNestedEnums(*descriptor.nested_type(i));
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor.enum_type_count(); ++i) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintEnum(*descriptor.enum_type(i));
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintTopLevelExtensions() const {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool is_extension = true;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->extension_count(); ++i) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor& extension_field = *file_->extension(i);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string constant_name = extension_field.name() + "_FIELD_NUMBER";
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpperString(&constant_name);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("$constant_name$ = $number$\n",
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "constant_name", constant_name,
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "number", SimpleItoa(extension_field.number()));
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("$name$ = ", "name", extension_field.name());
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintFieldDescriptor(extension_field, is_extension);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("\n");
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("\n");
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints Python equivalents of all Descriptors in |file|.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintMessageDescriptors() const {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->message_type_count(); ++i) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintDescriptor(*file_->message_type(i));
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("\n");
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintServices() const {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->service_count(); ++i) {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintServiceDescriptor(*file_->service(i));
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintServiceClass(*file_->service(i));
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintServiceStub(*file_->service(i));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("\n");
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintServiceDescriptor(
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ServiceDescriptor& descriptor) const {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("\n");
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string service_name = ModuleLevelServiceDescriptorName(descriptor);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string options_string;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  descriptor.options().SerializeToString(&options_string);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(
471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "$service_name$ = _descriptor.ServiceDescriptor(\n",
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "service_name", service_name);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Indent();
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> m;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["name"] = descriptor.name();
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["full_name"] = descriptor.full_name();
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["file"] = kDescriptorKey;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["index"] = SimpleItoa(descriptor.index());
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["options_value"] = OptionsValue("ServiceOptions", options_string);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char required_function_arguments[] =
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "name='$name$',\n"
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "full_name='$full_name$',\n"
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "file=$file$,\n"
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "index=$index$,\n"
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options=$options_value$,\n";
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(m, required_function_arguments);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServiceDescriptorProto sdp;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintSerializedPbInterval(descriptor, sdp);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("methods=[\n");
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor.method_count(); ++i) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const MethodDescriptor* method = descriptor.method(i);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    method->options().SerializeToString(&options_string);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m.clear();
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m["name"] = method->name();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m["full_name"] = method->full_name();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m["index"] = SimpleItoa(method->index());
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m["serialized_options"] = CEscape(options_string);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m["input_type"] = ModuleLevelDescriptorName(*(method->input_type()));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m["output_type"] = ModuleLevelDescriptorName(*(method->output_type()));
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m["options_value"] = OptionsValue("MethodOptions", options_string);
504ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    printer_->Print("_descriptor.MethodDescriptor(\n");
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Indent();
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print(
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        m,
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "name='$name$',\n"
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "full_name='$full_name$',\n"
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "index=$index$,\n"
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "containing_service=None,\n"
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "input_type=$input_type$,\n"
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "output_type=$output_type$,\n"
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "options=$options_value$,\n");
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Outdent();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("),\n");
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Outdent();
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("])\n\n");
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Print the service.
525ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  printer_->Print("class $class_name$(_service.Service):\n",
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "class_name", descriptor.name());
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Indent();
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "__metaclass__ = service_reflection.GeneratedServiceType\n"
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$descriptor_key$ = $descriptor_name$\n",
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "descriptor_key", kDescriptorKey,
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "descriptor_name", ModuleLevelServiceDescriptorName(descriptor));
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Outdent();
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Print the service stub.
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("class $class_name$_Stub($class_name$):\n",
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "class_name", descriptor.name());
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Indent();
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "__metaclass__ = service_reflection.GeneratedServiceStubType\n"
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$descriptor_key$ = $descriptor_name$\n",
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "descriptor_key", kDescriptorKey,
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "descriptor_name", ModuleLevelServiceDescriptorName(descriptor));
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Outdent();
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints statement assigning ModuleLevelDescriptorName(message_descriptor)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to a Python Descriptor object for message_descriptor.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mutually recursive with PrintNestedDescriptors().
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintNestedDescriptors(message_descriptor);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("\n");
557ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n",
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "descriptor_name",
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  ModuleLevelDescriptorName(message_descriptor));
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Indent();
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> m;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["name"] = message_descriptor.name();
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["full_name"] = message_descriptor.full_name();
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["file"] = kDescriptorKey;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char required_function_arguments[] =
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "name='$name$',\n"
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "full_name='$full_name$',\n"
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "filename=None,\n"
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "file=$file$,\n"
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "containing_type=None,\n";
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(m, required_function_arguments);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintFieldsInDescriptor(message_descriptor);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintExtensionsInDescriptor(message_descriptor);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nested types
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("nested_types=[");
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < message_descriptor.nested_type_count(); ++i) {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string nested_name = ModuleLevelDescriptorName(
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *message_descriptor.nested_type(i));
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("$name$, ", "name", nested_name);
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("],\n");
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enum types
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("enum_types=[\n");
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Indent();
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < message_descriptor.enum_type_count(); ++i) {
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string descriptor_name = ModuleLevelDescriptorName(
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *message_descriptor.enum_type(i));
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print(descriptor_name.c_str());
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print(",\n");
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Outdent();
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("],\n");
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string options_string;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_descriptor.options().SerializeToString(&options_string);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options=$options_value$,\n"
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "is_extendable=$extendable$",
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options_value", OptionsValue("MessageOptions", options_string),
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "extendable", message_descriptor.extension_range_count() > 0 ?
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "True" : "False");
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(",\n");
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extension ranges
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("extension_ranges=[");
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < message_descriptor.extension_range_count(); ++i) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor::ExtensionRange* range =
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_descriptor.extension_range(i);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("($start$, $end$), ",
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "start", SimpleItoa(range->start),
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "end", SimpleItoa(range->end));
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("],\n");
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Serialization of proto
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DescriptorProto edp;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintSerializedPbInterval(message_descriptor, edp);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Outdent();
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(")\n");
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints Python Descriptor objects for all nested types contained in
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message_descriptor.
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mutually recursive with PrintDescriptor().
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintNestedDescriptors(
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor& containing_descriptor) const {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintDescriptor(*containing_descriptor.nested_type(i));
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints all messages in |file|.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintMessages() const {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->message_type_count(); ++i) {
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintMessage(*file_->message_type(i));
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("\n");
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints a Python class for the given message descriptor.  We defer to the
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// metaclass to do almost all of the work of actually creating a useful class.
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The purpose of this function and its many helper functions above is merely
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to output a Python version of the descriptors, which the metaclass in
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reflection.py will use to construct the meat of the class itself.
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mutually recursive with PrintNestedMessages().
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintMessage(
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor& message_descriptor) const {
652ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  printer_->Print("class $name$(_message.Message):\n", "name",
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  message_descriptor.name());
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Indent();
655ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  printer_->Print("__metaclass__ = _reflection.GeneratedProtocolMessageType\n");
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintNestedMessages(message_descriptor);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> m;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["descriptor_key"] = kDescriptorKey;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(m, "$descriptor_key$ = $descriptor_name$\n");
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n"
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "# @@protoc_insertion_point(class_scope:$full_name$)\n",
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "full_name", message_descriptor.full_name());
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Outdent();
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints all nested messages within |containing_descriptor|.
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mutually recursive with PrintMessage().
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintNestedMessages(
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor& containing_descriptor) const {
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print("\n");
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintMessage(*containing_descriptor.nested_type(i));
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Recursively fixes foreign fields in all nested types in |descriptor|, then
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sets the message_type and enum_type of all message and enum fields to point
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to their respective descriptors.
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Args:
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   descriptor: descriptor to print fields for.
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   containing_descriptor: if descriptor is a nested type, this is its
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       containing type, or NULL if this is a root/top-level type.
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::FixForeignFieldsInDescriptor(
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor& descriptor,
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* containing_descriptor) const {
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor.nested_type_count(); ++i) {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FixForeignFieldsInDescriptor(*descriptor.nested_type(i), &descriptor);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor.field_count(); ++i) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor& field_descriptor = *descriptor.field(i);
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FixForeignFieldsInField(&descriptor, field_descriptor, "fields_by_name");
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FixContainingTypeInDescriptor(descriptor, containing_descriptor);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor.enum_type_count(); ++i) {
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FixContainingTypeInDescriptor(enum_descriptor, &descriptor);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> m;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["descriptor_name"] = kDescriptorKey;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["message_name"] = descriptor.name();
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char file_descriptor_template[] =
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$descriptor_name$.message_types_by_name['$message_name$'] = "
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$message_descriptor_name$\n";
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(m, file_descriptor_template);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sets any necessary message_type and enum_type attributes
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for the Python version of |field|.
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// containing_type may be NULL, in which case this is a module-level field.
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// python_dict_name is the name of the Python dict where we should
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// look the field up in the containing type.  (e.g., fields_by_name
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or extensions_by_name).  We ignore python_dict_name if containing_type
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is NULL.
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::FixForeignFieldsInField(const Descriptor* containing_type,
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const FieldDescriptor& field,
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const string& python_dict_name) const {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string field_referencing_expression = FieldReferencingExpression(
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      containing_type, field, python_dict_name);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> m;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["field_ref"] = field_referencing_expression;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Descriptor* foreign_message_type = field.message_type();
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (foreign_message_type) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m["foreign_type"] = ModuleLevelDescriptorName(*foreign_message_type);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print(m, "$field_ref$.message_type = $foreign_type$\n");
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const EnumDescriptor* enum_type = field.enum_type();
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enum_type) {
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m["enum_type"] = ModuleLevelDescriptorName(*enum_type);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print(m, "$field_ref$.enum_type = $enum_type$\n");
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the module-level expression for the given FieldDescriptor.
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Only works for fields in the .proto file this Generator is generating for.
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// containing_type may be NULL, in which case this is a module-level field.
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// python_dict_name is the name of the Python dict where we should
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// look the field up in the containing type.  (e.g., fields_by_name
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or extensions_by_name).  We ignore python_dict_name if containing_type
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is NULL.
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Generator::FieldReferencingExpression(
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* containing_type,
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor& field,
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& python_dict_name) const {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should only ever be looking up fields in the current file.
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The only things we refer to from other files are message descriptors.
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. "
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                << file_->name();
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!containing_type) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return field.name();
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return strings::Substitute(
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$0.$1['$2']",
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ModuleLevelDescriptorName(*containing_type),
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      python_dict_name, field.name());
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints containing_type for nested descriptors or enum descriptors.
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename DescriptorT>
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::FixContainingTypeInDescriptor(
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DescriptorT& descriptor,
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* containing_descriptor) const {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (containing_descriptor != NULL) {
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string nested_name = ModuleLevelDescriptorName(descriptor);
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string parent_name = ModuleLevelDescriptorName(
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *containing_descriptor);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print(
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "$nested_name$.containing_type = $parent_name$;\n",
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "nested_name", nested_name,
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "parent_name", parent_name);
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints statements setting the message_type and enum_type fields in the
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Python descriptor objects we've already output in ths file.  We must
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// do this in a separate step due to circular references (otherwise, we'd
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// just set everything in the initial assignment statements).
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::FixForeignFieldsInDescriptors() const {
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->message_type_count(); ++i) {
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FixForeignFieldsInDescriptor(*file_->message_type(i), NULL);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->message_type_count(); ++i) {
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddMessageToFileDescriptor(*file_->message_type(i));
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("\n");
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We need to not only set any necessary message_type fields, but
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// also need to call RegisterExtension() on each message we're
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// extending.
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::FixForeignFieldsInExtensions() const {
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Top-level extensions.
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->extension_count(); ++i) {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FixForeignFieldsInExtension(*file_->extension(i));
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nested extensions.
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->message_type_count(); ++i) {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FixForeignFieldsInNestedExtensions(*file_->message_type(i));
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
813ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  printer_->Print("\n");
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::FixForeignFieldsInExtension(
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor& extension_field) const {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(extension_field.is_extension());
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension_scope() will be NULL for top-level extensions, which is
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exactly what FixForeignFieldsInField() wants.
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FixForeignFieldsInField(extension_field.extension_scope(), extension_field,
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          "extensions_by_name");
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> m;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Confusingly, for FieldDescriptors that happen to be extensions,
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // containing_type() means "extended type."
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On the other hand, extension_scope() will give us what we normally
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mean by containing_type().
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["extended_message_class"] = ModuleLevelMessageName(
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *extension_field.containing_type());
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["field"] = FieldReferencingExpression(extension_field.extension_scope(),
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          extension_field,
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          "extensions_by_name");
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(m, "$extended_message_class$.RegisterExtension($field$)\n");
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::FixForeignFieldsInNestedExtensions(
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor& descriptor) const {
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Recursively fix up extensions in all nested types.
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor.nested_type_count(); ++i) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FixForeignFieldsInNestedExtensions(*descriptor.nested_type(i));
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fix up extensions directly contained within this type.
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor.extension_count(); ++i) {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FixForeignFieldsInExtension(*descriptor.extension(i));
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a Python expression that instantiates a Python EnumValueDescriptor
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object for the given C++ descriptor.
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintEnumValueDescriptor(
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EnumValueDescriptor& descriptor) const {
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(robinson): Fix up EnumValueDescriptor "type" fields.
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // More circular references.  ::sigh::
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string options_string;
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  descriptor.options().SerializeToString(&options_string);
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> m;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["name"] = descriptor.name();
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["index"] = SimpleItoa(descriptor.index());
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["number"] = SimpleItoa(descriptor.number());
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["options"] = OptionsValue("EnumValueOptions", options_string);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      m,
864ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "_descriptor.EnumValueDescriptor(\n"
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  name='$name$', index=$index$, number=$number$,\n"
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  options=$options$,\n"
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  type=None)");
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a Python expression that calls descriptor._ParseOptions using
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the given descriptor class name and serialized options protobuf string.
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Generator::OptionsValue(
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& class_name, const string& serialized_options) const {
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "None";
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string full_class_name = "descriptor_pb2." + class_name;
878ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return "_descriptor._ParseOptions(" + full_class_name + "(), '"
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        + CEscape(serialized_options)+ "')";
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints an expression for a Python FieldDescriptor for |field|.
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintFieldDescriptor(
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor& field, bool is_extension) const {
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string options_string;
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  field.options().SerializeToString(&options_string);
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> m;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["name"] = field.name();
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["full_name"] = field.full_name();
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["index"] = SimpleItoa(field.index());
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["number"] = SimpleItoa(field.number());
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["type"] = SimpleItoa(field.type());
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["cpp_type"] = SimpleItoa(field.cpp_type());
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["label"] = SimpleItoa(field.label());
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["has_default_value"] = field.has_default_value() ? "True" : "False";
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["default_value"] = StringifyDefaultValue(field);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["is_extension"] = is_extension ? "True" : "False";
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  m["options"] = OptionsValue("FieldOptions", options_string);
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We always set message_type and enum_type to None at this point, and then
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // these fields in correctly after all referenced descriptors have been
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // defined and/or imported (see FixForeignFieldsInDescriptors()).
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char field_descriptor_decl[] =
904ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    "_descriptor.FieldDescriptor(\n"
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  name='$name$', full_name='$full_name$', index=$index$,\n"
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  has_default_value=$has_default_value$, default_value=$default_value$,\n"
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  message_type=None, enum_type=None, containing_type=None,\n"
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  is_extension=$is_extension$, extension_scope=None,\n"
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  options=$options$)";
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print(m, field_descriptor_decl);
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper for Print{Fields,Extensions}InDescriptor().
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintFieldDescriptorsInDescriptor(
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor& message_descriptor,
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_extension,
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& list_variable_name,
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int (Descriptor::*CountFn)() const,
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const {
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("$list$=[\n", "list", list_variable_name);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Indent();
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < (message_descriptor.*CountFn)(); ++i) {
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintFieldDescriptor(*(message_descriptor.*GetterFn)(i),
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         is_extension);
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_->Print(",\n");
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Outdent();
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("],\n");
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints a statement assigning "fields" to a list of Python FieldDescriptors,
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// one for each field present in message_descriptor.
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintFieldsInDescriptor(
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor& message_descriptor) const {
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool is_extension = false;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintFieldDescriptorsInDescriptor(
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message_descriptor, is_extension, "fields",
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Descriptor::field_count, &Descriptor::field);
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints a statement assigning "extensions" to a list of Python
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FieldDescriptors, one for each extension present in message_descriptor.
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintExtensionsInDescriptor(
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor& message_descriptor) const {
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool is_extension = true;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintFieldDescriptorsInDescriptor(
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message_descriptor, is_extension, "extensions",
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Descriptor::extension_count, &Descriptor::extension);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Generator::GeneratingDescriptorProto() const {
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return file_->name() == "google/protobuf/descriptor.proto";
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the unique Python module-level identifier given to a descriptor.
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This name is module-qualified iff the given descriptor describes an
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// entity that doesn't come from the current file.
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename DescriptorT>
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Generator::ModuleLevelDescriptorName(
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DescriptorT& descriptor) const {
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIXME(robinson):
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We currently don't worry about collisions with underscores in the type
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // names, so these would collide in nasty ways if found in the same file:
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   OuterProto.ProtoA.ProtoB
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   OuterProto_ProtoA.ProtoB  # Underscore instead of period.
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As would these:
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   OuterProto.ProtoA_.ProtoB
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   OuterProto.ProtoA._ProtoB  # Leading vs. trailing underscore.
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (Contrived, but certainly possible).
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The C++ implementation doesn't guard against this either.  Leaving
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it for now...
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string name = NamePrefixedWithNestedTypes(descriptor, "_");
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpperString(&name);
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Module-private for now.  Easy to make public later; almost impossible
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to make private later.
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  name = "_" + name;
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We now have the name relative to its own module.  Also qualify with
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the module name iff this descriptor is from a different .proto file.
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor.file() != file_) {
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = ModuleName(descriptor.file()->name()) + "." + name;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return name;
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the name of the message class itself, not the descriptor.
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Like ModuleLevelDescriptorName(), module-qualifies the name iff
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the given descriptor describes an entity that doesn't come from
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the current file.
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Generator::ModuleLevelMessageName(const Descriptor& descriptor) const {
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string name = NamePrefixedWithNestedTypes(descriptor, ".");
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor.file() != file_) {
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = ModuleName(descriptor.file()->name()) + "." + name;
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return name;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the unique Python module-level identifier given to a service
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// descriptor.
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Generator::ModuleLevelServiceDescriptorName(
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ServiceDescriptor& descriptor) const {
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string name = descriptor.name();
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpperString(&name);
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  name = "_" + name;
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor.file() != file_) {
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = ModuleName(descriptor.file()->name()) + "." + name;
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return name;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints standard constructor arguments serialized_start and serialized_end.
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Args:
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   descriptor: The cpp descriptor to have a serialized reference.
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   proto: A proto
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Example printer output:
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// serialized_start=41,
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// serialized_end=43,
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename DescriptorT, typename DescriptorProtoT>
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Generator::PrintSerializedPbInterval(
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DescriptorT& descriptor, DescriptorProtoT& proto) const {
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  descriptor.CopyTo(&proto);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string sp;
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto.SerializeToString(&sp);
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int offset = file_descriptor_serialized_.find(sp);
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_GE(offset, 0);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_->Print("serialized_start=$serialized_start$,\n"
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "serialized_end=$serialized_end$,\n",
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "serialized_start", SimpleItoa(offset),
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "serialized_end", SimpleItoa(offset + sp.size()));
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace {
1036ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PrintDescriptorOptionsFixingCode(const string& descriptor,
1037ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                      const string& options,
1038ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                      io::Printer* printer) {
1039ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase
1040ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // in proto2 python runtime but it couldn't be used here because appengine
1041ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // uses a snapshot version of the library in which the new method is not
1042ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // yet present. After appengine has synced their runtime library, the code
1043ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // below should be cleaned up to use _SetOptions().
1044ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  printer->Print(
1045ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "$descriptor$.has_options = True\n"
1046ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "$descriptor$._options = $options$\n",
1047ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "descriptor", descriptor, "options", options);
1048ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
1049ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace
1050ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1051ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Prints expressions that set the options field of all descriptors.
1052ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid Generator::FixAllDescriptorOptions() const {
1053ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Prints an expression that sets the file descriptor's options.
1054ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  string file_options = OptionsValue(
1055ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "FileOptions", file_->options().SerializeAsString());
1056ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (file_options != "None") {
1057ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_);
1058ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1059ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Prints expressions that set the options for all top level enums.
1060ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < file_->enum_type_count(); ++i) {
1061ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
1062ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FixOptionsForEnum(enum_descriptor);
1063ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1064ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Prints expressions that set the options for all top level extensions.
1065ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < file_->extension_count(); ++i) {
1066ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FieldDescriptor& field = *file_->extension(i);
1067ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FixOptionsForField(field);
1068ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1069ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Prints expressions that set the options for all messages, nested enums,
1070ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // nested extensions and message fields.
1071ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < file_->message_type_count(); ++i) {
1072ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FixOptionsForMessage(*file_->message_type(i));
1073ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1074ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
1075ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1076ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Prints expressions that set the options for an enum descriptor and its
1077ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// value descriptors.
1078ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
1079ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  string descriptor_name = ModuleLevelDescriptorName(enum_descriptor);
1080ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  string enum_options = OptionsValue(
1081ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "EnumOptions", enum_descriptor.options().SerializeAsString());
1082ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (enum_options != "None") {
1083ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_);
1084ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1085ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < enum_descriptor.value_count(); ++i) {
1086ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i);
1087ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    string value_options = OptionsValue(
1088ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        "EnumValueOptions", value_descriptor.options().SerializeAsString());
1089ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (value_options != "None") {
1090ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      PrintDescriptorOptionsFixingCode(
1091ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
1092ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       value_descriptor.name().c_str()),
1093ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          value_options, printer_);
1094ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
1095ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1096ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
1097ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1098ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Prints expressions that set the options for field descriptors (including
1099ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// extensions).
1100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid Generator::FixOptionsForField(
1101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FieldDescriptor& field) const {
1102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  string field_options = OptionsValue(
1103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "FieldOptions", field.options().SerializeAsString());
1104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (field_options != "None") {
1105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    string field_name;
1106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (field.is_extension()) {
1107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (field.extension_scope() == NULL) {
1108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        // Top level extensions.
1109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        field_name = field.name();
1110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      } else {
1111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        field_name = FieldReferencingExpression(
1112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            field.extension_scope(), field, "extensions_by_name");
1113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
1114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else {
1115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      field_name = FieldReferencingExpression(
1116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          field.containing_type(), field, "fields_by_name");
1117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
1118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PrintDescriptorOptionsFixingCode(field_name, field_options, printer_);
1119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
1121ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Prints expressions that set the options for a message and all its inner
1123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// types (nested messages, nested enums, extensions, fields).
1124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
1125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Nested messages.
1126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < descriptor.nested_type_count(); ++i) {
1127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FixOptionsForMessage(*descriptor.nested_type(i));
1128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Enums.
1130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < descriptor.enum_type_count(); ++i) {
1131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FixOptionsForEnum(*descriptor.enum_type(i));
1132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Fields.
1134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < descriptor.field_count(); ++i) {
1135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FieldDescriptor& field = *descriptor.field(i);
1136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FixOptionsForField(field);
1137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Extensions.
1139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < descriptor.extension_count(); ++i) {
1140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FieldDescriptor& field = *descriptor.extension(i);
1141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FixOptionsForField(field);
1142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Message option for this message.
1144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  string message_options = OptionsValue(
1145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "MessageOptions", descriptor.options().SerializeAsString());
1146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (message_options != "None") {
1147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    string descriptor_name = ModuleLevelDescriptorName(descriptor);
1148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PrintDescriptorOptionsFixingCode(descriptor_name,
1149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     message_options,
1150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     printer_);
1151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
1153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace python
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace compiler
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protobuf
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace google
1158