THRIFT-2451: Do not use pointers for optional fields with defaults. Do not write such fields if its value set to default. Also, do not use pointers for any optional fields mapped to go map or slice. generate Get accessors
Client: Go
Patch: Aleksey Pesternikov
This closes #101
commit e6e5dcf3a07cd931183991ff031179b425e2740b
Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
Date: 2014-04-16T14:06:52Z
initial change
commit f65730e951a4310160a9f7e3e4eeb7e55abd2c55
Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
Date: 2014-04-16T14:16:03Z
no IsSet for required
commit 9865f700eb9354d6053994da989a907766c42d1d
Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
Date: 2014-04-17T19:32:13Z
inlined required structs
commit ca52300c07cefcf553f1ebf35569953c933b2367
Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
Date: 2014-04-17T19:44:24Z
do not use heap for args struct
commit 012ca3e512d2bc8822de8a715b4f3d3cae5c0c42
Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
Date: 2014-04-17T19:52:41Z
do not use heap for result struct
commit 2fc4afc53ff7db43e08eadeaa30e34bc1fd9c889
Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
Date: 2014-04-17T21:32:43Z
do not set result field on error
commit 6e5da0062b139f02dcafe3148cdf02f97c23442a
Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
Date: 2014-04-17T21:57:57Z
Jens' thrift source as test case
commit 7317957ed708831e280f182f081043fbe9d38a0c
Author: Aleksey Pesternikov <ap@alekseys-macbook-pro.local>
Date: 2014-04-17T23:43:08Z
support for cpp.ref
commit 1c4f3efc7b54fd335db633f86faf8c426ae9c87d
Author: Aleksey Pesternikov <ap@alekseys-macbook-pro.local>
Date: 2014-04-18T00:13:24Z
package flag
commit c9d7e54f5c5d29c776f42fb861bc9e82da4e542f
Author: Aleksey Pesternikov <ap@alekseys-macbook-pro.local>
Date: 2014-04-18T00:21:18Z
Merge branch 'master' into go_inlines
diff --git a/compiler/cpp/src/generate/t_go_generator.cc b/compiler/cpp/src/generate/t_go_generator.cc
index 94e1db6..4893c71 100644
--- a/compiler/cpp/src/generate/t_go_generator.cc
+++ b/compiler/cpp/src/generate/t_go_generator.cc
@@ -60,6 +60,7 @@
bool format_go_output(const string &file_path);
const string default_thrift_import = "git.apache.org/thrift.git/lib/go/thrift";
+static std::string package_flag;
/**
* Go code generator.
@@ -87,6 +88,12 @@
if (iter != parsed_options.end()) {
gen_thrift_import_ = (iter->second);
}
+
+ iter = parsed_options.find("package");
+
+ if (iter != parsed_options.end()) {
+ package_flag = (iter->second);
+ }
}
/**
@@ -115,6 +122,7 @@
void generate_go_struct(t_struct* tstruct, bool is_exception);
void generate_go_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception = false, bool is_result = false, bool is_args = false);
+ void generate_go_struct_initializer(std::ofstream& out, t_struct* tstruct, bool is_args_or_result = false);
void generate_isset_helpers(std::ofstream& out, t_struct* tstruct, const string& tstruct_name, bool is_result = false);
void generate_go_struct_reader(std::ofstream& out, t_struct* tstruct, const string& tstruct_name, bool is_result = false);
void generate_go_struct_writer(std::ofstream& out, t_struct* tstruct, const string& tstruct_name, bool is_result = false);
@@ -144,16 +152,18 @@
std::string prefix = "",
bool inclass = false,
bool coerceData = false,
- bool inkey = false);
+ bool inkey = false,
+ bool in_container = false);
void generate_deserialize_struct(std::ofstream &out,
t_struct* tstruct,
+ bool is_pointer_field,
bool declare,
std::string prefix = "");
void generate_deserialize_container(std::ofstream &out,
t_type* ttype,
- bool optional_field,
+ bool pointer_field,
bool declare,
std::string prefix = "");
@@ -183,7 +193,7 @@
void generate_serialize_container(std::ofstream &out,
t_type* ttype,
- bool optional_field,
+ bool pointer_field,
std::string prefix = "");
void generate_serialize_map_element(std::ofstream &out,
@@ -233,12 +243,16 @@
std::string function_signature_if(t_function* tfunction, std::string prefix = "", bool addError = false);
std::string argument_list(t_struct* tstruct);
std::string type_to_enum(t_type* ttype);
- std::string type_to_go_type(t_type* ttype);
- std::string type_to_go_type_with_opt(t_type* ttype, bool optional_field);
+ std::string type_to_go_type(t_type* ttype, bool is_container_value = false);
+ std::string type_to_go_type_with_opt(t_type* ttype, bool optional_field, bool is_container_value = false);
std::string type_to_go_key_type(t_type* ttype);
std::string type_to_spec_args(t_type* ttype);
static std::string get_real_go_module(const t_program* program) {
+
+ if (!package_flag.empty()) {
+ return package_flag;
+ }
std::string real_module = program->get_namespace("go");
if (real_module.empty()) {
@@ -271,10 +285,116 @@
static std::string new_prefix(const std::string& value);
static std::string privatize(const std::string& value);
static std::string variable_name_to_go_name(const std::string& value);
- static bool can_be_nil(t_type* value);
-
+ static bool is_pointer_field(t_field* tfield, bool in_container = false);
+ static bool omit_initialization(t_field* tfield);
};
+//returns true if field initialization can be omitted since it has corresponding go type zero value
+//or default value is not set
+bool t_go_generator::omit_initialization(t_field* tfield) {
+ t_const_value* value = tfield->get_value();
+ if (!value) {
+ return true;
+ }
+ t_type* type = tfield->get_type()->get_true_type();
+ if (type->is_base_type()) {
+ t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+
+ switch (tbase) {
+ case t_base_type::TYPE_VOID:
+ throw "";
+
+ case t_base_type::TYPE_STRING:
+ if (((t_base_type*)type)->is_binary()) {
+ //[]byte are always inline
+ return false;
+ }
+ //strings are pointers if has no default
+ return value->get_string().empty();
+
+ case t_base_type::TYPE_BOOL:
+ case t_base_type::TYPE_BYTE:
+ case t_base_type::TYPE_I16:
+ case t_base_type::TYPE_I32:
+ case t_base_type::TYPE_I64:
+ return value->get_integer()==0;
+ case t_base_type::TYPE_DOUBLE:
+ if (value->get_type() == t_const_value::CV_INTEGER) {
+ return value->get_integer()==0;
+ } else {
+ return value->get_double()==0.;
+ }
+ }
+ }
+ return false;
+}
+
+//Returns true if the type need a reference if used as optional without default
+static bool type_need_reference(t_type* type) {
+ type = type->get_true_type();
+ if( type->is_map()
+ || type->is_set()
+ || type->is_list()
+ || (type->is_string() && ((t_base_type*)type)->is_binary() )) {
+ return false;
+ }
+ return true;
+}
+
+//returns false if field could not use comparison to default value as !IsSet*
+bool t_go_generator::is_pointer_field(t_field* tfield, bool in_container_value) {
+ if (tfield->annotations_.count("cpp.ref")!=0) {
+ return true;
+ }
+ t_type* type = tfield->get_type()->get_true_type();
+ //Structs in containers are pointers
+ if (in_container_value && type->is_struct()) {
+ return true;
+ }
+ if (!(tfield->get_req() == t_field::T_OPTIONAL)) {
+ return false;
+ }
+
+ bool has_default = tfield->get_value();
+ if (type->is_base_type()) {
+ t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+
+ switch (tbase) {
+ case t_base_type::TYPE_VOID:
+ throw "";
+
+ case t_base_type::TYPE_STRING:
+ if (((t_base_type*)type)->is_binary()) {
+ //[]byte are always inline
+ return false;
+ }
+ //strings are pointers if has no default
+ return !has_default;
+
+ case t_base_type::TYPE_BOOL:
+ case t_base_type::TYPE_BYTE:
+ case t_base_type::TYPE_I16:
+ case t_base_type::TYPE_I32:
+ case t_base_type::TYPE_I64:
+ case t_base_type::TYPE_DOUBLE:
+ return !has_default;
+ }
+ } else if (type->is_enum()) {
+ return !has_default;
+ } else if (type->is_struct() || type->is_xception()) {
+ return true;
+ } else if (type->is_map()) {
+ return has_default;
+ } else if (type->is_set()) {
+ return has_default;
+ } else if (type->is_list()) {
+ return has_default;
+ } else if (type->is_typedef()) {
+ return has_default;
+ }
+
+ throw "INVALID TYPE IN type_to_go_type: " + type->get_name();
+}
std::string t_go_generator::publicize(const std::string& value, bool is_args_or_result)
{
@@ -622,7 +742,8 @@
{
return
string("import (\n"
- "\t\"fmt\"\n"
+ "\t\"bytes\"\n"
+ "\t\"fmt\"\n"
"\t\"" + gen_thrift_import_ + "\"\n");
}
@@ -639,7 +760,8 @@
")\n\n"
"// (needed to ensure safety because of naive import list construction.)\n"
"var _ = thrift.ZERO\n"
- "var _ = fmt.Printf\n\n");
+ "var _ = fmt.Printf\n"
+ "var _ = bytes.Equal\n\n");
}
/**
@@ -864,7 +986,7 @@
t_type* vtype = ((t_map*)type)->get_val_type();
const map<t_const_value*, t_const_value*>& val = value->get_map();
out <<
- "map[" << type_to_go_type(ktype) << "]" << type_to_go_type(vtype) << "{" << endl;
+ "map[" << type_to_go_type(ktype) << "]" << type_to_go_type(vtype, true) << "{" << endl;
indent_up();
map<t_const_value*, t_const_value*>::const_iterator v_iter;
@@ -955,6 +1077,24 @@
*OUT_def_value = tfield->get_value();
}
+void t_go_generator::generate_go_struct_initializer(ofstream& out,
+ t_struct* tstruct,
+ bool is_args_or_result)
+{
+ out << publicize(type_name(tstruct), is_args_or_result) << "{";
+ const vector<t_field*>& members = tstruct->get_members();
+ for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ bool pointer_field = is_pointer_field(*m_iter);
+ string publicized_name;
+ t_const_value* def_value;
+ get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value);
+ if (!pointer_field && def_value != NULL && !omit_initialization(*m_iter)) {
+ out << endl << indent() << publicized_name << ": " << render_field_initial_value(*m_iter, (*m_iter)->get_name(), pointer_field) << "," << endl;
+ }
+ }
+
+ out << "}" << endl;
+}
/**
* Generates a struct definition for a thrift data type.
@@ -1010,8 +1150,7 @@
}
t_type* fieldType = (*m_iter)->get_type();
- bool optional_field = ((*m_iter)->get_req() == t_field::T_OPTIONAL);
- string goType = type_to_go_type_with_opt(fieldType, optional_field);
+ string goType = type_to_go_type_with_opt(fieldType, is_pointer_field(*m_iter));
indent(out) << publicize(variable_name_to_go_name((*m_iter)->get_name())) << " "
<< goType << " `thrift:\""
@@ -1038,42 +1177,43 @@
out <<
indent() << "}" << endl << endl <<
indent() << "func New" << tstruct_name << "() *" << tstruct_name << " {" << endl <<
- indent() << " rval := &" << tstruct_name << "{";
-
+ indent() << " return &";
+ generate_go_struct_initializer(out, tstruct, is_result || is_args);
+ out <<
+ indent() << "}" << endl << endl;
+ // Default values for optional fields
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- bool optional_field = ((*m_iter)->get_req() == t_field::T_OPTIONAL);
-
- // Initialize struct fields, assigning defaults for non-optional (i.e.,
- // non-pointer) fields.
string publicized_name;
t_const_value* def_value;
get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value);
- if (def_value != NULL) {
- out << endl << indent() << publicized_name << ": " << render_field_initial_value(*m_iter, (*m_iter)->get_name(), optional_field) << "," << endl;
- }
- }
-
- out << "}" << endl;
-
- // Assign actual default values for optional fields in a second pass. See
- // the comment in render_field_initial_value for context and motivation.
- for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
- string publicized_name;
- t_const_value* def_value;
- get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value);
+ t_type* fieldType = (*m_iter)->get_type();
+ string goType = type_to_go_type_with_opt(fieldType, false);
+ string def_var_name = tstruct_name + "_" + publicized_name + "_DEFAULT";
+ if ((*m_iter)->get_req() == t_field::T_OPTIONAL || is_pointer_field(*m_iter)) {
+ out << indent() << "var " << def_var_name <<" "<<goType ;
if (def_value != NULL) {
- // XXX
- // t_type* ttype = get_true_type((*m_iter)->get_type());
- t_type* ttype = (*m_iter)->get_type();
- out << indent() << "*(rval." << publicized_name << ") = " << render_const_value(ttype, def_value, (*m_iter)->get_name()) << endl;
+ out << " = " << render_const_value(fieldType, def_value, (*m_iter)->get_name()) ;
}
+ out <<endl;
+ }
+ if (is_pointer_field(*m_iter)) {
+ string goOptType = type_to_go_type_with_opt(fieldType, true);
+ string maybepointer = goOptType!=goType?"*":"";
+ out <<indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() "<< goType<<" {" << endl
+ <<indent() << " if !p.IsSet" <<publicized_name <<"() {" <<endl
+ <<indent() << " return " <<def_var_name <<endl
+ <<indent() << " }" <<endl
+ <<indent() << "return "<<maybepointer <<"p." <<publicized_name <<endl
+ <<indent() << "}" <<endl;
+ } else {
+ out <<endl
+ <<indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() "<< goType<<" {" << endl
+ <<indent() << "return p." <<publicized_name <<endl
+ <<indent() << "}" <<endl;
+
}
}
- out << "return rval" << endl;
-
- out << "}" << endl << endl;
generate_isset_helpers(out, tstruct, tstruct_name, is_result);
generate_go_struct_reader(out, tstruct, tstruct_name, is_result);
generate_go_struct_writer(out, tstruct, tstruct_name, is_result);
@@ -1108,12 +1248,27 @@
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
const string field_name(publicize(variable_name_to_go_name(escape_string((*f_iter)->get_name()))));
- if ((*f_iter)->get_req() == t_field::T_OPTIONAL) {
+ if ((*f_iter)->get_req() == t_field::T_OPTIONAL || is_pointer_field(*f_iter)) {
out <<
indent() << "func (p *" << tstruct_name << ") IsSet" << field_name << "() bool {" << endl;
indent_up();
- out <<
- indent() << "return p." << field_name << " != nil" << endl;
+ t_type* ttype = (*f_iter)->get_type()->get_true_type();
+ bool is_byteslice = ttype->is_base_type() && ((t_base_type*)ttype)->is_binary() ;
+ bool compare_to_nil_only = ttype->is_set()
+ || ttype->is_list()
+ || ttype->is_map()
+ || (is_byteslice && !(*f_iter)->get_value());
+ if (is_pointer_field(*f_iter) || compare_to_nil_only) {
+ out <<
+ indent() << "return p." << field_name << " != nil" << endl;
+ } else {
+ string def_var_name = tstruct_name + "_" + field_name + "_DEFAULT";
+ if (is_byteslice) {
+ out << indent() << "return !bytes.Equal(p." << field_name << ", "<<def_var_name << ")" << endl;
+ } else {
+ out << indent() << "return p." << field_name << " != "<<def_var_name << endl;
+ }
+ }
indent_down();
out <<
indent() << "}" << endl << endl;
@@ -1267,53 +1422,22 @@
string escape_field_name;
//t_const_value* field_default_value;
t_field::e_req field_required;
- bool field_can_be_nil = false;
int32_t field_id = -1;
- if (is_result && fields.size()) {
- out <<
- indent() << "switch {" << endl;
- vector<t_field*>::const_reverse_iterator fr_iter;
+ for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+ string field_method_prefix("writeField");
+ field_name = (*f_iter)->get_name();
+ escape_field_name = escape_string(field_name);
+ field_id = (*f_iter)->get_key();
- for (fr_iter = fields.rbegin(); fr_iter != fields.rend(); ++fr_iter) {
- string field_method_prefix("writeField");
- field_name = (*fr_iter)->get_name();
- field_id = (*fr_iter)->get_key();
-
- if (field_id < 0) {
- field_method_prefix += "_";
- field_id *= -1;
- }
-
- if (can_be_nil((*fr_iter)->get_type()) && field_id != 0) {
- out <<
- indent() << "case p." << publicize(variable_name_to_go_name(field_name)) << " != nil:" << endl <<
- indent() << " if err := p." << field_method_prefix << field_id << "(oprot); err != nil { return err }" << endl;
- } else {
- out <<
- indent() << "default:" << endl <<
- indent() << " if err := p." << field_method_prefix << field_id << "(oprot); err != nil { return err }" << endl;
- }
+ if (field_id < 0) {
+ field_method_prefix += "_";
+ field_id *= -1;
}
out <<
- indent() << "}" << endl;
- } else {
- for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
- string field_method_prefix("writeField");
- field_name = (*f_iter)->get_name();
- escape_field_name = escape_string(field_name);
- field_id = (*f_iter)->get_key();
+ indent() << "if err := p." << field_method_prefix << field_id << "(oprot); err != nil { return err }" << endl;
- if (field_id < 0) {
- field_method_prefix += "_";
- field_id *= -1;
- }
-
- out <<
- indent() << "if err := p." << field_method_prefix << field_id << "(oprot); err != nil { return err }" << endl;
-
- }
}
// Write the struct map
@@ -1334,7 +1458,6 @@
escape_field_name = escape_string(field_name);
//field_default_value = (*f_iter)->get_value();
field_required = (*f_iter)->get_req();
- field_can_be_nil = can_be_nil((*f_iter)->get_type());
if (field_id < 0) {
field_method_prefix += "_";
@@ -1345,13 +1468,6 @@
indent() << "func (p *" << tstruct_name << ") " << field_method_prefix << field_id << "(oprot thrift.TProtocol) (err error) {" << endl;
indent_up();
- // Write field header
- if (field_can_be_nil) {
- out <<
- indent() << "if p." << publicize(variable_name_to_go_name(field_name)) << " != nil {" << endl;
- indent_up();
- }
-
if (field_required == t_field::T_OPTIONAL) {
out <<
indent() << "if p.IsSet" << publicize(variable_name_to_go_name(field_name)) << "() {" << endl;
@@ -1380,12 +1496,6 @@
indent() << "}" << endl;
}
- if (field_can_be_nil) {
- indent_down();
- out <<
- indent() << "}" << endl;
- }
-
indent_down();
out <<
indent() << " return err" << endl <<
@@ -1447,6 +1557,7 @@
if (!tfunction->is_oneway()) {
t_struct result(program_, tfunction->get_name() + "_result");
t_field success(tfunction->get_returntype(), "success", 0);
+ success.set_req(t_field::T_OPTIONAL);
if (!tfunction->get_returntype()->is_void()) {
result.append(&success);
@@ -1457,7 +1568,9 @@
vector<t_field*>::const_iterator f_iter;
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
- result.append(*f_iter);
+ t_field* f = *f_iter;
+ f->set_req(t_field::T_OPTIONAL);
+ result.append(f);
}
generate_go_struct_definition(f_service_, &result, false, true);
@@ -1664,7 +1777,6 @@
indent_up();
std::string argsname = publicize((*f_iter)->get_name() + "_args",true);
// Serialize the request header
- string args(tmp("args"));
f_service_ <<
indent() << "oprot := p.OutputProtocol" << endl <<
indent() << "if oprot == nil {" << endl <<
@@ -1679,16 +1791,18 @@
indent_down();
f_service_ <<
indent() << "}" << endl <<
- indent() << args << " := New" << argsname << "()" << endl;
+ indent() << "args := " << argsname << "{" << endl;
for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
f_service_ <<
- indent() << args << "." << publicize(variable_name_to_go_name((*fld_iter)->get_name())) << " = " << variable_name_to_go_name((*fld_iter)->get_name()) << endl;
+ indent() << publicize(variable_name_to_go_name((*fld_iter)->get_name())) << " : " << variable_name_to_go_name((*fld_iter)->get_name()) << ","<< endl;
}
+ f_service_ <<
+ indent() << "}" << endl;
// Write to the stream
f_service_ <<
- indent() << "if err = " << args << ".Write(oprot); err != nil {" << endl;
+ indent() << "if err = args.Write(oprot); err != nil {" << endl;
indent_up();
f_service_ <<
indent() << "return" << endl;
@@ -1723,7 +1837,6 @@
"err error) {" << endl;
indent_up();
// TODO(mcslee): Validate message reply here, seq ids etc.
- string result(tmp("result"));
string error(tmp("error"));
string error2(tmp("error"));
f_service_ <<
@@ -1753,8 +1866,8 @@
indent() << " err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, \"" << (*f_iter)->get_name() << " failed: out of sequence response\")" << endl <<
indent() << " return" << endl <<
indent() << "}" << endl <<
- indent() << result << " := New" << resultname << "()" << endl <<
- indent() << "if err = " << result << ".Read(iprot); err != nil {" << endl <<
+ indent() << "result := " << resultname << "{}" << endl <<
+ indent() << "if err = result.Read(iprot); err != nil {" << endl <<
indent() << " return" << endl <<
indent() << "}" << endl <<
indent() << "if err = iprot.ReadMessageEnd(); err != nil {" << endl <<
@@ -1770,8 +1883,8 @@
const std::string pubname = publicize(varname);
f_service_ <<
- indent() << "if " << result << "." << pubname << " != nil {" << endl <<
- indent() << "err = " << result << "." << pubname << endl <<
+ indent() << "if result." << pubname << " != nil {" << endl <<
+ indent() << "err = result." << pubname << endl <<
indent() << "return " << endl <<
indent() << "}";
@@ -1785,7 +1898,7 @@
// Careful, only return _result if not a void function
if (!(*f_iter)->get_returntype()->is_void()) {
f_service_ <<
- indent() << "value = " << result << ".Success" << endl;
+ indent() << "value = result.GetSuccess()" << endl;
}
f_service_ <<
@@ -2344,7 +2457,7 @@
indent() << "func (p *" << processorName << ") Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {" << endl;
indent_up();
f_service_ <<
- indent() << "args := New" << argsname << "()" << endl <<
+ indent() << "args := " << argsname << "{}" << endl <<
indent() << "if err = args.Read(iprot); err != nil {" << endl <<
indent() << " iprot.ReadMessageEnd()" << endl;
if (!tfunction->is_oneway()) {
@@ -2362,7 +2475,11 @@
if (!tfunction->is_oneway()) {
f_service_ <<
- indent() << "result := New" << resultname << "()" << endl;
+ indent() << "result := " << resultname << "{}" << endl;
+ }
+ bool need_reference = type_need_reference(tfunction->get_returntype());
+ if (need_reference && !tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+ f_service_ << "var retval " <<type_to_go_type(tfunction->get_returntype()) <<endl;
}
f_service_ <<
@@ -2371,7 +2488,11 @@
if (!tfunction->is_oneway()) {
if (!tfunction->get_returntype()->is_void()) {
- f_service_ << "result.Success, ";
+ if( need_reference) {
+ f_service_ << "retval, ";
+ } else {
+ f_service_ << "result.Success, ";
+ }
}
}
@@ -2404,7 +2525,7 @@
for (xf_iter = x_fields.begin(); xf_iter != x_fields.end(); ++xf_iter) {
f_service_ <<
- indent() << " case *" << type_name((*xf_iter)->get_type()) << ":" << endl <<
+ indent() << " case *" << type_to_go_type(((*xf_iter)->get_type())) << ":" << endl <<
indent() << "result." << publicize(variable_name_to_go_name((*xf_iter)->get_name())) << " = v" << endl;
}
@@ -2434,6 +2555,9 @@
indent() << "}" << endl;
if (!tfunction->is_oneway()) {
+ if (need_reference && !tfunction->get_returntype()->is_void()) {
+ f_service_ << "result.Success = &retval" << endl;
+ }
f_service_ <<
indent() << "if err2 = oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) <<
"\", thrift.REPLY, seqId); err2 != nil {" << endl <<
@@ -2470,7 +2594,8 @@
string prefix,
bool inclass,
bool coerceData,
- bool inkey)
+ bool inkey,
+ bool in_container_value)
{
t_type* orig_type = tfield->get_type();
t_type* type = get_true_type(orig_type);
@@ -2483,12 +2608,13 @@
if (type->is_struct() || type->is_xception()) {
generate_deserialize_struct(out,
(t_struct*)type,
+ is_pointer_field(tfield, in_container_value),
declare,
name);
} else if (type->is_container()) {
generate_deserialize_container(out,
orig_type,
- tfield->get_req() == t_field::T_OPTIONAL,
+ is_pointer_field(tfield),
declare,
name);
} else if (type->is_base_type() || type->is_enum()) {
@@ -2564,7 +2690,7 @@
wrap = "int8";
}
- string maybe_address = ((tfield->get_req() == t_field::T_OPTIONAL) ? "&" : "");
+ string maybe_address = (is_pointer_field(tfield) ? "&" : "");
if (wrap == "") {
indent(out) << name << " = " << maybe_address << "v" << endl;
} else {
@@ -2583,17 +2709,15 @@
*/
void t_go_generator::generate_deserialize_struct(ofstream &out,
t_struct* tstruct,
+ bool pointer_field,
bool declare,
string prefix)
{
- string eq(" := ");
+ string eq(declare ? " := " : " = ");
- if (!declare) {
- eq = " = ";
- }
-
+ out << indent() << prefix << eq <<(pointer_field?"&":"");
+ generate_go_struct_initializer(out, tstruct);
out <<
- indent() << prefix << eq << new_prefix(type_name(tstruct)) << "()" << endl <<
indent() << "if err := " << prefix << ".Read(iprot); err != nil {" << endl <<
indent() << " return fmt.Errorf(\"%T error reading struct: %s\", " << prefix << ", err)" << endl <<
indent() << "}" << endl;
@@ -2605,7 +2729,7 @@
*/
void t_go_generator::generate_deserialize_container(ofstream &out,
t_type* orig_type,
- bool optional_field,
+ bool pointer_field,
bool declare,
string prefix)
{
@@ -2624,7 +2748,7 @@
indent() << " return fmt.Errorf(\"error reading map begin: %s\", err)" << endl <<
indent() << "}" << endl <<
indent() << "tMap := make(" << type_to_go_type(orig_type) << ", size)" << endl <<
- indent() << prefix << eq << " " << (optional_field ? "&" : "") << "tMap" << endl;
+ indent() << prefix << eq << " " << (pointer_field ? "&" : "") << "tMap" << endl;
} else if (ttype->is_set()) {
t_set* t = (t_set*)ttype;
out <<
@@ -2633,7 +2757,7 @@
indent() << " return fmt.Errorf(\"error reading set begin: %s\", err)" << endl <<
indent() << "}" << endl <<
indent() << "tSet := make(map[" << type_to_go_key_type(t->get_elem_type()) << "]bool, size)" << endl <<
- indent() << prefix << eq << " " << (optional_field ? "&" : "") << "tSet" << endl;
+ indent() << prefix << eq << " " << (pointer_field ? "&" : "") << "tSet" << endl;
} else if (ttype->is_list()) {
out <<
indent() << "_, size, err := iprot.ReadListBegin()" << endl <<
@@ -2641,7 +2765,7 @@
indent() << " return fmt.Errorf(\"error reading list begin: %s\", err)" << endl <<
indent() << "}" << endl <<
indent() << "tSlice := make(" << type_to_go_type(orig_type) << ", 0, size)" << endl <<
- indent() << prefix << eq << " " << (optional_field ? "&" : "") << "tSlice" << endl;
+ indent() << prefix << eq << " " << (pointer_field ? "&" : "") << "tSlice" << endl;
} else {
throw "INVALID TYPE IN generate_deserialize_container '" + ttype->get_name() + "' for prefix '" + prefix + "'";
}
@@ -2651,7 +2775,7 @@
indent() << "for i := 0; i < size; i ++ {" << endl;
indent_up();
- if (optional_field) {
+ if (pointer_field) {
prefix = "(*" + prefix + ")";
}
if (ttype->is_map()) {
@@ -2701,7 +2825,7 @@
fkey.set_req(t_field::T_OPT_IN_REQ_OUT);
fval.set_req(t_field::T_OPT_IN_REQ_OUT);
generate_deserialize_field(out, &fkey, true, "", false, false, true);
- generate_deserialize_field(out, &fval, true);
+ generate_deserialize_field(out, &fval, true, "", false, false, false, true);
indent(out) <<
prefix << "[" << key << "] = " << val << endl;
@@ -2734,7 +2858,7 @@
string elem = tmp("_elem");
t_field felem(((t_list*)tlist)->get_elem_type(), elem);
felem.set_req(t_field::T_OPT_IN_REQ_OUT);
- generate_deserialize_field(out, &felem, true, "");
+ generate_deserialize_field(out, &felem, true, "", false, false, false, true);
indent(out) <<
prefix << " = append(" << prefix << ", " << elem << ")" << endl;
}
@@ -2766,13 +2890,13 @@
} else if (type->is_container()) {
generate_serialize_container(out,
type,
- tfield->get_req() == t_field::T_OPTIONAL,
+ is_pointer_field(tfield),
name);
} else if (type->is_base_type() || type->is_enum()) {
indent(out) <<
"if err := oprot.";
- if (tfield->get_req() == t_field::T_OPTIONAL) {
+ if (is_pointer_field(tfield)) {
name = "*" + name;
}
@@ -2851,10 +2975,10 @@
void t_go_generator::generate_serialize_container(ofstream &out,
t_type* ttype,
- bool optional_field,
+ bool pointer_field,
string prefix)
{
- if (optional_field) {
+ if (pointer_field) {
prefix = "*" + prefix;
}
if (ttype->is_map()) {
@@ -3264,17 +3388,17 @@
/**
* Converts the parse type to a go type
*/
-string t_go_generator::type_to_go_type(t_type* type) {
- return type_to_go_type_with_opt(type, false);
+string t_go_generator::type_to_go_type(t_type* type, bool is_container_value) {
+ return type_to_go_type_with_opt(type, false, is_container_value);
}
/**
* Converts the parse type to a go type, taking into account whether the field
* associated with the type is T_OPTIONAL.
*/
-string t_go_generator::type_to_go_type_with_opt(t_type* type, bool optional_field)
+string t_go_generator::type_to_go_type_with_opt(t_type* type, bool optional_field, bool is_container_value)
{
- string maybe_pointer = (optional_field ? "*" : "");
+ string maybe_pointer(optional_field ? "*" : "");
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
@@ -3310,13 +3434,14 @@
} else if (type->is_enum()) {
return maybe_pointer + publicize(type_name(type));
} else if (type->is_struct() || type->is_xception()) {
- // Note that we always have a pointer type for the is_struct() or
- // is_xception() cases, regardless of optional_field.
- return string("*") + publicize(type_name(type));
+ if (is_container_value) {
+ maybe_pointer = "*";
+ }
+ return maybe_pointer + publicize(type_name(type));
} else if (type->is_map()) {
t_map* t = (t_map*)type;
string keyType = type_to_go_key_type(t->get_key_type());
- string valueType = type_to_go_type(t->get_val_type());
+ string valueType = type_to_go_type(t->get_val_type(), true);
return maybe_pointer + string("map[") + keyType + "]" + valueType;
} else if (type->is_set()) {
t_set* t = (t_set*)type;
@@ -3324,7 +3449,7 @@
return maybe_pointer + string("map[") + elemType + string("]bool");
} else if (type->is_list()) {
t_list* t = (t_list*)type;
- string elemType = type_to_go_type(t->get_elem_type());
+ string elemType = type_to_go_type(t->get_elem_type(), true);
return maybe_pointer + string("[]") + elemType;
} else if (type->is_typedef()) {
return maybe_pointer + publicize(type_name(type));
@@ -3333,49 +3458,6 @@
throw "INVALID TYPE IN type_to_go_type: " + type->get_name();
}
-
-/**
- * Converts the parse type to a go tyoe
- */
-bool t_go_generator::can_be_nil(t_type* type)
-{
- type = get_true_type(type);
-
- if (type->is_base_type()) {
- t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-
- switch (tbase) {
- case t_base_type::TYPE_VOID:
- throw "Invalid Type for can_be_nil";
-
- case t_base_type::TYPE_BOOL:
- case t_base_type::TYPE_BYTE:
- case t_base_type::TYPE_I16:
- case t_base_type::TYPE_I32:
- case t_base_type::TYPE_I64:
- case t_base_type::TYPE_DOUBLE:
- return false;
-
- case t_base_type::TYPE_STRING:
- return (((t_base_type*)type)->is_binary());
- }
- } else if (type->is_enum()) {
- return false;
- } else if (type->is_struct() || type->is_xception()) {
- return true;
- } else if (type->is_map()) {
- return true;
- } else if (type->is_set()) {
- return true;
- } else if (type->is_list()) {
- return true;
- }
-
- throw "INVALID TYPE IN can_be_nil: " + type->get_name();
-}
-
-
-
/** See the comment inside generate_go_struct_definition for what this is. */
string t_go_generator::type_to_spec_args(t_type* ttype)
{
@@ -3424,4 +3506,5 @@
THRIFT_REGISTER_GENERATOR(go, "Go",
" package_prefix= Package prefix for generated files.\n" \
- " thrift_import= Override thrift package import path (default:" + default_thrift_import + ")\n")
+ " thrift_import= Override thrift package import path (default:" + default_thrift_import + ")\n" \
+ " package= Package name (default: inferred from thrift file name)\n")
diff --git a/lib/go/test/Makefile.am b/lib/go/test/Makefile.am
index ca8fa64..5499fb7 100644
--- a/lib/go/test/Makefile.am
+++ b/lib/go/test/Makefile.am
@@ -25,19 +25,33 @@
IncludesTest.thrift \
NamespacedTest.thrift \
MultiplexedProtocolTest.thrift \
- OnewayTest.thrift
+ OnewayTest.thrift \
+ OptionalFieldsTest.thrift \
+ ServicesTest.thrift \
+ TypedefFieldTest.thrift \
+ RefAnnotationFieldsTest.thrift
mkdir -p gopath/src
- grep -v list.*map.*list.*map $(THRIFTTEST) > ThriftTest.thrift
+ grep -v list.*map.*list.*map $(THRIFTTEST) | grep -v 'set<Insanity>' > ThriftTest.thrift
$(THRIFT) -r IncludesTest.thrift
$(THRIFT) BinaryKeyTest.thrift
$(THRIFT) MultiplexedProtocolTest.thrift
$(THRIFT) OnewayTest.thrift
+ $(THRIFT) OptionalFieldsTest.thrift
+ $(THRIFT) ServicesTest.thrift
+ $(THRIFT) TypedefFieldTest.thrift
+ $(THRIFT) RefAnnotationFieldsTest.thrift
+ GOPATH=`pwd`/gopath $(GO) get code.google.com/p/gomock/gomock
ln -nfs ../../../thrift gopath/src/thrift
ln -nfs ../../tests gopath/src/tests
touch gopath
check: gopath
- GOPATH=`pwd`/gopath $(GO) build IncludesTest BinaryKeyTest
+ GOPATH=`pwd`/gopath $(GO) build \
+ IncludesTest \
+ BinaryKeyTest \
+ ServicesTest \
+ TypedefFieldTest \
+ RefAnnotationFieldsTest
GOPATH=`pwd`/gopath $(GO) test thrift tests
clean-local:
diff --git a/lib/go/test/OptionalFieldsTest.thrift b/lib/go/test/OptionalFieldsTest.thrift
new file mode 100644
index 0000000..25b0ef6
--- /dev/null
+++ b/lib/go/test/OptionalFieldsTest.thrift
@@ -0,0 +1,43 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+struct structA {
+ 1: required i64 sa_i
+}
+
+struct all_optional {
+ 1: optional string s = "DEFAULT",
+ 2: optional i64 i = 42,
+ 3: optional bool b = false,
+ 4: optional string s2,
+ 5: optional i64 i2,
+ 6: optional bool b2,
+ 7: optional structA aa,
+ 9: optional list<i64> l,
+ 10: optional list<i64> l2 = [1, 2],
+ 11: optional map<i64, i64> m,
+ 12: optional map<i64, i64> m2 = {1:2, 3:4},
+ 13: optional binary bin,
+ 14: optional binary bin2 = "asdf",
+}
+
+struct structB {
+ 1: required structA required_struct_thing
+ 2: optional structA optional_struct_thing
+}
diff --git a/lib/go/test/RefAnnotationFieldsTest.thrift b/lib/go/test/RefAnnotationFieldsTest.thrift
new file mode 100644
index 0000000..b7f28c2
--- /dev/null
+++ b/lib/go/test/RefAnnotationFieldsTest.thrift
@@ -0,0 +1,58 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+struct structA {
+ 1: required i64 sa_i
+}
+
+struct all_referenced {
+ 1: optional string s = "DEFAULT" (cpp.ref = ""),
+ 2: optional i64 i = 42 (cpp.ref = ""),
+ 3: optional bool b = false (cpp.ref = ""),
+ 4: optional string s2 (cpp.ref = ""),
+ 5: optional i64 i2 (cpp.ref = ""),
+ 6: optional bool b2 (cpp.ref = ""),
+ 7: optional structA aa (cpp.ref = ""),
+ 9: optional list<i64> l (cpp.ref = ""),
+ 10: optional list<i64> l2 = [1, 2] (cpp.ref = ""),
+ 11: optional map<i64, i64> m (cpp.ref = ""),
+ 12: optional map<i64, i64> m2 = {1:2, 3:4} (cpp.ref = ""),
+ 13: optional binary bin (cpp.ref = ""),
+ 14: optional binary bin2 = "asdf" (cpp.ref = ""),
+
+ 15: required string ref_s = "DEFAULT" (cpp.ref = ""),
+ 16: required i64 ref_i = 42 (cpp.ref = ""),
+ 17: required bool ref_b = false (cpp.ref = ""),
+ 18: required string ref_s2 (cpp.ref = ""),
+ 19: required i64 ref_i2 (cpp.ref = ""),
+ 20: required bool ref_b2 (cpp.ref = ""),
+ 21: required structA ref_aa (cpp.ref = ""),
+ 22: required list<i64> ref_l (cpp.ref = ""),
+ 23: required list<i64> ref_l2 = [1, 2] (cpp.ref = ""),
+ 24: required map<i64, i64> ref_m (cpp.ref = ""),
+ 25: required map<i64, i64> ref_m2 = {1:2, 3:4} (cpp.ref = ""),
+ 26: required binary ref_bin (cpp.ref = ""),
+ 27: required binary ref_bin2 = "asdf" (cpp.ref = ""),
+
+}
+
+struct structB {
+ 1: required structA required_struct_thing
+ 2: optional structA optional_struct_thing
+}
diff --git a/lib/go/test/ServicesTest.thrift b/lib/go/test/ServicesTest.thrift
new file mode 100644
index 0000000..1b8be36
--- /dev/null
+++ b/lib/go/test/ServicesTest.thrift
@@ -0,0 +1,109 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# We are only testing that generated code compiles, no correctness checking is done
+
+exception moderate_disaster {
+ 1: i32 errorCode,
+ 2: string message
+}
+
+exception total_disaster {
+ 1: string message
+ 2: optional bool president_was_woken_up = false
+}
+
+struct struct_a {
+ 1: required i64 whatever
+}
+
+service a_serv {
+ void voidfunc(),
+ void void_with_1ex() throws(1: moderate_disaster err1)
+ void void_with_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ string stringfunc()
+ string stringfunc_1ex() throws(1: moderate_disaster err1)
+ string stringfunc_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ i64 i64func()
+ i64 i64func_1ex() throws(1: moderate_disaster err1)
+ i64 i64func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ list<string> list_of_strings_func()
+ list<string> list_of_strings_func_1ex() throws(1: moderate_disaster err1)
+ list<string> list_of_strings_func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ map<i64,string> map_func()
+ map<i64,string> map_func_1ex() throws(1: moderate_disaster err1)
+ map<i64,string> map_func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ struct_a struct_a_func()
+ struct_a struct_a_func_1ex() throws(1: moderate_disaster err1)
+ struct_a struct_a_func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ void voidfunc_1int(1: i64 i),
+ void void_with_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+ void void_with_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ string stringfunc_1int(1: i64 i)
+ string stringfunc_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+ string stringfunc_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ i64 i64func_1int(1: i64 i)
+ i64 i64func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+ i64 i64func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ list<string> list_of_strings_func_1int(1: i64 i)
+ list<string> list_of_strings_func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+ list<string> list_of_strings_func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ map<i64,string> map_func_1int(1: i64 i)
+ map<i64,string> map_func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+ map<i64,string> map_func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ struct_a struct_a_func_1int(1: i64 i)
+ struct_a struct_a_func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+ struct_a struct_a_func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ void voidfunc_1int_1s(1: i64 i, 2: string s),
+ void void_with_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+ void void_with_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ string stringfunc_1int_1s(1: i64 i, 2: string s)
+ string stringfunc_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+ string stringfunc_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ i64 i64func_1int_1s(1: i64 i, 2: string s)
+ i64 i64func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+ i64 i64func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ list<string> list_of_strings_func_1int_1s(1: i64 i, 2: string s)
+ list<string> list_of_strings_func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+ list<string> list_of_strings_func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ map<i64,string> map_func_1int_1s(1: i64 i, 2: string s)
+ map<i64,string> map_func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+ map<i64,string> map_func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+ struct_a struct_a_func_1int_1s(1: i64 i, 2: string s)
+ struct_a struct_a_func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+ struct_a struct_a_func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+}
diff --git a/lib/go/test/TypedefFieldTest.thrift b/lib/go/test/TypedefFieldTest.thrift
new file mode 100644
index 0000000..390e8c8
--- /dev/null
+++ b/lib/go/test/TypedefFieldTest.thrift
@@ -0,0 +1,39 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# We are only testing that generated code compiles, no correctness checking is done
+
+enum Details {
+ Everything = 0
+ StateOnly = 1
+ StateAndOptions = 2
+ SomethingElse = 3
+}
+
+typedef list< Details> DetailsWanted
+
+struct BaseRequest {
+ 1 : optional string RequestID
+}
+
+struct GetMyDetails {
+ 1 : required BaseRequest base_
+ 2 : required string ObjectID
+ 3 : optional DetailsWanted DetailsWanted
+}
diff --git a/lib/go/test/tests/optional_fields_test.go b/lib/go/test/tests/optional_fields_test.go
new file mode 100644
index 0000000..4b0797c
--- /dev/null
+++ b/lib/go/test/tests/optional_fields_test.go
@@ -0,0 +1,280 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package tests
+
+import (
+ "OptionalFieldsTest"
+ "bytes"
+ gomock "code.google.com/p/gomock/gomock"
+ "testing"
+ "thrift"
+)
+
+func TestIsSetReturnFalseOnCreation(t *testing.T) {
+ ao := OptionalFieldsTest.NewAllOptional()
+ if ao.IsSetS() {
+ t.Errorf("Optional field S is set on initialization")
+ }
+ if ao.IsSetI() {
+ t.Errorf("Optional field I is set on initialization")
+ }
+ if ao.IsSetB() {
+ t.Errorf("Optional field B is set on initialization")
+ }
+ if ao.IsSetS2() {
+ t.Errorf("Optional field S2 is set on initialization")
+ }
+ if ao.IsSetI2() {
+ t.Errorf("Optional field I2 is set on initialization")
+ }
+ if ao.IsSetB2() {
+ t.Errorf("Optional field B2 is set on initialization")
+ }
+ if ao.IsSetAa() {
+ t.Errorf("Optional field Aa is set on initialization")
+ }
+ if ao.IsSetL() {
+ t.Errorf("Optional field L is set on initialization")
+ }
+ if ao.IsSetL2() {
+ t.Errorf("Optional field L2 is set on initialization")
+ }
+ if ao.IsSetM() {
+ t.Errorf("Optional field M is set on initialization")
+ }
+ if ao.IsSetM2() {
+ t.Errorf("Optional field M2 is set on initialization")
+ }
+ if ao.IsSetBin() {
+ t.Errorf("Optional field Bin is set on initialization")
+ }
+ if ao.IsSetBin2() {
+ t.Errorf("Optional field Bin2 is set on initialization")
+ }
+}
+
+func TestDefaultValuesOnCreation(t *testing.T) {
+ ao := OptionalFieldsTest.NewAllOptional()
+ if ao.GetS() != "DEFAULT" {
+ t.Errorf("Unexpected default value %#v for field S", ao.GetS())
+ }
+ if ao.GetI() != 42 {
+ t.Errorf("Unexpected default value %#v for field I", ao.GetI())
+ }
+ if ao.GetB() != false {
+ t.Errorf("Unexpected default value %#v for field B", ao.GetB())
+ }
+ if ao.GetS2() != "" {
+ t.Errorf("Unexpected default value %#v for field S2", ao.GetS2())
+ }
+ if ao.GetI2() != 0 {
+ t.Errorf("Unexpected default value %#v for field I2", ao.GetI2())
+ }
+ if ao.GetB2() != false {
+ t.Errorf("Unexpected default value %#v for field B2", ao.GetB2())
+ }
+ if l := ao.GetL(); len(l) != 0 {
+ t.Errorf("Unexpected default value %#v for field L", l)
+ }
+ if l := ao.GetL2(); len(l) != 2 || l[0] != 1 || l[1] != 2 {
+ t.Errorf("Unexpected default value %#v for field L2", l)
+ }
+ //FIXME: should we return empty map here?
+ if m := ao.GetM(); m != nil {
+ t.Errorf("Unexpected default value %#v for field M", m)
+ }
+ if m := ao.GetM2(); len(m) != 2 || m[1] != 2 || m[3] != 4 {
+ t.Errorf("Unexpected default value %#v for field M2", m)
+ }
+ if bv := ao.GetBin(); bv != nil {
+ t.Errorf("Unexpected default value %#v for field Bin", bv)
+ }
+ if bv := ao.GetBin2(); !bytes.Equal(bv, []byte("asdf")) {
+ t.Errorf("Unexpected default value %#v for field Bin2", bv)
+ }
+}
+
+func TestInitialValuesOnCreation(t *testing.T) {
+ ao := OptionalFieldsTest.NewAllOptional()
+ if ao.S != "DEFAULT" {
+ t.Errorf("Unexpected initial value %#v for field S", ao.S)
+ }
+ if ao.I != 42 {
+ t.Errorf("Unexpected initial value %#v for field I", ao.I)
+ }
+ if ao.B != false {
+ t.Errorf("Unexpected initial value %#v for field B", ao.B)
+ }
+ if ao.S2 != nil {
+ t.Errorf("Unexpected initial value %#v for field S2", ao.S2)
+ }
+ if ao.I2 != nil {
+ t.Errorf("Unexpected initial value %#v for field I2", ao.I2)
+ }
+ if ao.B2 != nil {
+ t.Errorf("Unexpected initial value %#v for field B2", ao.B2)
+ }
+ if ao.L != nil || len(ao.L) != 0 {
+ t.Errorf("Unexpected initial value %#v for field L", ao.L)
+ }
+ if ao.L2 != nil {
+ t.Errorf("Unexpected initial value %#v for field L2", ao.L2)
+ }
+ if ao.M != nil {
+ t.Errorf("Unexpected initial value %#v for field M", ao.M)
+ }
+ if ao.M2 != nil {
+ t.Errorf("Unexpected initial value %#v for field M2", ao.M2)
+ }
+ if ao.Bin != nil || len(ao.Bin) != 0 {
+ t.Errorf("Unexpected initial value %#v for field Bin", ao.Bin)
+ }
+ if !bytes.Equal(ao.Bin2, []byte("asdf")) {
+ t.Errorf("Unexpected initial value %#v for field Bin2", ao.Bin2)
+ }
+}
+
+func TestIsSetReturnTrueAfterUpdate(t *testing.T) {
+ ao := OptionalFieldsTest.NewAllOptional()
+ ao.S = "somevalue"
+ ao.I = 123
+ ao.B = true
+ ao.Aa = OptionalFieldsTest.NewStructA()
+ if !ao.IsSetS() {
+ t.Errorf("Field S should be set")
+ }
+ if !ao.IsSetI() {
+ t.Errorf("Field I should be set")
+ }
+ if !ao.IsSetB() {
+ t.Errorf("Field B should be set")
+ }
+ if !ao.IsSetAa() {
+ t.Errorf("Field aa should be set")
+ }
+}
+
+func TestListNotEmpty(t *testing.T) {
+ ao := OptionalFieldsTest.NewAllOptional()
+ ao.L = []int64{1, 2, 3}
+ if !ao.IsSetL() {
+ t.Errorf("Field L should be set")
+ }
+}
+
+//Make sure that optional fields are not being serialized
+func TestNoOptionalUnsetFieldsOnWire(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ proto := NewMockTProtocol(mockCtrl)
+ gomock.InOrder(
+ proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+ proto.EXPECT().WriteFieldStop().Return(nil),
+ proto.EXPECT().WriteStructEnd().Return(nil),
+ )
+ ao := OptionalFieldsTest.NewAllOptional()
+ ao.Write(proto)
+}
+
+func TestNoSetToDefaultFieldsOnWire(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ proto := NewMockTProtocol(mockCtrl)
+ gomock.InOrder(
+ proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+ proto.EXPECT().WriteFieldStop().Return(nil),
+ proto.EXPECT().WriteStructEnd().Return(nil),
+ )
+ ao := OptionalFieldsTest.NewAllOptional()
+ ao.I = 42
+ ao.Write(proto)
+}
+
+//Make sure that only one field is being serialized when set to non-default
+func TestOneISetFieldOnWire(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ proto := NewMockTProtocol(mockCtrl)
+ gomock.InOrder(
+ proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+ proto.EXPECT().WriteFieldBegin("i", thrift.TType(thrift.I64), int16(2)).Return(nil),
+ proto.EXPECT().WriteI64(int64(123)).Return(nil),
+ proto.EXPECT().WriteFieldEnd().Return(nil),
+ proto.EXPECT().WriteFieldStop().Return(nil),
+ proto.EXPECT().WriteStructEnd().Return(nil),
+ )
+ ao := OptionalFieldsTest.NewAllOptional()
+ ao.I = 123
+ ao.Write(proto)
+}
+
+func TestOneLSetFieldOnWire(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ proto := NewMockTProtocol(mockCtrl)
+ gomock.InOrder(
+ proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+ proto.EXPECT().WriteFieldBegin("l", thrift.TType(thrift.LIST), int16(9)).Return(nil),
+ proto.EXPECT().WriteListBegin(thrift.TType(thrift.I64), 2).Return(nil),
+ proto.EXPECT().WriteI64(int64(1)).Return(nil),
+ proto.EXPECT().WriteI64(int64(2)).Return(nil),
+ proto.EXPECT().WriteListEnd().Return(nil),
+ proto.EXPECT().WriteFieldEnd().Return(nil),
+ proto.EXPECT().WriteFieldStop().Return(nil),
+ proto.EXPECT().WriteStructEnd().Return(nil),
+ )
+ ao := OptionalFieldsTest.NewAllOptional()
+ ao.L = []int64{1, 2}
+ ao.Write(proto)
+}
+
+func TestOneBinSetFieldOnWire(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ proto := NewMockTProtocol(mockCtrl)
+ gomock.InOrder(
+ proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+ proto.EXPECT().WriteFieldBegin("bin", thrift.TType(thrift.STRING), int16(13)).Return(nil),
+ proto.EXPECT().WriteBinary([]byte("somebytestring")).Return(nil),
+ proto.EXPECT().WriteFieldEnd().Return(nil),
+ proto.EXPECT().WriteFieldStop().Return(nil),
+ proto.EXPECT().WriteStructEnd().Return(nil),
+ )
+ ao := OptionalFieldsTest.NewAllOptional()
+ ao.Bin = []byte("somebytestring")
+ ao.Write(proto)
+}
+
+func TestOneEmptyBinSetFieldOnWire(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ proto := NewMockTProtocol(mockCtrl)
+ gomock.InOrder(
+ proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+ proto.EXPECT().WriteFieldBegin("bin", thrift.TType(thrift.STRING), int16(13)).Return(nil),
+ proto.EXPECT().WriteBinary([]byte{}).Return(nil),
+ proto.EXPECT().WriteFieldEnd().Return(nil),
+ proto.EXPECT().WriteFieldStop().Return(nil),
+ proto.EXPECT().WriteStructEnd().Return(nil),
+ )
+ ao := OptionalFieldsTest.NewAllOptional()
+ ao.Bin = []byte{}
+ ao.Write(proto)
+}
diff --git a/lib/go/test/tests/protocol_mock.go b/lib/go/test/tests/protocol_mock.go
new file mode 100644
index 0000000..d3f4078
--- /dev/null
+++ b/lib/go/test/tests/protocol_mock.go
@@ -0,0 +1,511 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// Automatically generated by MockGen. DO NOT EDIT!
+// Source: thrift (interfaces: TProtocol)
+
+package tests
+
+import (
+ thrift "thrift"
+ gomock "code.google.com/p/gomock/gomock"
+)
+
+// Mock of TProtocol interface
+type MockTProtocol struct {
+ ctrl *gomock.Controller
+ recorder *_MockTProtocolRecorder
+}
+
+// Recorder for MockTProtocol (not exported)
+type _MockTProtocolRecorder struct {
+ mock *MockTProtocol
+}
+
+func NewMockTProtocol(ctrl *gomock.Controller) *MockTProtocol {
+ mock := &MockTProtocol{ctrl: ctrl}
+ mock.recorder = &_MockTProtocolRecorder{mock}
+ return mock
+}
+
+func (_m *MockTProtocol) EXPECT() *_MockTProtocolRecorder {
+ return _m.recorder
+}
+
+func (_m *MockTProtocol) Flush() error {
+ ret := _m.ctrl.Call(_m, "Flush")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) Flush() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "Flush")
+}
+
+func (_m *MockTProtocol) ReadBinary() ([]byte, error) {
+ ret := _m.ctrl.Call(_m, "ReadBinary")
+ ret0, _ := ret[0].([]byte)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadBinary() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadBinary")
+}
+
+func (_m *MockTProtocol) ReadBool() (bool, error) {
+ ret := _m.ctrl.Call(_m, "ReadBool")
+ ret0, _ := ret[0].(bool)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadBool() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadBool")
+}
+
+func (_m *MockTProtocol) ReadByte() (byte, error) {
+ ret := _m.ctrl.Call(_m, "ReadByte")
+ ret0, _ := ret[0].(byte)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadByte() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadByte")
+}
+
+func (_m *MockTProtocol) ReadDouble() (float64, error) {
+ ret := _m.ctrl.Call(_m, "ReadDouble")
+ ret0, _ := ret[0].(float64)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadDouble() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadDouble")
+}
+
+func (_m *MockTProtocol) ReadFieldBegin() (string, thrift.TType, int16, error) {
+ ret := _m.ctrl.Call(_m, "ReadFieldBegin")
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(thrift.TType)
+ ret2, _ := ret[2].(int16)
+ ret3, _ := ret[3].(error)
+ return ret0, ret1, ret2, ret3
+}
+
+func (_mr *_MockTProtocolRecorder) ReadFieldBegin() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadFieldBegin")
+}
+
+func (_m *MockTProtocol) ReadFieldEnd() error {
+ ret := _m.ctrl.Call(_m, "ReadFieldEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadFieldEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadFieldEnd")
+}
+
+func (_m *MockTProtocol) ReadI16() (int16, error) {
+ ret := _m.ctrl.Call(_m, "ReadI16")
+ ret0, _ := ret[0].(int16)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadI16() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadI16")
+}
+
+func (_m *MockTProtocol) ReadI32() (int32, error) {
+ ret := _m.ctrl.Call(_m, "ReadI32")
+ ret0, _ := ret[0].(int32)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadI32() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadI32")
+}
+
+func (_m *MockTProtocol) ReadI64() (int64, error) {
+ ret := _m.ctrl.Call(_m, "ReadI64")
+ ret0, _ := ret[0].(int64)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadI64() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadI64")
+}
+
+func (_m *MockTProtocol) ReadListBegin() (thrift.TType, int, error) {
+ ret := _m.ctrl.Call(_m, "ReadListBegin")
+ ret0, _ := ret[0].(thrift.TType)
+ ret1, _ := ret[1].(int)
+ ret2, _ := ret[2].(error)
+ return ret0, ret1, ret2
+}
+
+func (_mr *_MockTProtocolRecorder) ReadListBegin() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadListBegin")
+}
+
+func (_m *MockTProtocol) ReadListEnd() error {
+ ret := _m.ctrl.Call(_m, "ReadListEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadListEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadListEnd")
+}
+
+func (_m *MockTProtocol) ReadMapBegin() (thrift.TType, thrift.TType, int, error) {
+ ret := _m.ctrl.Call(_m, "ReadMapBegin")
+ ret0, _ := ret[0].(thrift.TType)
+ ret1, _ := ret[1].(thrift.TType)
+ ret2, _ := ret[2].(int)
+ ret3, _ := ret[3].(error)
+ return ret0, ret1, ret2, ret3
+}
+
+func (_mr *_MockTProtocolRecorder) ReadMapBegin() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadMapBegin")
+}
+
+func (_m *MockTProtocol) ReadMapEnd() error {
+ ret := _m.ctrl.Call(_m, "ReadMapEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadMapEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadMapEnd")
+}
+
+func (_m *MockTProtocol) ReadMessageBegin() (string, thrift.TMessageType, int32, error) {
+ ret := _m.ctrl.Call(_m, "ReadMessageBegin")
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(thrift.TMessageType)
+ ret2, _ := ret[2].(int32)
+ ret3, _ := ret[3].(error)
+ return ret0, ret1, ret2, ret3
+}
+
+func (_mr *_MockTProtocolRecorder) ReadMessageBegin() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadMessageBegin")
+}
+
+func (_m *MockTProtocol) ReadMessageEnd() error {
+ ret := _m.ctrl.Call(_m, "ReadMessageEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadMessageEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadMessageEnd")
+}
+
+func (_m *MockTProtocol) ReadSetBegin() (thrift.TType, int, error) {
+ ret := _m.ctrl.Call(_m, "ReadSetBegin")
+ ret0, _ := ret[0].(thrift.TType)
+ ret1, _ := ret[1].(int)
+ ret2, _ := ret[2].(error)
+ return ret0, ret1, ret2
+}
+
+func (_mr *_MockTProtocolRecorder) ReadSetBegin() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadSetBegin")
+}
+
+func (_m *MockTProtocol) ReadSetEnd() error {
+ ret := _m.ctrl.Call(_m, "ReadSetEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadSetEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadSetEnd")
+}
+
+func (_m *MockTProtocol) ReadString() (string, error) {
+ ret := _m.ctrl.Call(_m, "ReadString")
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadString() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadString")
+}
+
+func (_m *MockTProtocol) ReadStructBegin() (string, error) {
+ ret := _m.ctrl.Call(_m, "ReadStructBegin")
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadStructBegin() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadStructBegin")
+}
+
+func (_m *MockTProtocol) ReadStructEnd() error {
+ ret := _m.ctrl.Call(_m, "ReadStructEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadStructEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadStructEnd")
+}
+
+func (_m *MockTProtocol) Skip(_param0 thrift.TType) error {
+ ret := _m.ctrl.Call(_m, "Skip", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) Skip(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "Skip", arg0)
+}
+
+func (_m *MockTProtocol) Transport() thrift.TTransport {
+ ret := _m.ctrl.Call(_m, "Transport")
+ ret0, _ := ret[0].(thrift.TTransport)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) Transport() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "Transport")
+}
+
+func (_m *MockTProtocol) WriteBinary(_param0 []byte) error {
+ ret := _m.ctrl.Call(_m, "WriteBinary", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteBinary(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteBinary", arg0)
+}
+
+func (_m *MockTProtocol) WriteBool(_param0 bool) error {
+ ret := _m.ctrl.Call(_m, "WriteBool", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteBool(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteBool", arg0)
+}
+
+func (_m *MockTProtocol) WriteByte(_param0 byte) error {
+ ret := _m.ctrl.Call(_m, "WriteByte", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteByte(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteByte", arg0)
+}
+
+func (_m *MockTProtocol) WriteDouble(_param0 float64) error {
+ ret := _m.ctrl.Call(_m, "WriteDouble", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteDouble(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteDouble", arg0)
+}
+
+func (_m *MockTProtocol) WriteFieldBegin(_param0 string, _param1 thrift.TType, _param2 int16) error {
+ ret := _m.ctrl.Call(_m, "WriteFieldBegin", _param0, _param1, _param2)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteFieldBegin(arg0, arg1, arg2 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteFieldBegin", arg0, arg1, arg2)
+}
+
+func (_m *MockTProtocol) WriteFieldEnd() error {
+ ret := _m.ctrl.Call(_m, "WriteFieldEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteFieldEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteFieldEnd")
+}
+
+func (_m *MockTProtocol) WriteFieldStop() error {
+ ret := _m.ctrl.Call(_m, "WriteFieldStop")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteFieldStop() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteFieldStop")
+}
+
+func (_m *MockTProtocol) WriteI16(_param0 int16) error {
+ ret := _m.ctrl.Call(_m, "WriteI16", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteI16(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteI16", arg0)
+}
+
+func (_m *MockTProtocol) WriteI32(_param0 int32) error {
+ ret := _m.ctrl.Call(_m, "WriteI32", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteI32(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteI32", arg0)
+}
+
+func (_m *MockTProtocol) WriteI64(_param0 int64) error {
+ ret := _m.ctrl.Call(_m, "WriteI64", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteI64(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteI64", arg0)
+}
+
+func (_m *MockTProtocol) WriteListBegin(_param0 thrift.TType, _param1 int) error {
+ ret := _m.ctrl.Call(_m, "WriteListBegin", _param0, _param1)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteListBegin(arg0, arg1 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteListBegin", arg0, arg1)
+}
+
+func (_m *MockTProtocol) WriteListEnd() error {
+ ret := _m.ctrl.Call(_m, "WriteListEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteListEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteListEnd")
+}
+
+func (_m *MockTProtocol) WriteMapBegin(_param0 thrift.TType, _param1 thrift.TType, _param2 int) error {
+ ret := _m.ctrl.Call(_m, "WriteMapBegin", _param0, _param1, _param2)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteMapBegin(arg0, arg1, arg2 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteMapBegin", arg0, arg1, arg2)
+}
+
+func (_m *MockTProtocol) WriteMapEnd() error {
+ ret := _m.ctrl.Call(_m, "WriteMapEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteMapEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteMapEnd")
+}
+
+func (_m *MockTProtocol) WriteMessageBegin(_param0 string, _param1 thrift.TMessageType, _param2 int32) error {
+ ret := _m.ctrl.Call(_m, "WriteMessageBegin", _param0, _param1, _param2)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteMessageBegin(arg0, arg1, arg2 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteMessageBegin", arg0, arg1, arg2)
+}
+
+func (_m *MockTProtocol) WriteMessageEnd() error {
+ ret := _m.ctrl.Call(_m, "WriteMessageEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteMessageEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteMessageEnd")
+}
+
+func (_m *MockTProtocol) WriteSetBegin(_param0 thrift.TType, _param1 int) error {
+ ret := _m.ctrl.Call(_m, "WriteSetBegin", _param0, _param1)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteSetBegin(arg0, arg1 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteSetBegin", arg0, arg1)
+}
+
+func (_m *MockTProtocol) WriteSetEnd() error {
+ ret := _m.ctrl.Call(_m, "WriteSetEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteSetEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteSetEnd")
+}
+
+func (_m *MockTProtocol) WriteString(_param0 string) error {
+ ret := _m.ctrl.Call(_m, "WriteString", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteString(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteString", arg0)
+}
+
+func (_m *MockTProtocol) WriteStructBegin(_param0 string) error {
+ ret := _m.ctrl.Call(_m, "WriteStructBegin", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteStructBegin(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteStructBegin", arg0)
+}
+
+func (_m *MockTProtocol) WriteStructEnd() error {
+ ret := _m.ctrl.Call(_m, "WriteStructEnd")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteStructEnd() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteStructEnd")
+}
diff --git a/lib/go/thrift/pointerize.go b/lib/go/thrift/pointerize.go
index c2ae261..8d6b2c2 100644
--- a/lib/go/thrift/pointerize.go
+++ b/lib/go/thrift/pointerize.go
@@ -46,3 +46,5 @@
func StringPtr(v string) *string { return &v }
func Uint32Ptr(v uint32) *uint32 { return &v }
func Uint64Ptr(v uint64) *uint64 { return &v }
+func BoolPtr(v bool) *bool { return &v }
+func ByteSlicePtr(v []byte) *[]byte { return &v }