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#include <sstream> 32 33#include <google/protobuf/compiler/code_generator.h> 34#include <google/protobuf/compiler/plugin.h> 35#include <google/protobuf/descriptor.h> 36#include <google/protobuf/descriptor.pb.h> 37#include <google/protobuf/io/printer.h> 38#include <google/protobuf/io/zero_copy_stream.h> 39 40#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> 41#include <google/protobuf/compiler/csharp/csharp_helpers.h> 42#include <google/protobuf/compiler/csharp/csharp_options.h> 43#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> 44 45namespace google { 46namespace protobuf { 47namespace compiler { 48namespace csharp { 49 50WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor, 51 int fieldOrdinal, const Options *options) 52 : FieldGeneratorBase(descriptor, fieldOrdinal, options) { 53 variables_["has_property_check"] = name() + "_ != null"; 54 variables_["has_not_property_check"] = name() + "_ == null"; 55 const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); 56 is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING && 57 wrapped_field->type() != FieldDescriptor::TYPE_BYTES; 58 if (is_value_type) { 59 variables_["nonnullable_type_name"] = type_name(wrapped_field); 60 } 61} 62 63WrapperFieldGenerator::~WrapperFieldGenerator() { 64} 65 66void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) { 67 printer->Print( 68 variables_, 69 "private static readonly pb::FieldCodec<$type_name$> _single_$name$_codec = "); 70 GenerateCodecCode(printer); 71 printer->Print( 72 variables_, 73 ";\n" 74 "private $type_name$ $name$_;\n"); 75 WritePropertyDocComment(printer, descriptor_); 76 AddDeprecatedFlag(printer); 77 printer->Print( 78 variables_, 79 "$access_level$ $type_name$ $property_name$ {\n" 80 " get { return $name$_; }\n" 81 " set {\n" 82 " $name$_ = value;\n" 83 " }\n" 84 "}\n"); 85} 86 87void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) { 88 printer->Print( 89 variables_, 90 "if (other.$has_property_check$) {\n" 91 " if ($has_not_property_check$ || other.$property_name$ != $default_value$) {\n" 92 " $property_name$ = other.$property_name$;\n" 93 " }\n" 94 "}\n"); 95} 96 97void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) { 98 printer->Print( 99 variables_, 100 "$type_name$ value = _single_$name$_codec.Read(input);\n" 101 "if ($has_not_property_check$ || value != $default_value$) {\n" 102 " $property_name$ = value;\n" 103 "}\n"); 104} 105 106void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) { 107 printer->Print( 108 variables_, 109 "if ($has_property_check$) {\n" 110 " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n" 111 "}\n"); 112} 113 114void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { 115 printer->Print( 116 variables_, 117 "if ($has_property_check$) {\n" 118 " size += _single_$name$_codec.CalculateSizeWithTag($property_name$);\n" 119 "}\n"); 120} 121 122void WrapperFieldGenerator::WriteHash(io::Printer* printer) { 123 printer->Print( 124 variables_, 125 "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); 126} 127 128void WrapperFieldGenerator::WriteEquals(io::Printer* printer) { 129 printer->Print( 130 variables_, 131 "if ($property_name$ != other.$property_name$) return false;\n"); 132} 133 134void WrapperFieldGenerator::WriteToString(io::Printer* printer) { 135 // TODO: Implement if we ever actually need it... 136} 137 138void WrapperFieldGenerator::GenerateCloningCode(io::Printer* printer) { 139 printer->Print(variables_, 140 "$property_name$ = other.$property_name$;\n"); 141} 142 143void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) { 144 if (is_value_type) { 145 printer->Print( 146 variables_, 147 "pb::FieldCodec.ForStructWrapper<$nonnullable_type_name$>($tag$)"); 148 } else { 149 printer->Print( 150 variables_, 151 "pb::FieldCodec.ForClassWrapper<$type_name$>($tag$)"); 152 } 153} 154 155WrapperOneofFieldGenerator::WrapperOneofFieldGenerator( 156 const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) 157 : WrapperFieldGenerator(descriptor, fieldOrdinal, options) { 158 SetCommonOneofFieldVariables(&variables_); 159} 160 161WrapperOneofFieldGenerator::~WrapperOneofFieldGenerator() { 162} 163 164void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) { 165 // Note: deliberately _oneof_$name$_codec, not _$oneof_name$_codec... we have one codec per field. 166 printer->Print( 167 variables_, 168 "private static readonly pb::FieldCodec<$type_name$> _oneof_$name$_codec = "); 169 GenerateCodecCode(printer); 170 printer->Print(";\n"); 171 WritePropertyDocComment(printer, descriptor_); 172 AddDeprecatedFlag(printer); 173 printer->Print( 174 variables_, 175 "$access_level$ $type_name$ $property_name$ {\n" 176 " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n" 177 " set {\n" 178 " $oneof_name$_ = value;\n" 179 " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" 180 " }\n" 181 "}\n"); 182} 183 184void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { 185 printer->Print( 186 variables_, 187 "$property_name$ = _oneof_$name$_codec.Read(input);\n"); 188} 189 190void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { 191 // TODO: I suspect this is wrong... 192 printer->Print( 193 variables_, 194 "if ($has_property_check$) {\n" 195 " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n" 196 "}\n"); 197} 198 199void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { 200 // TODO: I suspect this is wrong... 201 printer->Print( 202 variables_, 203 "if ($has_property_check$) {\n" 204 " size += _oneof_$name$_codec.CalculateSizeWithTag($property_name$);\n" 205 "}\n"); 206} 207 208} // namespace csharp 209} // namespace compiler 210} // namespace protobuf 211} // namespace google 212