// protobuf-matlab - FarSounder's Protocol Buffer support for Matlab// Copyright (c) 2008, FarSounder Inc. All rights reserved.// http://code.google.com/p/protobuf-matlab///// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.//// * Redistributions in binary form must reproduce the above copyright// notice, this list of conditions and the following disclaimer in the// documentation and/or other materials provided with the distribution.//// * Neither the name of the FarSounder Inc. nor the names of its// contributors may be used to endorse or promote products derived from this// software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE// POSSIBILITY OF SUCH DAMAGE.// Author: fedor.labounko@gmail.com (Fedor Labounko)// Based on Google's C++ Protobuf compiler.//// Generates Matlab code for a given .proto file.#include<farsounder/protobuf/compiler/matlab/matlab_generator.h>#include<algorithm>#include<map>#include<set>#include<string>#include<sstream>#include<utility>#include<vector>#include<google/protobuf/io/printer.h>#include<google/protobuf/io/zero_copy_stream.h>#include<google/protobuf/descriptor.pb.h>#include<google/protobuf/stubs/strutil.h>#include<google/protobuf/wire_format.h>namespacefarsounder{namespaceprotobuf{namespacecompiler{namespacematlab{using::google::protobuf::Descriptor;using::google::protobuf::FieldDescriptor;using::google::protobuf::FieldDescriptor;using::google::protobuf::FileDescriptor;using::google::protobuf::LowerString;using::google::protobuf::SimpleDtoa;using::google::protobuf::SimpleFtoa;using::google::protobuf::SimpleItoa;using::google::protobuf::StringReplace;using::google::protobuf::compiler::GeneratorContext;using::google::protobuf::internal::MutexLock;using::google::protobuf::io::Printer;using::std::make_pair;using::std::map;using::std::max;using::std::pair;using::std::set;using::std::string;using::std::stringstream;using::std::vector;namespace{// CamelToLower taken from Dave Benson's modification for a C implementation// of Protocol BuffersstringCamelToLower(conststring&name){stringnew_name;if(name.size()<2){new_name=name;LowerString(&new_name);returnnew_name;}new_name+=tolower(name[0]);for(inti=1;i<name.size();++i){if(isupper(name[i]))new_name+="_";new_name+=tolower(name[i]);}returnnew_name;}}// namespace// See Type enum in descriptor.hconstMatlabGenerator::MatlabTypeMatlabGenerator::kTypeToMatlabTypeMap[FieldDescriptor::MAX_TYPE+1]={static_cast<MatlabGenerator::MatlabType>(-1),//invalidMATLABTYPE_DOUBLE,// TYPE_DOUBLEMATLABTYPE_SINGLE,// TYPE_FLOATMATLABTYPE_INT64,// TYPE_INT64MATLABTYPE_UINT64,// TYPE_UINT64MATLABTYPE_INT32,// TYPE_INT32MATLABTYPE_UINT64,// TYPE_FIXED64MATLABTYPE_UINT32,// TYPE_FIXED32MATLABTYPE_UINT32,// TYPE_BOOLMATLABTYPE_STRING,// TYPE_STRINGMATLABTYPE_MESSAGE,// TYPE_GROUPMATLABTYPE_MESSAGE,// TYPE_MESSAGEMATLABTYPE_BYTES,// TYPE_BYTESMATLABTYPE_UINT32,// TYPE_UINT32MATLABTYPE_ENUM,// TYPE_ENUMMATLABTYPE_INT32,// TYPE_SFIXED32MATLABTYPE_INT64,// TYPE_SFIXED64MATLABTYPE_INT32,// TYPE_SINT32MATLABTYPE_INT64// TYPE_SINT64};conststringMatlabGenerator::kMatlabTypeToString[MatlabGenerator::MAX_MATLABTYPE+1]={"invalid",// invalid index"int32",// MATLABTYPE_INT32"int64",// MATLABTYPE_INT64"uint32",// MATLABTYPE_UINT32"uint64",// MATLABTYPE_UINT64"double",// MATLABTYPE_DOUBLE"single",// MATLABTYPE_SINGLE"string",// MATLABTYPE_STRING"uint8 vector",// MATLABTYPE_BYTES"message",// MATLABTYPE_MESSAGE"enum",// MATLABTYPE_ENUM};MatlabGenerator::MatlabGenerator(){}MatlabGenerator::~MatlabGenerator(){}boolMatlabGenerator::Generate(constFileDescriptor*file,conststring&parameter,GeneratorContext*output_directory,string*error)const{MutexLocklock(&mutex_);file_=file;output_directory_=output_directory;PrintMessageFunctions();returntrue;}voidMatlabGenerator::PrintMessageFunctions()const{for(inti=0;i<file_->message_type_count();++i){PrintDescriptorFunction(*file_->message_type(i));PrintReadFunction(*file_->message_type(i));}}voidMatlabGenerator::PrintDescriptorFunction(constDescriptor&descriptor)const{// Print nested messagesfor(inti=0;i<descriptor.nested_type_count();++i){PrintDescriptorFunction(*descriptor.nested_type(i));}stringfilename=DescriptorFunctionName(descriptor);filename+=".m";google::protobuf::internal::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream>output(output_directory_->Open(filename));Printerprinter(output.get(),'$');PrintDescriptorHeader(printer,descriptor);PrintDescriptorComment(printer,descriptor);printer.Indent();PrintDescriptorBody(printer,descriptor);printer.Outdent();}voidMatlabGenerator::PrintDescriptorHeader(Printer&printer,constDescriptor&descriptor)const{stringfunction_name=DescriptorFunctionName(descriptor);printer.Print("function [descriptor] = $function_name$()\n","function_name",function_name);}voidMatlabGenerator::PrintDescriptorComment(Printer&printer,constDescriptor&descriptor)const{stringname=descriptor.name();stringfunction_name=DescriptorFunctionName(descriptor);printer.Print("%$function_name$ Returns the descriptor for message $name$.\n","name",name,"function_name",function_name);printer.Print("% ");PrintDescriptorHeader(printer,descriptor);printer.Print("%\n");printer.Print("% See also $read_function$","read_function",ReadFunctionName(descriptor));printer.Print("\n");}voidMatlabGenerator::PrintDescriptorBody(Printer&printer,constDescriptor&descriptor)const{printer.Print("\n");printer.Print("descriptor = struct( ...\n");printer.Indent();printer.Print("'name', '$name$', ...\n","name",descriptor.name());printer.Print("'full_name', '$full_name$', ...\n","full_name",descriptor.full_name());printer.Print("'filename', '$filename$', ...\n","filename",descriptor.file()->name());printer.Print("'containing_type', '$containing_type$', ...\n","containing_type",descriptor.containing_type()==NULL?"":descriptor.containing_type()->full_name());printer.Print("'fields', [ ...\n");printer.Indent();PrintFieldDescriptors(printer,descriptor);printer.Outdent();printer.Print("], ...\n");printer.Print("'extensions', [ ... % Not Implemented\n");printer.Indent();// PrintExtensions(printer, descriptor);printer.Outdent();printer.Print("], ...\n");printer.Print("'nested_types', [ ... % Not implemented\n");printer.Indent();// PrintNestedTypes(printer, descriptor);printer.Outdent();printer.Print("], ...\n");printer.Print("'enum_types', [ ... % Not Implemented\n");printer.Indent();// PrintEnumTypes(printer, descriptor);printer.Outdent();printer.Print("], ...\n");printer.Print("'options', [ ... % Not Implemented\n");printer.Indent();// PrintOptions(printer, descriptor);printer.Outdent();printer.Print("] ...\n");printer.Outdent();printer.Print(");\n\n");PrintFieldIndecesByNumber(printer,descriptor);}voidMatlabGenerator::PrintFieldDescriptors(Printer&printer,constDescriptor&descriptor)const{vector<pair<int,int>>sorted_fields;for(inti=0;i<descriptor.field_count();++i){sorted_fields.push_back(make_pair(descriptor.field(i)->number(),i));}sort(sorted_fields.begin(),sorted_fields.end());constFieldDescriptor*field;map<string,string>m;for(inti=0;i<descriptor.field_count();++i){field=descriptor.field(sorted_fields[i].second);m.clear();printer.Print("struct( ...\n");printer.Indent();m["name"]=field->name();m["full_name"]=field->full_name();m["index"]=SimpleItoa(i+1);m["number"]=SimpleItoa(field->number());m["type"]=SimpleItoa(field->type());m["matlab_type"]=SimpleItoa(kTypeToMatlabTypeMap[field->type()]);m["wire_type"]=SimpleItoa(google::protobuf::internal::WireFormat::WireTypeForFieldType(field->type()));m["label"]=SimpleItoa(field->label());m["default_value"]=DefaultValueToString(*field);m["read_function"]=MakeReadFunctionHandle(*field);m["write_function"]=MakeWriteFunctionHandle(*field);if(field->options().packed()){m["packed"]="true";}else{m["packed"]="false";}printer.Print(m,"'name', '$name$', ...\n""'full_name', '$full_name$', ...\n""'index', $index$, ...\n""'number', uint32($number$), ...\n""'type', uint32($type$), ...\n""'matlab_type', uint32($matlab_type$), ...\n""'wire_type', uint32($wire_type$), ...\n""'label', uint32($label$), ...\n""'default_value', $default_value$, ...\n""'read_function', $read_function$, ...\n""'write_function', $write_function$, ...\n""'options', struct('packed', $packed$) ...\n");printer.Outdent();if(i!=descriptor.field_count()-1)printer.Print("), ...\n");elseprinter.Print(") ...\n");}}voidMatlabGenerator::PrintFieldIndecesByNumber(Printer&printer,constDescriptor&descriptor)const{// Assumes the fields are entered into an array by increasing tag valuesprinter.Print("descriptor.field_indeces_by_number = java.util.HashMap;\n");constFieldDescriptor*field;map<string,string>map_values;vector<pair<int,int>>sorted_fields;for(inti=0;i<descriptor.field_count();++i){sorted_fields.push_back(make_pair(descriptor.field(i)->number(),i));}sort(sorted_fields.begin(),sorted_fields.end());for(inti=0;i<descriptor.field_count();++i){field=descriptor.field(sorted_fields[i].second);printer.Print("put(descriptor.field_indeces_by_number, uint32($number$), $index$);\n","number",SimpleItoa(field->number()),"index",SimpleItoa(i+1));}printer.Print("\n");}voidMatlabGenerator::PrintReadFunction(constDescriptor&descriptor)const{// Print nested messagesfor(inti=0;i<descriptor.nested_type_count();++i){PrintReadFunction(*descriptor.nested_type(i));}stringfilename=ReadFunctionName(descriptor);filename+=".m";google::protobuf::internal::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream>output(output_directory_->Open(filename));Printerprinter(output.get(),'$');PrintReadHeader(printer,descriptor);PrintReadComment(printer,descriptor);printer.Indent();PrintReadBody(printer,descriptor);printer.Outdent();}voidMatlabGenerator::PrintReadHeader(Printer&printer,constDescriptor&descriptor)const{stringname=CamelToLower(descriptor.name());stringfunction_name=ReadFunctionName(descriptor);printer.Print("function [$name$] = $function_name$(buffer, buffer_start, buffer_end)\n","name",name,"function_name",function_name);}voidMatlabGenerator::PrintReadComment(Printer&printer,constDescriptor&descriptor)const{stringname=descriptor.name();stringfunction_name=ReadFunctionName(descriptor);printer.Print("%$function_name$ Reads the protobuf message $name$.\n","name",name,"function_name",function_name);printer.Print("% ");PrintReadHeader(printer,descriptor);printer.Print("%\n");printer.Print("% INPUTS:\n""% buffer : a buffer of uint8's to parse\n""% buffer_start : optional starting index to consider of the buffer\n""% defaults to 1\n""% buffer_end : optional ending index to consider of the buffer\n""% defaults to length(buffer)\n""%\n""% MEMBERS:\n");for(inti=0;i<descriptor.field_count();++i){constFieldDescriptor&field=*descriptor.field(i);stringbuffer_space(max(0,static_cast<int>(15-field.name().size())),' ');printer.Print("% $name$$buffer$: ","name",field.name(),"buffer",buffer_space);switch(field.label()){caseFieldDescriptor::LABEL_OPTIONAL:printer.Print("optional ");break;caseFieldDescriptor::LABEL_REQUIRED:printer.Print("required ");break;caseFieldDescriptor::LABEL_REPEATED:printer.Print("repeated ");break;default:GOOGLE_LOG(FATAL)<<"Unhandled case in print comment.";}if(field.type()==FieldDescriptor::TYPE_MESSAGE){printer.Print("<a href=\"matlab:help $read_function$\">$type$</a>","read_function",ReadFunctionName(*field.message_type()),"type",field.message_type()->full_name());}else{printer.Print("$type$","type",kMatlabTypeToString[kTypeToMatlabTypeMap[field.type()]]);}printer.Print(", defaults to $default$.\n","default",DefaultValueToString(field));}boolfirst_to_print=true;stringbeginning_string="%\n% See also";// Will store all the types we'll print in the See also help string// Used so we don't print duplicatesintnum=0;set<constDescriptor*>used_types;#define PRINT_SEE_ALSO(DESCRIPTOR) \ if (used_types.count(DESCRIPTOR) == 0) { \ if (first_to_print) { \ printer.Print("$beginning$ $function$", \ "beginning", beginning_string, \ "function", ReadFunctionName(*(DESCRIPTOR))); \ first_to_print = false; \ } else { \ printer.Print(", $function$", \ "function", ReadFunctionName(*(DESCRIPTOR))); \ } \ used_types.insert(DESCRIPTOR); \ }// Add the containing typeif(descriptor.containing_type()!=NULL){PRINT_SEE_ALSO(descriptor.containing_type());}// Add types used as fields in this messagefor(inti=0;i<descriptor.field_count();++i){if(descriptor.field(i)->type()!=::google::protobuf::FieldDescriptor::TYPE_MESSAGE){continue;}PRINT_SEE_ALSO(descriptor.field(i)->message_type());}// Add nested types defined in this messagefor(inti=0;i<descriptor.nested_type_count();++i){PRINT_SEE_ALSO(descriptor.nested_type(i));}// Print other message types defined in the same filefor(inti=0;i<file_->message_type_count();++i){if(file_->message_type(i)==&descriptor)continue;PRINT_SEE_ALSO(file_->message_type(i));}#undef PRINT_SEE_ALSOif(!first_to_print){printer.Print(".\n");}}voidMatlabGenerator::PrintReadBody(Printer&printer,constDescriptor&descriptor)const{printer.Print("\n");printer.Print("if (nargin < 1)\n"" buffer = uint8([]);\n""end\n""if (nargin < 2)\n"" buffer_start = 1;\n""end\n""if (nargin < 3)\n"" buffer_end = length(buffer);\n""end\n""\n");stringname=CamelToLower(descriptor.name());stringdescriptor_function=DescriptorFunctionName(descriptor);printer.Print("descriptor = $descriptor_function$();\n","descriptor_function",descriptor_function);printer.Print("$name$ = pblib_generic_parse_from_string(buffer, descriptor, buffer_start, buffer_end);\n","name",name);printer.Print("$name$.descriptor_function = @$descriptor_function$;\n","name",name,"descriptor_function",descriptor_function);}stringMatlabGenerator::DefaultValueToString(constFieldDescriptor&field)const{MatlabTypetype=kTypeToMatlabTypeMap[field.type()];field.has_default_value();stringstreams;if(field.is_repeated()){switch(type){caseMATLABTYPE_INT32:return"int32([])";caseMATLABTYPE_INT64:return"int64([])";caseMATLABTYPE_UINT32:return"uint32([])";caseMATLABTYPE_UINT64:return"uint64([])";caseMATLABTYPE_DOUBLE:return"double([])";caseMATLABTYPE_SINGLE:return"single([])";caseMATLABTYPE_MESSAGE:return"struct([])";caseMATLABTYPE_ENUM:return"int32([])";caseMATLABTYPE_STRING:return"char([])";caseMATLABTYPE_BYTES:return"uint8([])";}}else{switch(type){caseMATLABTYPE_INT32:s<<"int32("<<SimpleItoa(field.default_value_int32())<<")";returns.str();caseMATLABTYPE_INT64:s<<"int64("<<SimpleItoa(field.default_value_int64())<<")";returns.str();caseMATLABTYPE_UINT32:s<<"uint32(";// This is needed as the default values are in a union and if the bool// value is set it doesn't set the full 32 bitsif(field.type()==FieldDescriptor::TYPE_BOOL){s<<SimpleItoa(field.default_value_bool());}else{s<<SimpleItoa(field.default_value_uint32());}s<<")";returns.str();caseMATLABTYPE_UINT64:s<<"uint64("<<SimpleItoa(field.default_value_uint64())<<")";returns.str();caseMATLABTYPE_DOUBLE:s<<"double("<<SimpleDtoa(field.default_value_double())<<")";returns.str();caseMATLABTYPE_SINGLE:s<<"single("<<SimpleFtoa(field.default_value_float())<<")";returns.str();caseMATLABTYPE_MESSAGE:return"struct([])";caseMATLABTYPE_ENUM:s<<"int32("<<SimpleItoa(field.default_value_enum()->number())<<")";returns.str();caseMATLABTYPE_STRING:s<<"'"<<StringReplace(field.default_value_string(),"'","''",true)<<"'";returns.str();caseMATLABTYPE_BYTES:s<<"uint8('"<<StringReplace(field.default_value_string(),"'","''",true)<<"')";returns.str();}}GOOGLE_LOG(FATAL)<<"Not reached.";return"''";}stringMatlabGenerator::MakeReadFunctionHandle(constFieldDescriptor&field)const{MatlabTypetype=kTypeToMatlabTypeMap[field.type()];FieldDescriptor::Typeproto_type=field.type();stringfunction_handle;switch(type){caseMATLABTYPE_INT32:// We must call pblib_helpers_first because the standard varint// will put the result into a uint64//// We must also figure out whether this is encoded using the ZigZag// encoding, which is the case if its type was specificied as sint32 or// sint64if(proto_type==FieldDescriptor::TYPE_SINT32){return"@(x) pblib_helpers_first(typecast(pblib_helpers_iff(bitget(x, 1), bitset(bitshift(bitxor(intmax('uint64'), x), -1), 64), bitshift(x, -1)), 'int32'))";}else{return"@(x) pblib_helpers_first(typecast(x, 'int32'))";}caseMATLABTYPE_INT64:// We must figure out whether this is encoded using the ZigZag encoding,// which is the case if its type was specificied as sint32 or sint64if(proto_type==FieldDescriptor::TYPE_SINT64){return"@(x) typecast(pblib_helpers_iff(bitget(x, 1), bitset(bitshift(bitxor(intmax('uint64'), x), -1), 64), bitshift(x, -1)), 'int64')";}else{return"@(x) typecast(x, 'int64')";}caseMATLABTYPE_UINT32:// We must call pblib_helpers_first because the standard varint// will put the result into a uint64return"@(x) pblib_helpers_first(typecast(x, 'uint32'))";caseMATLABTYPE_UINT64:return"@(x) typecast(x, 'uint64')";caseMATLABTYPE_DOUBLE:return"@(x) typecast(x, 'double')";caseMATLABTYPE_SINGLE:return"@(x) typecast(x, 'single')";caseMATLABTYPE_STRING:return"@(x) char(x{1}(x{2} : x{3}))";caseMATLABTYPE_BYTES:return"@(x) uint8(x{1}(x{2} : x{3}))";caseMATLABTYPE_MESSAGE:return"@(x) "+ReadFunctionName(*field.message_type())+"(x{1}, x{2}, x{3})";caseMATLABTYPE_ENUM:// We must call pblib_helpers_first because the standard varint// will put the result into a uint64return"@(x) pblib_helpers_first(typecast(x, 'int32'))";}GOOGLE_LOG(FATAL)<<"Shouldn't get here since switch should catch all cases.";return"";}stringMatlabGenerator::MakeWriteFunctionHandle(constFieldDescriptor&field)const{// These functions should undo the work done by the read functions so as to// pass as input to write_varint the same values that read_varint would pass// back as output. That's why, in particular, we typecast fixed32,// sfixed32, etc. into uint8 as that's how read_varint would return them to// us.MatlabTypematlab_type=kTypeToMatlabTypeMap[field.type()];FieldDescriptor::Typetype=field.type();stringfunction_handle;switch(matlab_type){caseMATLABTYPE_INT32:// We must figure out whether this is encoded using the ZigZag encoding,// which is the case if its type was specificied as sint32 or sint64 I// am not able to find an arithmetic shift in Matlab, but if one is// found we can do the zigzag with (n<<1) ^ (n>>31)switch(type){caseFieldDescriptor::TYPE_INT32:return"@(x) typecast(int32(x), 'uint32')";caseFieldDescriptor::TYPE_SFIXED32:return"@(x) typecast(int32(x), 'uint8')";caseFieldDescriptor::TYPE_SINT32:return"@(x) typecast(pblib_helpers_iff(int32(x) < 0, -2 * int32(x) - 1, 2 * int32(x)), 'uint32')";}GOOGLE_LOG(DFATAL)<<"Unhandled matlabtype_int32 type "<<type<<" in WriteFunctionHandle.";break;caseMATLABTYPE_INT64:// We must figure out whether this is encoded using the ZigZag encoding,// which is the case if its type was specificied as sint32 or sint64 I// am not able to find an arithmetic shift in Matlab, but if one is// found we can do the zigzag with (n<<1) ^ (n>>63)switch(type){caseFieldDescriptor::TYPE_INT64:return"@(x) typecast(int64(x), 'uint64')";caseFieldDescriptor::TYPE_SFIXED64:return"@(x) typecast(int64(x), 'uint8')";caseFieldDescriptor::TYPE_SINT64:return"@(x) pblib_helpers_iff(int64(x) < 0, bitxor(bitshift(typecast(int64(x), 'uint64'), 1), intmax('uint64')), bitshift(typecast(int64(x), 'uint64'), 1))";}GOOGLE_LOG(DFATAL)<<"Unhandled matlabtype_int32 type "<<type<<" in WriteFunctionHandle.";break;caseMATLABTYPE_UINT32:switch(type){caseFieldDescriptor::TYPE_FIXED32:return"@(x) typecast(uint32(x), 'uint8')";caseFieldDescriptor::TYPE_BOOL:caseFieldDescriptor::TYPE_UINT32:return"@(x) typecast(uint32(x), 'uint32')";}GOOGLE_LOG(DFATAL)<<"Unhandled matlabtype_uint32 type "<<type<<" in WriteFunctionHandle.";break;caseMATLABTYPE_UINT64:switch(type){caseFieldDescriptor::TYPE_UINT64:return"@(x) typecast(uint64(x), 'uint64')";caseFieldDescriptor::TYPE_FIXED64:return"@(x) typecast(uint64(x), 'uint8')";}GOOGLE_LOG(DFATAL)<<"Unhandled matlabtype_uint64 type "<<type<<" in WriteFunctionHandle.";break;caseMATLABTYPE_DOUBLE:return"@(x) typecast(double(x), 'uint8')";caseMATLABTYPE_SINGLE:return"@(x) typecast(single(x), 'uint8')";caseMATLABTYPE_STRING:return"@uint8";caseMATLABTYPE_BYTES:return"@uint8";caseMATLABTYPE_MESSAGE:return"@pblib_generic_serialize_to_string";caseMATLABTYPE_ENUM:// We must call pblib_helpers_first because the standard varint// will put the result into a uint64return"@(x) typecast(int32(x), 'uint32')";}GOOGLE_LOG(DFATAL)<<"Shouldn't get here since switch should catch all cases.";return"";}stringMatlabGenerator::DescriptorFunctionName(constDescriptor&descriptor)const{return"pb_descriptor_"+StringReplace(descriptor.full_name(),".","__",true);}stringMatlabGenerator::ReadFunctionName(constDescriptor&descriptor)const{return"pb_read_"+StringReplace(descriptor.full_name(),".","__",true);}}// namespace matlab}// namespace compiler}// namespace protobuf}// namespace google