1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34
35#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
36#define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
37
38#include <string>
39#include <google/protobuf/port.h>
40#include <google/protobuf/stubs/common.h>
41#include <google/protobuf/descriptor.pb.h>
42#include <google/protobuf/descriptor.h>
43#include <google/protobuf/compiler/code_generator.h>
44#include <google/protobuf/io/printer.h>
45
46#include <google/protobuf/port_def.inc>
47
48namespace google {
49namespace protobuf {
50namespace compiler {
51namespace csharp {
52
53struct Options;
54class FieldGeneratorBase;
55
56// TODO: start using this enum.
57enum CSharpType {
58 CSHARPTYPE_INT32 = 1,
59 CSHARPTYPE_INT64 = 2,
60 CSHARPTYPE_UINT32 = 3,
61 CSHARPTYPE_UINT64 = 4,
62 CSHARPTYPE_FLOAT = 5,
63 CSHARPTYPE_DOUBLE = 6,
64 CSHARPTYPE_BOOL = 7,
65 CSHARPTYPE_STRING = 8,
66 CSHARPTYPE_BYTESTRING = 9,
67 CSHARPTYPE_MESSAGE = 10,
68 CSHARPTYPE_ENUM = 11,
69 MAX_CSHARPTYPE = 11
70};
71
72// Converts field type to corresponding C# type.
73CSharpType GetCSharpType(FieldDescriptor::Type type);
74
75std::string StripDotProto(const std::string& proto_file);
76
77// Gets unqualified name of the reflection class
78std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor);
79// Gets unqualified name of the extension class
80std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor);
81
82std::string GetClassName(const EnumDescriptor* descriptor);
83
84std::string GetFieldName(const FieldDescriptor* descriptor);
85
86std::string GetFieldConstantName(const FieldDescriptor* field);
87
88std::string GetPropertyName(const FieldDescriptor* descriptor);
89
90std::string GetOneofCaseName(const FieldDescriptor* descriptor);
91
92int GetFixedSize(FieldDescriptor::Type type);
93
94std::string UnderscoresToCamelCase(const std::string& input,
95 bool cap_next_letter,
96 bool preserve_period);
97
98inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) {
99 return UnderscoresToCamelCase(input, cap_next_letter, preserve_period: false);
100}
101
102std::string UnderscoresToPascalCase(const std::string& input);
103
104// Note that we wouldn't normally want to export this (we're not expecting
105// it to be used outside libprotoc itself) but this exposes it for testing.
106std::string PROTOC_EXPORT GetEnumValueName(const std::string& enum_name,
107 const std::string& enum_value_name);
108
109// TODO(jtattermusch): perhaps we could move this to strutil
110std::string StringToBase64(const std::string& input);
111
112std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
113
114FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
115 int presenceIndex,
116 const Options* options);
117
118std::string GetFullExtensionName(const FieldDescriptor* descriptor);
119
120bool IsNullable(const FieldDescriptor* descriptor);
121
122// Determines whether the given message is a map entry message,
123// i.e. one implicitly created by protoc due to a map<key, value> field.
124inline bool IsMapEntryMessage(const Descriptor* descriptor) {
125 return descriptor->options().map_entry();
126}
127
128// Checks if this descriptor is for a group and gets its end tag or 0 if it's not a group
129uint GetGroupEndTag(const Descriptor* descriptor);
130
131// Determines whether we're generating code for the proto representation of
132// descriptors etc, for use in the runtime. This is the only type which is
133// allowed to use proto2 syntax, and it generates internal classes.
134inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
135 return descriptor->name() == "google/protobuf/descriptor.proto" ||
136 descriptor->name() == "net/proto2/proto/descriptor.proto";
137}
138
139// Determines whether the given message is an options message within descriptor.proto.
140inline bool IsDescriptorOptionMessage(const Descriptor* descriptor) {
141 if (!IsDescriptorProto(descriptor: descriptor->file())) {
142 return false;
143 }
144 const std::string name = descriptor->name();
145 return name == "FileOptions" ||
146 name == "MessageOptions" ||
147 name == "FieldOptions" ||
148 name == "OneofOptions" ||
149 name == "EnumOptions" ||
150 name == "EnumValueOptions" ||
151 name == "ServiceOptions" ||
152 name == "MethodOptions";
153}
154
155inline bool IsWrapperType(const FieldDescriptor* descriptor) {
156 return descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
157 descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
158}
159
160inline bool IsProto2(const FileDescriptor* descriptor) {
161 return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
162}
163
164inline bool SupportsPresenceApi(const FieldDescriptor* descriptor) {
165 // Unlike most languages, we don't generate Has/Clear members for message
166 // types, because they can always be set to null in C#. They're not really
167 // needed for oneof fields in proto2 either, as everything can be done via
168 // oneof case, but we follow the convention from other languages. Proto3
169 // oneof fields never have Has/Clear members - but will also never have
170 // the explicit optional keyword either.
171 //
172 // None of the built-in helpers (descriptor->has_presence() etc) describe
173 // quite the behavior we want, so the rules are explicit below.
174
175 if (descriptor->is_repeated() ||
176 descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
177 return false;
178 }
179 // has_optional_keyword() has more complex rules for proto2, but that
180 // doesn't matter given the first part of this condition.
181 return IsProto2(descriptor: descriptor->file()) || descriptor->has_optional_keyword();
182}
183
184inline bool RequiresPresenceBit(const FieldDescriptor* descriptor) {
185 return SupportsPresenceApi(descriptor) &&
186 !IsNullable(descriptor) &&
187 !descriptor->is_extension() &&
188 !descriptor->real_containing_oneof();
189}
190
191} // namespace csharp
192} // namespace compiler
193} // namespace protobuf
194} // namespace google
195
196#include <google/protobuf/port_undef.inc>
197
198#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
199