From 0e87c46c18a3a62d17d7e45a5bddde989d31351c Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 18 Jun 2013 22:25:07 +0200 Subject: [PATCH] THRIFT-2012 Modernizing Go Patch: Travis Cline --- .gitignore | 9 + compiler/cpp/src/generate/t_go_generator.cc | 5384 +++++++++-------- configure.ac | 48 +- lib/Makefile.am | 5 +- lib/go/Make.deps | 159 - lib/go/Makefile | 64 - lib/go/Makefile.am | 12 + lib/go/README | 31 + lib/go/deps.bash | 41 - lib/go/thrift/Makefile | 58 - lib/go/thrift/_testmain.go | 68 - lib/go/thrift/application_exception.go | 142 + ..._test.go => application_exception_test.go} | 33 +- lib/go/thrift/binary_protocol.go | 489 ++ ...otocol_test.go => binary_protocol_test.go} | 9 +- lib/go/thrift/compact_protocol.go | 752 +++ lib/go/thrift/compact_protocol_test.go | 54 + ...tnonblocking_transport.go => exception.go} | 5 +- lib/go/thrift/field.go | 79 + lib/go/thrift/framed_transport.go | 124 + ...sport_test.go => framed_transport_test.go} | 9 +- lib/go/thrift/http_client.go | 141 + ...ttp_client_test.go => http_client_test.go} | 25 +- lib/go/thrift/iostream_transport.go | 168 + ...ontainer.go => iostream_transport_test.go} | 14 +- lib/go/thrift/json_protocol.go | 556 ++ lib/go/thrift/json_protocol_test.go | 639 ++ lib/go/thrift/memory_buffer.go | 79 + ...y_buffer_test.go => memory_buffer_test.go} | 9 +- .../{tmessagetype.go => messagetype.go} | 15 +- lib/go/thrift/numeric.go | 164 + lib/go/thrift/{tprocessor.go => processor.go} | 11 +- ...cessor_factory.go => processor_factory.go} | 24 +- lib/go/thrift/protocol.go | 154 + lib/go/thrift/protocol_exception.go | 77 + ...rotocol_factory.go => protocol_factory.go} | 7 +- lib/go/thrift/protocol_test.go | 458 ++ lib/go/thrift/server.go | 35 + lib/go/thrift/server_socket.go | 107 + .../{tserver_test.go => server_test.go} | 4 +- .../{texception.go => server_transport.go} | 46 +- lib/go/thrift/simple_json_protocol.go | 1298 ++++ lib/go/thrift/simple_json_protocol_test.go | 632 ++ lib/go/thrift/simple_server.go | 164 + lib/go/thrift/socket.go | 159 + lib/go/thrift/tapplication_exception.go | 172 - lib/go/thrift/tbase.go | 66 - lib/go/thrift/tbinary_protocol.go | 493 -- lib/go/thrift/tcompact_protocol.go | 856 --- lib/go/thrift/tcompact_protocol_test.go | 56 - lib/go/thrift/tcompare.go | 127 - lib/go/thrift/tfield.go | 281 - lib/go/thrift/tframed_transport.go | 133 - lib/go/thrift/thttp_client.go | 148 - lib/go/thrift/tiostream_transport.go | 231 - lib/go/thrift/tiostream_transport_test.go | 31 - lib/go/thrift/tjson_protocol.go | 537 -- lib/go/thrift/tjson_protocol_test.go | 674 --- lib/go/thrift/tlist.go | 222 - lib/go/thrift/tmap.go | 763 --- lib/go/thrift/tmemory_buffer.go | 127 - lib/go/thrift/tmessage.go | 70 - lib/go/thrift/tnonblocking_server.go | 178 - lib/go/thrift/tnonblocking_server_socket.go | 169 - lib/go/thrift/tnonblocking_socket.go | 192 - lib/go/thrift/tnonblocking_transport_test.go | 88 - lib/go/thrift/tnumeric.go | 165 - lib/go/thrift/tprotocol.go | 201 - lib/go/thrift/tprotocol_exception.go | 130 - lib/go/thrift/tprotocol_test.go | 1825 ------ lib/go/thrift/transport.go | 46 + lib/go/thrift/transport_exception.go | 68 + ...nsport_factory.go => transport_factory.go} | 24 +- lib/go/thrift/transport_test.go | 120 + lib/go/thrift/tserver.go | 61 - lib/go/thrift/tserver_socket.go | 194 - lib/go/thrift/tserver_transport.go | 41 - lib/go/thrift/tset.go | 207 - lib/go/thrift/tsimple_json_protocol.go | 1281 ---- lib/go/thrift/tsimple_json_protocol_test.go | 662 -- lib/go/thrift/tsimple_server.go | 166 - lib/go/thrift/tsocket.go | 203 - lib/go/thrift/tstruct.go | 93 - lib/go/thrift/ttransport.go | 182 - lib/go/thrift/ttransport_exception.go | 84 - lib/go/thrift/ttransport_test.go | 131 - lib/go/thrift/ttype.go | 975 --- lib/go/thrift/type.go | 68 + tutorial/Makefile.am | 4 + tutorial/go/Make.deps | 135 - tutorial/go/Makefile | 44 - tutorial/go/Makefile.am | 51 + tutorial/go/deps.bash | 45 - tutorial/go/src/CalculatorHandler.go | 101 - tutorial/go/src/GoClient.go | 92 - tutorial/go/src/GoServer.go | 85 - tutorial/go/src/Makefile | 22 - tutorial/go/src/client.go | 85 + tutorial/go/src/handler.go | 99 + tutorial/go/src/main.go | 102 +- .../go/src/server.go | 29 +- 101 files changed, 10026 insertions(+), 15970 deletions(-) delete mode 100644 lib/go/Make.deps delete mode 100644 lib/go/Makefile create mode 100644 lib/go/Makefile.am create mode 100644 lib/go/README delete mode 100644 lib/go/deps.bash delete mode 100644 lib/go/thrift/Makefile delete mode 100644 lib/go/thrift/_testmain.go create mode 100644 lib/go/thrift/application_exception.go rename lib/go/thrift/{tapplication_exception_test.go => application_exception_test.go} (55%) create mode 100644 lib/go/thrift/binary_protocol.go rename lib/go/thrift/{tbinary_protocol_test.go => binary_protocol_test.go} (87%) create mode 100644 lib/go/thrift/compact_protocol.go create mode 100644 lib/go/thrift/compact_protocol_test.go rename lib/go/thrift/{tnonblocking_transport.go => exception.go} (92%) create mode 100644 lib/go/thrift/field.go create mode 100644 lib/go/thrift/framed_transport.go rename lib/go/thrift/{tframed_transport_test.go => framed_transport_test.go} (86%) create mode 100644 lib/go/thrift/http_client.go rename lib/go/thrift/{thttp_client_test.go => http_client_test.go} (72%) create mode 100644 lib/go/thrift/iostream_transport.go rename lib/go/thrift/{tcontainer.go => iostream_transport_test.go} (82%) create mode 100644 lib/go/thrift/json_protocol.go create mode 100644 lib/go/thrift/json_protocol_test.go create mode 100644 lib/go/thrift/memory_buffer.go rename lib/go/thrift/{tmemory_buffer_test.go => memory_buffer_test.go} (88%) rename lib/go/thrift/{tmessagetype.go => messagetype.go} (76%) create mode 100644 lib/go/thrift/numeric.go rename lib/go/thrift/{tprocessor.go => processor.go} (80%) rename lib/go/thrift/{tprocessor_factory.go => processor_factory.go} (78%) create mode 100644 lib/go/thrift/protocol.go create mode 100644 lib/go/thrift/protocol_exception.go rename lib/go/thrift/{tprotocol_factory.go => protocol_factory.go} (88%) create mode 100644 lib/go/thrift/protocol_test.go create mode 100644 lib/go/thrift/server.go create mode 100644 lib/go/thrift/server_socket.go rename lib/go/thrift/{tserver_test.go => server_test.go} (96%) rename lib/go/thrift/{texception.go => server_transport.go} (62%) create mode 100644 lib/go/thrift/simple_json_protocol.go create mode 100644 lib/go/thrift/simple_json_protocol_test.go create mode 100644 lib/go/thrift/simple_server.go create mode 100644 lib/go/thrift/socket.go delete mode 100644 lib/go/thrift/tapplication_exception.go delete mode 100644 lib/go/thrift/tbase.go delete mode 100644 lib/go/thrift/tbinary_protocol.go delete mode 100644 lib/go/thrift/tcompact_protocol.go delete mode 100644 lib/go/thrift/tcompact_protocol_test.go delete mode 100644 lib/go/thrift/tcompare.go delete mode 100644 lib/go/thrift/tfield.go delete mode 100644 lib/go/thrift/tframed_transport.go delete mode 100644 lib/go/thrift/thttp_client.go delete mode 100644 lib/go/thrift/tiostream_transport.go delete mode 100644 lib/go/thrift/tiostream_transport_test.go delete mode 100644 lib/go/thrift/tjson_protocol.go delete mode 100644 lib/go/thrift/tjson_protocol_test.go delete mode 100644 lib/go/thrift/tlist.go delete mode 100644 lib/go/thrift/tmap.go delete mode 100644 lib/go/thrift/tmemory_buffer.go delete mode 100644 lib/go/thrift/tmessage.go delete mode 100644 lib/go/thrift/tnonblocking_server.go delete mode 100644 lib/go/thrift/tnonblocking_server_socket.go delete mode 100644 lib/go/thrift/tnonblocking_socket.go delete mode 100644 lib/go/thrift/tnonblocking_transport_test.go delete mode 100644 lib/go/thrift/tnumeric.go delete mode 100644 lib/go/thrift/tprotocol.go delete mode 100644 lib/go/thrift/tprotocol_exception.go delete mode 100644 lib/go/thrift/tprotocol_test.go create mode 100644 lib/go/thrift/transport.go create mode 100644 lib/go/thrift/transport_exception.go rename lib/go/thrift/{ttransport_factory.go => transport_factory.go} (68%) create mode 100644 lib/go/thrift/transport_test.go delete mode 100644 lib/go/thrift/tserver.go delete mode 100644 lib/go/thrift/tserver_socket.go delete mode 100644 lib/go/thrift/tserver_transport.go delete mode 100644 lib/go/thrift/tset.go delete mode 100644 lib/go/thrift/tsimple_json_protocol.go delete mode 100644 lib/go/thrift/tsimple_json_protocol_test.go delete mode 100644 lib/go/thrift/tsimple_server.go delete mode 100644 lib/go/thrift/tsocket.go delete mode 100644 lib/go/thrift/tstruct.go delete mode 100644 lib/go/thrift/ttransport.go delete mode 100644 lib/go/thrift/ttransport_exception.go delete mode 100644 lib/go/thrift/ttransport_test.go delete mode 100644 lib/go/thrift/ttype.go create mode 100644 lib/go/thrift/type.go delete mode 100644 tutorial/go/Make.deps delete mode 100644 tutorial/go/Makefile create mode 100644 tutorial/go/Makefile.am delete mode 100644 tutorial/go/deps.bash delete mode 100644 tutorial/go/src/CalculatorHandler.go delete mode 100644 tutorial/go/src/GoClient.go delete mode 100644 tutorial/go/src/GoServer.go delete mode 100644 tutorial/go/src/Makefile create mode 100644 tutorial/go/src/client.go create mode 100644 tutorial/go/src/handler.go rename lib/go/thrift/texception_test.go => tutorial/go/src/server.go (59%) diff --git a/.gitignore b/.gitignore index be5ced21..581f867f 100644 --- a/.gitignore +++ b/.gitignore @@ -160,6 +160,8 @@ gen-* /lib/hs/dist /lib/hs/Makefile /lib/hs/Makefile.in +/lib/go/Makefile +/lib/go/Makefile.in /lib/java/Makefile /lib/java/Makefile.in /lib/java/build @@ -258,6 +260,13 @@ gen-* /tutorial/cpp/Makefile.in /tutorial/cpp/TutorialClient /tutorial/cpp/TutorialServer +/tutorial/go/Makefile +/tutorial/go/Makefile.in +/tutorial/go/go-tutorial +/tutorial/go/calculator-remote +/tutorial/go/src/shared +/tutorial/go/src/tutorial +/tutorial/go/src/git.apache.org /tutorial/java/Makefile /tutorial/java/Makefile.in /tutorial/java/build/ diff --git a/compiler/cpp/src/generate/t_go_generator.cc b/compiler/cpp/src/generate/t_go_generator.cc index 0b9f16e9..82af8a89 100644 --- a/compiler/cpp/src/generate/t_go_generator.cc +++ b/compiler/cpp/src/generate/t_go_generator.cc @@ -17,6 +17,14 @@ * under the License. */ +/* + * This file is programmatically sanitized for style: + * astyle --style=1tbs -f -p -H -j -U t_go_generator.cc + * + * The output of astyle should not be taken unquestioningly, but it is a good + * guide for ensuring uniformity and readability. + */ + #include #include #include @@ -31,325 +39,387 @@ #include "platform.h" #include "version.h" -using std::map; -using std::ofstream; -using std::ostringstream; -using std::string; -using std::stringstream; -using std::vector; +using namespace std; + +/** + * A helper for automatically formatting the emitted Go code from the Thrift + * IDL per the Go style guide. + * + * Returns: + * - true, if the formatting process succeeded. + * - false, if the formatting process failed, which means the basic output was + * still generated. + */ +bool format_go_output(const string &file_path); -static const string endl = "\n"; // avoid ostream << std::endl flushes +const string default_thrift_import = "git.apache.org/thrift.git/lib/go/thrift"; /** * Go code generator. - * */ -class t_go_generator : public t_generator { - public: - t_go_generator( - t_program* program, - const std::map& parsed_options, - const std::string& option_string) - : t_generator(program) - { - (void) parsed_options; - (void) option_string; - std::map::const_iterator iter; - out_dir_base_ = "gen-go"; - } - - /** - * Init and close methods - */ - - void init_generator(); - void close_generator(); - - /** - * Program-level generation functions - */ - - void generate_typedef (t_typedef* ttypedef); - void generate_enum (t_enum* tenum); - void generate_const (t_const* tconst); - void generate_struct (t_struct* tstruct); - void generate_xception (t_struct* txception); - void generate_service (t_service* tservice); - - std::string render_const_value(t_type* type, t_const_value* value, const string& name); - - /** - * Struct generation code - */ - - 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); - 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); - void generate_go_function_helpers(t_function* tfunction); - - /** - * Service-level generation functions - */ - - void generate_service_helpers (t_service* tservice); - void generate_service_interface (t_service* tservice); - void generate_service_client (t_service* tservice); - void generate_service_remote (t_service* tservice); - void generate_service_server (t_service* tservice); - void generate_process_function (t_service* tservice, t_function* tfunction); - - /** - * Serialization constructs - */ - - void generate_deserialize_field (std::ofstream &out, - t_field* tfield, - bool declare, - std::string prefix="", - std::string err="err", - bool inclass=false, - bool coerceData=false); +class t_go_generator : public t_generator +{ +public: + t_go_generator( + t_program* program, + const std::map& parsed_options, + const std::string& option_string) + : t_generator(program) { + std::map::const_iterator iter; + out_dir_base_ = "gen-go"; + gen_thrift_import_ = default_thrift_import; + + iter = parsed_options.find("package_prefix"); + + if (iter != parsed_options.end()) { + gen_package_prefix_ = (iter->second); + } - void generate_deserialize_struct (std::ofstream &out, - t_struct* tstruct, - bool declare, - std::string prefix="", - std::string err="err"); + iter = parsed_options.find("thrift_import"); - void generate_deserialize_container (std::ofstream &out, - t_type* ttype, - bool declare, - std::string prefix="", - std::string err="err"); + if (iter != parsed_options.end()) { + gen_thrift_import_ = (iter->second); + } + } - void generate_deserialize_set_element (std::ofstream &out, + /** + * Init and close methods + */ + + void init_generator(); + void close_generator(); + + /** + * Program-level generation functions + */ + + void generate_typedef(t_typedef* ttypedef); + void generate_enum(t_enum* tenum); + void generate_const(t_const* tconst); + void generate_struct(t_struct* tstruct); + void generate_xception(t_struct* txception); + void generate_service(t_service* tservice); + + std::string render_const_value(t_type* type, t_const_value* value, const string& name); + + /** + * Struct generation code + */ + + 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); + 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); + void generate_go_function_helpers(t_function* tfunction); + + /** + * Service-level generation functions + */ + + void generate_service_helpers(t_service* tservice); + void generate_service_interface(t_service* tservice); + void generate_service_client(t_service* tservice); + void generate_service_remote(t_service* tservice); + void generate_service_server(t_service* tservice); + void generate_process_function(t_service* tservice, t_function* tfunction); + + /** + * Serialization constructs + */ + + void generate_deserialize_field(std::ofstream &out, + t_field* tfield, + bool declare, + std::string prefix = "", + bool inclass = false, + bool coerceData = false); + + void generate_deserialize_struct(std::ofstream &out, + t_struct* tstruct, + bool declare, + std::string prefix = ""); + + void generate_deserialize_container(std::ofstream &out, + t_type* ttype, + bool declare, + std::string prefix = ""); + + void generate_deserialize_set_element(std::ofstream &out, t_set* tset, bool declare, - std::string prefix="", - std::string err="err"); + std::string prefix = ""); - void generate_deserialize_map_element (std::ofstream &out, + void generate_deserialize_map_element(std::ofstream &out, t_map* tmap, bool declare, - std::string prefix="", - std::string err="err"); + std::string prefix = ""); + + void generate_deserialize_list_element(std::ofstream &out, + t_list* tlist, + bool declare, + std::string prefix = ""); + + void generate_serialize_field(std::ofstream &out, + t_field* tfield, + std::string prefix = ""); + + void generate_serialize_struct(std::ofstream &out, + t_struct* tstruct, + std::string prefix = ""); + + void generate_serialize_container(std::ofstream &out, + t_type* ttype, + std::string prefix = ""); + + void generate_serialize_map_element(std::ofstream &out, + t_map* tmap, + std::string kiter, + std::string viter); + + void generate_serialize_set_element(std::ofstream &out, + t_set* tmap, + std::string iter); + + void generate_serialize_list_element(std::ofstream &out, + t_list* tlist, + std::string iter); + + void generate_go_docstring(std::ofstream& out, + t_struct* tstruct); + + void generate_go_docstring(std::ofstream& out, + t_function* tfunction); + + void generate_go_docstring(std::ofstream& out, + t_doc* tdoc, + t_struct* tstruct, + const char* subheader); + + void generate_go_docstring(std::ofstream& out, + t_doc* tdoc); + + /** + * Helper rendering functions + */ + + std::string go_autogen_comment(); + std::string go_package(); + std::string go_imports_begin(); + std::string go_imports_end(); + std::string render_includes(); + std::string render_fastbinary_includes(); + std::string declare_argument(t_field* tfield); + std::string render_field_default_value(t_field* tfield, const string& name); + std::string type_name(t_type* ttype); + std::string function_signature(t_function* tfunction, std::string prefix = ""); + 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_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) { + std::string real_module = program->get_namespace("go"); + + if (real_module.empty()) { + return program->get_name(); + } - void generate_deserialize_list_element (std::ofstream &out, - t_list* tlist, - bool declare, - std::string prefix="", - std::string err="err"); + return real_module; + } - void generate_serialize_field (std::ofstream &out, - t_field* tfield, - std::string prefix="", - std::string err="err"); +private: - void generate_serialize_struct (std::ofstream &out, - t_struct* tstruct, - std::string prefix="", - std::string err="err"); + std::string gen_package_prefix_; + std::string gen_thrift_import_; - void generate_serialize_container (std::ofstream &out, - t_type* ttype, - std::string prefix="", - std::string err="err"); + /** + * File streams + */ - void generate_serialize_map_element (std::ofstream &out, - t_map* tmap, - std::string kiter, - std::string viter, - std::string err="err"); - - void generate_serialize_set_element (std::ofstream &out, - t_set* tmap, - std::string iter, - std::string err="err"); - - void generate_serialize_list_element (std::ofstream &out, - t_list* tlist, - std::string iter, - std::string err="err"); - - void generate_go_docstring (std::ofstream& out, - t_struct* tstruct); - - void generate_go_docstring (std::ofstream& out, - t_function* tfunction); - - void generate_go_docstring (std::ofstream& out, - t_doc* tdoc, - t_struct* tstruct, - const char* subheader); - - void generate_go_docstring (std::ofstream& out, - t_doc* tdoc); - - /** - * Helper rendering functions - */ - - std::string go_autogen_comment(); - std::string go_package(); - std::string go_imports(); - std::string render_includes(); - std::string render_fastbinary_includes(); - std::string declare_argument(t_field* tfield); - std::string render_field_default_value(t_field* tfield, const string& name); - std::string type_name(t_type* ttype); - std::string function_signature(t_function* tfunction, std::string prefix=""); - std::string function_signature_if(t_function* tfunction, std::string prefix="", bool addOsError=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_spec_args(t_type* ttype); - - static std::string get_real_go_module(const t_program* program) { - std::string real_module = program->get_namespace("go"); - if (real_module.empty()) { - return program->get_name(); - } - return real_module; - } - - private: - - /** - * File streams - */ - - std::ofstream f_types_; - std::stringstream f_consts_; - std::ofstream f_service_; - - std::string package_name_; - std::string package_dir_; - - static std::string publicize(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); + std::ofstream f_types_; + std::string f_types_name_; + std::ofstream f_consts_; + std::string f_consts_name_; + std::stringstream f_const_values_; + std::ofstream f_service_; + + std::string package_name_; + std::string package_dir_; + + static std::string publicize(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); }; -std::string t_go_generator::publicize(const std::string& value) { - if(value.size() <= 0) return value; - std::string value2(value); - if(!isupper(value2[0])) - value2[0] = toupper(value2[0]); - // as long as we are changing things, let's change _ followed by lowercase to capital - for(string::size_type i=1; i services = program_->get_services(); - vector::iterator sv_iter; - string f_init_name = package_dir_+"/Makefile"; - ofstream f_init; - f_init.open(f_init_name.c_str()); - f_init << - endl << - "include $(GOROOT)/src/Make.inc" << endl << endl << - "all: install" << endl << endl << - "TARG=thriftlib/" << target << endl << endl << - "DIRS=\\" << endl; - for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { - f_init << " " << (*sv_iter)->get_name() << "\\" << endl; - } - f_init << endl << - "GOFILES=\\" << endl << - " ttypes.go\\" << endl; - // " constants.go\\" << endl; - for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { - f_init << " " << (*sv_iter)->get_name() << ".go\\" << endl; - } - f_init << endl << endl << - "include $(GOROOT)/src/Make.pkg" << endl << endl; - f_init.close(); - - for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { - string service_dir = package_dir_+"/"+(*sv_iter)->get_name(); +void t_go_generator::init_generator() +{ + // Make output directory + string module = get_real_go_module(program_); + string target = module; + package_dir_ = get_out_dir(); + + while (true) { + // TODO: Do better error checking here. + MKDIR(package_dir_.c_str()); + + if (module.empty()) { + break; + } + + string::size_type pos = module.find('.'); + + if (pos == string::npos) { + package_dir_ += "/"; + package_dir_ += module; + package_name_ = module; + module.clear(); + } else { + package_dir_ += "/"; + package_dir_ += module.substr(0, pos); + module.erase(0, pos + 1); + } + } + + string::size_type loc; + + while ((loc = target.find(".")) != string::npos) { + target.replace(loc, 1, 1, '/'); + } + + // Make output files + f_types_name_ = package_dir_ + "/" + "ttypes.go"; + f_types_.open(f_types_name_.c_str()); + + f_consts_name_ = package_dir_ + "/" + "constants.go"; + f_consts_.open(f_consts_name_.c_str()); + + vector services = program_->get_services(); + vector::iterator sv_iter; + + for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { + string service_dir = package_dir_ + "/" + underscore((*sv_iter)->get_name()) + "-remote"; #ifdef MINGW - mkdir(service_dir.c_str()); + mkdir(service_dir.c_str()); #else - mkdir(service_dir.c_str(), 0755); + mkdir(service_dir.c_str(), 0755); #endif - string f_init_name = service_dir+"/Makefile"; - ofstream f_init; - f_init.open(f_init_name.c_str()); - f_init << - endl << - "include $(GOROOT)/src/Make.inc" << endl << endl << - "all: install" << endl << endl << - "TARG=" << publicize((*sv_iter)->get_name()) << "-remote" << endl << endl << - "DIRS=\\" << endl << endl << - "GOFILES=\\" << endl << - " " << (*sv_iter)->get_name() << "-remote.go\\" << endl << endl << - "include $(GOROOT)/src/Make.cmd" << endl << endl; - f_init.close(); - } - - // Print header - f_types_ << - go_autogen_comment() << - go_package() << - go_imports() << - render_includes() << - render_fastbinary_includes() << endl << endl; + } + + // Print header + f_types_ << + go_package() << + go_autogen_comment() << + go_imports_begin() << + render_fastbinary_includes() << + go_imports_end(); + + f_consts_ << + go_package() << + go_autogen_comment(); + + f_const_values_ << endl << "func init() {" << endl; + } /** * Renders all the imports necessary for including another Thrift program */ -string t_go_generator::render_includes() { - const vector& includes = program_->get_includes(); - string result = ""; - for (size_t i = 0; i < includes.size(); ++i) { - result += "import \"thriftlib/" + get_real_go_module(includes[i]) + "\"\n"; - } - if (includes.size() > 0) { - result += "\n"; - } - return result; +string t_go_generator::render_includes() +{ + const vector& includes = program_->get_includes(); + string result = ""; + + for (size_t i = 0; i < includes.size(); ++i) { + result += "\t\"" + gen_package_prefix_ + get_real_go_module(includes[i]) + "\"\n"; + } + + if (includes.size() > 0) { + result += "\n"; + } + + return result; } /** * Renders all the imports necessary to use the accelerated TBinaryProtocol */ -string t_go_generator::render_fastbinary_includes() { - return ""; +string t_go_generator::render_fastbinary_includes() +{ + return ""; } /** * Autogen'd comment */ -string t_go_generator::go_autogen_comment() { - return - std::string() + - "/* Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" - " *\n" - " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" - " */\n"; +string t_go_generator::go_autogen_comment() +{ + return + std::string() + + "// Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\n"; } /** * Prints standard thrift package */ -string t_go_generator::go_package() { - return - string("package ") + package_name_ + ";\n\n"; +string t_go_generator::go_package() +{ + return string("package ") + package_name_ + "\n\n"; +} + +/** + * Render the beginning of the import statement + */ +string t_go_generator::go_imports_begin() +{ + return + string("import (\n" + "\t\"fmt\"\n" + "\t\"math\"\n" + "\t\"" + gen_thrift_import_ + "\"\n"); } /** - * Prints standard thrift imports + * End the import statement, include undscore-assignments + * + * These "_ =" prevent the go compiler complaining about used imports. + * This will have to do in lieu of more intelligent import statement construction */ -string t_go_generator::go_imports() { - return - string("import (\n" - " \"thrift\"\n" -// " \"strings\"\n" - " \"fmt\"\n" - ")\n\n"); +string t_go_generator::go_imports_end() +{ + return + string( + ")\n\n" + "// (needed to ensure safety because of naive import list constrution.)\n" + "var _ = math.MinInt32\n\n"); } /** * Closes the type files */ -void t_go_generator::close_generator() { - // Close types file - f_consts_ << "}" << endl; - f_types_ << f_consts_.str() << endl; - f_types_.close(); - f_consts_.clear(); +void t_go_generator::close_generator() +{ + f_const_values_ << "}" << endl << endl; + f_consts_ << f_const_values_.str(); + + // Close types and constants files + f_consts_.close(); + f_types_.close(); + format_go_output(f_types_name_); + format_go_output(f_consts_name_); } /** @@ -518,15 +592,18 @@ void t_go_generator::close_generator() { * * @param ttypedef The type definition */ -void t_go_generator::generate_typedef(t_typedef* ttypedef) { - - generate_go_docstring(f_types_, ttypedef); - string newTypeDef(publicize(ttypedef->get_symbolic())); - string baseType(type_to_go_type(ttypedef->get_type())); - if(baseType == newTypeDef) - return; - f_types_ << - "type " << newTypeDef << " " << baseType << endl << endl; +void t_go_generator::generate_typedef(t_typedef* ttypedef) +{ + generate_go_docstring(f_types_, ttypedef); + string newTypeDef(publicize(ttypedef->get_symbolic())); + string baseType(type_to_go_type(ttypedef->get_type())); + + if (baseType == newTypeDef) { + return; + } + + f_types_ << + "type " << newTypeDef << " " << baseType << endl << endl; } /** @@ -535,83 +612,85 @@ void t_go_generator::generate_typedef(t_typedef* ttypedef) { * * @param tenum The enumeration */ -void t_go_generator::generate_enum(t_enum* tenum) { - std::ostringstream to_string_mapping, from_string_mapping; - std::string tenum_name(publicize(tenum->get_name())); - - generate_go_docstring(f_types_, tenum); - f_types_ << - "type " << tenum_name << " int" << endl << - "const (" << endl; - - to_string_mapping << - indent() << "func (p " << tenum_name << ") String() string {" << endl << - indent() << " switch p {" << endl; - from_string_mapping << - indent() << "func From" << tenum_name << "String(s string) " << tenum_name << " {" << endl << - indent() << " switch s {" << endl; - - vector constants = tenum->get_constants(); - vector::iterator c_iter; - int value = -1; - for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { - if ((*c_iter)->has_value()) { - value = (*c_iter)->get_value(); - } else { - ++value; - } - string iter_std_name(escape_string((*c_iter)->get_name())); - string iter_name((*c_iter)->get_name()); +void t_go_generator::generate_enum(t_enum* tenum) +{ + std::ostringstream to_string_mapping, from_string_mapping; + std::string tenum_name(publicize(tenum->get_name())); + generate_go_docstring(f_types_, tenum); f_types_ << - indent() << " " << iter_name << ' ' << tenum_name << " = " << value << endl; - - // Dictionaries to/from string names of enums + "type " << tenum_name << " int64" << endl << + "const (" << endl; to_string_mapping << - indent() << " case " << iter_name << ": return \"" << iter_std_name << "\"" << endl; - if(iter_std_name != escape_string(iter_name)) { - from_string_mapping << - indent() << " case \"" << iter_std_name << "\", \"" << escape_string(iter_name) << "\": return " << iter_name << endl; - } else { - from_string_mapping << - indent() << " case \"" << iter_std_name << "\": return " << iter_name << endl; - } - } - to_string_mapping << - indent() << " }" << endl << - indent() << " return \"\"" << endl << - indent() << "}" << endl; - from_string_mapping << - indent() << " }" << endl << - indent() << " return " << tenum_name << "(-10000)" << endl << - indent() << "}" << endl; - - f_types_ << - indent() << ")" << endl << - to_string_mapping.str() << endl << from_string_mapping.str() << endl << - indent() << "func (p " << tenum_name << ") Value() int {" << endl << - indent() << " return int(p)" << endl << - indent() << "}" << endl << endl << - indent() << "func (p " << tenum_name << ") IsEnum() bool {" << endl << - indent() << " return true" << endl << - indent() << "}" << endl << endl; + indent() << "func (p " << tenum_name << ") String() string {" << endl << + indent() << " switch p {" << endl; + from_string_mapping << + indent() << "func " << tenum_name << "FromString(s string) (" << tenum_name << ", error) {" << endl << + indent() << " switch s {" << endl; + vector constants = tenum->get_constants(); + vector::iterator c_iter; + int value = -1; + + for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { + if ((*c_iter)->has_value()) { + value = (*c_iter)->get_value(); + } else { + ++value; + } + + string iter_std_name(escape_string((*c_iter)->get_name())); + string iter_name((*c_iter)->get_name()); + f_types_ << + indent() << " " << tenum_name << "_" << iter_name << ' ' << tenum_name << " = " << value << endl; + // Dictionaries to/from string names of enums + to_string_mapping << + indent() << " case " << tenum_name << "_" << iter_name << ": return \"" << tenum_name << "_" << iter_std_name << "\"" << endl; + + if (iter_std_name != escape_string(iter_name)) { + from_string_mapping << + indent() << " case \"" << tenum_name << "_" << iter_std_name << "\", \"" << escape_string(iter_name) << "\": return " << + tenum_name << "_" << iter_name << ", nil " << endl; + } else { + from_string_mapping << + indent() << " case \"" << tenum_name << "_" << iter_std_name << "\": return " << + tenum_name << "_" << iter_name << ", nil " << endl; + } + } + + to_string_mapping << + indent() << " }" << endl << + indent() << " return \"\"" << endl << + indent() << "}" << endl; + from_string_mapping << + indent() << " }" << endl << + indent() << " return " << tenum_name << "(math.MinInt32 - 1)," << + " fmt.Errorf(\"not a valid " << tenum_name << " string\")" << endl << + indent() << "}" << endl; + + f_types_ << ")" << endl << endl + << to_string_mapping.str() << endl + << from_string_mapping.str() << endl << endl; + } + /** * Generate a constant value */ -void t_go_generator::generate_const(t_const* tconst) { - t_type* type = tconst->get_type(); - string name = publicize(tconst->get_name()); - t_const_value* value = tconst->get_value(); - - if(type->is_base_type() || type->is_enum()) { - indent(f_types_) << "const " << name << " = " << render_const_value(type, value, name) << endl; - } else { - f_types_ << - indent() << "var " << name << " " << " " << type_to_go_type(type) << endl; - f_consts_ << - " " << name << " = " << render_const_value(type, value, name) << endl; - } +void t_go_generator::generate_const(t_const* tconst) +{ + t_type* type = tconst->get_type(); + string name = publicize(tconst->get_name()); + t_const_value* value = tconst->get_value(); + + if (type->is_base_type() || type->is_enum()) { + indent(f_consts_) << "const " << name << " = " << render_const_value(type, value, name) << endl; + } else { + f_const_values_ << + indent() << name << " = " << render_const_value(type, value, name) << endl << endl; + + f_consts_ << + indent() << "var " << name << " " << type_to_go_type(type) << endl; + } } /** @@ -619,136 +698,150 @@ void t_go_generator::generate_const(t_const* tconst) { * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ -string t_go_generator::render_const_value(t_type* type, t_const_value* value, const string& name) { - type = get_true_type(type); - std::ostringstream out; - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_STRING: - out << '"' << get_escaped_string(value) << '"'; - break; - case t_base_type::TYPE_BOOL: - out << (value->get_integer() > 0 ? "true" : "false"); - break; - case t_base_type::TYPE_BYTE: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - out << value->get_integer(); - break; - case t_base_type::TYPE_DOUBLE: - if (value->get_type() == t_const_value::CV_INTEGER) { - out << value->get_integer(); - } else { - out << value->get_double(); - } - break; - default: - throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); - } - } else if (type->is_enum()) { - indent(out) << value->get_integer(); - } else if (type->is_struct() || type->is_xception()) { - out << - "New" << publicize(type->get_name()) << "()" << endl << - indent() << "{" << endl; - indent_up(); - const vector& fields = ((t_struct*)type)->get_members(); - vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - t_type* field_type = NULL; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if ((*f_iter)->get_name() == v_iter->first->get_string()) { - field_type = (*f_iter)->get_type(); +string t_go_generator::render_const_value(t_type* type, t_const_value* value, const string& name) +{ + type = get_true_type(type); + std::ostringstream out; + + if (type->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); + + switch (tbase) { + case t_base_type::TYPE_STRING: + if (((t_base_type*)type)->is_binary()) { + out << "[]byte(\"" << get_escaped_string(value) << "\")"; + } else { + out << '"' << get_escaped_string(value) << '"'; + } + + break; + + case t_base_type::TYPE_BOOL: + out << (value->get_integer() > 0 ? "true" : "false"); + break; + + case t_base_type::TYPE_BYTE: + case t_base_type::TYPE_I16: + case t_base_type::TYPE_I32: + case t_base_type::TYPE_I64: + out << value->get_integer(); + break; + + case t_base_type::TYPE_DOUBLE: + if (value->get_type() == t_const_value::CV_INTEGER) { + out << value->get_integer(); + } else { + out << value->get_double(); + } + + break; + + default: + throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } - } - if (field_type == NULL) { - throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); - } - if(field_type->is_base_type() || field_type->is_enum()) { + } else if (type->is_enum()) { + indent(out) << value->get_integer(); + } else if (type->is_struct() || type->is_xception()) { out << - indent() << name << "." << publicize(v_iter->first->get_string()) << " = " << render_const_value(field_type, v_iter->second, name) << endl; - } else { - string k(tmp("k")); - string v(tmp("v")); + "&" << publicize(type->get_name()) << "{"; + indent_up(); + const vector& fields = ((t_struct*)type)->get_members(); + vector::const_iterator f_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; + + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { + t_type* field_type = NULL; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + if ((*f_iter)->get_name() == v_iter->first->get_string()) { + field_type = (*f_iter)->get_type(); + } + } + + if (field_type == NULL) { + throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); + } + + if (field_type->is_base_type() || field_type->is_enum()) { + out << endl << + indent() << publicize(v_iter->first->get_string()) << ": " << render_const_value(field_type, v_iter->second, name) << ","; + } else { + string k(tmp("k")); + string v(tmp("v")); + out << endl << + indent() << v << " := " << render_const_value(field_type, v_iter->second, v) << endl << + indent() << name << "." << publicize(v_iter->first->get_string()) << " = " << v; + } + } + + out << "}"; + + indent_down(); + } else if (type->is_map()) { + t_type* ktype = ((t_map*)type)->get_key_type(); + t_type* vtype = ((t_map*)type)->get_val_type(); + const map& val = value->get_map(); out << - indent() << v << " := " << render_const_value(field_type, v_iter->second, v) << endl << - indent() << name << "." << publicize(v_iter->first->get_string()) << " = " << v << endl; - } - } - indent_down(); - out << - indent() << "}"; - } else if (type->is_map()) { - t_type* ktype = ((t_map*)type)->get_key_type(); - t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - out << - "thrift.NewTMap(" << type_to_enum(ktype) << ", " << type_to_enum(vtype) << ", " << val.size() << ")" << endl << - indent() << "{" << endl; - indent_up(); - map::const_iterator v_iter; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - string k(tmp("k")); - string v(tmp("v")); - out << - indent() << k << " := " << render_const_value(ktype, v_iter->first, k) << endl << - indent() << v << " := " << render_const_value(vtype, v_iter->second, v) << endl << - indent() << name << ".Set(" << k << ", " << v << ")" << endl; - } - indent_down(); - out << - indent() << "}" << endl; - } else if (type->is_list()) { - t_type* etype = ((t_list*)type)->get_elem_type(); - const vector& val = value->get_list(); - out << - "thrift.NewTList(" << type_to_enum(etype) << ", " << val.size() << ")" << endl << - indent() << "{" << endl; - indent_up(); - vector::const_iterator v_iter; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - string v(tmp("v")); - out << - indent() << v << " := " << render_const_value(etype, *v_iter, v) << endl << - indent() << name << ".Push(" << v << ")" << endl; - } - indent_down(); - out << - indent() << "}" << endl; - } else if (type->is_set()) { - t_type* etype = ((t_set*)type)->get_elem_type(); - const vector& val = value->get_list(); - out << - "thrift.NewTSet(" << type_to_enum(etype) << ", " << val.size() << ")" << endl << - indent() << "{" << endl; - indent_up(); - vector::const_iterator v_iter; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - string v(tmp("v")); - out << - indent() << v << " := " << render_const_value(etype, *v_iter, v) << endl << - indent() << name << ".Add(" << v << ")" << endl; + "map[" << type_to_go_type(ktype) << "]" << type_to_go_type(vtype) << "{" << endl; + indent_up(); + map::const_iterator v_iter; + + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { + out << + indent() << render_const_value(ktype, v_iter->first, name) << ": " << + render_const_value(vtype, v_iter->second, name) << "," << endl; + } + + indent_down(); + out << + indent() << "}"; + } else if (type->is_list()) { + t_type* etype = ((t_list*)type)->get_elem_type(); + const vector& val = value->get_list(); + out << + "[]" << type_to_go_type(etype) << "{" << endl; + indent_up(); + vector::const_iterator v_iter; + + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { + out << + indent() << render_const_value(etype, *v_iter, name) << ", "; + } + + indent_down(); + out << + indent() << "}"; + } else if (type->is_set()) { + t_type* etype = ((t_set*)type)->get_elem_type(); + const vector& val = value->get_list(); + out << + "map[" << type_to_go_key_type(etype) << "]bool{" << endl; + indent_up(); + vector::const_iterator v_iter; + + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { + out << + indent() << render_const_value(etype, *v_iter, name) << ": true," << endl; + + } + + indent_down(); + out << + indent() << "}"; + } else { + throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); } - indent_down(); - out << - indent() << "}" << endl; - } else { - throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); - } - return out.str(); + return out.str(); } /** * Generates a go struct */ -void t_go_generator::generate_struct(t_struct* tstruct) { - generate_go_struct(tstruct, false); +void t_go_generator::generate_struct(t_struct* tstruct) +{ + generate_go_struct(tstruct, false); } /** @@ -757,16 +850,18 @@ void t_go_generator::generate_struct(t_struct* tstruct) { * * @param txception The struct definition */ -void t_go_generator::generate_xception(t_struct* txception) { - generate_go_struct(txception, true); +void t_go_generator::generate_xception(t_struct* txception) +{ + generate_go_struct(txception, true); } /** * Generates a go struct */ void t_go_generator::generate_go_struct(t_struct* tstruct, - bool is_exception) { - generate_go_struct_definition(f_types_, tstruct, is_exception); + bool is_exception) +{ + generate_go_struct_definition(f_types_, tstruct, is_exception); } /** @@ -775,459 +870,472 @@ void t_go_generator::generate_go_struct(t_struct* tstruct, * @param tstruct The struct definition */ void t_go_generator::generate_go_struct_definition(ofstream& out, - t_struct* tstruct, - bool is_exception, - bool is_result) { - - (void) is_exception; - const vector& members = tstruct->get_members(); - const vector& sorted_members = tstruct->get_sorted_members(); - vector::const_iterator m_iter; - - generate_go_docstring(out, tstruct); - std::string tstruct_name(publicize(tstruct->get_name())); - out << - indent() << "type " << tstruct_name << " struct {" << endl << - indent() << " thrift.TStruct" << endl; - - /* - Here we generate the structure specification for the fastbinary codec. - These specifications have the following structure: - thrift_spec -> tuple of item_spec - item_spec -> nil | (tag, type_enum, name, spec_args, default) - tag -> integer - type_enum -> TType.I32 | TType.STRING | TType.STRUCT | ... - name -> string_literal - default -> nil # Handled by __init__ - spec_args -> nil # For simple types - | (type_enum, spec_args) # Value type for list/set - | (type_enum, spec_args, type_enum, spec_args) - # Key and value for map - | (class_name, spec_args_ptr) # For struct/exception - class_name -> identifier # Basically a pointer to the class - spec_args_ptr -> expression # just class_name.spec_args - - TODO(dreiss): Consider making this work for structs with negative tags. - */ - - // TODO(dreiss): Look into generating an empty tuple instead of nil - // for structures with no members. - // TODO(dreiss): Test encoding of structs where some inner structs - // don't have thrift_spec. - indent_up(); - if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) { - int sorted_keys_pos = 0; - for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) { - - for (; sorted_keys_pos != (*m_iter)->get_key(); sorted_keys_pos++) { - if (sorted_keys_pos != 0) { - indent(out) << "_ interface{} \"" << escape_string((*m_iter)->get_name()) << "\"; // nil # " << sorted_keys_pos << endl; - } - } - t_type* fieldType = (*m_iter)->get_type(); - string goType(type_to_go_type(fieldType)); - indent(out) << publicize(variable_name_to_go_name((*m_iter)->get_name())) << " " - << goType << " \"" << escape_string((*m_iter)->get_name()) - << "\"; // " << sorted_keys_pos - << endl; + t_struct* tstruct, + bool is_exception, + bool is_result) +{ + const vector& members = tstruct->get_members(); + const vector& sorted_members = tstruct->get_sorted_members(); + vector::const_iterator m_iter; + + std::string tstruct_name(publicize(tstruct->get_name())); + out << + indent() << "type " << tstruct_name << " struct {" << endl; + /* + Here we generate the structure specification for the fastbinary codec. + These specifications have the following structure: + thrift_spec -> tuple of item_spec + item_spec -> nil | (tag, type_enum, name, spec_args, default) + tag -> integer + type_enum -> TType.I32 | TType.STRING | TType.STRUCT | ... + name -> string_literal + default -> nil # Handled by __init__ + spec_args -> nil # For simple types + | (type_enum, spec_args) # Value type for list/set + | (type_enum, spec_args, type_enum, spec_args) + # Key and value for map + | (class_name, spec_args_ptr) # For struct/exception + class_name -> identifier # Basically a pointer to the class + spec_args_ptr -> expression # just class_name.spec_args + + TODO(dreiss): Consider making this work for structs with negative tags. + */ + // TODO(dreiss): Look into generating an empty tuple instead of nil + // for structures with no members. + // TODO(dreiss): Test encoding of structs where some inner structs + // don't have thrift_spec. + indent_up(); + + if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) { + int sorted_keys_pos = 0; + + for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) { + for (; sorted_keys_pos != (*m_iter)->get_key(); sorted_keys_pos++) { + if (sorted_keys_pos != 0) { + indent(out) << "// unused field # " << sorted_keys_pos << endl; + } + } - sorted_keys_pos ++; + t_type* fieldType = (*m_iter)->get_type(); + string goType(type_to_go_type(fieldType)); + + indent(out) << publicize(variable_name_to_go_name((*m_iter)->get_name())) << " " + << goType << " `thrift:\"" + << escape_string((*m_iter)->get_name()) + << "," << sorted_keys_pos; + + if ((*m_iter)->get_req() == t_field::T_REQUIRED) { + out << ",required"; + } + + out << "\"`" << endl; + sorted_keys_pos ++; + } + } else { + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + // This fills in default values, as opposed to nulls + out << + indent() << publicize((*m_iter)->get_name()) << " " << + type_to_go_type((*m_iter)->get_type()) << endl; + } } - } else { - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - // This fills in default values, as opposed to nulls - out << - indent() << publicize((*m_iter)->get_name()) << " " << - type_to_enum((*m_iter)->get_type()) << endl; - } - } - indent_down(); - out << - indent() << "}" << endl << endl << - indent() << "func New" << tstruct_name << "() *" << tstruct_name << " {" << endl << - indent() << " output := &" << tstruct_name << "{" << endl << - indent() << " TStruct:thrift.NewTStruct(\"" << escape_string(tstruct->get_name()) << "\", []thrift.TField{" << endl; - indent_up(); - indent_up(); - for(m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - string thrift_name((*m_iter)->get_name()); + indent_down(); out << - indent() << "thrift.NewTField(\"" << escape_string(thrift_name) << "\", " << type_to_enum((*m_iter)->get_type()) << ", "<< (*m_iter)->get_key() << ")," << endl; - } - out << - indent() << "})," << endl; - indent_down(); - out << - indent() << "}" << endl << - indent() << "{" << endl; - indent_up(); - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - // Initialize fields - //t_type* type = (*m_iter)->get_type(); - string fieldName(publicize((*m_iter)->get_name())); - string fullFieldName = "output." + fieldName; - if ((*m_iter)->get_value() != NULL) { - out << - indent() << fullFieldName << " = " << - render_field_default_value(*m_iter, fullFieldName) << endl; - } - } - indent_down(); - out << - indent() << "}" << endl << - indent() << "return output" << endl; - indent_down(); - out << - indent() << "}" << endl << endl; - - generate_go_struct_reader(out, tstruct, tstruct_name, is_result); - generate_go_struct_writer(out, tstruct, tstruct_name, is_result); - - // Printing utilities so that on the command line thrift - // structs look pretty like dictionaries - out << - indent() << "func (p *" << tstruct_name << ") TStructName() string {" << endl << - indent() << " return \"" << escape_string(tstruct_name) << "\"" << endl << - indent() << "}" << endl << endl; - - out << - indent() << "func (p *" << tstruct_name << ") ThriftName() string {" << endl << - indent() << " return \"" << escape_string(tstruct->get_name()) << "\"" << endl << - indent() << "}" << endl << endl; - - out << - indent() << "func (p *" << tstruct_name << ") String() string {" << endl << - indent() << " if p == nil {" << endl << - indent() << " return \"\"" << endl << - indent() << " }" << endl << - indent() << " return fmt.Sprintf(\"" << escape_string(tstruct_name) << "(%+v)\", *p)" << endl << - indent() << "}" << endl << endl; - - // Equality and inequality methods that compare by value - if(members.size() <= 0) { - out << - indent() << "func (p *" << tstruct_name << ") CompareTo(other interface{}) (int, bool) {" << endl << - indent() << " if other == nil {" << endl << - indent() << " return 1, true" << endl << - indent() << " }" << endl << - indent() << " _, ok := other.(*" << tstruct_name << ")" << endl << - indent() << " if !ok {" << endl << - indent() << " return 0, false" << endl << - indent() << " }" << endl << - indent() << " return 0, true" << endl << - indent() << "}" << endl << endl; - } else { - out << - indent() << "func (p *" << tstruct_name << ") CompareTo(other interface{}) (int, bool) {" << endl << - indent() << " if other == nil {" << endl << - indent() << " return 1, true" << endl << - indent() << " }" << endl << - indent() << " data, ok := other.(*" << tstruct_name << ")" << endl << - indent() << " if !ok {" << endl << - indent() << " return 0, false" << endl << - indent() << " }" << endl; - indent_up(); - for(m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* orig_type = (*m_iter)->get_type(); - t_type* type = get_true_type(orig_type); - string field_name(publicize(variable_name_to_go_name((*m_iter)->get_name()))); - if(type->is_base_type() || type->is_enum()) { - if(type->is_bool()) { - out << - indent() << "if cmp := thrift.CompareBool(p." << field_name << ", data." << field_name << "); cmp != 0 {" << endl << - indent() << " return cmp, true" << endl << - indent() << "}" << endl; - } else { - out << - indent() << "if p." << field_name << " != data." << field_name << " {" << endl << - indent() << " if p." << field_name << " < data." << field_name << " {" << endl << - indent() << " return -1, true" << endl << - indent() << " }" << endl << - indent() << " return 1, true" << endl << - indent() << "}" << endl; + indent() << "}" << endl << endl << + indent() << "func New" << tstruct_name << "() *" << tstruct_name << " {" << endl << + indent() << " return &" << tstruct_name << "{"; + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + // Initialize fields + const string base_field_name = (*m_iter)->get_name(); + const string escaped_field_name = escape_string(base_field_name); + const string go_safe_name = variable_name_to_go_name(escaped_field_name); + const string publicized_name = publicize(go_safe_name); + const t_type* type = get_true_type((*m_iter)->get_type()); + const bool has_default_value = (*m_iter)->get_value() != NULL; + const bool type_is_enum = type->is_enum(); + + if (has_default_value) { + out << endl << indent() << publicized_name << ": " << render_field_default_value(*m_iter, base_field_name) << "," << endl; + } else if (type_is_enum) { + out << endl << indent() << publicized_name << ": math.MinInt32 - 1, // unset sentinal value" << endl; } - } else if(type->is_container() || type->is_struct() || type->is_xception()) { - out << - indent() << "if cmp, ok := p." << field_name << ".CompareTo(data." << field_name << "); !ok || cmp != 0 {" << endl << - indent() << " return cmp, ok" << endl << - indent() << "}" << endl; - } else { - throw "INVALID TYPE IN generate_go_struct_definition: " + type->get_name(); - } } - indent_down(); - out << - indent() << " return 0, true" << endl << - indent() << "}" << endl << endl; - } - - // Equality and inequality methods that compare by value - out << - indent() << "func (p *" << tstruct_name << ") AttributeByFieldId(id int) interface{} {" << endl << - indent() << " switch id {" << endl << - indent() << " default: return nil" << endl; - indent_up(); - for(m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - string field_name(publicize(variable_name_to_go_name((*m_iter)->get_name()))); - out << - indent() << "case " << (*m_iter)->get_key() << ": return p." << field_name << endl; - } - indent_down(); - out << - indent() << " }" << endl << - indent() << " return nil" << endl << - indent() << "}" << endl << endl; - - out << - indent() << "func (p *" << tstruct_name << ") TStructFields() thrift.TFieldContainer {" << endl << - indent() << " return thrift.NewTFieldContainer([]thrift.TField{" << endl; - indent_up(); - indent_up(); - for(m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - string thrift_name((*m_iter)->get_name()); + + out << "}" << 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); + out << - indent() << "thrift.NewTField(\"" << escape_string(thrift_name) << "\", " << type_to_enum((*m_iter)->get_type()) << ", "<< (*m_iter)->get_key() << ")," << endl; - } - out << - indent() << "})" << endl; - indent_down(); - indent_down(); - out << - indent() << "}" << endl << endl; + indent() << "func (p *" << tstruct_name << ") String() string {" << endl << + indent() << " if p == nil {" << endl << + indent() << " return \"\"" << endl << + indent() << " }" << endl << + indent() << " return fmt.Sprintf(\"" << escape_string(tstruct_name) << "(%+v)\", *p)" << endl << + indent() << "}" << endl << endl; + +} + +/** + * Generates the IsSet helper methods for a struct + */ +void t_go_generator::generate_isset_helpers(ofstream& out, + t_struct* tstruct, + const string& tstruct_name, + bool is_result) +{ + const vector& fields = tstruct->get_members(); + vector::const_iterator f_iter; + const string escaped_tstruct_name(escape_string(tstruct->get_name())); + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + t_type* type = get_true_type((*f_iter)->get_type()); + + if ((*f_iter)->get_req() == t_field::T_OPTIONAL || type->is_enum()) { + const string field_name(publicize(variable_name_to_go_name(escape_string((*f_iter)->get_name())))); + t_const_value* field_default_value = (*f_iter)->get_value(); + out << + indent() << "func (p *" << tstruct_name << ") IsSet" << field_name << "() bool {" << endl; + indent_up(); + string s_check_value; + int64_t i_check_value; + double d_check_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_STRING: + if (((t_base_type*)type)->is_binary()) { + // ignore default value for binary + out << + indent() << "return p." << field_name << " != nil" << endl; + } else { + s_check_value = (field_default_value == NULL) ? "\"\"" : render_const_value(type, field_default_value, tstruct_name); + out << + indent() << "return p." << field_name << " != " << s_check_value << endl; + } + + break; + + case t_base_type::TYPE_BOOL: + s_check_value = (field_default_value != NULL && field_default_value->get_integer() > 0) ? "true" : "false"; + out << + indent() << "return p." << field_name << " != " << s_check_value << endl; + break; + + case t_base_type::TYPE_BYTE: + case t_base_type::TYPE_I16: + case t_base_type::TYPE_I32: + case t_base_type::TYPE_I64: + i_check_value = (field_default_value == NULL) ? 0 : field_default_value->get_integer(); + out << + indent() << "return p." << field_name << " != " << i_check_value << endl; + break; + + case t_base_type::TYPE_DOUBLE: + d_check_value = (field_default_value == NULL) ? 0.0 : field_default_value->get_double(); + out << + indent() << "return p." << field_name << " != " << d_check_value << endl; + break; + + default: + throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); + } + } else if (type->is_enum()) { + out << indent() << "return int64(p." << field_name << ") != " + << "math.MinInt32 - 1" << endl; + } else if (type->is_struct() || type->is_xception()) { + out << + indent() << "return p." << field_name << " != nil" << endl; + } else if (type->is_list() || type->is_set()) { + if (field_default_value != NULL && field_default_value->get_list().size() > 0) { + out << + indent() << "return p." << field_name << " != nil" << endl; + } else { + out << + indent() << "return p." << field_name << " != nil && len(p." << field_name << ") > 0" << endl; + } + } else if (type->is_map()) { + if (field_default_value != NULL && field_default_value->get_map().size() > 0) { + out << + indent() << "return p." << field_name << " != nil" << endl; + } else { + out << + indent() << "return p." << field_name << " != nil && len(p." << field_name << ") > 0" << endl; + } + } else { + throw "CANNOT GENERATE ISSET HELPERS FOR TYPE: " + type->get_name(); + } + + indent_down(); + out << + indent() << "}" << endl << endl; + } + } } /** * Generates the read method for a struct */ void t_go_generator::generate_go_struct_reader(ofstream& out, - t_struct* tstruct, - const string& tstruct_name, - bool is_result) { - (void) is_result; - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - string escaped_tstruct_name(escape_string(tstruct->get_name())); - - out << - indent() << "func (p *" << tstruct_name << ") Read(iprot thrift.TProtocol) (err thrift.TProtocolException) {" << endl; - indent_up(); - - out << - indent() << "_, err = iprot.ReadStructBegin()" << endl << - indent() << "if err != nil { return thrift.NewTProtocolExceptionReadStruct(p.ThriftName(), err); }" << endl; - - // Loop over reading in fields - indent(out) << "for {" << endl; - indent_up(); - - // Read beginning field marker - out << - indent() << "fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()" << endl << - indent() << "if fieldId < 0 {" << endl << - indent() << " fieldId = int16(p.FieldIdFromFieldName(fieldName))" << endl << - indent() << "} else if fieldName == \"\" {" << endl << - indent() << " fieldName = p.FieldNameFromFieldId(int(fieldId))" << endl << - indent() << "}" << endl << - indent() << "if fieldTypeId == thrift.GENERIC {" << endl << - indent() << " fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId()" << endl << - indent() << "}" << endl << - indent() << "if err != nil {" << endl << - indent() << " return thrift.NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)" << endl << - indent() << "}" << endl; - - // Check for field STOP marker and break - out << - indent() << "if fieldTypeId == thrift.STOP { break; }" << endl; - - // Switch statement on the field we are reading - bool first = true; - - // Generate deserialization code for known cases - int32_t field_id = -1; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - field_id = (*f_iter)->get_key(); - if (first) { - first = false; - indent(out); - } else { - indent(out) << "} else "; - } - out << "if fieldId == " << field_id << " || fieldName == \"" << escape_string((*f_iter)->get_name()) << "\" {" << endl; + t_struct* tstruct, + const string& tstruct_name, + bool is_result) +{ + const vector& fields = tstruct->get_members(); + vector::const_iterator f_iter; + string escaped_tstruct_name(escape_string(tstruct->get_name())); + out << + indent() << "func (p *" << tstruct_name << ") Read(iprot thrift.TProtocol) error {" << endl; indent_up(); out << - indent() << "if fieldTypeId == " << type_to_enum((*f_iter)->get_type()) << " {" << endl << - indent() << " err = p.ReadField" << field_id << "(iprot)" << endl << - indent() << " if err != nil { return thrift.NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err); }" << endl << - indent() << "} else if fieldTypeId == thrift.VOID {" << endl << - indent() << " err = iprot.Skip(fieldTypeId)" << endl << - indent() << " if err != nil { return thrift.NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err); }" << endl << - indent() << "} else {" << endl << - indent() << " err = p.ReadField" << field_id << "(iprot)" << endl << - indent() << " if err != nil { return thrift.NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err); }" << endl << - indent() << "}" << endl; - indent_down(); - } - - // In the default case we skip the field - if (first) { + indent() << "if _, err := iprot.ReadStructBegin(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"%T read error\", p)" << endl << + indent() << "}" << endl; + // Loop over reading in fields + indent(out) << "for {" << endl; + indent_up(); + // Read beginning field marker out << - indent() << "err = iprot.Skip(fieldTypeId)" << endl << - indent() << "if err != nil { return thrift.NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err); }" << endl; - } else { + indent() << "_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()" << endl << + indent() << "if err != nil {" << endl << + indent() << " return fmt.Errorf(\"%T field %d read error: %s\", p, fieldId, err)" << endl << + indent() << "}" << endl; + // Check for field STOP marker and break out << - indent() << "} else {" << endl << - indent() << " err = iprot.Skip(fieldTypeId)" << endl << - indent() << " if err != nil { return thrift.NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err); }" << endl << - indent() << "}" << endl; - } - // Read field end marker - out << - indent() << "err = iprot.ReadFieldEnd()" << endl << - indent() << "if err != nil { return thrift.NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err); }" << endl; - - indent_down(); - out << - indent() << "}" << endl << - indent() << "err = iprot.ReadStructEnd()" << endl << - indent() << "if err != nil { return thrift.NewTProtocolExceptionReadStruct(p.ThriftName(), err); }" << endl << - indent() << "return err" << endl; - - indent_down(); - out << - indent() << "}" << endl << endl; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - string field_type_name(publicize((*f_iter)->get_type()->get_name())); - string field_name(publicize((*f_iter)->get_name())); - int32_t field_id = (*f_iter)->get_key(); + indent() << "if fieldTypeId == thrift.STOP { break; }" << endl; + // Switch statement on the field we are reading + bool first = true; + string thriftFieldTypeId; + // Generate deserialization code for known cases + int32_t field_id = -1; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + field_id = (*f_iter)->get_key(); + + if (first) { + first = false; + indent(out) << "switch fieldId {" << endl; + } + + // if negative id, ensure we generate a valid method name + string field_method_prefix("readField"); + + if (field_id < 0) { + field_method_prefix += "_"; + field_id *= -1; + } + + indent_up(); + out << "case " << field_id << ":" << endl; + thriftFieldTypeId = type_to_enum((*f_iter)->get_type()); + + if (thriftFieldTypeId == "thrift.BINARY") { + thriftFieldTypeId = "thrift.STRING"; + } + + out << + indent() << "if err := p." << field_method_prefix << field_id << "(iprot); err != nil {" << endl << + indent() << " return err" << endl << + indent() << "}" << endl; + indent_down(); + } + + // In the default case we skip the field + if (!first) { + out << + indent() << "default:" << endl << + indent() << " if err := iprot.Skip(fieldTypeId); err != nil {" << endl << + indent() << " return err" << endl << + indent() << " }" << endl << + indent() << "}" << endl; + } + + // Read field end marker out << - indent() << "func (p *" << tstruct_name << ") ReadField" << field_id << "(iprot thrift.TProtocol) (err thrift.TProtocolException) {" << endl; - indent_up(); - generate_deserialize_field(out, *f_iter, false, "p."); + indent() << "if err := iprot.ReadFieldEnd(); err != nil {" << endl << + indent() << " return err" << endl << + indent() << "}" << endl; indent_down(); out << - indent() << " return err" << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << tstruct_name << ") ReadField" << field_name << "(iprot thrift.TProtocol) (thrift.TProtocolException) {" << endl << - indent() << " return p.ReadField" << field_id << "(iprot)" << endl << - indent() << "}" << endl << endl; - } + indent() << "}" << endl << + indent() << "if err := iprot.ReadStructEnd(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"%T read struct end error: %s\", p, err)" << endl << + indent() << "}" << endl << + indent() << "return nil" << endl; + indent_down(); + out << + indent() << "}" << endl << endl; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + string field_type_name(publicize((*f_iter)->get_type()->get_name())); + string field_name(publicize((*f_iter)->get_name())); + string field_method_prefix("readField"); + int32_t field_id = (*f_iter)->get_key(); + + if (field_id < 0) { + field_method_prefix += "_"; + field_id *= -1; + } + + out << + indent() << "func (p *" << tstruct_name << ") " << field_method_prefix << field_id << "(iprot thrift.TProtocol) error {" << endl; + indent_up(); + generate_deserialize_field(out, *f_iter, false, "p."); + indent_down(); + out << + indent() << " return nil" << endl << + indent() << "}" << endl << endl; + } } void t_go_generator::generate_go_struct_writer(ofstream& out, - t_struct* tstruct, - const string& tstruct_name, - bool is_result) { - string name(tstruct->get_name()); - const vector& fields = tstruct->get_sorted_members(); - vector::const_iterator f_iter; - - indent(out) << - "func (p *" << tstruct_name << ") Write(oprot thrift.TProtocol) (err thrift.TProtocolException) {" << endl; - indent_up(); - - out << - indent() << "err = oprot.WriteStructBegin(\"" << name << "\")" << endl << - indent() << "if err != nil { return thrift.NewTProtocolExceptionWriteStruct(" << - "p.ThriftName(), err); }" << endl; - - string field_name; - string escape_field_name; - int32_t fieldId = -1; - if (is_result && fields.size()) { + t_struct* tstruct, + const string& tstruct_name, + bool is_result) +{ + string name(tstruct->get_name()); + const vector& fields = tstruct->get_sorted_members(); + vector::const_iterator f_iter; + indent(out) << + "func (p *" << tstruct_name << ") Write(oprot thrift.TProtocol) error {" << endl; + indent_up(); out << - indent() << "switch {" << endl; - vector::const_reverse_iterator fr_iter; - for (fr_iter = fields.rbegin(); fr_iter != fields.rend(); ++fr_iter) { - field_name = (*fr_iter)->get_name(); - fieldId = (*fr_iter)->get_key(); - if(can_be_nil((*fr_iter)->get_type()) && fieldId != 0) { + indent() << "if err := oprot.WriteStructBegin(\"" << name << "\"); err != nil {" << endl << + indent() << " return fmt.Errorf(\"%T write struct begin error: %s\", p, err) }" << endl; + + string field_name; + 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() << "case p." << publicize(variable_name_to_go_name(field_name)) << " != nil:" << endl << - indent() << " if err = p.WriteField" << fieldId << "(oprot); err != nil {" << endl << - indent() << " return err" << endl << - indent() << " }" << endl; - } else { + indent() << "switch {" << endl; + vector::const_reverse_iterator fr_iter; + + 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; + } + } + out << - indent() << "default:" << endl << - indent() << " if err = p.WriteField" << fieldId << "(oprot); err != nil {" << endl << - indent() << " return err" << endl << - indent() << " }" << endl; - } - } - out << - indent() << "}" << endl; - } else { - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - field_name = (*f_iter)->get_name(); - escape_field_name = escape_string(field_name); - fieldId = (*f_iter)->get_key(); - out << - indent() << "err = p.WriteField" << fieldId << "(oprot)" << endl << - indent() << "if err != nil { return err }" << endl; - } - } - - // Write the struct map - out << - indent() << "err = oprot.WriteFieldStop()" << endl << - indent() << "if err != nil { return thrift.NewTProtocolExceptionWriteField(-1, \"STOP\", p.ThriftName(), err); }" << endl << - indent() << "err = oprot.WriteStructEnd()" << endl << - indent() << "if err != nil { return thrift.NewTProtocolExceptionWriteStruct(" << - "p.ThriftName(), err); }" << endl << - indent() << "return err" << endl; - - indent_down(); - out << - indent() << "}" << endl << endl; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - fieldId = (*f_iter)->get_key(); - field_name = (*f_iter)->get_name(); - escape_field_name = escape_string(field_name); - out << - indent() << "func (p *" << tstruct_name << ") WriteField" << fieldId << "(oprot thrift.TProtocol) (err thrift.TProtocolException) {" << endl; - indent_up(); - // Write field header - if (can_be_nil((*f_iter)->get_type())) { - out << - indent() << "if p." << publicize(variable_name_to_go_name(field_name)) << " != nil {" << endl; - indent_up(); + 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(); + + 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 out << - indent() << "err = oprot.WriteFieldBegin(\"" << - escape_field_name << "\", " << - type_to_enum((*f_iter)->get_type()) << ", " << - fieldId << ")" << endl << - indent() << "if err != nil { return thrift.NewTProtocolExceptionWriteField(" << - fieldId << ", \"" << - escape_field_name << "\", " << - "p.ThriftName(), err); }" << endl; - - // Write field contents - generate_serialize_field(out, *f_iter, "p."); - - // Write field closer + indent() << "if err := oprot.WriteFieldStop(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"%T write field stop error: %s\", err) }" << endl << + indent() << "if err := oprot.WriteStructEnd(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"%T write struct stop error: %s\", err) }" << endl << + indent() << "return nil" << endl; + indent_down(); out << - indent() << "err = oprot.WriteFieldEnd()" << endl << - indent() << "if err != nil { return thrift.NewTProtocolExceptionWriteField(" << - fieldId << ", \"" << - escape_field_name << "\", " << - "p.ThriftName(), err); }" << endl; + indent() << "}" << endl << endl; - if (can_be_nil((*f_iter)->get_type())) { - indent_down(); - out << - indent() << "}" << endl; + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + string field_method_prefix("writeField"); + field_id = (*f_iter)->get_key(); + field_name = (*f_iter)->get_name(); + 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 += "_"; + field_id *= -1; + } + + out << + 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 || (*f_iter)->get_type()->is_enum()) { + out << + indent() << "if p.IsSet" << publicize(variable_name_to_go_name(field_name)) << "() {" << endl; + indent_up(); + } + + out << + indent() << "if err := oprot.WriteFieldBegin(\"" << + escape_field_name << "\", " << + type_to_enum((*f_iter)->get_type()) << ", " << + field_id << "); err != nil {" << endl << + indent() << " return fmt.Errorf(\"%T write field begin error " << field_id << ":" << escape_field_name << ": %s\", p, err); }" << endl; + + // Write field contents + generate_serialize_field(out, *f_iter, "p."); + + + // Write field closer + out << + indent() << "if err := oprot.WriteFieldEnd(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"%T write field end error " << field_id << ":" << escape_field_name << ": %s\", p, err); }" << endl; + + if (field_required == t_field::T_OPTIONAL || (*f_iter)->get_type()->is_enum()) { + indent_down(); + out << + indent() << "}" << endl; + } + + if (field_can_be_nil) { + indent_down(); + out << + indent() << "}" << endl; + } + + indent_down(); + out << + indent() << " return err" << endl << + indent() << "}" << endl << endl; } - indent_down(); - out << - indent() << " return err" << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << tstruct_name << ") WriteField" << publicize(field_name) << "(oprot thrift.TProtocol) (thrift.TProtocolException) {" << endl << - indent() << " return p.WriteField" << fieldId << "(oprot)" << endl << - indent() << "}" << endl << endl; - } } /** @@ -1235,38 +1343,31 @@ void t_go_generator::generate_go_struct_writer(ofstream& out, * * @param tservice The service definition */ -void t_go_generator::generate_service(t_service* tservice) { - string f_service_name = package_dir_+"/"+service_name_+".go"; - f_service_.open(f_service_name.c_str()); +void t_go_generator::generate_service(t_service* tservice) +{ + string f_service_name = package_dir_ + "/" + underscore(service_name_) + ".go"; + f_service_.open(f_service_name.c_str()); + f_service_ << + go_autogen_comment() << + go_package() << + go_imports_begin(); - f_service_ << - go_autogen_comment() << - go_package() << - go_imports(); + if (tservice->get_extends() != NULL) { + f_service_ << "\t\"" << gen_package_prefix_ + get_real_go_module(tservice->get_extends()->get_program()) << "\"\n"; + } - if (tservice->get_extends() != NULL) { - f_service_ << - "import \"thriftlib/" << get_real_go_module(tservice->get_extends()->get_program()) << "\"" << endl; - } - - f_service_ << - "import (" << endl << - indent() << " \"os\"" << endl << - indent() << ")" << endl << endl << - render_fastbinary_includes(); - - f_service_ << endl; - - // Generate the three main parts of the service (well, two for now in PHP) - generate_service_interface(tservice); - generate_service_client(tservice); - generate_service_server(tservice); - generate_service_helpers(tservice); - generate_service_remote(tservice); - - // Close service file - f_service_ << endl; - f_service_.close(); + f_service_ << render_fastbinary_includes(); + f_service_ << go_imports_end(); + + generate_service_interface(tservice); + generate_service_client(tservice); + generate_service_server(tservice); + generate_service_helpers(tservice); + generate_service_remote(tservice); + // Close service file + f_service_ << endl; + f_service_.close(); + format_go_output(f_service_name); } /** @@ -1274,18 +1375,18 @@ void t_go_generator::generate_service(t_service* tservice) { * * @param tservice The service to generate a header definition for */ -void t_go_generator::generate_service_helpers(t_service* tservice) { - vector functions = tservice->get_functions(); - vector::iterator f_iter; - - f_service_ << - "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl; - - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - t_struct* ts = (*f_iter)->get_arglist(); - generate_go_struct_definition(f_service_, ts, false); - generate_go_function_helpers(*f_iter); - } +void t_go_generator::generate_service_helpers(t_service* tservice) +{ + vector functions = tservice->get_functions(); + vector::iterator f_iter; + f_service_ << + "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + t_struct* ts = (*f_iter)->get_arglist(); + generate_go_struct_definition(f_service_, ts, false); + generate_go_function_helpers(*f_iter); + } } /** @@ -1293,22 +1394,26 @@ void t_go_generator::generate_service_helpers(t_service* tservice) { * * @param tfunction The function */ -void t_go_generator::generate_go_function_helpers(t_function* tfunction) { - if (true || !tfunction->is_oneway()) { - t_struct result(program_, tfunction->get_name() + "_result"); - t_field success(tfunction->get_returntype(), "success", 0); - if (!tfunction->get_returntype()->is_void()) { - result.append(&success); - } +void t_go_generator::generate_go_function_helpers(t_function* tfunction) +{ + if (true || !tfunction->is_oneway()) { + t_struct result(program_, tfunction->get_name() + "_result"); + t_field success(tfunction->get_returntype(), "success", 0); + + if (!tfunction->get_returntype()->is_void()) { + result.append(&success); + } - t_struct* xs = tfunction->get_xceptions(); - const vector& fields = xs->get_members(); - vector::const_iterator f_iter; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - result.append(*f_iter); + t_struct* xs = tfunction->get_xceptions(); + const vector& fields = xs->get_members(); + vector::const_iterator f_iter; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + result.append(*f_iter); + } + + generate_go_struct_definition(f_service_, &result, false, true); } - generate_go_struct_definition(f_service_, &result, false, true); - } } /** @@ -1316,39 +1421,44 @@ void t_go_generator::generate_go_function_helpers(t_function* tfunction) { * * @param tservice The service to generate a header definition for */ -void t_go_generator::generate_service_interface(t_service* tservice) { - string extends = ""; - string extends_if = ""; - string serviceName(publicize(tservice->get_name())); - string interfaceName = "I" + serviceName; - if (tservice->get_extends() != NULL) { - extends = type_name(tservice->get_extends()); - size_t index = extends.rfind("."); - if(index != string::npos) { - extends_if = "\n" + indent() + " " + extends.substr(0, index + 1) + "I" + publicize(extends.substr(index + 1)) + "\n"; - } else { - extends_if = "\n" + indent() + "I" + publicize(extends) + "\n"; +void t_go_generator::generate_service_interface(t_service* tservice) +{ + string extends = ""; + string extends_if = ""; + string serviceName(publicize(tservice->get_name())); + string interfaceName = serviceName; + + if (tservice->get_extends() != NULL) { + extends = type_name(tservice->get_extends()); + size_t index = extends.rfind("."); + + if (index != string::npos) { + extends_if = "\n" + indent() + " " + extends.substr(0, index + 1) + publicize(extends.substr(index + 1)) + "\n"; + } else { + extends_if = "\n" + indent() + publicize(extends) + "\n"; + } } - } - f_service_ << - indent() << "type " << interfaceName << " interface {" << extends_if; - indent_up(); - generate_go_docstring(f_service_, tservice); - vector functions = tservice->get_functions(); - if (!functions.empty()) { - f_service_ << endl; - vector::iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - generate_go_docstring(f_service_, (*f_iter)); - f_service_ << - indent() << function_signature_if(*f_iter, "", true) << endl; + f_service_ << + indent() << "type " << interfaceName << " interface {" << extends_if; + indent_up(); + generate_go_docstring(f_service_, tservice); + vector functions = tservice->get_functions(); + + if (!functions.empty()) { + f_service_ << endl; + vector::iterator f_iter; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + generate_go_docstring(f_service_, (*f_iter)); + f_service_ << + indent() << function_signature_if(*f_iter, "", true) << endl; + } } - } - indent_down(); - f_service_ << - indent() << "}" << endl << endl; + indent_down(); + f_service_ << + indent() << "}" << endl << endl; } /** @@ -1356,259 +1466,268 @@ void t_go_generator::generate_service_interface(t_service* tservice) { * * @param tservice The service to generate a server for. */ -void t_go_generator::generate_service_client(t_service* tservice) { - string extends = ""; - string extends_client = ""; - string extends_client_new = ""; - string serviceName(publicize(tservice->get_name())); - if (tservice->get_extends() != NULL) { - extends = type_name(tservice->get_extends()); - size_t index = extends.rfind("."); - if(index != string::npos) { - extends_client = extends.substr(0, index + 1) + publicize(extends.substr(index + 1)) + "Client"; - extends_client_new = extends.substr(0, index + 1) + "New" + publicize(extends.substr(index + 1)) + "Client"; - } else { - extends_client = publicize(extends) + "Client"; - extends_client_new = "New" + extends_client; - } - } - - generate_go_docstring(f_service_, tservice); - f_service_ << - indent() << "type " << serviceName << "Client struct {" << endl; - indent_up(); - if(!extends_client.empty()) { - f_service_ << - indent() << "*" << extends_client << endl; - } else { - f_service_ << - indent() << "Transport thrift.TTransport" << endl << - indent() << "ProtocolFactory thrift.TProtocolFactory" << endl << - indent() << "InputProtocol thrift.TProtocol" << endl << - indent() << "OutputProtocol thrift.TProtocol" << endl << - indent() << "SeqId int32" << endl /*<< - indent() << "reqs map[int32]Deferred" << endl*/; - } - indent_down(); - f_service_ << - indent() << "}" << endl << endl; - - // Constructor function - f_service_ << - indent() << "func New" << serviceName << "ClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *" << serviceName << "Client {" << endl; - indent_up(); - f_service_ << - indent() << "return &" << serviceName << "Client"; - if (!extends.empty()) { - f_service_ << - "{" << extends_client << ": " << extends_client_new << "Factory(t, f)}"; - } else { - indent_up(); - f_service_ << "{Transport: t," << endl << - indent() << "ProtocolFactory: f," << endl << - indent() << "InputProtocol: f.GetProtocol(t)," << endl << - indent() << "OutputProtocol: f.GetProtocol(t)," << endl << - indent() << "SeqId: 0," << endl /*<< - indent() << "Reqs: make(map[int32]Deferred)" << endl*/; - indent_down(); +void t_go_generator::generate_service_client(t_service* tservice) +{ + string extends = ""; + string extends_field = ""; + string extends_client = ""; + string extends_client_new = ""; + string serviceName(publicize(tservice->get_name())); + + if (tservice->get_extends() != NULL) { + extends = type_name(tservice->get_extends()); + size_t index = extends.rfind("."); + + if (index != string::npos) { + extends_client = extends.substr(0, index + 1) + publicize(extends.substr(index + 1)) + "Client"; + extends_client_new = extends.substr(0, index + 1) + "New" + publicize(extends.substr(index + 1)) + "Client"; + } else { + extends_client = publicize(extends) + "Client"; + extends_client_new = "New" + extends_client; + } + } + + extends_field = extends_client.substr(extends_client.find(".") + 1); + + generate_go_docstring(f_service_, tservice); f_service_ << - indent() << "}" << endl; - } - indent_down(); - f_service_ << - indent() << "}" << endl << endl; - - - // Constructor function - f_service_ << - indent() << "func New" << serviceName << "ClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *" << serviceName << "Client {" << endl; - indent_up(); - f_service_ << - indent() << "return &" << serviceName << "Client"; - if (!extends.empty()) { - f_service_ << - "{" << extends_client << ": " << extends_client_new << "Protocol(t, iprot, oprot)}" << endl; - } else { + indent() << "type " << serviceName << "Client struct {" << endl; indent_up(); - f_service_ << "{Transport: t," << endl << - indent() << "ProtocolFactory: nil," << endl << - indent() << "InputProtocol: iprot," << endl << - indent() << "OutputProtocol: oprot," << endl << - indent() << "SeqId: 0," << endl /*<< - indent() << "Reqs: make(map[int32]interface{})" << endl*/; + + if (!extends_client.empty()) { + f_service_ << + indent() << "*" << extends_client << endl; + } else { + f_service_ << + indent() << "Transport thrift.TTransport" << endl << + indent() << "ProtocolFactory thrift.TProtocolFactory" << endl << + indent() << "InputProtocol thrift.TProtocol" << endl << + indent() << "OutputProtocol thrift.TProtocol" << endl << + indent() << "SeqId int32" << endl /*<< + indent() << "reqs map[int32]Deferred" << endl*/; + } + indent_down(); f_service_ << - indent() << "}" << endl; - } - indent_down(); - f_service_ << - indent() << "}" << endl << endl; - - // Generate client method implementations - vector functions = tservice->get_functions(); - vector::const_iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - t_struct* arg_struct = (*f_iter)->get_arglist(); - const vector& fields = arg_struct->get_members(); - vector::const_iterator fld_iter; - string funname = publicize((*f_iter)->get_name()); - - // Open function - generate_go_docstring(f_service_, (*f_iter)); + indent() << "}" << endl << endl; + // Constructor function f_service_ << - indent() << "func (p *" << serviceName << "Client) " << function_signature_if(*f_iter, "", true) << " {" << endl; + indent() << "func New" << serviceName << "ClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *" << serviceName << "Client {" << endl; indent_up(); - /* - f_service_ << - indent() << "p.SeqId += 1" << endl; - if (!(*f_iter)->is_oneway()) { - f_service_ << - indent() << "d := defer.Deferred()" << endl << - indent() << "p.Reqs[p.SeqId] = d" << endl; - } - */ f_service_ << - indent() << "err = p.Send" << funname << "("; + indent() << "return &" << serviceName << "Client"; - bool first = true; - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - if (first) { - first = false; - } else { - f_service_ << ", "; - } - f_service_ << variable_name_to_go_name((*fld_iter)->get_name()); - } - f_service_ << ")" << endl << - indent() << "if err != nil { return }" << endl; - - - if (!(*f_iter)->is_oneway()) { - f_service_ << - indent() << "return p.Recv" << funname << "()" << endl; + if (!extends.empty()) { + f_service_ << + "{" << extends_field << ": " << extends_client_new << "Factory(t, f)}"; } else { - f_service_ << - indent() << "return" << endl; + indent_up(); + f_service_ << "{Transport: t," << endl << + indent() << "ProtocolFactory: f," << endl << + indent() << "InputProtocol: f.GetProtocol(t)," << endl << + indent() << "OutputProtocol: f.GetProtocol(t)," << endl << + indent() << "SeqId: 0," << endl /*<< + indent() << "Reqs: make(map[int32]Deferred)" << endl*/; + indent_down(); + f_service_ << + indent() << "}" << endl; } + indent_down(); - f_service_ << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Client) Send" << function_signature(*f_iter) << "(err os.Error) {" << endl; - + f_service_ << + indent() << "}" << endl << endl; + // Constructor function + f_service_ << + indent() << "func New" << serviceName << "ClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *" << serviceName << "Client {" << endl; indent_up(); - - std::string argsname = privatize((*f_iter)->get_name()) + "Args"; - - // Serialize the request header - string args(tmp("args")); f_service_ << - indent() << "oprot := p.OutputProtocol" << endl << - indent() << "if oprot != nil {" << endl << - indent() << " oprot = p.ProtocolFactory.GetProtocol(p.Transport)" << endl << - indent() << " p.OutputProtocol = oprot" << endl << - indent() << "}" << endl << - indent() << "p.SeqId++" << endl << - indent() << "oprot.WriteMessageBegin(\"" << (*f_iter)->get_name() << "\", thrift.CALL, p.SeqId)" << endl << - indent() << args << " := New" << publicize(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() << "return &" << serviceName << "Client"; + + if (!extends.empty()) { + f_service_ << + "{" << extends_field << ": " << extends_client_new << "Protocol(t, iprot, oprot)}" << endl; + } else { + indent_up(); + f_service_ << "{Transport: t," << endl << + indent() << "ProtocolFactory: nil," << endl << + indent() << "InputProtocol: iprot," << endl << + indent() << "OutputProtocol: oprot," << endl << + indent() << "SeqId: 0," << endl /*<< + indent() << "Reqs: make(map[int32]interface{})" << endl*/; + indent_down(); + f_service_ << + indent() << "}" << endl; } - - // Write to the stream - f_service_ << - indent() << "err = " << args << ".Write(oprot)" << endl << - indent() << "oprot.WriteMessageEnd()" << endl << - indent() << "oprot.Transport().Flush()" << endl << - indent() << "return" << endl; + indent_down(); f_service_ << - indent() << "}" << endl << endl; - - if (true) { //!(*f_iter)->is_oneway() || true) {} - std::string resultname = privatize((*f_iter)->get_name()) + "Result"; - // Open function - f_service_ << endl << - indent() << "func (p *" << serviceName << "Client) Recv" << publicize((*f_iter)->get_name()) << - "() ("; - if(!(*f_iter)->get_returntype()->is_void()) { + indent() << "}" << endl << endl; + // Generate client method implementations + vector functions = tservice->get_functions(); + vector::const_iterator f_iter; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + t_struct* arg_struct = (*f_iter)->get_arglist(); + const vector& fields = arg_struct->get_members(); + vector::const_iterator fld_iter; + string funname = publicize((*f_iter)->get_name()); + // Open function + generate_go_docstring(f_service_, (*f_iter)); f_service_ << - "value " << type_to_go_type((*f_iter)->get_returntype()) << ", "; - } - t_struct* exceptions = (*f_iter)->get_xceptions(); - string errs = argument_list(exceptions); - if(errs.size()) { - f_service_ << errs << ", "; - } - f_service_ << - "err os.Error) {" << endl; - indent_up(); + indent() << "func (p *" << serviceName << "Client) " << function_signature_if(*f_iter, "", true) << " {" << endl; + indent_up(); + /* + f_service_ << + indent() << "p.SeqId += 1" << endl; + if (!(*f_iter)->is_oneway()) { + f_service_ << + indent() << "d := defer.Deferred()" << endl << + indent() << "p.Reqs[p.SeqId] = d" << endl; + } + */ + f_service_ << + indent() << "if err = p.send" << funname << "("; + bool first = true; - // TODO(mcslee): Validate message reply here, seq ids etc. - - string result(tmp("result")); - string error(tmp("error")); - string error2(tmp("error")); - - f_service_ << - indent() << "iprot := p.InputProtocol" << endl << - indent() << "if iprot == nil {" << endl << - indent() << " iprot = p.ProtocolFactory.GetProtocol(p.Transport)" << endl << - indent() << " p.InputProtocol = iprot" << endl << - indent() << "}" << endl << - indent() << "_, mTypeId, seqId, err := iprot.ReadMessageBegin()" << endl << - indent() << "if err != nil {" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << "if mTypeId == thrift.EXCEPTION {" << endl << - indent() << " " << error << " := thrift.NewTApplicationExceptionDefault()" << endl << - indent() << " " << error2 << ", err := " << error << ".Read(iprot)" << endl << - indent() << " if err != nil {" << endl << - indent() << " return" << endl << - indent() << " }" << endl << - indent() << " if err = iprot.ReadMessageEnd(); err != nil {" << endl << - indent() << " return" << endl << - indent() << " }" << endl << - indent() << " err = " << error2 << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << "if p.SeqId != seqId {" << endl << - indent() << " err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, \"ping failed: out of sequence response\")" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << result << " := New" << publicize(resultname) << "()" << endl << - indent() << "err = " << result << ".Read(iprot)" << endl << - indent() << "iprot.ReadMessageEnd()" << endl; + for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { + if (first) { + first = false; + } else { + f_service_ << ", "; + } + + f_service_ << variable_name_to_go_name((*fld_iter)->get_name()); + } + + f_service_ << "); err != nil { return }" << endl; - // Careful, only return _result if not a void function - if (!(*f_iter)->get_returntype()->is_void()) { + if (!(*f_iter)->is_oneway()) { + f_service_ << + indent() << "return p.recv" << funname << "()" << endl; + } else { + f_service_ << + indent() << "return" << endl; + } + + indent_down(); f_service_ << - indent() << "value = " << result << ".Success" << endl; - } - - t_struct* xs = (*f_iter)->get_xceptions(); - const std::vector& xceptions = xs->get_members(); - vector::const_iterator x_iter; - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { + indent() << "}" << endl << endl << + indent() << "func (p *" << serviceName << "Client) send" << function_signature(*f_iter) << "(err error) {" << endl; + indent_up(); + std::string argsname = privatize((*f_iter)->get_name()) + "Args"; + // Serialize the request header + string args(tmp("args")); f_service_ << - indent() << "if " << result << "." << publicize((*x_iter)->get_name()) << " != nil {" << endl << - indent() << " " << (*x_iter)->get_name() << " = " << result << "." << publicize((*x_iter)->get_name()) << endl << - indent() << "}" << endl; - } - - f_service_ << - indent() << "return" << endl; - // Close function - indent_down(); - f_service_ << - indent() << "}" << endl << endl; + indent() << "oprot := p.OutputProtocol" << endl << + indent() << "if oprot == nil {" << endl << + indent() << " oprot = p.ProtocolFactory.GetProtocol(p.Transport)" << endl << + indent() << " p.OutputProtocol = oprot" << endl << + indent() << "}" << endl << + indent() << "p.SeqId++" << endl << + indent() << "oprot.WriteMessageBegin(\"" << (*f_iter)->get_name() << "\", thrift.CALL, p.SeqId)" << endl << + indent() << args << " := New" << publicize(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; + } + + // Write to the stream + f_service_ << + indent() << "err = " << args << ".Write(oprot)" << endl << + indent() << "oprot.WriteMessageEnd()" << endl << + indent() << "oprot.Flush()" << endl << + indent() << "return" << endl; + indent_down(); + f_service_ << + indent() << "}" << endl << endl; + + if (true) { //!(*f_iter)->is_oneway() || true) {} + std::string resultname = privatize((*f_iter)->get_name()) + "Result"; + // Open function + f_service_ << endl << + indent() << "func (p *" << serviceName << "Client) recv" << publicize((*f_iter)->get_name()) << + "() ("; + + if (!(*f_iter)->get_returntype()->is_void()) { + f_service_ << + "value " << type_to_go_type((*f_iter)->get_returntype()) << ", "; + } + + t_struct* exceptions = (*f_iter)->get_xceptions(); + string errs = argument_list(exceptions); + + if (errs.size()) { + f_service_ << errs << ", "; + } + + f_service_ << + "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_ << + indent() << "iprot := p.InputProtocol" << endl << + indent() << "if iprot == nil {" << endl << + indent() << " iprot = p.ProtocolFactory.GetProtocol(p.Transport)" << endl << + indent() << " p.InputProtocol = iprot" << endl << + indent() << "}" << endl << + indent() << "_, mTypeId, seqId, err := iprot.ReadMessageBegin()" << endl << + indent() << "if err != nil {" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << "if mTypeId == thrift.EXCEPTION {" << endl << + indent() << " " << error << " := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, \"Unknown Exception\")" << endl << + indent() << " var " << error2 << " error" << endl << + indent() << " " << error2 << ", err = " << error << ".Read(iprot)" << endl << + indent() << " if err != nil {" << endl << + indent() << " return" << endl << + indent() << " }" << endl << + indent() << " if err = iprot.ReadMessageEnd(); err != nil {" << endl << + indent() << " return" << endl << + indent() << " }" << endl << + indent() << " err = " << error2 << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << "if p.SeqId != seqId {" << endl << + indent() << " err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, \"ping failed: out of sequence response\")" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << result << " := New" << publicize(resultname) << "()" << endl << + indent() << "err = " << result << ".Read(iprot)" << endl << + indent() << "iprot.ReadMessageEnd()" << endl; + + // Careful, only return _result if not a void function + if (!(*f_iter)->get_returntype()->is_void()) { + f_service_ << + indent() << "value = " << result << ".Success" << endl; + } + + t_struct* xs = (*f_iter)->get_xceptions(); + const std::vector& xceptions = xs->get_members(); + vector::const_iterator x_iter; + + for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { + f_service_ << + indent() << "if " << result << "." << publicize((*x_iter)->get_name()) << " != nil {" << endl << + indent() << " " << (*x_iter)->get_name() << " = " << result << "." << publicize((*x_iter)->get_name()) << endl << + indent() << "}" << endl; + } + + f_service_ << + indent() << "return" << endl; + // Close function + indent_down(); + f_service_ << + indent() << "}" << endl << endl; + } } - } - //indent_down(); - f_service_ << - endl; + //indent_down(); + f_service_ << + endl; } /** @@ -1616,367 +1735,414 @@ void t_go_generator::generate_service_client(t_service* tservice) { * * @param tservice The service to generate a remote for. */ -void t_go_generator::generate_service_remote(t_service* tservice) { - vector functions = tservice->get_functions(); - vector::iterator f_iter; - - string f_remote_name = package_dir_+"/"+service_name_+"/"+service_name_+"-remote.go"; - ofstream f_remote; - f_remote.open(f_remote_name.c_str()); - string service_module = get_real_go_module(program_); - string::size_type loc; - while((loc = service_module.find(".")) != string::npos) { - service_module.replace(loc, 1, 1, '/'); - } - - f_remote << - go_autogen_comment() << - indent() << "package main" << endl << endl << - indent() << "import (" << endl << - indent() << " \"flag\"" << endl << - indent() << " \"fmt\"" << endl << - indent() << " \"http\"" << endl << - indent() << " \"net\"" << endl << - indent() << " \"os\"" << endl << - indent() << " \"strconv\"" << endl << - indent() << " \"thrift\"" << endl << - indent() << " \"thriftlib/" << service_module << "\"" << endl << - indent() << ")" << endl << - indent() << endl << - indent() << "func Usage() {" << endl << - indent() << " fmt.Fprint(os.Stderr, \"Usage of \", os.Args[0], \" [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:\\n\")" << endl << - indent() << " flag.PrintDefaults()" << endl << - indent() << " fmt.Fprint(os.Stderr, \"Functions:\\n\")" << endl; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - string funcName((*f_iter)->get_name()); - string funcSignature(function_signature_if(*f_iter, "", true)); +void t_go_generator::generate_service_remote(t_service* tservice) +{ + vector functions = tservice->get_functions(); + t_service* parent = tservice->get_extends(); + + // collect inherited functions + while (parent != NULL) { + vector p_functions = parent->get_functions(); + functions.insert(functions.end(), p_functions.begin(), p_functions.end()); + parent = parent->get_extends(); + } + + vector::iterator f_iter; + string f_remote_name = package_dir_ + "/" + underscore(service_name_) + "-remote/" + underscore(service_name_) + "-remote.go"; + ofstream f_remote; + f_remote.open(f_remote_name.c_str()); + string service_module = get_real_go_module(program_); + string::size_type loc; + + while ((loc = service_module.find(".")) != string::npos) { + service_module.replace(loc, 1, 1, '/'); + } + f_remote << - indent() << " fmt.Fprint(os.Stderr, \" " << funcName << funcSignature.substr(funcSignature.find("(")) << "\\n\")" << endl; - } - f_remote << - indent() << " fmt.Fprint(os.Stderr, \"\\n\")" << endl << - indent() << " os.Exit(0)" << endl << - indent() << "}" << endl << - indent() << endl << - indent() << "func main() {" << endl; - indent_up(); - f_remote << - indent() << "flag.Usage = Usage" << endl << - indent() << "var host string" << endl << - indent() << "var port int" << endl << - indent() << "var protocol string" << endl << - indent() << "var urlString string" << endl << - indent() << "var framed bool" << endl << - indent() << "var useHttp bool" << endl << - indent() << "var help bool" << endl << - indent() << "var url http.URL" << endl << - indent() << "var trans thrift.TTransport" << endl << - indent() << "flag.Usage = Usage" << endl << - indent() << "flag.StringVar(&host, \"h\", \"localhost\", \"Specify host and port\")" << endl << - indent() << "flag.IntVar(&port, \"p\", 9090, \"Specify port\")" << endl << - indent() << "flag.StringVar(&protocol, \"P\", \"binary\", \"Specify the protocol (binary, compact, simplejson, json)\")" << endl << - indent() << "flag.StringVar(&urlString, \"u\", \"\", \"Specify the url\")" << endl << - indent() << "flag.BoolVar(&framed, \"framed\", false, \"Use framed transport\")" << endl << - indent() << "flag.BoolVar(&useHttp, \"http\", false, \"Use http\")" << endl << - indent() << "flag.BoolVar(&help, \"help\", false, \"See usage string\")" << endl << - indent() << "flag.Parse()" << endl << - indent() << "if help || flag.NArg() == 0 {" << endl << - indent() << " flag.Usage()" << endl << - indent() << "}" << endl << - indent() << endl << - indent() << "if len(urlString) > 0 {" << endl << - indent() << " url, err := http.ParseURL(urlString)" << endl << - indent() << " if err != nil {" << endl << - indent() << " fmt.Fprint(os.Stderr, \"Error parsing URL: \", err.String(), \"\\n\")" << endl << - indent() << " flag.Usage()" << endl << - indent() << " }" << endl << - indent() << " host = url.Host" << endl << - //indent() << " if len(url.Port) == 0 { url.Port = \"80\"; }" << endl << - //indent() << " port = int(url.Port)" << endl << - indent() << " useHttp = len(url.Scheme) <= 0 || url.Scheme == \"http\"" << endl << - indent() << "} else if useHttp {" << endl << - indent() << " _, err := http.ParseURL(fmt.Sprint(\"http://\", host, \":\", port))" << endl << - indent() << " if err != nil {" << endl << - indent() << " fmt.Fprint(os.Stderr, \"Error parsing URL: \", err.String(), \"\\n\")" << endl << - indent() << " flag.Usage()" << endl << - indent() << " }" << endl << - indent() << "}" << endl << - indent() << endl << - indent() << "cmd := flag.Arg(0)" << endl << - indent() << "var err os.Error" << endl << - indent() << "if useHttp {" << endl << - indent() << " trans, err = thrift.NewTHttpClient(url.Raw)" << endl << - indent() << "} else {" << endl << - indent() << " addr, err := net.ResolveTCPAddr(\"tcp\", fmt.Sprint(host, \":\", port))" << endl << - indent() << " if err != nil {" << endl << - indent() << " fmt.Fprint(os.Stderr, \"Error resolving address\", err.String())" << endl << - indent() << " os.Exit(1)" << endl << - indent() << " }" << endl << - indent() << " trans, err = thrift.NewTNonblockingSocketAddr(addr)" << endl << - indent() << " if framed {" << endl << - indent() << " trans = thrift.NewTFramedTransport(trans)" << endl << - indent() << " }" << endl << - indent() << "}" << endl << - indent() << "if err != nil {" << endl << - indent() << " fmt.Fprint(os.Stderr, \"Error creating transport\", err.String())" << endl << - indent() << " os.Exit(1)" << endl << - indent() << "}" << endl << - indent() << "defer trans.Close()" << endl << - indent() << "var protocolFactory thrift.TProtocolFactory" << endl << - indent() << "switch protocol {" << endl << - indent() << "case \"compact\":" << endl << - indent() << " protocolFactory = thrift.NewTCompactProtocolFactory()" << endl << - indent() << " break" << endl << - indent() << "case \"simplejson\":" << endl << - indent() << " protocolFactory = thrift.NewTSimpleJSONProtocolFactory()" << endl << - indent() << " break" << endl << - indent() << "case \"json\":" << endl << - indent() << " protocolFactory = thrift.NewTJSONProtocolFactory()" << endl << - indent() << " break" << endl << - indent() << "case \"binary\", \"\":" << endl << - indent() << " protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()" << endl << - indent() << " break" << endl << - indent() << "default:" << endl << - indent() << " fmt.Fprint(os.Stderr, \"Invalid protocol specified: \", protocol, \"\\n\")" << endl << - indent() << " Usage()" << endl << - indent() << " os.Exit(1)" << endl << - indent() << "}" << endl << - indent() << "client := " << package_name_ << ".New" << publicize(service_name_) << "ClientFactory(trans, protocolFactory)" << endl << - indent() << "if err = trans.Open(); err != nil {" << endl << - indent() << " fmt.Fprint(os.Stderr, \"Error opening socket to \", host, \":\", port, \" \", err.String())" << endl << - indent() << " os.Exit(1)" << endl << - indent() << "}" << endl << - indent() << endl << - indent() << "switch cmd {" << endl; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - - t_struct* arg_struct = (*f_iter)->get_arglist(); - const std::vector& args = arg_struct->get_members(); - vector::const_iterator a_iter; - int num_args = args.size(); - string funcName((*f_iter)->get_name()); - string pubName(publicize(funcName)); - + indent() << "package main" << endl << endl << + go_autogen_comment() << + indent() << "import (" << endl << + indent() << " \"flag\"" << endl << + indent() << " \"fmt\"" << endl << + indent() << " \"math\"" << endl << + indent() << " \"net\"" << endl << + indent() << " \"net/url\"" << endl << + indent() << " \"os\"" << endl << + indent() << " \"strconv\"" << endl << + indent() << " \"strings\"" << endl << + indent() << " \"" + gen_thrift_import_ + "\"" << endl << + indent() << " \"" << service_module << "\"" << endl << + indent() << ")" << endl << + indent() << endl << + indent() << "func Usage() {" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"Usage of \", os.Args[0], \" [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:\")" << endl << + indent() << " flag.PrintDefaults()" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"\\nFunctions:\")" << endl; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + f_remote << + " fmt.Fprintln(os.Stderr, \" " << (*f_iter)->get_returntype()->get_name() << " " << (*f_iter)->get_name() << "("; + t_struct* arg_struct = (*f_iter)->get_arglist(); + const std::vector& args = arg_struct->get_members(); + vector::const_iterator a_iter; + int num_args = args.size(); + bool first = true; + + for (int i = 0; i < num_args; ++i) { + if (first) { + first = false; + } else { + f_remote << ", "; + } + + f_remote << + args[i]->get_type()->get_name() << " " << args[i]->get_name(); + } + + f_remote << ")\")" << endl; + } + f_remote << - indent() << "case \"" << escape_string(funcName) << "\":" << endl; + indent() << " fmt.Fprintln(os.Stderr)" << endl << + indent() << " os.Exit(0)" << endl << + indent() << "}" << endl << + indent() << endl << + indent() << "func main() {" << endl; indent_up(); f_remote << - indent() << "if flag.NArg() - 1 != " << num_args << " {" << endl << - indent() << " fmt.Fprint(os.Stderr, \"" << escape_string(pubName) << " requires " << num_args << " args\\n\")" << endl << - indent() << " flag.Usage()" << endl << - indent() << "}" << endl; - for (int i = 0; i < num_args; ++i) { - int flagArg = i + 1; - t_type* the_type(args[i]->get_type()); - t_type* the_type2(get_true_type(the_type)); - if(the_type2->is_enum()) { - f_remote << - indent() << "tmp" << i << ", err := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl << - indent() << "if err != nil {" << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << "argvalue" << i << " := " << package_name_ << "." << publicize(the_type->get_name()) << "(tmp" << i << ")" << endl; - } else if(the_type2->is_base_type()) { - t_base_type::t_base e = ((t_base_type*)the_type2)->get_base(); - string err(tmp("err")); - switch(e) { - case t_base_type::TYPE_VOID: break; - case t_base_type::TYPE_STRING: - f_remote << - indent() << "argvalue" << i << " := flag.Arg(" << flagArg << ")" << endl; - break; - case t_base_type::TYPE_BOOL: - f_remote << - indent() << "argvalue" << i << " := flag.Arg(" << flagArg << ") == \"true\"" << endl; - break; - case t_base_type::TYPE_BYTE: - f_remote << - indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl << - indent() << "if " << err << " != nil {" << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << "argvalue" << i << " := byte(tmp" << i << ")" << endl; - break; - case t_base_type::TYPE_I16: - f_remote << - indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl << - indent() << "if " << err << " != nil {" << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << "argvalue" << i << " := byte(tmp" << i << ")" << endl; - break; - case t_base_type::TYPE_I32: - f_remote << - indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl << - indent() << "if " << err << " != nil {" << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << "argvalue" << i << " := int32(tmp" << i << ")" << endl; - break; - case t_base_type::TYPE_I64: - f_remote << - indent() << "argvalue" << i << ", " << err << " := (strconv.Atoi64(flag.Arg(" << flagArg << ")))" << endl << - indent() << "if " << err << " != nil {" << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl; - break; - case t_base_type::TYPE_DOUBLE: - f_remote << - indent() << "argvalue" << i << ", " << err << " := (strconv.Atof64(flag.Arg(" << flagArg << ")))" << endl << - indent() << "if " << err << " != nil {" << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl; - break; - default: - throw("Invalid base type in generate_service_remote"); - } - //f_remote << publicize(args[i]->get_name()) << "(strconv.Atoi(flag.Arg(" << flagArg << ")))"; - } else if(the_type2->is_struct()) { - string arg(tmp("arg")); - string mbTrans(tmp("mbTrans")); - string err1(tmp("err")); - string factory(tmp("factory")); - string jsProt(tmp("jsProt")); - string err2(tmp("err")); - std::string tstruct_name(publicize(the_type->get_name())); - f_remote << - indent() << arg << " := flag.Arg(" << flagArg << ")" << endl << - indent() << mbTrans << " := thrift.NewTMemoryBufferLen(len(" << arg << "))" << endl << - indent() << "defer " << mbTrans << ".Close()" << endl << - indent() << "_, " << err1 << " := " << mbTrans << ".WriteString(" << arg << ")" << endl << - indent() << "if " << err1 << " != nil {" << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << factory << " := thrift.NewTSimpleJSONProtocolFactory()" << endl << - indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")" << endl << - indent() << "argvalue" << i << " := " << package_name_ << ".New" << tstruct_name << "()" << endl << - indent() << err2 << " := argvalue" << i << ".Read(" << jsProt << ")" << endl << - indent() << "if " << err2 << " != nil {" << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl; - } else if(the_type2->is_container() || the_type2->is_xception()) { - string arg(tmp("arg")); - string mbTrans(tmp("mbTrans")); - string err1(tmp("err")); - string factory(tmp("factory")); - string jsProt(tmp("jsProt")); - string err2(tmp("err")); - std::string argName(publicize(args[i]->get_name())); - f_remote << - indent() << arg << " := flag.Arg(" << flagArg << ")" << endl << - indent() << mbTrans << " := thrift.NewTMemoryBufferLen(len(" << arg << "))" << endl << - indent() << "defer " << mbTrans << ".Close()" << endl << - indent() << "_, " << err1 << " := " << mbTrans << ".WriteString(" << arg << ")" << endl << - indent() << "if " << err1 << " != nil { " << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << factory << " := thrift.NewTSimpleJSONProtocolFactory()" << endl << - indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")" << endl << - indent() << "containerStruct" << i << " := " << package_name_ << ".New" << pubName << "Args()" << endl << - indent() << err2 << " := containerStruct" << i << ".ReadField" << (i + 1) << "(" << jsProt << ")" << endl << - indent() << "if " << err2 << " != nil {" << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << "argvalue" << i << " := containerStruct" << i << "." << argName << endl; - } else { - throw("Invalid argument type in generate_service_remote"); - string err1(tmp("err")); + indent() << "flag.Usage = Usage" << endl << + indent() << "var host string" << endl << + indent() << "var port int" << endl << + indent() << "var protocol string" << endl << + indent() << "var urlString string" << endl << + indent() << "var framed bool" << endl << + indent() << "var useHttp bool" << endl << + indent() << "var parsedUrl url.URL" << endl << + indent() << "var trans thrift.TTransport" << endl << + indent() << "_ = math.MinInt32 // will become unneeded eventually" << endl << + indent() << "_ = strconv.Atoi" << endl << + indent() << "flag.Usage = Usage" << endl << + indent() << "flag.StringVar(&host, \"h\", \"localhost\", \"Specify host and port\")" << endl << + indent() << "flag.IntVar(&port, \"p\", 9090, \"Specify port\")" << endl << + indent() << "flag.StringVar(&protocol, \"P\", \"binary\", \"Specify the protocol (binary, compact, simplejson, json)\")" << endl << + indent() << "flag.StringVar(&urlString, \"u\", \"\", \"Specify the url\")" << endl << + indent() << "flag.BoolVar(&framed, \"framed\", false, \"Use framed transport\")" << endl << + indent() << "flag.BoolVar(&useHttp, \"http\", false, \"Use http\")" << endl << + indent() << "flag.Parse()" << endl << + indent() << endl << + indent() << "if len(urlString) > 0 {" << endl << + indent() << " parsedUrl, err := url.Parse(urlString)" << endl << + indent() << " if err != nil {" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"Error parsing URL: \", err)" << endl << + indent() << " flag.Usage()" << endl << + indent() << " }" << endl << + indent() << " host = parsedUrl.Host" << endl << + indent() << " useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == \"http\"" << endl << + indent() << "} else if useHttp {" << endl << + indent() << " _, err := url.Parse(fmt.Sprint(\"http://\", host, \":\", port))" << endl << + indent() << " if err != nil {" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"Error parsing URL: \", err)" << endl << + indent() << " flag.Usage()" << endl << + indent() << " }" << endl << + indent() << "}" << endl << + indent() << endl << + indent() << "cmd := flag.Arg(0)" << endl << + indent() << "var err error" << endl << + indent() << "if useHttp {" << endl << + indent() << " trans, err = thrift.NewTHttpClient(parsedUrl.String())" << endl << + indent() << "} else {" << endl << + indent() << " portStr := fmt.Sprint(port)" << endl << + indent() << " if strings.Contains(host, \":\") {" << endl << + indent() << " host, portStr, err = net.SplitHostPort(host)" << endl << + indent() << " if err != nil {" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"error with host:\", err)" << endl << + indent() << " os.Exit(1)" << endl << + indent() << " }" << endl << + indent() << " }" << endl << + indent() << " trans, err = thrift.NewTSocket(net.JoinHostPort(host, portStr))" << endl << + indent() << " if err != nil {" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"error resolving address:\", err)" << endl << + indent() << " os.Exit(1)" << endl << + indent() << " }" << endl << + indent() << " if framed {" << endl << + indent() << " trans = thrift.NewTFramedTransport(trans)" << endl << + indent() << " }" << endl << + indent() << "}" << endl << + indent() << "if err != nil {" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"Error creating transport\", err)" << endl << + indent() << " os.Exit(1)" << endl << + indent() << "}" << endl << + indent() << "defer trans.Close()" << endl << + indent() << "var protocolFactory thrift.TProtocolFactory" << endl << + indent() << "switch protocol {" << endl << + indent() << "case \"compact\":" << endl << + indent() << " protocolFactory = thrift.NewTCompactProtocolFactory()" << endl << + indent() << " break" << endl << + indent() << "case \"simplejson\":" << endl << + indent() << " protocolFactory = thrift.NewTSimpleJSONProtocolFactory()" << endl << + indent() << " break" << endl << + indent() << "case \"json\":" << endl << + indent() << " protocolFactory = thrift.NewTJSONProtocolFactory()" << endl << + indent() << " break" << endl << + indent() << "case \"binary\", \"\":" << endl << + indent() << " protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()" << endl << + indent() << " break" << endl << + indent() << "default:" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"Invalid protocol specified: \", protocol)" << endl << + indent() << " Usage()" << endl << + indent() << " os.Exit(1)" << endl << + indent() << "}" << endl << + indent() << "client := " << package_name_ << ".New" << publicize(service_name_) << "ClientFactory(trans, protocolFactory)" << endl << + indent() << "if err := trans.Open(); err != nil {" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"Error opening socket to \", host, \":\", port, \" \", err)" << endl << + indent() << " os.Exit(1)" << endl << + indent() << "}" << endl << + indent() << endl << + indent() << "switch cmd {" << endl; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + t_struct* arg_struct = (*f_iter)->get_arglist(); + const std::vector& args = arg_struct->get_members(); + vector::const_iterator a_iter; + int num_args = args.size(); + string funcName((*f_iter)->get_name()); + string pubName(publicize(funcName)); f_remote << - indent() << "argvalue" << i << ", " << err1 << " := eval(flag.Arg(" << flagArg << "))" << endl << - indent() << "if " << err1 << " != nil {" << endl << - indent() << " Usage()" << endl << - indent() << " return" << endl << - indent() << "}" << endl; - } - if(the_type->is_typedef()) { + indent() << "case \"" << escape_string(funcName) << "\":" << endl; + indent_up(); f_remote << - indent() << "value" << i << " := " << package_name_ << "." << publicize(the_type->get_name()) << "(argvalue" << i << ")" << endl; - } else { + indent() << "if flag.NArg() - 1 != " << num_args << " {" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"" << escape_string(pubName) << " requires " << num_args << " args\")" << endl << + indent() << " flag.Usage()" << endl << + indent() << "}" << endl; + + for (int i = 0; i < num_args; ++i) { + int flagArg = i + 1; + t_type* the_type(args[i]->get_type()); + t_type* the_type2(get_true_type(the_type)); + + if (the_type2->is_enum()) { + f_remote << + indent() << "tmp" << i << ", err := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl << + indent() << "if err != nil {" << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << "argvalue" << i << " := " << package_name_ << "." << publicize(the_type->get_name()) << "(tmp" << i << ")" << endl; + } else if (the_type2->is_base_type()) { + t_base_type::t_base e = ((t_base_type*)the_type2)->get_base(); + string err(tmp("err")); + + switch (e) { + case t_base_type::TYPE_VOID: + break; + + case t_base_type::TYPE_STRING: + f_remote << + indent() << "argvalue" << i << " := flag.Arg(" << flagArg << ")" << endl; + break; + + case t_base_type::TYPE_BOOL: + f_remote << + indent() << "argvalue" << i << " := flag.Arg(" << flagArg << ") == \"true\"" << endl; + break; + + case t_base_type::TYPE_BYTE: + f_remote << + indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl << + indent() << "if " << err << " != nil {" << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << "argvalue" << i << " := byte(tmp" << i << ")" << endl; + break; + + case t_base_type::TYPE_I16: + f_remote << + indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl << + indent() << "if " << err << " != nil {" << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << "argvalue" << i << " := byte(tmp" << i << ")" << endl; + break; + + case t_base_type::TYPE_I32: + f_remote << + indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl << + indent() << "if " << err << " != nil {" << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << "argvalue" << i << " := int32(tmp" << i << ")" << endl; + break; + + case t_base_type::TYPE_I64: + f_remote << + indent() << "argvalue" << i << ", " << err << " := (strconv.ParseInt(flag.Arg(" << flagArg << "), 10, 64))" << endl << + indent() << "if " << err << " != nil {" << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl; + break; + + case t_base_type::TYPE_DOUBLE: + f_remote << + indent() << "argvalue" << i << ", " << err << " := (strconv.ParseFloat(flag.Arg(" << flagArg << "), 64))" << endl << + indent() << "if " << err << " != nil {" << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl; + break; + + default: + throw ("Invalid base type in generate_service_remote"); + } + + //f_remote << publicize(args[i]->get_name()) << "(strconv.Atoi(flag.Arg(" << flagArg << ")))"; + } else if (the_type2->is_struct()) { + string arg(tmp("arg")); + string mbTrans(tmp("mbTrans")); + string err1(tmp("err")); + string factory(tmp("factory")); + string jsProt(tmp("jsProt")); + string err2(tmp("err")); + std::string tstruct_name(publicize(the_type->get_name())); + f_remote << + indent() << arg << " := flag.Arg(" << flagArg << ")" << endl << + indent() << mbTrans << " := thrift.NewTMemoryBufferLen(len(" << arg << "))" << endl << + indent() << "defer " << mbTrans << ".Close()" << endl << + indent() << "_, " << err1 << " := " << mbTrans << ".WriteString(" << arg << ")" << endl << + indent() << "if " << err1 << " != nil {" << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << factory << " := thrift.NewTSimpleJSONProtocolFactory()" << endl << + indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")" << endl << + indent() << "argvalue" << i << " := " << package_name_ << ".New" << tstruct_name << "()" << endl << + indent() << err2 << " := argvalue" << i << ".Read(" << jsProt << ")" << endl << + indent() << "if " << err2 << " != nil {" << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl; + } else if (the_type2->is_container() || the_type2->is_xception()) { + string arg(tmp("arg")); + string mbTrans(tmp("mbTrans")); + string err1(tmp("err")); + string factory(tmp("factory")); + string jsProt(tmp("jsProt")); + string err2(tmp("err")); + std::string argName(publicize(args[i]->get_name())); + f_remote << + indent() << arg << " := flag.Arg(" << flagArg << ")" << endl << + indent() << mbTrans << " := thrift.NewTMemoryBufferLen(len(" << arg << "))" << endl << + indent() << "defer " << mbTrans << ".Close()" << endl << + indent() << "_, " << err1 << " := " << mbTrans << ".WriteString(" << arg << ")" << endl << + indent() << "if " << err1 << " != nil { " << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << factory << " := thrift.NewTSimpleJSONProtocolFactory()" << endl << + indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")" << endl << + indent() << "containerStruct" << i << " := " << package_name_ << ".New" << pubName << "Args()" << endl << + indent() << err2 << " := containerStruct" << i << ".ReadField" << (i + 1) << "(" << jsProt << ")" << endl << + indent() << "if " << err2 << " != nil {" << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << "argvalue" << i << " := containerStruct" << i << "." << argName << endl; + } else { + throw ("Invalid argument type in generate_service_remote"); + string err1(tmp("err")); + f_remote << + indent() << "argvalue" << i << ", " << err1 << " := eval(flag.Arg(" << flagArg << "))" << endl << + indent() << "if " << err1 << " != nil {" << endl << + indent() << " Usage()" << endl << + indent() << " return" << endl << + indent() << "}" << endl; + } + + if (the_type->is_typedef()) { + f_remote << + indent() << "value" << i << " := " << package_name_ << "." << publicize(the_type->get_name()) << "(argvalue" << i << ")" << endl; + } else { + f_remote << + indent() << "value" << i << " := argvalue" << i << endl; + } + } + f_remote << - indent() << "value" << i << " := argvalue" << i << endl; - } - } - f_remote << - indent() << "fmt.Print(client." << pubName << "("; - bool argFirst = true; - for (int i = 0; i < num_args; ++i) { - if (argFirst) { - argFirst = false; - } else { - f_remote << ", "; - } - if(args[i]->get_type()->is_enum()) { - f_remote << "value" << i; - } else if(args[i]->get_type()->is_base_type()) { - t_base_type::t_base e = ((t_base_type*)(args[i]->get_type()))->get_base(); - switch(e) { - case t_base_type::TYPE_VOID: break; - case t_base_type::TYPE_STRING: - 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: - f_remote << "value" << i; - break; - default: - throw("Invalid base type in generate_service_remote"); + indent() << "fmt.Print(client." << pubName << "("; + bool argFirst = true; + + for (int i = 0; i < num_args; ++i) { + if (argFirst) { + argFirst = false; + } else { + f_remote << ", "; + } + + if (args[i]->get_type()->is_enum()) { + f_remote << "value" << i; + } else if (args[i]->get_type()->is_base_type()) { + t_base_type::t_base e = ((t_base_type*)(args[i]->get_type()))->get_base(); + + switch (e) { + case t_base_type::TYPE_VOID: + break; + + case t_base_type::TYPE_STRING: + 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: + f_remote << "value" << i; + break; + + default: + throw ("Invalid base type in generate_service_remote"); + } + + //f_remote << publicize(args[i]->get_name()) << "(strconv.Atoi(flag.Arg(" << flagArg << ")))"; + } else { + f_remote << "value" << i; + } } - //f_remote << publicize(args[i]->get_name()) << "(strconv.Atoi(flag.Arg(" << flagArg << ")))"; - } else { - f_remote << "value" << i; - } + + f_remote << + "))" << endl << + indent() << "fmt.Print(\"\\n\")" << endl << + indent() << "break" << endl; + indent_down(); } + f_remote << - "))" << endl << - indent() << "fmt.Print(\"\\n\")" << endl << - indent() << "break" << endl; + indent() << "case \"\":" << endl << + indent() << " Usage()" << endl << + indent() << " break" << endl << + indent() << "default:" << endl << + indent() << " fmt.Fprintln(os.Stderr, \"Invalid function \", cmd)" << endl << + indent() << "}" << endl; indent_down(); - } - f_remote << - indent() << "case \"\":" << endl << - indent() << " Usage()" << endl << - indent() << " break" << endl << - indent() << "default:" << endl << - indent() << " fmt.Fprint(os.Stderr, \"Invalid function \", cmd, \"\\n\")" << endl << - indent() << "}" << endl; - indent_down(); - - f_remote << - indent() << "}" << endl; - - - // Close service file - f_remote.close(); - -#ifndef _MSC_VER - - // Make file executable, love that bitwise OR action - chmod(f_remote_name.c_str(), + f_remote << + indent() << "}" << endl; + // Close service file + f_remote.close(); + format_go_output(f_remote_name); + // Make file executable, love that bitwise OR action + chmod(f_remote_name.c_str(), S_IRUSR - | S_IWUSR - | S_IXUSR + | S_IWUSR + | S_IXUSR #ifndef MINGW - | S_IRGRP - | S_IXGRP - | S_IROTH - | S_IXOTH + | S_IRGRP + | S_IXGRP + | S_IROTH + | S_IXOTH #endif - ); - -#endif // _MSC_VER - + ); } /** @@ -1984,114 +2150,103 @@ void t_go_generator::generate_service_remote(t_service* tservice) { * * @param tservice The service to generate a server for. */ -void t_go_generator::generate_service_server(t_service* tservice) { - // Generate the dispatch methods - vector functions = tservice->get_functions(); - vector::iterator f_iter; - - string extends = ""; - string extends_processor = ""; - string extends_processor_new = ""; - string serviceName(publicize(tservice->get_name())); - if (tservice->get_extends() != NULL) { - extends = type_name(tservice->get_extends()); - size_t index = extends.rfind("."); - if(index != string::npos) { - extends_processor = extends.substr(0, index + 1) + publicize(extends.substr(index + 1)) + "Processor"; - extends_processor_new = extends.substr(0, index + 1) + "New" + publicize(extends.substr(index + 1)) + "Processor"; - } else { - extends_processor = publicize(extends) + "Processor"; - extends_processor_new = "New" + extends_processor; +void t_go_generator::generate_service_server(t_service* tservice) +{ + // Generate the dispatch methods + vector functions = tservice->get_functions(); + vector::iterator f_iter; + string extends = ""; + string extends_processor = ""; + string extends_processor_new = ""; + string serviceName(publicize(tservice->get_name())); + + if (tservice->get_extends() != NULL) { + extends = type_name(tservice->get_extends()); + size_t index = extends.rfind("."); + + if (index != string::npos) { + extends_processor = extends.substr(0, index + 1) + publicize(extends.substr(index + 1)) + "Processor"; + extends_processor_new = extends.substr(0, index + 1) + "New" + publicize(extends.substr(index + 1)) + "Processor"; + } else { + extends_processor = publicize(extends) + "Processor"; + extends_processor_new = "New" + extends_processor; + } } - } - string pServiceName(privatize(serviceName)); - // Generate the header portion - string self(tmp("self")); - if(extends_processor.empty()) { - f_service_ << - indent() << "type " << serviceName << "Processor struct {" << endl << - indent() << " handler I" << serviceName << endl << - indent() << " processorMap map[string]thrift.TProcessorFunction" << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Processor) Handler() I" << serviceName << " {" << endl << - indent() << " return p.handler" << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Processor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {" << endl << - indent() << " p.processorMap[key] = processor" << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Processor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, exists bool) {" << endl << - indent() << " processor, exists = p.processorMap[key]" << endl << - indent() << " return processor, exists" << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Processor) ProcessorMap() map[string]thrift.TProcessorFunction {" << endl << - indent() << " return p.processorMap" << endl << - indent() << "}" << endl << endl << - indent() << "func New" << serviceName << "Processor(handler I" << serviceName << ") *" << serviceName << "Processor {" << endl << endl << - indent() << " " << self << " := &" << serviceName << "Processor{handler:handler, processorMap:make(map[string]thrift.TProcessorFunction)}" << endl; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - string escapedFuncName(escape_string((*f_iter)->get_name())); - f_service_ << - indent() << " " << self << ".processorMap[\"" << escapedFuncName << "\"] = &" << pServiceName << "Processor" << publicize((*f_iter)->get_name()) << "{handler:handler}" << endl; + string pServiceName(privatize(serviceName)); + // Generate the header portion + string self(tmp("self")); + + if (extends_processor.empty()) { + f_service_ << + indent() << "type " << serviceName << "Processor struct {" << endl << + indent() << " processorMap map[string]thrift.TProcessorFunction" << endl << + indent() << " handler " << serviceName << endl << + indent() << "}" << endl << endl << + indent() << "func (p *" << serviceName << "Processor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {" << endl << + indent() << " p.processorMap[key] = processor" << endl << + indent() << "}" << endl << endl << + indent() << "func (p *" << serviceName << "Processor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {" << endl << + indent() << " processor, ok = p.processorMap[key]" << endl << + indent() << " return processor, ok" << endl << + indent() << "}" << endl << endl << + indent() << "func (p *" << serviceName << "Processor) ProcessorMap() map[string]thrift.TProcessorFunction {" << endl << + indent() << " return p.processorMap" << endl << + indent() << "}" << endl << endl << + indent() << "func New" << serviceName << "Processor(handler " << serviceName << ") *" << serviceName << "Processor {" << endl << endl << + indent() << " " << self << " := &" << serviceName << "Processor{handler:handler, processorMap:make(map[string]thrift.TProcessorFunction)}" << endl; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + string escapedFuncName(escape_string((*f_iter)->get_name())); + f_service_ << + indent() << " " << self << ".processorMap[\"" << escapedFuncName << "\"] = &" << pServiceName << "Processor" << publicize((*f_iter)->get_name()) << "{handler:handler}" << endl; + } + + string x(tmp("x")); + f_service_ << + indent() << "return " << self << endl << + indent() << "}" << endl << endl << + indent() << "func (p *" << serviceName << "Processor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {" << endl << + indent() << " name, _, seqId, err := iprot.ReadMessageBegin()" << endl << + indent() << " if err != nil { return false, err }" << endl << + indent() << " if processor, ok := p.GetProcessorFunction(name); ok {" << endl << + indent() << " return processor.Process(seqId, iprot, oprot)" << endl << + indent() << " } else {" << endl << + indent() << " iprot.Skip(thrift.STRUCT)" << endl << + indent() << " iprot.ReadMessageEnd()" << endl << + indent() << " " << x << " := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, \"Unknown function \" + name)" << endl << + indent() << " oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)" << endl << + indent() << " " << x << ".Write(oprot)" << endl << + indent() << " oprot.WriteMessageEnd()" << endl << + indent() << " oprot.Flush()" << endl << + indent() << " return false, " << x << endl << + indent() << " }" << endl << + indent() << "}" << endl << endl; + } else { + f_service_ << + indent() << "type " << serviceName << "Processor struct {" << endl << + indent() << " *" << extends_processor << endl << + indent() << "}" << endl << endl << + indent() << "func New" << serviceName << "Processor(handler " << serviceName << ") *" << serviceName << "Processor {" << endl << + indent() << " " << self << " := &" << serviceName << "Processor{" << extends_processor_new << "(handler)}" << endl; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + string escapedFuncName(escape_string((*f_iter)->get_name())); + f_service_ << + indent() << " " << self << ".AddToProcessorMap(\"" << escapedFuncName << "\", &" << pServiceName << "Processor" << publicize((*f_iter)->get_name()) << "{handler:handler})" << endl; + } + + f_service_ << + indent() << " return " << self << endl << + indent() << "}" << endl << endl; } - string x(tmp("x")); - f_service_ << - indent() << "return " << self << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Processor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {" << endl << - indent() << " name, _, seqId, err := iprot.ReadMessageBegin()" << endl << - indent() << " if err != nil { return }" << endl << - indent() << " process, nameFound := p.GetProcessorFunction(name)" << endl << - indent() << " if !nameFound || process == nil {" << endl << - indent() << " iprot.Skip(thrift.STRUCT)" << endl << - indent() << " iprot.ReadMessageEnd()" << endl << - indent() << " " << x << " := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, \"Unknown function \" + name)" << endl << - indent() << " oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)" << endl << - indent() << " " << x << ".Write(oprot)" << endl << - indent() << " oprot.WriteMessageEnd()" << endl << - indent() << " oprot.Transport().Flush()" << endl << - indent() << " return false, " << x << endl << - indent() << " }" << endl << - indent() << " return process.Process(seqId, iprot, oprot)" << endl << - indent() << "}" << endl << endl; - } else { - f_service_ << - indent() << "type " << serviceName << "Processor struct {" << endl << - indent() << " super *" << extends_processor << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Processor) Handler() I" << serviceName << " {" << endl << - indent() << " return p.super.Handler().(I" << serviceName << ")" << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Processor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {" << endl << - indent() << " p.super.AddToProcessorMap(key, processor)" << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Processor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, exists bool) {" << endl << - indent() << " return p.super.GetProcessorFunction(key)" << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Processor) ProcessorMap() map[string]thrift.TProcessorFunction {" << endl << - indent() << " return p.super.ProcessorMap()" << endl << - indent() << "}" << endl << endl << - indent() << "func New" << serviceName << "Processor(handler I" << serviceName << ") *" << serviceName << "Processor {" << endl << - indent() << " " << self << " := &" << serviceName << "Processor{super: " << extends_processor_new << "(handler)}" << endl; + + // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - string escapedFuncName(escape_string((*f_iter)->get_name())); - f_service_ << - indent() << " " << self << ".AddToProcessorMap(\"" << escapedFuncName << "\", &" << pServiceName << "Processor" << publicize((*f_iter)->get_name()) << "{handler:handler})" << endl; + generate_process_function(tservice, *f_iter); } - f_service_ << - indent() << " return " << self << endl << - indent() << "}" << endl << endl << - indent() << "func (p *" << serviceName << "Processor) Process(iprot, oprot thrift.TProtocol) (bool, thrift.TException) {" << endl << - indent() << " return p.super.Process(iprot, oprot)" << endl << - indent() << "}" << endl << endl; - } - - // Generate the process subfunctions - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - generate_process_function(tservice, *f_iter); - } - - f_service_ << endl; + + f_service_ << endl; } /** @@ -2100,265 +2255,275 @@ void t_go_generator::generate_service_server(t_service* tservice) { * @param tfunction The function to write a dispatcher for */ void t_go_generator::generate_process_function(t_service* tservice, - t_function* tfunction) { - // Open function - string processorName = privatize(tservice->get_name()) + "Processor" + publicize(tfunction->get_name()); - - string argsname = publicize(tfunction->get_name()) + "Args"; - string resultname = publicize(tfunction->get_name()) + "Result"; - - //t_struct* xs = tfunction->get_xceptions(); - //const std::vector& xceptions = xs->get_members(); - vector::const_iterator x_iter; - - f_service_ << - indent() << "type " << processorName << " struct {" << endl << - indent() << " handler I" << publicize(tservice->get_name()) << endl << - indent() << "}" << endl << endl << - 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() << "if err = args.Read(iprot); err != nil {" << endl << - indent() << " iprot.ReadMessageEnd()" << endl << - indent() << " x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.String())" << endl << - indent() << " oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << "\", thrift.EXCEPTION, seqId)" << endl << - indent() << " x.Write(oprot)" << endl << - indent() << " oprot.WriteMessageEnd()" << endl << - indent() << " oprot.Transport().Flush()" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << "iprot.ReadMessageEnd()" << endl << - indent() << "result := New" << resultname << "()" << endl << - indent() << "if "; - if (!tfunction->is_oneway()) { - if(!tfunction->get_returntype()->is_void()) { - f_service_ << "result.Success, "; + t_function* tfunction) +{ + // Open function + string processorName = privatize(tservice->get_name()) + "Processor" + publicize(tfunction->get_name()); + string argsname = publicize(tfunction->get_name()) + "Args"; + string resultname = publicize(tfunction->get_name()) + "Result"; + //t_struct* xs = tfunction->get_xceptions(); + //const std::vector& xceptions = xs->get_members(); + vector::const_iterator x_iter; + f_service_ << + indent() << "type " << processorName << " struct {" << endl << + indent() << " handler " << publicize(tservice->get_name()) << endl << + indent() << "}" << endl << endl << + 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() << "if err = args.Read(iprot); err != nil {" << endl << + indent() << " iprot.ReadMessageEnd()" << endl << + indent() << " x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())" << endl << + indent() << " oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << "\", thrift.EXCEPTION, seqId)" << endl << + indent() << " x.Write(oprot)" << endl << + indent() << " oprot.WriteMessageEnd()" << endl << + indent() << " oprot.Flush()" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << "iprot.ReadMessageEnd()" << endl << + indent() << "result := New" << resultname << "()" << endl << + indent() << "if "; + + if (!tfunction->is_oneway()) { + if (!tfunction->get_returntype()->is_void()) { + f_service_ << "result.Success, "; + } + + t_struct* exceptions = tfunction->get_xceptions(); + const vector& fields = exceptions->get_members(); + vector::const_iterator f_iter; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + f_service_ << "result." << publicize(variable_name_to_go_name((*f_iter)->get_name())) << ", "; + } } - t_struct* exceptions = tfunction->get_xceptions(); - const vector& fields = exceptions->get_members(); + + // Generate the function call + t_struct* arg_struct = tfunction->get_arglist(); + const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; + f_service_ << + "err = p.handler." << publicize(tfunction->get_name()) << "("; + bool first = true; + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - f_service_ << "result." << publicize(variable_name_to_go_name((*f_iter)->get_name())) << ", "; - } - } - - - // Generate the function call - t_struct* arg_struct = tfunction->get_arglist(); - const std::vector& fields = arg_struct->get_members(); - vector::const_iterator f_iter; - - f_service_ << - "err = p.handler." << publicize(tfunction->get_name()) << "("; - bool first = true; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (first) { - first = false; - } else { - f_service_ << ", "; - } - f_service_ << "args." << publicize(variable_name_to_go_name((*f_iter)->get_name())); - } - f_service_ << "); err != nil {" << endl << - indent() << " x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, \"Internal error processing " << escape_string(tfunction->get_name()) << ": \" + err.String())" << endl << - indent() << " oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << "\", thrift.EXCEPTION, seqId)" << endl << - indent() << " x.Write(oprot)" << endl << - indent() << " oprot.WriteMessageEnd()" << endl << - indent() << " oprot.Transport().Flush()" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << "if err2 := oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << "\", thrift.REPLY, seqId); err2 != nil {" << endl << - indent() << " err = err2" << endl << - indent() << "}" << endl << - indent() << "if err2 := result.Write(oprot); err == nil && err2 != nil {" << endl << - indent() << " err = err2" << endl << - indent() << "}" << endl << - indent() << "if err2 := oprot.WriteMessageEnd(); err == nil && err2 != nil {" << endl << - indent() << " err = err2" << endl << - indent() << "}" << endl << - indent() << "if err2 := oprot.Transport().Flush(); err == nil && err2 != nil {" << endl << - indent() << " err = err2" << endl << - indent() << "}" << endl << - indent() << "if err != nil {" << endl << - indent() << " return" << endl << - indent() << "}" << endl << - indent() << "return true, err" << endl; - indent_down(); - f_service_ << - indent() << "}" << endl << endl; - /* - indent(f_service_) << - "func (p *" << publicize(tservice->get_name()) << "Client) WriteResultsSuccess" << publicize(tfunction->get_name()) << - "(success bool, result " << publicize(tfunction->get_name()) << "Result, seqid int32, oprot thrift.TProtocol) (err os.Error) {" << endl; - indent_up(); - f_service_ << - indent() << "result.Success = success" << endl << - indent() << "oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << "\", thrift.REPLY, seqid)" << endl << - indent() << "result.Write(oprot)" << endl << - indent() << "oprot.WriteMessageEnd()" << endl << - indent() << "oprot.Transport().Flush()" << endl << - indent() << "return" << endl; - indent_down(); - f_service_ << - indent() << "}" << endl << endl; - */ - // Try block for a function with exceptions - /* - if (!tfunction->is_oneway() && xceptions.size() > 0) { + if (first) { + first = false; + } else { + f_service_ << ", "; + } + + f_service_ << "args." << publicize(variable_name_to_go_name((*f_iter)->get_name())); + } + + f_service_ << "); err != nil {" << endl << + indent() << " x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, \"Internal error processing " << escape_string(tfunction->get_name()) << ": \" + err.Error())" << endl << + indent() << " oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << "\", thrift.EXCEPTION, seqId)" << endl << + indent() << " x.Write(oprot)" << endl << + indent() << " oprot.WriteMessageEnd()" << endl << + indent() << " oprot.Flush()" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << "if err2 := oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << "\", thrift.REPLY, seqId); err2 != nil {" << endl << + indent() << " err = err2" << endl << + indent() << "}" << endl << + indent() << "if err2 := result.Write(oprot); err == nil && err2 != nil {" << endl << + indent() << " err = err2" << endl << + indent() << "}" << endl << + indent() << "if err2 := oprot.WriteMessageEnd(); err == nil && err2 != nil {" << endl << + indent() << " err = err2" << endl << + indent() << "}" << endl << + indent() << "if err2 := oprot.Flush(); err == nil && err2 != nil {" << endl << + indent() << " err = err2" << endl << + indent() << "}" << endl << + indent() << "if err != nil {" << endl << + indent() << " return" << endl << + indent() << "}" << endl << + indent() << "return true, err" << endl; + indent_down(); + f_service_ << + indent() << "}" << endl << endl; + /* indent(f_service_) << - "func (p *" << publicize(tservice->get_name()) << "Client) WriteResultsException" << publicize(tfunction->get_name()) << - "(error *" << publicize(tfunction->get_name()) << ", result *, seqid, oprot) (err os.Error) {" << endl; + "func (p *" << publicize(tservice->get_name()) << "Client) WriteResultsSuccess" << publicize(tfunction->get_name()) << + "(success bool, result " << publicize(tfunction->get_name()) << "Result, seqid int32, oprot thrift.TProtocol) (err error) {" << endl; indent_up(); + f_service_ << + indent() << "result.Success = success" << endl << + indent() << "oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << "\", thrift.REPLY, seqid)" << endl << + indent() << "result.Write(oprot)" << endl << + indent() << "oprot.WriteMessageEnd()" << endl << + indent() << "oprot.Flush()" << endl << + indent() << "return" << endl; + indent_down(); + f_service_ << + indent() << "}" << endl << endl; + */ + // Try block for a function with exceptions + /* + if (!tfunction->is_oneway() && xceptions.size() > 0) { + indent(f_service_) << + "func (p *" << publicize(tservice->get_name()) << "Client) WriteResultsException" << publicize(tfunction->get_name()) << + "(error *" << publicize(tfunction->get_name()) << ", result *, seqid, oprot) (err error) {" << endl; + indent_up(); - // Kinda absurd - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - f_service_ << - indent() << "except " << type_name((*x_iter)->get_type()) << ", " << (*x_iter)->get_name() << ":" << endl; - if (!tfunction->is_oneway()) { - indent_up(); - f_service_ << - indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << endl; - indent_down(); - } else { + // Kinda absurd + for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << - indent() << "pass" << endl; + indent() << "except " << type_name((*x_iter)->get_type()) << ", " << (*x_iter)->get_name() << ":" << endl; + if (!tfunction->is_oneway()) { + indent_up(); + f_service_ << + indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << endl; + indent_down(); + } else { + f_service_ << + indent() << "pass" << endl; + } } + f_service_ << + indent() << "err = oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << "\", thrift.REPLY, seqid)" << endl << + indent() << "if err != nil { return err }" << endl << + indent() << "err = result.Write(oprot)" << endl << + indent() << "if err != nil { return err }" << endl << + indent() << "err = oprot.WriteMessageEnd()" << endl << + indent() << "if err != nil { return err }" << endl << + indent() << "err = oprot.Flush()" << endl << + indent() << "if err != nil { return err }" << endl; + indent_down(); + f_service_ << "}" << endl << endl; } - f_service_ << - indent() << "err = oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << "\", thrift.REPLY, seqid)" << endl << - indent() << "if err != nil { return err }" << endl << - indent() << "err = result.Write(oprot)" << endl << - indent() << "if err != nil { return err }" << endl << - indent() << "err = oprot.WriteMessageEnd()" << endl << - indent() << "if err != nil { return err }" << endl << - indent() << "err = oprot.Transport().Flush()" << endl << - indent() << "if err != nil { return err }" << endl; - indent_down(); - f_service_ << "}" << endl << endl; - } - */ + */ } /** * Deserializes a field of any type. */ void t_go_generator::generate_deserialize_field(ofstream &out, - t_field* tfield, - bool declare, - string prefix, - string err, - bool inclass, - bool coerceData) { - (void) inclass; - (void) coerceData; - t_type* orig_type = tfield->get_type(); - t_type* type = get_true_type(orig_type); - string name(prefix + publicize(variable_name_to_go_name(tfield->get_name()))); - - if (type->is_void()) { - throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + name; - } - string v = tmp("v"); - string err2 = tmp("err"); - - if (type->is_struct() || type->is_xception()) { - generate_deserialize_struct(out, - (t_struct*)type, - declare, - name, - err); - } else if (type->is_container()) { - generate_deserialize_container(out, type, declare, name, err); - } else if (type->is_base_type() || type->is_enum()) { - indent(out) << - v << ", " << err2 << " := iprot."; - - 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 "compiler error: cannot serialize void field in a struct: " + - name; - break; - case t_base_type::TYPE_STRING: - out << "ReadString()"; - break; - case t_base_type::TYPE_BOOL: - out << "ReadBool()"; - break; - case t_base_type::TYPE_BYTE: - out << "ReadByte()"; - break; - case t_base_type::TYPE_I16: - out << "ReadI16()"; - break; - case t_base_type::TYPE_I32: - out << "ReadI32()"; - break; - case t_base_type::TYPE_I64: - out << "ReadI64()"; - break; - case t_base_type::TYPE_DOUBLE: - out << "ReadDouble()"; - break; - default: - throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase); - } - } else if (type->is_enum()) { - out << "ReadI32()"; + t_field* tfield, + bool declare, + string prefix, + bool inclass, + bool coerceData) +{ + t_type* orig_type = tfield->get_type(); + t_type* type = get_true_type(orig_type); + string name(prefix + publicize(variable_name_to_go_name(tfield->get_name()))); + + if (type->is_void()) { + throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + name; } - string structName("\"\""); - if(!prefix.size() || prefix.find(".") == string::npos) { - structName = "\"\""; - } else { - structName = prefix + "ThriftName()"; - } - out << endl << - indent() << "if " << err2 << " != nil { return thrift.NewTProtocolExceptionReadField(" << - tfield->get_key() << - ", \"" << escape_string(tfield->get_name()) << - "\", " << structName << ", " << err2 << "); }" << endl; - if(!prefix.size() || prefix.find(".") == string::npos) { - if(type->is_enum() || orig_type->is_typedef()) { - indent(out) << name << " := " << publicize(orig_type->get_name()) << "("<< v << ")" << endl; - } else { - indent(out) << name << " := " << v << endl; - } + + if (type->is_struct() || type->is_xception()) { + generate_deserialize_struct(out, + (t_struct*)type, + declare, + name); + } else if (type->is_container()) { + generate_deserialize_container(out, type, declare, name); + } else if (type->is_base_type() || type->is_enum()) { + + if (declare) { + out << "var " << tfield->get_name() << " " << type_to_go_type(tfield->get_type()) << endl; + } + + indent(out) << + "if v, err := iprot."; + + 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 "compiler error: cannot serialize void field in a struct: " + + name; + break; + + case t_base_type::TYPE_STRING: + if (((t_base_type*)type)->is_binary()) { + out << "ReadBinary()"; + } else { + out << "ReadString()"; + } + + break; + + case t_base_type::TYPE_BOOL: + out << "ReadBool()"; + break; + + case t_base_type::TYPE_BYTE: + out << "ReadByte()"; + break; + + case t_base_type::TYPE_I16: + out << "ReadI16()"; + break; + + case t_base_type::TYPE_I32: + out << "ReadI32()"; + break; + + case t_base_type::TYPE_I64: + out << "ReadI64()"; + break; + + case t_base_type::TYPE_DOUBLE: + out << "ReadDouble()"; + break; + + default: + throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase); + } + } else if (type->is_enum()) { + out << "ReadI32()"; + } + + out << "; err != nil {" << endl << + indent() << "return fmt.Errorf(\"error reading field " << + tfield->get_key() << ": %s\")" << endl; + + out << "} else {" << endl; + string wrap; + + if (type->is_enum() || orig_type->is_typedef()) { + wrap = publicize(orig_type->get_name()); + } else if (((t_base_type*)type)->get_base() == t_base_type::TYPE_BYTE) { + wrap = "int8"; + } + + if (wrap == "") { + indent(out) << name << " = v" << endl; + } else { + indent(out) << name << " = " << wrap << "(v)" << endl; + } + + out << "}" << endl; } else { - if(type->is_enum() || orig_type->is_typedef()) { - indent(out) << name << " = " << publicize(orig_type->get_name()) << "("<< v << ")" << endl; - } else { - indent(out) << name << " = " << v << endl; - } + throw "INVALID TYPE IN generate_deserialize_field '" + type->get_name() + "' for field '" + tfield->get_name() + "'"; } - - } else { - throw "INVALID TYPE IN generate_deserialize_field '" + type->get_name() + "' for field '" + tfield->get_name() + "'"; - } } /** * Generates an unserializer for a struct, calling read() */ void t_go_generator::generate_deserialize_struct(ofstream &out, - t_struct* tstruct, - bool declare, - string prefix, - string err) { - (void) err; - string err2(tmp("err")); - string eq(" := "); - if(!declare) { - eq = " = "; - } - out << - indent() << prefix << eq << "New" << publicize(type_name(tstruct)) << "()" << endl << - indent() << err2 << " := " << prefix << ".Read(iprot)" << endl << - indent() << "if " << err2 << " != nil { return thrift.NewTProtocolExceptionReadStruct(\"" << - escape_string(prefix + tstruct->get_name()) << "\", " << - err2 << "); }\n"; + t_struct* tstruct, + bool declare, + string prefix) +{ + string eq(" := "); + + if (!declare) { + eq = " = "; + } + + out << + indent() << prefix << eq << "New" << publicize(type_name(tstruct)) << "()" << endl << + indent() << "if err := " << prefix << ".Read(iprot); err != nil {" << endl << + indent() << " return fmt.Errorf(\"%T error reading struct: %s\", " << prefix << ")" << endl << + indent() << "}" << endl; } /** @@ -2366,99 +2531,79 @@ void t_go_generator::generate_deserialize_struct(ofstream &out, * data and then a footer. */ void t_go_generator::generate_deserialize_container(ofstream &out, - t_type* ttype, - bool declare, - string prefix, - string err) { - string size = tmp("_size"); - string ktype = tmp("_ktype"); - string vtype = tmp("_vtype"); - string etype = tmp("_etype"); - - t_field fsize(g_type_i32, size); - t_field fktype(g_type_byte, ktype); - t_field fvtype(g_type_byte, vtype); - t_field fetype(g_type_byte, etype); - - string eq(" = "); - if(declare) - eq = " := "; - - // Declare variables, read header - if (ttype->is_map()) { - out << - indent() << ktype << ", " << vtype << ", " << size << ", " << err << " := iprot.ReadMapBegin()" << endl << - indent() << "if " << err << " != nil {" << endl << - indent() << " return thrift.NewTProtocolExceptionReadField(" << - -1 << ", \"" << - escape_string(prefix) << "\", \"\", " << - err << ")" << endl << - indent() << "}" << endl << - indent() << prefix << eq << "thrift.NewTMap(" << ktype << ", " << vtype << ", " << size << ")" << endl; - } else if (ttype->is_set()) { - out << - indent() << etype << ", " << size << ", " << err << " := iprot.ReadSetBegin()" << endl << - indent() << "if " << err << " != nil {" << endl << - indent() <<" return thrift.NewTProtocolExceptionReadField(" << - -1 << ", \"" << - escape_string(prefix) << "\", \"\", " << - err << "); }" << endl << - indent() << "}" << endl << - indent() << prefix << eq << "thrift.NewTSet(" << etype << ", " << size << ")" << endl; - } else if (ttype->is_list()) { - out << - indent() << etype << ", " << size << ", " << err << " := iprot.ReadListBegin()" << endl << - indent() << "if " << err << " != nil {" << endl << - indent() <<" return thrift.NewTProtocolExceptionReadField(" << - -1 << ", \"" << - escape_string(prefix) << "\", \"\", " << - err << ")" << endl << - indent() << "}" << endl << - indent() << prefix << eq << "thrift.NewTList(" << etype << ", " << size << ")" << endl; - } else { - throw "INVALID TYPE IN generate_deserialize_container '" + ttype->get_name() + "' for prefix '" + prefix + "'"; - } - - // For loop iterates over elements - string i = tmp("_i"); - out << - indent() << "for " << i << ":= 0; " << i << " < " << size << "; " << i << "++ {" << endl; - indent_up(); - - if (ttype->is_map()) { - generate_deserialize_map_element(out, (t_map*)ttype, declare, prefix); - } else if (ttype->is_set()) { - generate_deserialize_set_element(out, (t_set*)ttype, declare, prefix); - } else if (ttype->is_list()) { - generate_deserialize_list_element(out, (t_list*)ttype, declare, prefix); - } - - indent_down(); - out << - indent() << "}" << endl; - // Read container end - if (ttype->is_map()) { - out << - indent() << err << " = iprot.ReadMapEnd()" << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionReadField(" - << -1 - << ", \"" << escape_string(((t_map*)ttype)->get_cpp_name()) - << "\", " << "\"map\", " << err << "); }" << endl; - } else if (ttype->is_set()) { + t_type* ttype, + bool declare, + string prefix) +{ + string eq(" = "); + + if (declare) { + eq = " := "; + } + + // Declare variables, read header + if (ttype->is_map()) { + t_map* t = (t_map*)ttype; + out << + indent() << "_, _, size, err := iprot.ReadMapBegin()" << endl << + indent() << "if err != nil {" << endl << + indent() << " return fmt.Errorf(\"error reading map begin: %s\")" << endl << + indent() << "}" << endl << + indent() << prefix << eq << "make(map[" << type_to_go_type(t->get_key_type()) << "]" << type_to_go_type(t->get_val_type()) << ", size)" << endl; + } else if (ttype->is_set()) { + t_set* t = (t_set*)ttype; + out << + indent() << "_, size, err := iprot.ReadSetBegin()" << endl << + indent() << "if err != nil {" << endl << + indent() << " return fmt.Errorf(\"error reading set being: %s\")" << endl << + indent() << "}" << endl << + indent() << prefix << eq << "make(map[" << type_to_go_type(t->get_elem_type()) << "]bool, size)" << endl; + } else if (ttype->is_list()) { + t_list* t = (t_list*)ttype; + out << + indent() << "_, size, err := iprot.ReadListBegin()" << endl << + indent() << "if err != nil {" << endl << + indent() << " return fmt.Errorf(\"error reading list being: %s\")" << endl << + indent() << "}" << endl << + indent() << prefix << eq << "make(" << type_to_go_type(t) << ", 0, size)" << endl; + } else { + throw "INVALID TYPE IN generate_deserialize_container '" + ttype->get_name() + "' for prefix '" + prefix + "'"; + } + + // For loop iterates over elements out << - indent() << err << " = iprot.ReadSetEnd()" << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionReadField(" - << -1 - << ", \"" << escape_string(((t_set*)ttype)->get_cpp_name()) - << "\", " << "\"set\", " << err << "); }" << endl; - } else if (ttype->is_list()) { + indent() << "for i := 0; i < size; i ++ {" << endl; + indent_up(); + + if (ttype->is_map()) { + generate_deserialize_map_element(out, (t_map*)ttype, declare, prefix); + } else if (ttype->is_set()) { + generate_deserialize_set_element(out, (t_set*)ttype, declare, prefix); + } else if (ttype->is_list()) { + generate_deserialize_list_element(out, (t_list*)ttype, declare, prefix); + } + + indent_down(); out << - indent() << err << " = iprot.ReadListEnd()" << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionReadField(" - << -1 - << ", \"" << escape_string(((t_list*)ttype)->get_cpp_name()) - << "\", " << "\"list\"," << err << "); }" << endl; - } + indent() << "}" << endl; + + // Read container end + if (ttype->is_map()) { + out << + indent() << "if err := iprot.ReadMapEnd(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"error reading map end: %s\")" << endl << + indent() << "}" << endl; + } else if (ttype->is_set()) { + out << + indent() << "if err := iprot.ReadSetEnd(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"error reading set end: %s\")" << endl << + indent() << "}" << endl; + } else if (ttype->is_list()) { + out << + indent() << "if err := iprot.ReadListEnd(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"error reading list end: %s\")" << endl << + indent() << "}" << endl; + } } @@ -2466,58 +2611,49 @@ void t_go_generator::generate_deserialize_container(ofstream &out, * Generates code to deserialize a map */ void t_go_generator::generate_deserialize_map_element(ofstream &out, - t_map* tmap, - bool declare, - string prefix, - string err) { - (void) declare; - (void) err; - string key = tmp("_key"); - string val = tmp("_val"); - t_field fkey(tmap->get_key_type(), key); - t_field fval(tmap->get_val_type(), val); - - generate_deserialize_field(out, &fkey, true); - generate_deserialize_field(out, &fval, true); - - indent(out) << - prefix << ".Set(" << key << ", " << val << ")" << endl; + t_map* tmap, + bool declare, + string prefix) +{ + string key = tmp("_key"); + string val = tmp("_val"); + t_field fkey(tmap->get_key_type(), key); + t_field fval(tmap->get_val_type(), val); + generate_deserialize_field(out, &fkey, true); + generate_deserialize_field(out, &fval, true); + indent(out) << + prefix << "[" << key << "] = " << val << endl; + } /** * Write a set element */ void t_go_generator::generate_deserialize_set_element(ofstream &out, - t_set* tset, - bool declare, - string prefix, - string err) { - (void) declare; - string elem = tmp("_elem"); - t_field felem(tset->get_elem_type(), elem); - - generate_deserialize_field(out, &felem, true, "", err); - - indent(out) << - prefix << ".Add(" << elem << ")" << endl; + t_set* tset, + bool declare, + string prefix) +{ + string elem = tmp("_elem"); + t_field felem(tset->get_elem_type(), elem); + generate_deserialize_field(out, &felem, true, ""); + indent(out) << + prefix << "[" << elem << "] = true" << endl; } /** * Write a list element */ void t_go_generator::generate_deserialize_list_element(ofstream &out, - t_list* tlist, - bool declare, - string prefix, - string err) { - (void) declare; - string elem = tmp("_elem"); - t_field felem(tlist->get_elem_type(), elem); - - generate_deserialize_field(out, &felem, true, "", err); - - indent(out) << - prefix << ".Push(" << elem << ")" << endl; + t_list* tlist, + bool declare, + string prefix) +{ + string elem = tmp("_elem"); + t_field felem(tlist->get_elem_type(), elem); + generate_deserialize_field(out, &felem, true, ""); + indent(out) << + prefix << " = append(" << prefix << ", " << elem << ")" << endl; } @@ -2528,75 +2664,84 @@ void t_go_generator::generate_deserialize_list_element(ofstream &out, * @param prefix Name to prepend to field name */ void t_go_generator::generate_serialize_field(ofstream &out, - t_field* tfield, - string prefix, - string err) { - t_type* type = get_true_type(tfield->get_type()); - string name(prefix + publicize(variable_name_to_go_name(tfield->get_name()))); - - // Do nothing for void types - if (type->is_void()) { - throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; - } - - if (type->is_struct() || type->is_xception()) { - generate_serialize_struct(out, - (t_struct*)type, - name, - err); - } else if (type->is_container()) { - generate_serialize_container(out, - type, - name, - err); - } else if (type->is_base_type() || type->is_enum()) { + t_field* tfield, + string prefix) +{ + t_type* type = get_true_type(tfield->get_type()); + string name(prefix + publicize(variable_name_to_go_name(tfield->get_name()))); + + // Do nothing for void types + if (type->is_void()) { + throw "compiler error: cannot generate serialize for void type: " + name; + } - indent(out) << - err << " = oprot."; + if (type->is_struct() || type->is_xception()) { + generate_serialize_struct(out, + (t_struct*)type, + name); + } else if (type->is_container()) { + generate_serialize_container(out, + type, + name); + } else if (type->is_base_type() || type->is_enum()) { + indent(out) << + "if err := oprot."; + + 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 + "compiler error: cannot serialize void field in a struct: " + name; + break; + + case t_base_type::TYPE_STRING: + if (((t_base_type*)type)->is_binary()) { + out << "WriteBinary(" << name << ")"; + } else { + out << "WriteString(string(" << name << "))"; + } + + break; + + case t_base_type::TYPE_BOOL: + out << "WriteBool(bool(" << name << "))"; + break; + + case t_base_type::TYPE_BYTE: + out << "WriteByte(byte(" << name << "))"; + break; + + case t_base_type::TYPE_I16: + out << "WriteI16(int16(" << name << "))"; + break; + + case t_base_type::TYPE_I32: + out << "WriteI32(int32(" << name << "))"; + break; + + case t_base_type::TYPE_I64: + out << "WriteI64(int64(" << name << "))"; + break; + + case t_base_type::TYPE_DOUBLE: + out << "WriteDouble(float64(" << name << "))"; + break; + + default: + throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase); + } + } else if (type->is_enum()) { + out << "WriteI32(int32(" << name << "))"; + } - 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 - "compiler error: cannot serialize void field in a struct: " + name; - break; - case t_base_type::TYPE_STRING: - out << "WriteString(string(" << name << "))"; - break; - case t_base_type::TYPE_BOOL: - out << "WriteBool(bool(" << name << "))"; - break; - case t_base_type::TYPE_BYTE: - out << "WriteByte(byte(" << name << "))"; - break; - case t_base_type::TYPE_I16: - out << "WriteI16(int16(" << name << "))"; - break; - case t_base_type::TYPE_I32: - out << "WriteI32(int32(" << name << "))"; - break; - case t_base_type::TYPE_I64: - out << "WriteI64(int64(" << name << "))"; - break; - case t_base_type::TYPE_DOUBLE: - out << "WriteDouble(float64(" << name << "))"; - break; - default: - throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase); - } - } else if (type->is_enum()) { - out << "WriteI32(int32(" << name << "))"; - } - string structName = (prefix.size()) ? prefix + "ThriftName()" : "\"\""; - out << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionWriteField(" - << tfield->get_key() - << ", \"" << escape_string(tfield->get_name()) - << "\", " << structName << ", " << err << "); }\n"; - } else { - throw "INVALID TYPE IN generate_serialize_field '" + type->get_name() + "' for field '" + name + "'"; - } + out << "; err != nil {" << endl + << indent() << "return fmt.Errorf(\"%T." << escape_string(tfield->get_name()) + << " (" << tfield->get_key() << ") field write error: %s\", p) }" << endl; + } else { + throw "compiler error: Invalid type in generate_serialize_field '" + type->get_name() + "' for field '" + name + "'"; + } } /** @@ -2606,109 +2751,88 @@ void t_go_generator::generate_serialize_field(ofstream &out, * @param prefix String prefix to attach to all fields */ void t_go_generator::generate_serialize_struct(ofstream &out, - t_struct* tstruct, - string prefix, - string err) { - out << - indent() << err << " = " << prefix << ".Write(oprot)" << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionWriteStruct(" - << "\"" << escape_string(tstruct->get_name()) << "\", " << err << "); }\n"; + t_struct* tstruct, + string prefix) +{ + out << + indent() << "if err := " << prefix << ".Write(oprot); err != nil {" << endl << + indent() << " return fmt.Errorf(\"%T error writing struct: %s\", " << prefix << ")" << endl << + indent() << "}" << endl; } void t_go_generator::generate_serialize_container(ofstream &out, - t_type* ttype, - string prefix, - string err) { - if (ttype->is_map()) { - out << - indent() << err << " = oprot.WriteMapBegin(" << - type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << - type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << - prefix << ".Len())" << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionWriteField(" - << -1 - << ", \"" << escape_string(ttype->get_name()) - << "\", " << "\"map\", " << err << "); }\n"; - } else if (ttype->is_set()) { - out << - indent() << err << " = oprot.WriteSetBegin(" << - type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << - prefix << ".Len())" << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionWriteField(" - << -1 - << ", \"" << escape_string(ttype->get_name()) - << "\", " << "\"set\", " << err << "); }\n"; - } else if (ttype->is_list()) { - out << - indent() << err << " = oprot.WriteListBegin(" << - type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << - prefix << ".Len())" << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionWriteField(" - << -1 - << ", \"" << escape_string(ttype->get_name()) - << "\", " << "\"list\", " << err << "); }\n"; - } else { - throw "INVALID TYPE IN generate_serialize_container '" + ttype->get_name() + "' for prefix '" + prefix + "'"; - } - - if (ttype->is_map()) { - string miter = tmp("Miter"); - string kiter = tmp("Kiter"); - string viter = tmp("Viter"); - t_map* tmap = (t_map*)ttype; - out << - indent() << "for " << miter << " := range " << prefix << ".Iter() {" << endl << - indent() << " " << kiter << ", " << viter << " := " << miter << ".Key().(" << type_to_go_type(tmap->get_key_type()) << "), " << miter << ".Value().(" << type_to_go_type(tmap->get_val_type()) << ")" << endl; - indent_up(); - generate_serialize_map_element(out, tmap, kiter, viter); - indent_down(); - indent(out) << "}" << endl; - } else if (ttype->is_set()) { - t_set* tset = (t_set*)ttype; - string iter = tmp("Iter"); - string iter2 = tmp("Iter"); - out << - indent() << "for " << iter << " := " << prefix << ".Front(); " << iter << " != nil; " << iter << " = " << iter << ".Next() {" << endl << - indent() << " " << iter2 << " := " << iter << ".Value.(" << type_to_go_type(tset->get_elem_type()) << ")" << endl; - indent_up(); - generate_serialize_set_element(out, tset, iter2); - indent_down(); - indent(out) << "}" << endl; - } else if (ttype->is_list()) { - t_list* tlist = (t_list*)ttype; - string iter = tmp("Iter"); - string iter2 = tmp("Iter"); - out << - indent() << "for " << iter << " := range " << prefix << ".Iter() {" << endl << - indent() << " " << iter2 << " := " << iter << ".(" << type_to_go_type(tlist->get_elem_type()) << ")" << endl; - indent_up(); - generate_serialize_list_element(out, tlist, iter2); - indent_down(); - indent(out) << "}" << endl; - } + t_type* ttype, + string prefix) +{ + if (ttype->is_map()) { + out << + indent() << "if err := oprot.WriteMapBegin(" << + type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << + type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << + "len(" << prefix << ")); err != nil {" << endl << + indent() << " return fmt.Errorf(\"error writing map begin: %s\")" << endl << + indent() << "}" << endl; + } else if (ttype->is_set()) { + out << + indent() << "if err := oprot.WriteSetBegin(" << + type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << + "len(" << prefix << ")); err != nil {" << endl << + indent() << " return fmt.Errorf(\"error writing set begin: %s\")" << endl << + indent() << "}" << endl; + } else if (ttype->is_list()) { + out << + indent() << "if err := oprot.WriteListBegin(" << + type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << + "len(" << prefix << ")); err != nil {" << endl << + indent() << " return fmt.Errorf(\"error writing list begin: %s\")" << endl << + indent() << "}" << endl; + } else { + throw "compiler error: Invalid type in generate_serialize_container '" + ttype->get_name() + "' for prefix '" + prefix + "'"; + } - if (ttype->is_map()) { - out << - indent() << err << " = oprot.WriteMapEnd()" << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionWriteField(" - << -1 - << ", \"" << escape_string(ttype->get_name()) - << "\", " << "\"map\", " << err << "); }\n"; - } else if (ttype->is_set()) { - out << - indent() << err << " = oprot.WriteSetEnd()" << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionWriteField(" - << -1 - << ", \"" << escape_string(ttype->get_name()) - << "\", " << "\"set\", " << err << "); }\n"; - } else if (ttype->is_list()) { - out << - indent() << err << " = oprot.WriteListEnd()" << endl << - indent() << "if " << err << " != nil { return thrift.NewTProtocolExceptionWriteField(" - << -1 - << ", \"" << escape_string(ttype->get_name()) - << "\", " << "\"list\", " << err << "); }\n"; - } + if (ttype->is_map()) { + t_map* tmap = (t_map*)ttype; + out << + indent() << "for k,v := range " << prefix << " {" << endl; + indent_up(); + generate_serialize_map_element(out, tmap, "k", "v"); + indent_down(); + indent(out) << "}" << endl; + } else if (ttype->is_set()) { + t_set* tset = (t_set*)ttype; + out << + indent() << "for v, _ := range " << prefix << " {" << endl; + indent_up(); + generate_serialize_set_element(out, tset, "v"); + indent_down(); + indent(out) << "}" << endl; + } else if (ttype->is_list()) { + t_list* tlist = (t_list*)ttype; + out << + indent() << "for _, v := range " << prefix << " {" << endl; + + indent_up(); + generate_serialize_list_element(out, tlist, "v"); + indent_down(); + indent(out) << "}" << endl; + } + + if (ttype->is_map()) { + out << + indent() << "if err := oprot.WriteMapEnd(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"error writing map end: %s\")" << endl << + indent() << "}" << endl; + } else if (ttype->is_set()) { + out << + indent() << "if err := oprot.WriteSetEnd(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"error writing set end: %s\")" << endl << + indent() << "}" << endl; + } else if (ttype->is_list()) { + out << + indent() << "if err := oprot.WriteListEnd(); err != nil {" << endl << + indent() << " return fmt.Errorf(\"error writing list end: %s\")" << endl << + indent() << "}" << endl; + } } /** @@ -2716,107 +2840,115 @@ void t_go_generator::generate_serialize_container(ofstream &out, * */ void t_go_generator::generate_serialize_map_element(ofstream &out, - t_map* tmap, - string kiter, - string viter, - string err) { - t_field kfield(tmap->get_key_type(), kiter); - generate_serialize_field(out, &kfield, "", err); - - t_field vfield(tmap->get_val_type(), viter); - generate_serialize_field(out, &vfield, "", err); + t_map* tmap, + string kiter, + string viter) +{ + t_field kfield(tmap->get_key_type(), ""); + generate_serialize_field(out, &kfield, kiter); + t_field vfield(tmap->get_val_type(), ""); + generate_serialize_field(out, &vfield, viter); } /** * Serializes the members of a set. */ void t_go_generator::generate_serialize_set_element(ofstream &out, - t_set* tset, - string iter, - string err) { - t_field efield(tset->get_elem_type(), iter); - generate_serialize_field(out, &efield, "", err); + t_set* tset, + string prefix) +{ + t_field efield(tset->get_elem_type(), ""); + generate_serialize_field(out, &efield, prefix); } /** * Serializes the members of a list. */ void t_go_generator::generate_serialize_list_element(ofstream &out, - t_list* tlist, - string iter, - string err) { - t_field efield(tlist->get_elem_type(), iter); - generate_serialize_field(out, &efield, "", err); + t_list* tlist, + string prefix) +{ + t_field efield(tlist->get_elem_type(), ""); + generate_serialize_field(out, &efield, prefix); } /** * Generates the docstring for a given struct. */ void t_go_generator::generate_go_docstring(ofstream& out, - t_struct* tstruct) { - generate_go_docstring(out, tstruct, tstruct, "Attributes"); + t_struct* tstruct) +{ + generate_go_docstring(out, tstruct, tstruct, "Attributes"); } /** * Generates the docstring for a given function. */ void t_go_generator::generate_go_docstring(ofstream& out, - t_function* tfunction) { - generate_go_docstring(out, tfunction, tfunction->get_arglist(), "Parameters"); + t_function* tfunction) +{ + generate_go_docstring(out, tfunction, tfunction->get_arglist(), "Parameters"); } /** * Generates the docstring for a struct or function. */ void t_go_generator::generate_go_docstring(ofstream& out, - t_doc* tdoc, - t_struct* tstruct, - const char* subheader) { - bool has_doc = false; - stringstream ss; - if (tdoc->has_doc()) { - has_doc = true; - ss << tdoc->get_doc(); - } - - const vector& fields = tstruct->get_members(); - if (fields.size() > 0) { - if (has_doc) { - ss << endl; - } - has_doc = true; - ss << subheader << ":\n"; - vector::const_iterator p_iter; - for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { - t_field* p = *p_iter; - ss << " - " << publicize(variable_name_to_go_name(p->get_name())); - if (p->has_doc()) { - ss << ": " << p->get_doc(); - } else { - ss << endl; - } + t_doc* tdoc, + t_struct* tstruct, + const char* subheader) +{ + bool has_doc = false; + stringstream ss; + + if (tdoc->has_doc()) { + has_doc = true; + ss << tdoc->get_doc(); + } + + const vector& fields = tstruct->get_members(); + + if (fields.size() > 0) { + if (has_doc) { + ss << endl; + } + + has_doc = true; + ss << subheader << ":\n"; + vector::const_iterator p_iter; + + for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { + t_field* p = *p_iter; + ss << " - " << publicize(variable_name_to_go_name(p->get_name())); + + if (p->has_doc()) { + ss << ": " << p->get_doc(); + } else { + ss << endl; + } + } } - } - if (has_doc) { - generate_docstring_comment(out, - "/**\n", - " * ", ss.str(), - " */\n"); - } + if (has_doc) { + generate_docstring_comment(out, + "", + "// ", ss.str(), + ""); + } } /** * Generates the docstring for a generic object. */ void t_go_generator::generate_go_docstring(ofstream& out, - t_doc* tdoc) { - if (tdoc->has_doc()) { - generate_docstring_comment(out, - "/**\n", - " *", tdoc->get_doc(), - " */\n"); - } + t_doc* tdoc) +{ + if (tdoc->has_doc()) { + generate_docstring_comment(out, + "", + "//", tdoc->get_doc(), + ""); + } } /** @@ -2824,16 +2956,19 @@ void t_go_generator::generate_go_docstring(ofstream& out, * * @param tfield The field */ -string t_go_generator::declare_argument(t_field* tfield) { - std::ostringstream result; - result << publicize(tfield->get_name()) << "="; - if (tfield->get_value() != NULL) { - result << "thrift_spec[" << - tfield->get_key() << "][4]"; - } else { - result << "nil"; - } - return result.str(); +string t_go_generator::declare_argument(t_field* tfield) +{ + std::ostringstream result; + result << publicize(tfield->get_name()) << "="; + + if (tfield->get_value() != NULL) { + result << "thrift_spec[" << + tfield->get_key() << "][4]"; + } else { + result << "nil"; + } + + return result.str(); } /** @@ -2841,13 +2976,15 @@ string t_go_generator::declare_argument(t_field* tfield) { * * @param tfield The field */ -string t_go_generator::render_field_default_value(t_field* tfield, const string& name) { - t_type* type = get_true_type(tfield->get_type()); - if (tfield->get_value() != NULL) { - return render_const_value(type, tfield->get_value(), name); - } else { - return "nil"; - } +string t_go_generator::render_field_default_value(t_field* tfield, const string& name) +{ + t_type* type = get_true_type(tfield->get_type()); + + if (tfield->get_value() != NULL) { + return render_const_value(type, tfield->get_value(), name); + } else { + return "nil"; + } } /** @@ -2857,11 +2994,12 @@ string t_go_generator::render_field_default_value(t_field* tfield, const string& * @return String of rendered function definition */ string t_go_generator::function_signature(t_function* tfunction, - string prefix) { - // TODO(mcslee): Nitpicky, no ',' if argument_list is empty - return - publicize(prefix + tfunction->get_name()) + - "(" + argument_list(tfunction->get_arglist()) + ")"; + string prefix) +{ + // TODO(mcslee): Nitpicky, no ',' if argument_list is empty + return + publicize(prefix + tfunction->get_name()) + + "(" + argument_list(tfunction->get_arglist()) + ")"; } /** @@ -2871,229 +3009,305 @@ string t_go_generator::function_signature(t_function* tfunction, * @return String of rendered function definition */ string t_go_generator::function_signature_if(t_function* tfunction, - string prefix, - bool addOsError) { - // TODO(mcslee): Nitpicky, no ',' if argument_list is empty - string signature = publicize(prefix + tfunction->get_name()) + "("; - signature += argument_list(tfunction->get_arglist()) + ") ("; - t_type* ret = tfunction->get_returntype(); - t_struct* exceptions = tfunction->get_xceptions(); - string errs = argument_list(exceptions); - string retval(tmp("retval")); - if(!ret->is_void()) { - signature += retval + " " + type_to_go_type(ret); - if(addOsError || errs.size()==0) { - signature += ", "; - } - } - if(errs.size()>0) { - signature += errs; - if(addOsError) - signature += ", "; - } - if(addOsError) { - signature += "err os.Error"; - } - signature += ")"; - return signature; + string prefix, + bool addError) +{ + // TODO(mcslee): Nitpicky, no ',' if argument_list is empty + string signature = publicize(prefix + tfunction->get_name()) + "("; + signature += argument_list(tfunction->get_arglist()) + ") ("; + t_type* ret = tfunction->get_returntype(); + t_struct* exceptions = tfunction->get_xceptions(); + string errs = argument_list(exceptions); + + if (!ret->is_void()) { + signature += "r " + type_to_go_type(ret); + + if (addError || errs.size() == 0) { + signature += ", "; + } + } + + if (errs.size() > 0) { + signature += errs; + + if (addError) { + signature += ", "; + } + } + + if (addError) { + signature += "err error"; + } + + signature += ")"; + return signature; } /** * Renders a field list */ -string t_go_generator::argument_list(t_struct* tstruct) { - string result = ""; - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - bool first = true; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (first) { - first = false; - } else { - result += ", "; +string t_go_generator::argument_list(t_struct* tstruct) +{ + string result = ""; + const vector& fields = tstruct->get_members(); + vector::const_iterator f_iter; + bool first = true; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + if (first) { + first = false; + } else { + result += ", "; + } + + result += variable_name_to_go_name((*f_iter)->get_name()) + " " + type_to_go_type((*f_iter)->get_type()); } - result += variable_name_to_go_name((*f_iter)->get_name()) + " " + type_to_go_type((*f_iter)->get_type()); - } - return result; + + return result; } -string t_go_generator::type_name(t_type* ttype) { - t_program* program = ttype->get_program(); - if (ttype->is_service()) { - return get_real_go_module(program) + "." + ttype->get_name(); - } - if (program != NULL && program != program_) { - return get_real_go_module(program) + ".ttypes." + ttype->get_name(); - } - return ttype->get_name(); +string t_go_generator::type_name(t_type* ttype) +{ + t_program* program = ttype->get_program(); + + if (ttype->is_service()) { + return get_real_go_module(program) + "." + ttype->get_name(); + } + + if (program != NULL && program != program_) { + return get_real_go_module(program) + ".ttypes." + ttype->get_name(); + } + + return ttype->get_name(); } /** * Converts the parse type to a go tyoe */ -string t_go_generator::type_to_enum(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 "NO T_VOID CONSTRUCT"; - case t_base_type::TYPE_STRING: - return "thrift.STRING"; - case t_base_type::TYPE_BOOL: - return "thrift.BOOL"; - case t_base_type::TYPE_BYTE: - return "thrift.BYTE"; - case t_base_type::TYPE_I16: - return "thrift.I16"; - case t_base_type::TYPE_I32: - return "thrift.I32"; - case t_base_type::TYPE_I64: - return "thrift.I64"; - case t_base_type::TYPE_DOUBLE: - return "thrift.DOUBLE"; - } - } else if (type->is_enum()) { - return "thrift.I32"; - } else if (type->is_struct() || type->is_xception()) { - return "thrift.STRUCT"; - } else if (type->is_map()) { - return "thrift.MAP"; - } else if (type->is_set()) { - return "thrift.SET"; - } else if (type->is_list()) { - return "thrift.LIST"; - } - - throw "INVALID TYPE IN type_to_enum: " + type->get_name(); +string t_go_generator::type_to_enum(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 "NO T_VOID CONSTRUCT"; + + case t_base_type::TYPE_STRING: + if (((t_base_type*)type)->is_binary()) { + return "thrift.BINARY"; + } + + return "thrift.STRING"; + + case t_base_type::TYPE_BOOL: + return "thrift.BOOL"; + + case t_base_type::TYPE_BYTE: + return "thrift.BYTE"; + + case t_base_type::TYPE_I16: + return "thrift.I16"; + + case t_base_type::TYPE_I32: + return "thrift.I32"; + + case t_base_type::TYPE_I64: + return "thrift.I64"; + + case t_base_type::TYPE_DOUBLE: + return "thrift.DOUBLE"; + } + } else if (type->is_enum()) { + return "thrift.I32"; + } else if (type->is_struct() || type->is_xception()) { + return "thrift.STRUCT"; + } else if (type->is_map()) { + return "thrift.MAP"; + } else if (type->is_set()) { + return "thrift.SET"; + } else if (type->is_list()) { + return "thrift.LIST"; + } + + throw "INVALID TYPE IN type_to_enum: " + type->get_name(); +} + + +/** + * Converts the parse type to a go map type, will throw an exception if it will + * not produce a valid go map type. + */ +string t_go_generator::type_to_go_key_type(t_type* type) +{ + string go_type = type_to_go_type(type); + + while (type->is_typedef()) { + type = ((t_typedef*)type)->get_type(); + } + + if (type->is_map() || type->is_list() || type->is_set()) { + throw "Cannot produce a valid type for a Go map key: " + type_to_go_type(type) + " - aborting."; + + } + + return type_to_go_type(type); } /** * Converts the parse type to a go tyoe */ -string t_go_generator::type_to_go_type(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 ""; - case t_base_type::TYPE_STRING: - return "string"; - case t_base_type::TYPE_BOOL: - return "bool"; - case t_base_type::TYPE_BYTE: - return "byte"; - case t_base_type::TYPE_I16: - return "int16"; - case t_base_type::TYPE_I32: - return "int32"; - case t_base_type::TYPE_I64: - return "int64"; - case t_base_type::TYPE_DOUBLE: - return "float64"; - } - } else if (type->is_enum()) { - return publicize(type->get_name()); - } else if (type->is_struct() || type->is_xception()) { - return string("*") + publicize(type->get_name()); - } else if (type->is_map()) { - return "thrift.TMap"; - //t_map* t = (t_map*)type; - //string keyType = type_to_go_type(t->get_key_type()); - //string valueType = type_to_go_type(t->get_val_type()); - //return string("map[") + keyType + "]" + valueType; - } else if (type->is_set()) { - return "thrift.TSet"; - //t_set* t = (t_set*)type; - //string elemType = type_to_go_type(t->get_elem_type()); - //return string("[]") + elemType; - } else if (type->is_list()) { - return "thrift.TList"; - //t_list* t = (t_list*)type; - //string elemType = type_to_go_type(t->get_elem_type()); - //return string("[]") + elemType; - } else if (type->is_typedef()) { - return publicize(((t_typedef*)type)->get_symbolic()); - } - - throw "INVALID TYPE IN type_to_go_type: " + type->get_name(); +string t_go_generator::type_to_go_type(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 ""; + + case t_base_type::TYPE_STRING: + if (((t_base_type*)type)->is_binary()) { + return "[]byte"; + } + + return "string"; + + case t_base_type::TYPE_BOOL: + return "bool"; + + case t_base_type::TYPE_BYTE: + return "int8"; + + case t_base_type::TYPE_I16: + return "int16"; + + case t_base_type::TYPE_I32: + return "int32"; + + case t_base_type::TYPE_I64: + return "int64"; + + case t_base_type::TYPE_DOUBLE: + return "float64"; + } + } else if (type->is_enum()) { + return publicize(type->get_name()); + } else if (type->is_struct() || type->is_xception()) { + return string("*") + publicize(type->get_name()); + } 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()); + return string("map[") + keyType + "]" + valueType; + } else if (type->is_set()) { + t_set* t = (t_set*)type; + string elemType = type_to_go_key_type(t->get_elem_type()); + return 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()); + return string("[]") + elemType; + } else if (type->is_typedef()) { + return publicize(((t_typedef*)type)->get_symbolic()); + } + + 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_STRING: - 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; - } - } 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(); +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) { - while (ttype->is_typedef()) { - ttype = ((t_typedef*)ttype)->get_type(); - } - - if (ttype->is_base_type() || ttype->is_enum()) { - return "nil"; - } else if (ttype->is_struct() || ttype->is_xception()) { - return "(" + type_name(ttype) + ", " + type_name(ttype) + ".thrift_spec)"; - } else if (ttype->is_map()) { - return "(" + - type_to_enum(((t_map*)ttype)->get_key_type()) + "," + - type_to_spec_args(((t_map*)ttype)->get_key_type()) + "," + - type_to_enum(((t_map*)ttype)->get_val_type()) + "," + - type_to_spec_args(((t_map*)ttype)->get_val_type()) + - ")"; - - } else if (ttype->is_set()) { - return "(" + - type_to_enum(((t_set*)ttype)->get_elem_type()) + "," + - type_to_spec_args(((t_set*)ttype)->get_elem_type()) + - ")"; - - } else if (ttype->is_list()) { - return "(" + - type_to_enum(((t_list*)ttype)->get_elem_type()) + "," + - type_to_spec_args(((t_list*)ttype)->get_elem_type()) + - ")"; - } - - throw "INVALID TYPE IN type_to_spec_args: " + ttype->get_name(); +string t_go_generator::type_to_spec_args(t_type* ttype) +{ + while (ttype->is_typedef()) { + ttype = ((t_typedef*)ttype)->get_type(); + } + + if (ttype->is_base_type() || ttype->is_enum()) { + return "nil"; + } else if (ttype->is_struct() || ttype->is_xception()) { + return "(" + type_name(ttype) + ", " + type_name(ttype) + ".thrift_spec)"; + } else if (ttype->is_map()) { + return "(" + + type_to_enum(((t_map*)ttype)->get_key_type()) + "," + + type_to_spec_args(((t_map*)ttype)->get_key_type()) + "," + + type_to_enum(((t_map*)ttype)->get_val_type()) + "," + + type_to_spec_args(((t_map*)ttype)->get_val_type()) + + ")"; + } else if (ttype->is_set()) { + return "(" + + type_to_enum(((t_set*)ttype)->get_elem_type()) + "," + + type_to_spec_args(((t_set*)ttype)->get_elem_type()) + + ")"; + } else if (ttype->is_list()) { + return "(" + + type_to_enum(((t_list*)ttype)->get_elem_type()) + "," + + type_to_spec_args(((t_list*)ttype)->get_elem_type()) + + ")"; + } + + throw "INVALID TYPE IN type_to_spec_args: " + ttype->get_name(); +} + +bool format_go_output(const string &file_path) +{ + const string command = "gofmt -w " + file_path; + + if (system(command.c_str()) == 0) { + return true; + } + + fprintf(stderr, "WARNING - Running '%s' failed.\n", command.c_str()); + return false; } -THRIFT_REGISTER_GENERATOR(go, "Go", "") +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") diff --git a/configure.ac b/configure.ac index ed2ba000..12cf52d7 100755 --- a/configure.ac +++ b/configure.ac @@ -75,20 +75,6 @@ AC_ARG_VAR([CABAL_CONFIGURE_FLAGS], AC_SUBST(CABAL_CONFIGURE_FLAGS) -AC_ARG_VAR([GOROOT], [Prefix for the Go source directory. - (Normal --prefix is ignored for Go because - Go has different conventions.) - Default = "/usr/local/share/go"]) -AS_IF([test "x$GOROOT" = x], [GOROOT="/usr/local/share/go"]) - -AC_ARG_VAR([GOARCH], [Architecture default for Go. - Default = "amd64"]) -AS_IF([test "x$GOARCH" = x], [GOARCH="amd64"]) - -AC_ARG_VAR([GOBIN], [Binary directory for Go. - Default = "/usr/local/bin"]) -AS_IF([test "x$GOBIN" = x], [GOBIN="/usr/local/bin"]) - AC_ARG_VAR([D_IMPORT_PREFIX], [Prefix for installing D modules. [INCLUDEDIR/d2]]) AS_IF([test "x$D_IMPORT_PREFIX" = x], [D_IMPORT_PREFIX="${includedir}/d2"]) @@ -270,29 +256,8 @@ AM_CONDITIONAL(WITH_HASKELL, [test "$have_haskell" = "yes"]) AX_THRIFT_LIB(go, [Go], yes) if test "$with_go" = "yes"; then - case X"$GOARCH" in - Xamd64) - GOARCH_NUM=6 - ;; - X386) - GOARCH_NUM=8 - ;; - Xarm) - GOARCH_NUM=5 - ;; - *) - GOARCH_NUM=6 - ;; - esac - GO_C=${GOBIN}/${GOARCH_NUM}g - GO_L=${GOBIN}/${GOARCH_NUM}l - GOMAKE=${GOBIN}/gomake - GOINSTALL=${GOBIN}/goinstall - AC_PATH_PROG([GO_C], [${GOARCH_NUM}g]) - AC_PATH_PROG([GO_L], [${GOARCH_NUM}l]) - AC_PATH_PROG([GOMAKE], [gomake]) - AC_PATH_PROG([GOINSTALL], [goinstall]) - if [[ -x "$GO_C" -a -x "$GO_L" -a -x "$GOMAKE" -a -x "$GOINSTALL" ]] ; then + AC_PATH_PROG([GO], [go]) + if [[ -x "$GO" ]] ; then have_go="yes" fi fi @@ -603,6 +568,7 @@ AC_CONFIG_FILES([ lib/d/Makefile lib/d/test/Makefile lib/erl/Makefile + lib/go/Makefile lib/hs/Makefile lib/java/Makefile lib/js/test/Makefile @@ -624,6 +590,7 @@ AC_CONFIG_FILES([ test/rb/Makefile tutorial/Makefile tutorial/cpp/Makefile + tutorial/go/Makefile tutorial/java/Makefile tutorial/js/Makefile tutorial/py/Makefile @@ -704,11 +671,8 @@ fi if test "$have_go" = "yes" ; then echo echo "Go Library:" - echo " Using GOROOT............... : $GOROOT" - echo " Using GOBIN................ : $GOBIN" - echo " Using GOARCH............... : $GOARCH" - echo " Using GO Compiler.......... : $GO_C" - echo " Using GO Linker............ : $GO_L" + echo " Using Go................... : $GO" + echo " Using Go version........... : $(go version)" fi if test "$have_d" = "yes" ; then echo diff --git a/lib/Makefile.am b/lib/Makefile.am index d26752b5..1cc5c6cb 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -62,6 +62,10 @@ if WITH_PHP SUBDIRS += php endif +if WITH_GO +SUBDIRS += go +endif + if WITH_D SUBDIRS += d endif @@ -73,7 +77,6 @@ EXTRA_DIST = \ cocoa \ d \ delphi \ - go \ javame \ js \ nodejs \ diff --git a/lib/go/Make.deps b/lib/go/Make.deps deleted file mode 100644 index 56e75da3..00000000 --- a/lib/go/Make.deps +++ /dev/null @@ -1,159 +0,0 @@ -thrift/.install: bufio.install bytes.install container/list.install container/vector.install encoding/base64.install encoding/binary.install fmt.install http.install io.install json.install log.install math.install net.install os.install reflect.install sort.install strconv.install strings.install -archive/tar.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/archive/tar.a -archive/zip.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/archive/zip.a -asn1.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/asn1.a -big.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/big.a -bufio.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/bufio.a -bytes.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/bytes.a -cmath.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/cmath.a -compress/bzip2.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/bzip2.a -compress/flate.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/flate.a -compress/gzip.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/gzip.a -compress/lzw.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/lzw.a -compress/zlib.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/zlib.a -container/heap.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/heap.a -container/list.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/list.a -container/ring.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/ring.a -container/vector.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/vector.a -crypto.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto.a -crypto/aes.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/aes.a -crypto/blowfish.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/blowfish.a -crypto/cast5.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/cast5.a -crypto/cipher.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/cipher.a -crypto/des.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/des.a -crypto/dsa.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/dsa.a -crypto/ecdsa.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/ecdsa.a -crypto/elliptic.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/elliptic.a -crypto/hmac.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/hmac.a -crypto/md4.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/md4.a -crypto/md5.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/md5.a -crypto/ocsp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/ocsp.a -crypto/openpgp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/openpgp.a -crypto/openpgp/armor.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/openpgp/armor.a -crypto/openpgp/error.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/openpgp/error.a -crypto/openpgp/packet.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/openpgp/packet.a -crypto/openpgp/s2k.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/openpgp/s2k.a -crypto/rand.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rand.a -crypto/rc4.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rc4.a -crypto/ripemd160.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/ripemd160.a -crypto/rsa.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rsa.a -crypto/sha1.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha1.a -crypto/sha256.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha256.a -crypto/sha512.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha512.a -crypto/subtle.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/subtle.a -crypto/tls.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/tls.a -crypto/twofish.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/twofish.a -crypto/x509.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/x509.a -crypto/x509/crl.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/x509/crl.a -crypto/xtea.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/xtea.a -debug/dwarf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/dwarf.a -debug/macho.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/macho.a -debug/elf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/elf.a -debug/gosym.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/gosym.a -debug/pe.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/pe.a -debug/proc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/proc.a -ebnf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/ebnf.a -encoding/ascii85.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/ascii85.a -encoding/base32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/base32.a -encoding/base64.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/base64.a -encoding/binary.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/binary.a -encoding/git85.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/git85.a -encoding/hex.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/hex.a -encoding/line.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/line.a -encoding/pem.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/pem.a -exec.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exec.a -exp/datafmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/datafmt.a -exp/draw.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/draw.a -exp/draw/x11.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/draw/x11.a -exp/eval.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/eval.a -expvar.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/expvar.a -flag.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/flag.a -fmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/fmt.a -go/ast.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/ast.a -go/doc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/doc.a -go/parser.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/parser.a -go/printer.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/printer.a -go/scanner.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/scanner.a -go/token.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/token.a -go/typechecker.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/typechecker.a -go/types.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/types.a -gob.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/gob.a -hash.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash.a -hash/adler32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/adler32.a -hash/crc32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/crc32.a -hash/crc64.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/crc64.a -hash/fnv.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/fnv.a -html.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/html.a -http.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http.a -http/cgi.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http/cgi.a -http/fcgi.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http/fcgi.a -http/pprof.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http/pprof.a -http/httptest.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http/httptest.a -http/spdy.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http/spdy.a -image.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image.a -image/bmp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/bmp.a -image/gif.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/gif.a -image/jpeg.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/jpeg.a -image/png.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/png.a -image/tiff.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/tiff.a -image/ycbcr.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/ycbcr.a -index/suffixarray.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/index/suffixarray.a -io.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/io.a -io/ioutil.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/io/ioutil.a -json.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/json.a -log.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/log.a -math.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/math.a -mime.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/mime.a -mime/multipart.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/mime/multipart.a -net.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net.a -net/dict.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net/dict.a -net/textproto.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net/textproto.a -netchan.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/netchan.a -os.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/os.a -os/signal.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/os/signal.a -os/user.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/os/user.a -patch.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/patch.a -path.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/path.a -path/filepath.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/path/filepath.a -rand.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rand.a -reflect.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/reflect.a -regexp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/regexp.a -rpc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rpc.a -rpc/jsonrpc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rpc/jsonrpc.a -runtime.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime.a -runtime/cgo.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/cgo.a -runtime/debug.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/debug.a -runtime/pprof.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/pprof.a -scanner.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/scanner.a -smtp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/smtp.a -sort.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/sort.a -strconv.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/strconv.a -strings.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/strings.a -sync.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/sync.a -sync/atomic.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/sync/atomic.a -syscall.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/syscall.a -syslog.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/syslog.a -tabwriter.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/tabwriter.a -template.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/template.a -testing.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing.a -testing/iotest.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/iotest.a -testing/quick.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/quick.a -testing/script.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/script.a -time.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/time.a -try.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/try.a -unicode.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/unicode.a -utf16.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/utf16.a -utf8.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/utf8.a -websocket.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/websocket.a -xml.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/xml.a -../cmd/cgo.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/cgo.a -../cmd/ebnflint.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/ebnflint.a -../cmd/godoc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/godoc.a -../cmd/gofix.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/gofix.a -../cmd/gofmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/gofmt.a -../cmd/goinstall.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/goinstall.a -../cmd/gotest.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/gotest.a -../cmd/gotype.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/gotype.a -../cmd/govet.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/govet.a -../cmd/goyacc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/goyacc.a -../cmd/hgpatch.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/hgpatch.a diff --git a/lib/go/Makefile b/lib/go/Makefile deleted file mode 100644 index 8e81d8d3..00000000 --- a/lib/go/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# After editing the DIRS= list or adding imports to any Go files -# in any of those directories, run: -# -# ./deps.bash -# -# to rebuild the dependency information in Make.deps. - - -include $(GOROOT)/src/Make.inc - -all: Make.deps install - -DIRS=\ - thrift/\ - -TEST=\ - $(filter-out $(NOTEST),$(DIRS)) - - -clean.dirs: $(addsuffix .clean, $(DIRS)) -install.dirs: $(addsuffix .install, $(DIRS)) -nuke.dirs: $(addsuffix .nuke, $(DIRS)) -test.dirs: $(addsuffix .test, $(DIRS)) -check.dirs: $(addsuffix .check, $(DIRS)) - -%.clean: - +cd $* && gomake clean - -%.install: - +cd $* && gomake install - -%.nuke: - +cd $* && gomake nuke - -%.test: - +cd $* && gomake test - -%.check: - +cd $* && gomake check - -clean: clean.dirs - -install: install.dirs - -test: test.dirs - -check: check.dirs - -#nuke: nuke.dirs -# rm -rf "$(GOROOT)"/pkg/thrift.* - -echo-dirs: - @echo $(DIRS) - -Make.deps: - ./deps.bash - -deps: - ./deps.bash - diff --git a/lib/go/Makefile.am b/lib/go/Makefile.am new file mode 100644 index 00000000..7c824678 --- /dev/null +++ b/lib/go/Makefile.am @@ -0,0 +1,12 @@ +install: + @echo '##############################################################' + @echo '##############################################################' + @echo 'The Go client library should be insalled via "go get", please see /lib/go/README' + @echo '##############################################################' + @echo '##############################################################' + +check-local: + go test ./thrift + +all-local: check-local + diff --git a/lib/go/README b/lib/go/README new file mode 100644 index 00000000..94628d9d --- /dev/null +++ b/lib/go/README @@ -0,0 +1,31 @@ +Thrift Python Software Library + +License +======= + +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. + +Using Thrift with Go +==================== + +In following Go conventions, we reccomend you use the 'go' tool to install +Thrift for go. + +$ go get git.apache.org/thrift.git/lib/go/thrift + +Will install the last stable release. diff --git a/lib/go/deps.bash b/lib/go/deps.bash deleted file mode 100644 index dabd404f..00000000 --- a/lib/go/deps.bash +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -OUT="Make.deps" -TMP="Make.deps.tmp" - -if [ -f $OUT ] && ! [ -w $OUT ]; then - echo "$0: $OUT is read-only; aborting." 1>&2 - exit 1 -fi - -# Get list of directories from Makefile -dirs=$(sed '1,/^DIRS=/d; /^$/,$d; s/\\//g' Makefile) -dirs2=$(sed '1,/^DIRS=/d; /^$/,$d; s/\\//g' $GOROOT/src/pkg/Makefile) -dirpat=$(echo $dirs $dirs2 | sed 's/ /|/g; s/.*/^(&)$/') - -for dir in $dirs; do ( - cd $dir || exit 1 - - sources=$(sed -n 's/\.go\\/.go/p' Makefile) - sources=$(ls $sources 2> /dev/null) # remove .s, .c, etc. - - deps=$( - sed -n '/^import.*"/p; /^import[ \t]*(/,/^)/p' $sources /dev/null | - cut -d '"' -f2 | - egrep "$dirpat" | - grep -v "^$dir\$" | - sed 's/$/.install/' | - sort -u - ) - - echo $dir.install: $deps -) done > $TMP - -for dir in $dirs2; do ( - echo $dir.install: \${GOROOT}/pkg/\${GOOS}_\${GOARCH}/${dir}.a -) done >> $TMP - -mv $TMP $OUT diff --git a/lib/go/thrift/Makefile b/lib/go/thrift/Makefile deleted file mode 100644 index 59f78625..00000000 --- a/lib/go/thrift/Makefile +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=thrift -GOFILES=\ - tapplication_exception.go\ - tbase.go\ - tbinary_protocol.go\ - tcompact_protocol.go\ - tcompare.go\ - tcontainer.go\ - texception.go\ - tfield.go\ - tframed_transport.go\ - thttp_client.go\ - tiostream_transport.go\ - tlist.go\ - tjson_protocol.go\ - tmap.go\ - tmemory_buffer.go\ - tmessage.go\ - tmessagetype.go\ - tnonblocking_server.go\ - tnonblocking_server_socket.go\ - tnonblocking_socket.go\ - tnonblocking_transport.go\ - tnumeric.go\ - tprocessor.go\ - tprocessor_factory.go\ - tprotocol.go\ - tprotocol_exception.go\ - tprotocol_factory.go\ - tserver.go\ - tserver_socket.go\ - tserver_transport.go\ - tset.go\ - tsimple_server.go\ - tsimple_json_protocol.go\ - tsocket.go\ - tstruct.go\ - ttransport.go\ - ttransport_exception.go\ - ttransport_factory.go\ - ttype.go - -DIRS=\ - -include $(GOROOT)/src/Make.pkg - -check: - gomake test - --include ../Make.deps - - diff --git a/lib/go/thrift/_testmain.go b/lib/go/thrift/_testmain.go deleted file mode 100644 index 3b0abfb4..00000000 --- a/lib/go/thrift/_testmain.go +++ /dev/null @@ -1,68 +0,0 @@ -package main - -import "./_xtest_" -import "testing" -import __regexp__ "regexp" - -var tests = []testing.InternalTest{ - {"thrift_test.TestTApplicationException", thrift_test.TestTApplicationException}, - {"thrift_test.TestReadWriteBinaryProtocol", thrift_test.TestReadWriteBinaryProtocol}, - {"thrift_test.TestReadWriteCompactProtocol", thrift_test.TestReadWriteCompactProtocol}, - {"thrift_test.TestTException", thrift_test.TestTException}, - {"thrift_test.TestFramedTransport", thrift_test.TestFramedTransport}, - {"thrift_test.TestHttpClient", thrift_test.TestHttpClient}, - {"thrift_test.TestIOStreamTransport", thrift_test.TestIOStreamTransport}, - {"thrift_test.TestWriteJSONProtocolBool", thrift_test.TestWriteJSONProtocolBool}, - {"thrift_test.TestReadJSONProtocolBool", thrift_test.TestReadJSONProtocolBool}, - {"thrift_test.TestWriteJSONProtocolByte", thrift_test.TestWriteJSONProtocolByte}, - {"thrift_test.TestReadJSONProtocolByte", thrift_test.TestReadJSONProtocolByte}, - {"thrift_test.TestWriteJSONProtocolI16", thrift_test.TestWriteJSONProtocolI16}, - {"thrift_test.TestReadJSONProtocolI16", thrift_test.TestReadJSONProtocolI16}, - {"thrift_test.TestWriteJSONProtocolI32", thrift_test.TestWriteJSONProtocolI32}, - {"thrift_test.TestReadJSONProtocolI32", thrift_test.TestReadJSONProtocolI32}, - {"thrift_test.TestWriteJSONProtocolI64", thrift_test.TestWriteJSONProtocolI64}, - {"thrift_test.TestReadJSONProtocolI64", thrift_test.TestReadJSONProtocolI64}, - {"thrift_test.TestWriteJSONProtocolDouble", thrift_test.TestWriteJSONProtocolDouble}, - {"thrift_test.TestReadJSONProtocolDouble", thrift_test.TestReadJSONProtocolDouble}, - {"thrift_test.TestWriteJSONProtocolString", thrift_test.TestWriteJSONProtocolString}, - {"thrift_test.TestReadJSONProtocolString", thrift_test.TestReadJSONProtocolString}, - {"thrift_test.TestWriteJSONProtocolBinary", thrift_test.TestWriteJSONProtocolBinary}, - {"thrift_test.TestReadJSONProtocolBinary", thrift_test.TestReadJSONProtocolBinary}, - {"thrift_test.TestWriteJSONProtocolList", thrift_test.TestWriteJSONProtocolList}, - {"thrift_test.TestWriteJSONProtocolSet", thrift_test.TestWriteJSONProtocolSet}, - {"thrift_test.TestWriteJSONProtocolMap", thrift_test.TestWriteJSONProtocolMap}, - {"thrift_test.TestReadWriteJSONStruct", thrift_test.TestReadWriteJSONStruct}, - {"thrift_test.TestReadWriteJSONProtocol", thrift_test.TestReadWriteJSONProtocol}, - {"thrift_test.TestMemoryBuffer", thrift_test.TestMemoryBuffer}, - {"thrift_test.TestNonblockingTransportServerToClient", thrift_test.TestNonblockingTransportServerToClient}, - {"thrift_test.TestNonblockingTransportClientToServer", thrift_test.TestNonblockingTransportClientToServer}, - {"thrift_test.TestNothing", thrift_test.TestNothing}, - {"thrift_test.TestWriteSimpleJSONProtocolBool", thrift_test.TestWriteSimpleJSONProtocolBool}, - {"thrift_test.TestReadSimpleJSONProtocolBool", thrift_test.TestReadSimpleJSONProtocolBool}, - {"thrift_test.TestWriteSimpleJSONProtocolByte", thrift_test.TestWriteSimpleJSONProtocolByte}, - {"thrift_test.TestReadSimpleJSONProtocolByte", thrift_test.TestReadSimpleJSONProtocolByte}, - {"thrift_test.TestWriteSimpleJSONProtocolI16", thrift_test.TestWriteSimpleJSONProtocolI16}, - {"thrift_test.TestReadSimpleJSONProtocolI16", thrift_test.TestReadSimpleJSONProtocolI16}, - {"thrift_test.TestWriteSimpleJSONProtocolI32", thrift_test.TestWriteSimpleJSONProtocolI32}, - {"thrift_test.TestReadSimpleJSONProtocolI32", thrift_test.TestReadSimpleJSONProtocolI32}, - {"thrift_test.TestWriteSimpleJSONProtocolI64", thrift_test.TestWriteSimpleJSONProtocolI64}, - {"thrift_test.TestReadSimpleJSONProtocolI64", thrift_test.TestReadSimpleJSONProtocolI64}, - {"thrift_test.TestWriteSimpleJSONProtocolDouble", thrift_test.TestWriteSimpleJSONProtocolDouble}, - {"thrift_test.TestReadSimpleJSONProtocolDouble", thrift_test.TestReadSimpleJSONProtocolDouble}, - {"thrift_test.TestWriteSimpleJSONProtocolString", thrift_test.TestWriteSimpleJSONProtocolString}, - {"thrift_test.TestReadSimpleJSONProtocolString", thrift_test.TestReadSimpleJSONProtocolString}, - {"thrift_test.TestWriteSimpleJSONProtocolBinary", thrift_test.TestWriteSimpleJSONProtocolBinary}, - {"thrift_test.TestReadSimpleJSONProtocolBinary", thrift_test.TestReadSimpleJSONProtocolBinary}, - {"thrift_test.TestWriteSimpleJSONProtocolList", thrift_test.TestWriteSimpleJSONProtocolList}, - {"thrift_test.TestWriteSimpleJSONProtocolSet", thrift_test.TestWriteSimpleJSONProtocolSet}, - {"thrift_test.TestWriteSimpleJSONProtocolMap", thrift_test.TestWriteSimpleJSONProtocolMap}, - {"thrift_test.TestReadWriteSimpleJSONStruct", thrift_test.TestReadWriteSimpleJSONStruct}, - {"thrift_test.TestReadWriteSimpleJSONProtocol", thrift_test.TestReadWriteSimpleJSONProtocol}, -} -var benchmarks = []testing.InternalBenchmark{ // -} - -func main() { - testing.Main(__regexp__.MatchString, tests) - testing.RunBenchmarks(__regexp__.MatchString, benchmarks) -} diff --git a/lib/go/thrift/application_exception.go b/lib/go/thrift/application_exception.go new file mode 100644 index 00000000..6655cc5a --- /dev/null +++ b/lib/go/thrift/application_exception.go @@ -0,0 +1,142 @@ +/* + * 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 thrift + +const ( + UNKNOWN_APPLICATION_EXCEPTION = 0 + UNKNOWN_METHOD = 1 + INVALID_MESSAGE_TYPE_EXCEPTION = 2 + WRONG_METHOD_NAME = 3 + BAD_SEQUENCE_ID = 4 + MISSING_RESULT = 5 + INTERNAL_ERROR = 6 + PROTOCOL_ERROR = 7 +) + +// Application level Thrift exception +type TApplicationException interface { + TException + TypeId() int32 + Read(iprot TProtocol) (TApplicationException, error) + Write(oprot TProtocol) error +} + +type tApplicationException struct { + message string + type_ int32 +} + +func (e tApplicationException) Error() string { + return e.message +} + +func NewTApplicationException(type_ int32, message string) TApplicationException { + return &tApplicationException{message, type_} +} + +func (p *tApplicationException) TypeId() int32 { + return p.type_ +} + +func (p *tApplicationException) Read(iprot TProtocol) (TApplicationException, error) { + _, err := iprot.ReadStructBegin() + if err != nil { + return nil, err + } + + message := "" + type_ := int32(UNKNOWN_APPLICATION_EXCEPTION) + + for { + _, ttype, id, err := iprot.ReadFieldBegin() + if err != nil { + return nil, err + } + if ttype == STOP { + break + } + switch id { + case 1: + if ttype == STRING { + if message, err = iprot.ReadString(); err != nil { + return nil, err + } + } else { + if err = SkipDefaultDepth(iprot, ttype); err != nil { + return nil, err + } + } + case 2: + if ttype == I32 { + if type_, err = iprot.ReadI32(); err != nil { + return nil, err + } + } else { + if err = SkipDefaultDepth(iprot, ttype); err != nil { + return nil, err + } + } + default: + if err = SkipDefaultDepth(iprot, ttype); err != nil { + return nil, err + } + } + if err = iprot.ReadFieldEnd(); err != nil { + return nil, err + } + } + return NewTApplicationException(type_, message), iprot.ReadStructEnd() +} + +func (p *tApplicationException) Write(oprot TProtocol) (err error) { + err = oprot.WriteStructBegin("TApplicationException") + if len(p.Error()) > 0 { + err = oprot.WriteFieldBegin("message", STRING, 1) + if err != nil { + return + } + err = oprot.WriteString(p.Error()) + if err != nil { + return + } + err = oprot.WriteFieldEnd() + if err != nil { + return + } + } + err = oprot.WriteFieldBegin("type", I32, 2) + if err != nil { + return + } + err = oprot.WriteI32(p.type_) + if err != nil { + return + } + err = oprot.WriteFieldEnd() + if err != nil { + return + } + err = oprot.WriteFieldStop() + if err != nil { + return + } + err = oprot.WriteStructEnd() + return +} diff --git a/lib/go/thrift/tapplication_exception_test.go b/lib/go/thrift/application_exception_test.go similarity index 55% rename from lib/go/thrift/tapplication_exception_test.go rename to lib/go/thrift/application_exception_test.go index d9572f49..7010f868 100644 --- a/lib/go/thrift/tapplication_exception_test.go +++ b/lib/go/thrift/application_exception_test.go @@ -17,26 +17,25 @@ * under the License. */ -package thrift_test +package thrift import ( - . "thrift" - "testing" + "testing" ) func TestTApplicationException(t *testing.T) { - exc := NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, "") - if exc.String() != "" { - t.Fatalf("Expected empty string for exception but found '%s'", exc.String()) - } - if exc.TypeId() != UNKNOWN_APPLICATION_EXCEPTION { - t.Fatalf("Expected type UNKNOWN for exception but found '%s'", exc.TypeId()) - } - exc = NewTApplicationException(WRONG_METHOD_NAME, "junk_method") - if exc.String() != "junk_method" { - t.Fatalf("Expected 'junk_method' for exception but found '%s'", exc.String()) - } - if exc.TypeId() != WRONG_METHOD_NAME { - t.Fatalf("Expected type WRONG_METHOD_NAME for exception but found '%s'", exc.TypeId()) - } + exc := NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, "") + if exc.Error() != "" { + t.Fatalf("Expected empty string for exception but found '%s'", exc.Error()) + } + if exc.TypeId() != UNKNOWN_APPLICATION_EXCEPTION { + t.Fatalf("Expected type UNKNOWN for exception but found '%s'", exc.TypeId()) + } + exc = NewTApplicationException(WRONG_METHOD_NAME, "junk_method") + if exc.Error() != "junk_method" { + t.Fatalf("Expected 'junk_method' for exception but found '%s'", exc.Error()) + } + if exc.TypeId() != WRONG_METHOD_NAME { + t.Fatalf("Expected type WRONG_METHOD_NAME for exception but found '%s'", exc.TypeId()) + } } diff --git a/lib/go/thrift/binary_protocol.go b/lib/go/thrift/binary_protocol.go new file mode 100644 index 00000000..5880f65c --- /dev/null +++ b/lib/go/thrift/binary_protocol.go @@ -0,0 +1,489 @@ +/* + * 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 thrift + +import ( + "encoding/binary" + "fmt" + "io" + "math" + "strings" +) + +type TBinaryProtocol struct { + trans TTransport + strictRead bool + strictWrite bool + readLength int + checkReadLength bool +} + +type TBinaryProtocolFactory struct { + strictRead bool + strictWrite bool +} + +func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol { + return NewTBinaryProtocol(t, false, true) +} + +func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol { + //return &TBinaryProtocol{TProtocolBase:TProtocolBase{trans:t}, strictRead:strictRead, strictWrite:strictWrite, readLength:0, checkReadLength:false}; + return &TBinaryProtocol{trans: t, strictRead: strictRead, strictWrite: strictWrite, readLength: 0, checkReadLength: false} +} + +func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory { + return NewTBinaryProtocolFactory(false, true) +} + +func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory { + return &TBinaryProtocolFactory{strictRead: strictRead, strictWrite: strictWrite} +} + +func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol { + return NewTBinaryProtocol(t, p.strictRead, p.strictWrite) +} + +/** + * Writing Methods + */ + +func (p *TBinaryProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error { + if p.strictWrite { + version := uint32(VERSION_1) | uint32(typeId) + e := p.WriteI32(int32(version)) + if e != nil { + return e + } + e = p.WriteString(name) + if e != nil { + return e + } + e = p.WriteI32(seqId) + return e + } else { + e := p.WriteString(name) + if e != nil { + return e + } + e = p.WriteByte(byte(typeId)) + if e != nil { + return e + } + e = p.WriteI32(seqId) + return e + } + return nil +} + +func (p *TBinaryProtocol) WriteMessageEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteStructBegin(name string) error { + return nil +} + +func (p *TBinaryProtocol) WriteStructEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { + e := p.WriteByte(byte(typeId)) + if e != nil { + return e + } + e = p.WriteI16(id) + return e +} + +func (p *TBinaryProtocol) WriteFieldEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteFieldStop() error { + e := p.WriteByte(STOP) + return e +} + +func (p *TBinaryProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { + e := p.WriteByte(byte(keyType)) + if e != nil { + return e + } + e = p.WriteByte(byte(valueType)) + if e != nil { + return e + } + e = p.WriteI32(int32(size)) + return e +} + +func (p *TBinaryProtocol) WriteMapEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteListBegin(elemType TType, size int) error { + e := p.WriteByte(byte(elemType)) + if e != nil { + return e + } + e = p.WriteI32(int32(size)) + return e +} + +func (p *TBinaryProtocol) WriteListEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteSetBegin(elemType TType, size int) error { + e := p.WriteByte(byte(elemType)) + if e != nil { + return e + } + e = p.WriteI32(int32(size)) + return e +} + +func (p *TBinaryProtocol) WriteSetEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteBool(value bool) error { + if value { + return p.WriteByte(1) + } + return p.WriteByte(0) +} + +func (p *TBinaryProtocol) WriteByte(value byte) error { + v := []byte{value} + _, e := p.trans.Write(v) + return NewTProtocolException(e) +} + +func (p *TBinaryProtocol) WriteI16(value int16) error { + h := byte(0xff & (value >> 8)) + l := byte(0xff & value) + v := []byte{h, l} + _, e := p.trans.Write(v) + return NewTProtocolException(e) +} + +func (p *TBinaryProtocol) WriteI32(value int32) error { + a := byte(0xff & (value >> 24)) + b := byte(0xff & (value >> 16)) + c := byte(0xff & (value >> 8)) + d := byte(0xff & value) + v := []byte{a, b, c, d} + _, e := p.trans.Write(v) + return NewTProtocolException(e) +} + +func (p *TBinaryProtocol) WriteI64(value int64) error { + a := byte(0xff & (value >> 56)) + b := byte(0xff & (value >> 48)) + c := byte(0xff & (value >> 40)) + d := byte(0xff & (value >> 32)) + e := byte(0xff & (value >> 24)) + f := byte(0xff & (value >> 16)) + g := byte(0xff & (value >> 8)) + h := byte(0xff & value) + v := []byte{a, b, c, d, e, f, g, h} + _, err := p.trans.Write(v) + return NewTProtocolException(err) +} + +func (p *TBinaryProtocol) WriteDouble(value float64) error { + return p.WriteI64(int64(math.Float64bits(value))) +} + +func (p *TBinaryProtocol) WriteString(value string) error { + return p.WriteBinaryFromReader(strings.NewReader(value), len(value)) +} + +func (p *TBinaryProtocol) WriteBinary(value []byte) error { + e := p.WriteI32(int32(len(value))) + if e != nil { + return e + } + _, err := p.trans.Write(value) + return NewTProtocolException(err) +} + +func (p *TBinaryProtocol) WriteBinaryFromReader(reader io.Reader, size int) error { + e := p.WriteI32(int32(size)) + if e != nil { + return e + } + _, err := io.CopyN(p.trans, reader, int64(size)) + return NewTProtocolException(err) +} + +/** + * Reading methods + */ + +func (p *TBinaryProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { + size, e := p.ReadI32() + if e != nil { + return "", typeId, 0, NewTProtocolException(e) + } + if size < 0 { + typeId = TMessageType(size & 0x0ff) + version := int64(int64(size) & VERSION_MASK) + if version != VERSION_1 { + return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Bad version in ReadMessageBegin")) + } + name, e = p.ReadString() + if e != nil { + return name, typeId, seqId, NewTProtocolException(e) + } + seqId, e = p.ReadI32() + if e != nil { + return name, typeId, seqId, NewTProtocolException(e) + } + return name, typeId, seqId, nil + } + if p.strictRead { + return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Missing version in ReadMessageBegin")) + } + name, e2 := p.readStringBody(int(size)) + if e2 != nil { + return name, typeId, seqId, e2 + } + b, e3 := p.ReadByte() + if e3 != nil { + return name, typeId, seqId, e3 + } + typeId = TMessageType(b) + seqId, e4 := p.ReadI32() + if e4 != nil { + return name, typeId, seqId, e4 + } + return name, typeId, seqId, nil +} + +func (p *TBinaryProtocol) ReadMessageEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadStructBegin() (name string, err error) { + return +} + +func (p *TBinaryProtocol) ReadStructEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadFieldBegin() (name string, typeId TType, seqId int16, err error) { + t, err := p.ReadByte() + typeId = TType(t) + if err != nil { + return name, typeId, seqId, err + } + if t != STOP { + seqId, err = p.ReadI16() + } + return name, typeId, seqId, err +} + +func (p *TBinaryProtocol) ReadFieldEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadMapBegin() (kType, vType TType, size int, err error) { + k, e := p.ReadByte() + if e != nil { + err = NewTProtocolException(e) + return + } + kType = TType(k) + v, e := p.ReadByte() + if e != nil { + err = NewTProtocolException(e) + return + } + vType = TType(v) + size32, e := p.ReadI32() + size = int(size32) + if e != nil { + err = NewTProtocolException(e) + return + } + return kType, vType, size, nil +} + +func (p *TBinaryProtocol) ReadMapEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadListBegin() (elemType TType, size int, err error) { + b, e := p.ReadByte() + if e != nil { + err = NewTProtocolException(e) + return + } + elemType = TType(b) + size32, e := p.ReadI32() + size = int(size32) + if e != nil { + err = NewTProtocolException(e) + return + } + return elemType, size, nil +} + +func (p *TBinaryProtocol) ReadListEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadSetBegin() (elemType TType, size int, err error) { + b, e := p.ReadByte() + if e != nil { + err = NewTProtocolException(e) + return + } + elemType = TType(b) + size32, e := p.ReadI32() + size = int(size32) + if e != nil { + err = NewTProtocolException(e) + return + } + return elemType, size, nil +} + +func (p *TBinaryProtocol) ReadSetEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadBool() (bool, error) { + b, e := p.ReadByte() + v := true + if b != 1 { + v = false + } + return v, e +} + +func (p *TBinaryProtocol) ReadByte() (value byte, err error) { + buf := []byte{0} + err = p.readAll(buf) + return buf[0], err +} + +func (p *TBinaryProtocol) ReadI16() (value int16, err error) { + buf := []byte{0, 0} + err = p.readAll(buf) + value = int16(binary.BigEndian.Uint16(buf)) + return value, err +} + +func (p *TBinaryProtocol) ReadI32() (value int32, err error) { + buf := []byte{0, 0, 0, 0} + err = p.readAll(buf) + value = int32(binary.BigEndian.Uint32(buf)) + return value, err +} + +func (p *TBinaryProtocol) ReadI64() (value int64, err error) { + buf := []byte{0, 0, 0, 0, 0, 0, 0, 0} + err = p.readAll(buf) + value = int64(binary.BigEndian.Uint64(buf)) + return value, err +} + +func (p *TBinaryProtocol) ReadDouble() (value float64, err error) { + buf := []byte{0, 0, 0, 0, 0, 0, 0, 0} + err = p.readAll(buf) + value = math.Float64frombits(binary.BigEndian.Uint64(buf)) + return value, err +} + +func (p *TBinaryProtocol) ReadString() (value string, err error) { + size, e := p.ReadI32() + if e != nil { + return "", e + } + return p.readStringBody(int(size)) +} + +func (p *TBinaryProtocol) ReadBinary() ([]byte, error) { + size, e := p.ReadI32() + if e != nil { + return nil, e + } + isize := int(size) + if e = p.readLengthOk(isize); e != nil { + return nil, e + } + buf := make([]byte, isize) + _, err := io.ReadFull(p.trans, buf) + return buf, NewTProtocolException(err) +} + +func (p *TBinaryProtocol) Flush() (err error) { + return NewTProtocolException(p.trans.Flush()) +} + +func (p *TBinaryProtocol) Skip(fieldType TType) (err error) { + return SkipDefaultDepth(p, fieldType) +} + +func (p *TBinaryProtocol) Transport() TTransport { + return p.trans +} + +func (p *TBinaryProtocol) readAll(buf []byte) error { + if e := p.readLengthOk(len(buf)); e != nil { + return e + } + _, err := io.ReadFull(p.trans, buf) + return NewTProtocolException(err) +} + +func (p *TBinaryProtocol) setReadLength(readLength int) { + p.readLength = readLength + p.checkReadLength = true +} + +func (p *TBinaryProtocol) readLengthOk(length int) error { + if p.checkReadLength { + p.readLength = p.readLength - length + if p.readLength < 0 { + return NewTProtocolExceptionWithType(UNKNOWN_PROTOCOL_EXCEPTION, fmt.Errorf("Message length exceeded: %d", length)) + } + } + return nil +} + +func (p *TBinaryProtocol) readStringBody(size int) (value string, err error) { + if size < 0 { + return "", nil + } + if err := p.readLengthOk(size); err != nil { + return "", err + } + isize := int(size) + buf := make([]byte, isize) + _, e := io.ReadFull(p.trans, buf) + return string(buf), NewTProtocolException(e) +} diff --git a/lib/go/thrift/tbinary_protocol_test.go b/lib/go/thrift/binary_protocol_test.go similarity index 87% rename from lib/go/thrift/tbinary_protocol_test.go rename to lib/go/thrift/binary_protocol_test.go index b21b2483..0462cc79 100644 --- a/lib/go/thrift/tbinary_protocol_test.go +++ b/lib/go/thrift/binary_protocol_test.go @@ -17,15 +17,12 @@ * under the License. */ -package thrift_test +package thrift import ( - . "thrift" - "testing" - //"bytes"; + "testing" ) - func TestReadWriteBinaryProtocol(t *testing.T) { - ReadWriteProtocolTest(t, NewTBinaryProtocolFactoryDefault()) + ReadWriteProtocolTest(t, NewTBinaryProtocolFactoryDefault()) } diff --git a/lib/go/thrift/compact_protocol.go b/lib/go/thrift/compact_protocol.go new file mode 100644 index 00000000..ba5f722f --- /dev/null +++ b/lib/go/thrift/compact_protocol.go @@ -0,0 +1,752 @@ +/* + * 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 thrift + +import ( + "encoding/binary" + "fmt" + "io" + "math" + "strings" +) + +const ( + COMPACT_PROTOCOL_ID = 0x082 + COMPACT_VERSION = 1 + COMPACT_VERSION_MASK = 0x1f + COMPACT_TYPE_MASK = 0x0E0 + COMPACT_TYPE_SHIFT_AMOUNT = 5 +) + +type tCompactType byte + +const ( + COMPACT_BOOLEAN_TRUE = 0x01 + COMPACT_BOOLEAN_FALSE = 0x02 + COMPACT_BYTE = 0x03 + COMPACT_I16 = 0x04 + COMPACT_I32 = 0x05 + COMPACT_I64 = 0x06 + COMPACT_DOUBLE = 0x07 + COMPACT_BINARY = 0x08 + COMPACT_LIST = 0x09 + COMPACT_SET = 0x0A + COMPACT_MAP = 0x0B + COMPACT_STRUCT = 0x0C +) + +var ( + ttypeToCompactType map[TType]tCompactType +) + +func init() { + ttypeToCompactType = map[TType]tCompactType{ + STOP: STOP, + BOOL: COMPACT_BOOLEAN_TRUE, + BYTE: COMPACT_BYTE, + I16: COMPACT_I16, + I32: COMPACT_I32, + I64: COMPACT_I64, + DOUBLE: COMPACT_DOUBLE, + STRING: COMPACT_BINARY, + LIST: COMPACT_LIST, + SET: COMPACT_SET, + MAP: COMPACT_MAP, + STRUCT: COMPACT_STRUCT, + } +} + +type TCompactProtocolFactory struct{} + +func NewTCompactProtocolFactory() *TCompactProtocolFactory { + return &TCompactProtocolFactory{} +} + +func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol { + return NewTCompactProtocol(trans) +} + +type TCompactProtocol struct { + trans TTransport + + // Used to keep track of the last field for the current and previous structs, + // so we can do the delta stuff. + lastField []int + lastFieldId int + + // If we encounter a boolean field begin, save the TField here so it can + // have the value incorporated. + booleanField *field + + // If we read a field header, and it's a boolean field, save the boolean + // value here so that readBool can use it. + boolValue bool + boolValueIsNotNull bool +} + +// Create a TCompactProtocol given a TTransport +func NewTCompactProtocol(trans TTransport) *TCompactProtocol { + return &TCompactProtocol{trans: trans, lastField: []int{}} +} + +// +// Public Writing methods. +// + +// Write a message header to the wire. Compact Protocol messages contain the +// protocol version so we can migrate forwards in the future if need be. +func (p *TCompactProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) error { + _, err := p.writeByteDirect(COMPACT_PROTOCOL_ID) + if err != nil { + return NewTProtocolException(err) + } + _, err = p.writeByteDirect((COMPACT_VERSION & COMPACT_VERSION_MASK) | ((byte(typeId) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK)) + if err != nil { + return NewTProtocolException(err) + } + _, err = p.writeVarint32(seqid) + if err != nil { + return NewTProtocolException(err) + } + e := p.WriteString(name) + return e + +} + +func (p *TCompactProtocol) WriteMessageEnd() error { return nil } + +// Write a struct begin. This doesn't actually put anything on the wire. We +// use it as an opportunity to put special placeholder markers on the field +// stack so we can get the field id deltas correct. +func (p *TCompactProtocol) WriteStructBegin(name string) error { + p.lastField = append(p.lastField, p.lastFieldId) + p.lastFieldId = 0 + return nil +} + +// Write a struct end. This doesn't actually put anything on the wire. We use +// this as an opportunity to pop the last field from the current struct off +// of the field stack. +func (p *TCompactProtocol) WriteStructEnd() error { + p.lastFieldId = p.lastField[len(p.lastField)-1] + p.lastField = p.lastField[:len(p.lastField)-1] + return nil +} + +func (p *TCompactProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { + if typeId == BOOL { + // we want to possibly include the value, so we'll wait. + p.booleanField = newField(name, typeId, int(id)) + return nil + } + _, err := p.writeFieldBeginInternal(name, typeId, id, 0xFF) + return NewTProtocolException(err) +} + +// The workhorse of writeFieldBegin. It has the option of doing a +// 'type override' of the type header. This is used specifically in the +// boolean field case. +func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id int16, typeOverride byte) (int, error) { + // short lastField = lastField_.pop(); + + // if there's a type override, use that. + var typeToWrite byte + if typeOverride == 0xFF { + typeToWrite = byte(p.getCompactType(typeId)) + } else { + typeToWrite = typeOverride + } + // check if we can use delta encoding for the field id + fieldId := int(id) + written := 0 + if fieldId > p.lastFieldId && fieldId-p.lastFieldId <= 15 { + // write them together + written, err := p.writeByteDirect(byte((fieldId-p.lastFieldId)<<4) | typeToWrite) + if err != nil { + return written, err + } + } else { + // write them separate + n, err := p.writeByteDirect(typeToWrite) + if err != nil { + return n, err + } + err = p.WriteI16(id) + written = n + 2 + if err != nil { + return written, err + } + } + + p.lastFieldId = fieldId + // p.lastField.Push(field.id); + return written, nil +} + +func (p *TCompactProtocol) WriteFieldEnd() error { return nil } + +func (p *TCompactProtocol) WriteFieldStop() error { + _, err := p.writeByteDirect(STOP) + return NewTProtocolException(err) +} + +func (p *TCompactProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { + if size == 0 { + _, err := p.writeByteDirect(0) + return NewTProtocolException(err) + } + _, err := p.writeVarint32(int32(size)) + if err != nil { + return NewTProtocolException(err) + } + _, err = p.writeByteDirect(byte(p.getCompactType(keyType))<<4 | byte(p.getCompactType(valueType))) + return NewTProtocolException(err) +} + +func (p *TCompactProtocol) WriteMapEnd() error { return nil } + +// Write a list header. +func (p *TCompactProtocol) WriteListBegin(elemType TType, size int) error { + _, err := p.writeCollectionBegin(elemType, size) + return NewTProtocolException(err) +} + +func (p *TCompactProtocol) WriteListEnd() error { return nil } + +// Write a set header. +func (p *TCompactProtocol) WriteSetBegin(elemType TType, size int) error { + _, err := p.writeCollectionBegin(elemType, size) + return NewTProtocolException(err) +} + +func (p *TCompactProtocol) WriteSetEnd() error { return nil } + +func (p *TCompactProtocol) WriteBool(value bool) error { + v := byte(COMPACT_BOOLEAN_FALSE) + if value { + v = byte(COMPACT_BOOLEAN_TRUE) + } + if p.booleanField != nil { + // we haven't written the field header yet + _, err := p.writeFieldBeginInternal(p.booleanField.Name(), p.booleanField.TypeId(), int16(p.booleanField.Id()), v) + p.booleanField = nil + return NewTProtocolException(err) + } + // we're not part of a field, so just write the value. + _, err := p.writeByteDirect(v) + return NewTProtocolException(err) +} + +// Write a byte. Nothing to see here! +func (p *TCompactProtocol) WriteByte(value byte) error { + _, err := p.writeByteDirect(value) + return NewTProtocolException(err) +} + +// Write an I16 as a zigzag varint. +func (p *TCompactProtocol) WriteI16(value int16) error { + _, err := p.writeVarint32(p.int32ToZigzag(int32(value))) + return NewTProtocolException(err) +} + +// Write an i32 as a zigzag varint. +func (p *TCompactProtocol) WriteI32(value int32) error { + _, err := p.writeVarint32(p.int32ToZigzag(value)) + return NewTProtocolException(err) +} + +// Write an i64 as a zigzag varint. +func (p *TCompactProtocol) WriteI64(value int64) error { + _, err := p.writeVarint64(p.int64ToZigzag(value)) + return NewTProtocolException(err) +} + +// Write a double to the wire as 8 bytes. +func (p *TCompactProtocol) WriteDouble(value float64) error { + buf := make([]byte, 8) + binary.LittleEndian.PutUint64(buf, math.Float64bits(value)) + _, err := p.trans.Write(buf) + return NewTProtocolException(err) +} + +// Write a string to the wire with a varint size preceeding. +func (p *TCompactProtocol) WriteString(value string) error { + buf := make([]byte, len(value)) + strings.NewReader(value).Read(buf) + return p.WriteBinary(buf) +} + +// Write a byte array, using a varint for the size. +func (p *TCompactProtocol) WriteBinary(bin []byte) error { + _, e := p.writeVarint32(int32(len(bin))) + if e != nil { + return NewTProtocolException(e) + } + if len(bin) > 0 { + _, e = p.trans.Write(bin) + return NewTProtocolException(e) + } + return nil +} + +// +// Reading methods. +// + +// Read a message header. +func (p *TCompactProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { + protocolId, err := p.ReadByte() + if protocolId != COMPACT_PROTOCOL_ID { + e := fmt.Errorf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId) + return "", typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, e) + } + versionAndType, err := p.ReadByte() + version := versionAndType & COMPACT_VERSION_MASK + typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & 0x03) + if err != nil { + return + } + if version != COMPACT_VERSION { + e := fmt.Errorf("Expected version %02x but got %02x", COMPACT_VERSION, version) + err = NewTProtocolExceptionWithType(BAD_VERSION, e) + return + } + seqId, e := p.readVarint32() + if e != nil { + err = NewTProtocolException(e) + return + } + name, err = p.ReadString() + return +} + +func (p *TCompactProtocol) ReadMessageEnd() error { return nil } + +// Read a struct begin. There's nothing on the wire for this, but it is our +// opportunity to push a new struct begin marker onto the field stack. +func (p *TCompactProtocol) ReadStructBegin() (name string, err error) { + p.lastField = append(p.lastField, p.lastFieldId) + p.lastFieldId = 0 + return +} + +// Doesn't actually consume any wire data, just removes the last field for +// this struct from the field stack. +func (p *TCompactProtocol) ReadStructEnd() error { + // consume the last field we read off the wire. + p.lastFieldId = p.lastField[len(p.lastField)-1] + return nil +} + +// Read a field header off the wire. +func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err error) { + t, err := p.ReadByte() + if err != nil { + return + } + + // if it's a stop, then we can return immediately, as the struct is over. + if (t & 0x0f) == STOP { + return "", STOP, 0,nil + } + + // mask off the 4 MSB of the type header. it could contain a field id delta. + modifier := int16((t & 0xf0) >> 4) + if modifier == 0 { + // not a delta. look ahead for the zigzag varint field id. + id, err = p.ReadI16() + if err != nil { + return + } + } else { + // has a delta. add the delta to the last read field id. + id = int16(p.lastFieldId) + modifier + } + typeId, e := p.getTType(tCompactType(t & 0x0f)) + if e != nil { + err = NewTProtocolException(e) + return + } + + // if this happens to be a boolean field, the value is encoded in the type + if p.isBoolType(t) { + // save the boolean value in a special instance variable. + p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE) + p.boolValueIsNotNull = true + } + + // push the new field onto the field stack so we can keep the deltas going. + p.lastFieldId = int(id) + return +} + +func (p *TCompactProtocol) ReadFieldEnd() error { return nil } + +// Read a map header off the wire. If the size is zero, skip reading the key +// and value type. This means that 0-length maps will yield TMaps without the +// "correct" types. +func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err error) { + size32, e := p.readVarint32() + size = int(size32) + if e != nil { + err = NewTProtocolException(e) + return + } + keyAndValueType := byte(STOP) + if size != 0 { + keyAndValueType, err = p.ReadByte() + if err != nil { + return + } + } + keyType, _ = p.getTType(tCompactType(keyAndValueType >> 4)) + valueType, _ = p.getTType(tCompactType(keyAndValueType & 0xf)) + return +} + +func (p *TCompactProtocol) ReadMapEnd() error { return nil } + +// Read a list header off the wire. If the list size is 0-14, the size will +// be packed into the element type header. If it's a longer list, the 4 MSB +// of the element type header will be 0xF, and a varint will follow with the +// true size. +func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err error) { + size_and_type, err := p.ReadByte() + if err != nil { + return + } + size = int((size_and_type >> 4) & 0x0f) + if size == 15 { + size2, e := p.readVarint32() + if e != nil { + err = NewTProtocolException(e) + return + } + size = int(size2) + } + elemType, e := p.getTType(tCompactType(size_and_type)) + if e != nil { + err = NewTProtocolException(e) + return + } + return +} + +func (p *TCompactProtocol) ReadListEnd() error { return nil } + +// Read a set header off the wire. If the set size is 0-14, the size will +// be packed into the element type header. If it's a longer set, the 4 MSB +// of the element type header will be 0xF, and a varint will follow with the +// true size. +func (p *TCompactProtocol) ReadSetBegin() (elemType TType, size int, err error) { + return p.ReadListBegin() +} + +func (p *TCompactProtocol) ReadSetEnd() error { return nil } + +// Read a boolean off the wire. If this is a boolean field, the value should +// already have been read during readFieldBegin, so we'll just consume the +// pre-stored value. Otherwise, read a byte. +func (p *TCompactProtocol) ReadBool() (value bool, err error) { + if p.boolValueIsNotNull { + p.boolValueIsNotNull = false + return p.boolValue, nil + } + v, err := p.ReadByte() + return v == COMPACT_BOOLEAN_TRUE, err +} + +// Read a single byte off the wire. Nothing interesting here. +func (p *TCompactProtocol) ReadByte() (value byte, err error) { + buf := []byte{0} + _, e := io.ReadFull(p.trans, buf) + if e != nil { + return 0, NewTProtocolException(e) + } + return buf[0], nil +} + +// Read an i16 from the wire as a zigzag varint. +func (p *TCompactProtocol) ReadI16() (value int16, err error) { + v, err := p.ReadI32() + return int16(v), err +} + +// Read an i32 from the wire as a zigzag varint. +func (p *TCompactProtocol) ReadI32() (value int32, err error) { + v, e := p.readVarint32() + if e != nil { + return 0, NewTProtocolException(e) + } + value = p.zigzagToInt32(v) + return value, nil +} + +// Read an i64 from the wire as a zigzag varint. +func (p *TCompactProtocol) ReadI64() (value int64, err error) { + v, e := p.readVarint64() + if e != nil { + return 0, NewTProtocolException(e) + } + value = p.zigzagToInt64(v) + return value, nil +} + +// No magic here - just read a double off the wire. +func (p *TCompactProtocol) ReadDouble() (value float64, err error) { + longBits := make([]byte, 8) + _, e := io.ReadFull(p.trans, longBits) + if e != nil { + return 0.0, NewTProtocolException(e) + } + return math.Float64frombits(p.bytesToUint64(longBits)), nil +} + +// Reads a []byte (via readBinary), and then UTF-8 decodes it. +func (p *TCompactProtocol) ReadString() (value string, err error) { + v, e := p.ReadBinary() + return string(v), NewTProtocolException(e) +} + +// Read a []byte from the wire. +func (p *TCompactProtocol) ReadBinary() (value []byte, err error) { + length, e := p.readVarint32() + if e != nil { + return []byte{}, NewTProtocolException(e) + } + if length == 0 { + return []byte{}, nil + } + + buf := make([]byte, length) + _, e = io.ReadFull(p.trans, buf) + return buf, NewTProtocolException(e) +} + +func (p *TCompactProtocol) Flush() (err error) { + return NewTProtocolException(p.trans.Flush()) +} + +func (p *TCompactProtocol) Skip(fieldType TType) (err error) { + return SkipDefaultDepth(p, fieldType) +} + +func (p *TCompactProtocol) Transport() TTransport { + return p.trans +} + +// +// Internal writing methods +// + +// Abstract method for writing the start of lists and sets. List and sets on +// the wire differ only by the type indicator. +func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, error) { + if size <= 14 { + return p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType)))) + } + n, err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType))) + if err != nil { + return n, err + } + m, err := p.writeVarint32(int32(size)) + return n + m, err +} + +// Write an i32 as a varint. Results in 1-5 bytes on the wire. +// TODO(pomack): make a permanent buffer like writeVarint64? +func (p *TCompactProtocol) writeVarint32(n int32) (int, error) { + i32buf := make([]byte, 5) + idx := 0 + for { + if (n & ^0x7F) == 0 { + i32buf[idx] = byte(n) + idx++ + // p.writeByteDirect(byte(n)); + break + // return; + } else { + i32buf[idx] = byte((n & 0x7F) | 0x80) + idx++ + // p.writeByteDirect(byte(((n & 0x7F) | 0x80))); + u := uint32(n) + n = int32(u >> 7) + } + } + return p.trans.Write(i32buf[0:idx]) +} + +// Write an i64 as a varint. Results in 1-10 bytes on the wire. +func (p *TCompactProtocol) writeVarint64(n int64) (int, error) { + varint64out := make([]byte, 10) + idx := 0 + for { + if (n & ^0x7F) == 0 { + varint64out[idx] = byte(n) + idx++ + break + } else { + varint64out[idx] = byte((n & 0x7F) | 0x80) + idx++ + u := uint64(n) + n = int64(u >> 7) + } + } + return p.trans.Write(varint64out[0:idx]) +} + +// Convert l into a zigzag long. This allows negative numbers to be +// represented compactly as a varint. +func (p *TCompactProtocol) int64ToZigzag(l int64) int64 { + return (l << 1) ^ (l >> 63) +} + +// Convert l into a zigzag long. This allows negative numbers to be +// represented compactly as a varint. +func (p *TCompactProtocol) int32ToZigzag(n int32) int32 { + return (n << 1) ^ (n >> 31) +} + +func (p *TCompactProtocol) fixedUint64ToBytes(n uint64, buf []byte) { + binary.LittleEndian.PutUint64(buf, n) +} + +func (p *TCompactProtocol) fixedInt64ToBytes(n int64, buf []byte) { + binary.LittleEndian.PutUint64(buf, uint64(n)) +} + +// Writes a byte without any possiblity of all that field header nonsense. +// Used internally by other writing methods that know they need to write a byte. +func (p *TCompactProtocol) writeByteDirect(b byte) (int, error) { + return p.trans.Write([]byte{b}) +} + +// Writes a byte without any possiblity of all that field header nonsense. +func (p *TCompactProtocol) writeIntAsByteDirect(n int) (int, error) { + return p.writeByteDirect(byte(n)) +} + +// +// Internal reading methods +// + +// Read an i32 from the wire as a varint. The MSB of each byte is set +// if there is another byte to follow. This can read up to 5 bytes. +func (p *TCompactProtocol) readVarint32() (int32, error) { + // if the wire contains the right stuff, this will just truncate the i64 we + // read and get us the right sign. + v, err := p.readVarint64() + return int32(v), err +} + +// Read an i64 from the wire as a proper varint. The MSB of each byte is set +// if there is another byte to follow. This can read up to 10 bytes. +func (p *TCompactProtocol) readVarint64() (int64, error) { + shift := uint(0) + result := int64(0) + for { + b, err := p.ReadByte() + if err != nil { + return 0, err + } + result |= int64(b&0x7f) << shift + if (b & 0x80) != 0x80 { + break + } + shift += 7 + } + return result, nil +} + +// +// encoding helpers +// + +// Convert from zigzag int to int. +func (p *TCompactProtocol) zigzagToInt32(n int32) int32 { + u := uint32(n) + return int32(u>>1) ^ -(n & 1) +} + +// Convert from zigzag long to long. +func (p *TCompactProtocol) zigzagToInt64(n int64) int64 { + u := uint64(n) + return int64(u>>1) ^ -(n & 1) +} + +// Note that it's important that the mask bytes are long literals, +// otherwise they'll default to ints, and when you shift an int left 56 bits, +// you just get a messed up int. +func (p *TCompactProtocol) bytesToInt64(b []byte) int64 { + return int64(binary.LittleEndian.Uint64(b)) +} + +// Note that it's important that the mask bytes are long literals, +// otherwise they'll default to ints, and when you shift an int left 56 bits, +// you just get a messed up int. +func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 { + return binary.LittleEndian.Uint64(b) +} + +// +// type testing and converting +// + +func (p *TCompactProtocol) isBoolType(b byte) bool { + return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE +} + +// Given a tCompactType constant, convert it to its corresponding +// TType value. +func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) { + switch byte(t) & 0x0f { + case STOP: + return STOP, nil + case COMPACT_BOOLEAN_FALSE: + case COMPACT_BOOLEAN_TRUE: + return BOOL, nil + case COMPACT_BYTE: + return BYTE, nil + case COMPACT_I16: + return I16, nil + case COMPACT_I32: + return I32, nil + case COMPACT_I64: + return I64, nil + case COMPACT_DOUBLE: + return DOUBLE, nil + case COMPACT_BINARY: + return STRING, nil + case COMPACT_LIST: + return LIST, nil + case COMPACT_SET: + return SET, nil + case COMPACT_MAP: + return MAP, nil + case COMPACT_STRUCT: + return STRUCT, nil + } + return STOP, TException(fmt.Errorf("don't know what type: %s", t&0x0f)) +} + +// Given a TType value, find the appropriate TCompactProtocol.Types constant. +func (p *TCompactProtocol) getCompactType(t TType) tCompactType { + return ttypeToCompactType[t] +} diff --git a/lib/go/thrift/compact_protocol_test.go b/lib/go/thrift/compact_protocol_test.go new file mode 100644 index 00000000..c874379c --- /dev/null +++ b/lib/go/thrift/compact_protocol_test.go @@ -0,0 +1,54 @@ +/* + * 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 thrift + +import ( + "testing" +) + +func TestReadWriteCompactProtocol(t *testing.T) { + ReadWriteProtocolTest(t, NewTCompactProtocolFactory()) + /* + transports := []TTransport{ + NewTMemoryBuffer(), + NewStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 16384))), + NewTFramedTransport(NewTMemoryBuffer()), + } + for _, trans := range transports { + p := NewTCompactProtocol(trans); + ReadWriteBool(t, p, trans); + p = NewTCompactProtocol(trans); + ReadWriteByte(t, p, trans); + p = NewTCompactProtocol(trans); + ReadWriteI16(t, p, trans); + p = NewTCompactProtocol(trans); + ReadWriteI32(t, p, trans); + p = NewTCompactProtocol(trans); + ReadWriteI64(t, p, trans); + p = NewTCompactProtocol(trans); + ReadWriteDouble(t, p, trans); + p = NewTCompactProtocol(trans); + ReadWriteString(t, p, trans); + p = NewTCompactProtocol(trans); + ReadWriteBinary(t, p, trans); + trans.Close(); + } + */ +} diff --git a/lib/go/thrift/tnonblocking_transport.go b/lib/go/thrift/exception.go similarity index 92% rename from lib/go/thrift/tnonblocking_transport.go rename to lib/go/thrift/exception.go index da9c26dc..e08ffc0c 100644 --- a/lib/go/thrift/tnonblocking_transport.go +++ b/lib/go/thrift/exception.go @@ -19,6 +19,7 @@ package thrift -type TNonblockingTransport interface { - TTransport +// Generic Thrift exception +type TException interface { + error } diff --git a/lib/go/thrift/field.go b/lib/go/thrift/field.go new file mode 100644 index 00000000..9d665255 --- /dev/null +++ b/lib/go/thrift/field.go @@ -0,0 +1,79 @@ +/* + * 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 thrift + +// Helper class that encapsulates field metadata. +type field struct { + name string + typeId TType + id int +} + +func newField(n string, t TType, i int) *field { + return &field{name: n, typeId: t, id: i} +} + +func (p *field) Name() string { + if p == nil { + return "" + } + return p.name +} + +func (p *field) TypeId() TType { + if p == nil { + return TType(VOID) + } + return p.typeId +} + +func (p *field) Id() int { + if p == nil { + return -1 + } + return p.id +} + +func (p *field) String() string { + if p == nil { + return "" + } + return "" +} + +var ANONYMOUS_FIELD *field + +type fieldSlice []field + +func (p fieldSlice) Len() int { + return len(p) +} + +func (p fieldSlice) Less(i, j int) bool { + return p[i].Id() < p[j].Id() +} + +func (p fieldSlice) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +func init() { + ANONYMOUS_FIELD = newField("", STOP, 0) +} diff --git a/lib/go/thrift/framed_transport.go b/lib/go/thrift/framed_transport.go new file mode 100644 index 00000000..3a59e7b9 --- /dev/null +++ b/lib/go/thrift/framed_transport.go @@ -0,0 +1,124 @@ +/* + * 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 thrift + +import ( + "bytes" + "encoding/binary" + "io" +) + +type TFramedTransport struct { + transport TTransport + writeBuffer *bytes.Buffer + readBuffer *bytes.Buffer +} + +type tFramedTransportFactory struct { + factory TTransportFactory +} + +func NewTFramedTransportFactory(factory TTransportFactory) TTransportFactory { + return &tFramedTransportFactory{factory: factory} +} + +func (p *tFramedTransportFactory) GetTransport(base TTransport) TTransport { + return NewTFramedTransport(p.factory.GetTransport(base)) +} + +func NewTFramedTransport(transport TTransport) *TFramedTransport { + writeBuf := make([]byte, 0, 1024) + readBuf := make([]byte, 0, 1024) + return &TFramedTransport{transport: transport, writeBuffer: bytes.NewBuffer(writeBuf), readBuffer: bytes.NewBuffer(readBuf)} +} + +func (p *TFramedTransport) Open() error { + return p.transport.Open() +} + +func (p *TFramedTransport) IsOpen() bool { + return p.transport.IsOpen() +} + +func (p *TFramedTransport) Peek() bool { + return p.transport.Peek() +} + +func (p *TFramedTransport) Close() error { + return p.transport.Close() +} + +func (p *TFramedTransport) Read(buf []byte) (int, error) { + if p.readBuffer.Len() > 0 { + got, err := p.readBuffer.Read(buf) + if got > 0 { + return got, NewTTransportExceptionFromError(err) + } + } + + // Read another frame of data + p.readFrame() + + got, err := p.readBuffer.Read(buf) + return got, NewTTransportExceptionFromError(err) +} + +func (p *TFramedTransport) Write(buf []byte) (int, error) { + n, err := p.writeBuffer.Write(buf) + return n, NewTTransportExceptionFromError(err) +} + +func (p *TFramedTransport) Flush() error { + size := p.writeBuffer.Len() + buf := []byte{0, 0, 0, 0} + binary.BigEndian.PutUint32(buf, uint32(size)) + _, err := p.transport.Write(buf) + if err != nil { + return NewTTransportExceptionFromError(err) + } + if size > 0 { + if n, err := p.writeBuffer.WriteTo(p.transport); err != nil { + print("Error while flushing write buffer of size ", size, " to transport, only wrote ", n, " bytes: ", err, "\n") + return NewTTransportExceptionFromError(err) + } + } + err = p.transport.Flush() + return NewTTransportExceptionFromError(err) +} + +func (p *TFramedTransport) readFrame() (int, error) { + buf := []byte{0, 0, 0, 0} + if _, err := io.ReadFull(p.transport, buf); err != nil { + return 0, err + } + size := int(binary.BigEndian.Uint32(buf)) + if size < 0 { + return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "Read a negative frame size ("+string(size)+")") + } + if size == 0 { + return 0, nil + } + buf2 := make([]byte, size) + if n, err := io.ReadFull(p.transport, buf2); err != nil { + return n, err + } + p.readBuffer = bytes.NewBuffer(buf2) + return size, nil +} diff --git a/lib/go/thrift/tframed_transport_test.go b/lib/go/thrift/framed_transport_test.go similarity index 86% rename from lib/go/thrift/tframed_transport_test.go rename to lib/go/thrift/framed_transport_test.go index 566318cc..8f683ef3 100644 --- a/lib/go/thrift/tframed_transport_test.go +++ b/lib/go/thrift/framed_transport_test.go @@ -17,14 +17,13 @@ * under the License. */ -package thrift_test +package thrift import ( - . "thrift" - "testing" + "testing" ) func TestFramedTransport(t *testing.T) { - trans := NewTFramedTransport(NewTMemoryBuffer()) - TransportTest(t, trans, trans) + trans := NewTFramedTransport(NewTMemoryBuffer()) + TransportTest(t, trans, trans) } diff --git a/lib/go/thrift/http_client.go b/lib/go/thrift/http_client.go new file mode 100644 index 00000000..18b1671d --- /dev/null +++ b/lib/go/thrift/http_client.go @@ -0,0 +1,141 @@ +/* + * 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 thrift + +import ( + "bytes" + "net/http" + "net/url" + "strconv" +) + +type THttpClient struct { + response *http.Response + url *url.URL + requestBuffer *bytes.Buffer + nsecConnectTimeout int64 + nsecReadTimeout int64 +} + +type THttpClientTransportFactory struct { + url string + isPost bool +} + +func (p *THttpClientTransportFactory) GetTransport(trans TTransport) TTransport { + if trans != nil { + t, ok := trans.(*THttpClient) + if ok && t.url != nil { + if t.requestBuffer != nil { + t2, _ := NewTHttpPostClient(t.url.String()) + return t2 + } + t2, _ := NewTHttpClient(t.url.String()) + return t2 + } + } + if p.isPost { + s, _ := NewTHttpPostClient(p.url) + return s + } + s, _ := NewTHttpClient(p.url) + return s +} + +func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory { + return &THttpClientTransportFactory{url: url, isPost: false} +} + +func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory { + return &THttpClientTransportFactory{url: url, isPost: true} +} + +func NewTHttpClient(urlstr string) (TTransport, error) { + parsedURL, err := url.Parse(urlstr) + if err != nil { + return nil, err + } + response, err := http.Get(urlstr) + if err != nil { + return nil, err + } + return &THttpClient{response: response, url: parsedURL}, nil +} + +func NewTHttpPostClient(urlstr string) (TTransport, error) { + parsedURL, err := url.Parse(urlstr) + if err != nil { + return nil, err + } + buf := make([]byte, 0, 1024) + return &THttpClient{url: parsedURL, requestBuffer: bytes.NewBuffer(buf)}, nil +} + +func (p *THttpClient) Open() error { + // do nothing + return nil +} + +func (p *THttpClient) IsOpen() bool { + return p.response != nil || p.requestBuffer != nil +} + +func (p *THttpClient) Peek() bool { + return p.IsOpen() +} + +func (p *THttpClient) Close() error { + if p.response != nil && p.response.Body != nil { + err := p.response.Body.Close() + p.response = nil + return err + } + if p.requestBuffer != nil { + p.requestBuffer.Reset() + p.requestBuffer = nil + } + return nil +} + +func (p *THttpClient) Read(buf []byte) (int, error) { + if p.response == nil { + return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.") + } + n, err := p.response.Body.Read(buf) + return n, NewTTransportExceptionFromError(err) +} + +func (p *THttpClient) Write(buf []byte) (int, error) { + n, err := p.requestBuffer.Write(buf) + return n, err +} + +func (p *THttpClient) Flush() error { + response, err := http.Post(p.url.String(), "application/x-thrift", p.requestBuffer) + if err != nil { + return NewTTransportExceptionFromError(err) + } + if response.StatusCode != http.StatusOK { + // TODO(pomack) log bad response + return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "HTTP Response code: "+strconv.Itoa(response.StatusCode)) + } + p.response = response + return nil +} diff --git a/lib/go/thrift/thttp_client_test.go b/lib/go/thrift/http_client_test.go similarity index 72% rename from lib/go/thrift/thttp_client_test.go rename to lib/go/thrift/http_client_test.go index fdd2f505..041faecc 100644 --- a/lib/go/thrift/thttp_client_test.go +++ b/lib/go/thrift/http_client_test.go @@ -17,22 +17,21 @@ * under the License. */ -package thrift_test +package thrift import ( - . "thrift" - "testing" + "testing" ) func TestHttpClient(t *testing.T) { - l, addr := HttpClientSetupForTest(t) - if l != nil { - defer l.Close() - } - trans, err := NewTHttpPostClient("http://" + addr.String()) - if err != nil { - l.Close() - t.Fatalf("Unable to connect to %s: %s", addr.String(), err) - } - TransportTest(t, trans, trans) + l, addr := HttpClientSetupForTest(t) + if l != nil { + defer l.Close() + } + trans, err := NewTHttpPostClient("http://" + addr.String()) + if err != nil { + l.Close() + t.Fatalf("Unable to connect to %s: %s", addr.String(), err) + } + TransportTest(t, trans, trans) } diff --git a/lib/go/thrift/iostream_transport.go b/lib/go/thrift/iostream_transport.go new file mode 100644 index 00000000..64b2958f --- /dev/null +++ b/lib/go/thrift/iostream_transport.go @@ -0,0 +1,168 @@ +/* + * 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 thrift + +import ( + "bufio" + "io" +) + +// StreamTransport is a Transport made of an io.Reader and/or an io.Writer +type StreamTransport struct { + Reader io.Reader + Writer io.Writer + isReadWriter bool +} + +type StreamTransportFactory struct { + Reader io.Reader + Writer io.Writer + isReadWriter bool +} + +func (p *StreamTransportFactory) GetTransport(trans TTransport) TTransport { + if trans != nil { + t, ok := trans.(*StreamTransport) + if ok { + if t.isReadWriter { + return NewStreamTransportRW(t.Reader.(io.ReadWriter)) + } + if t.Reader != nil && t.Writer != nil { + return NewStreamTransport(t.Reader, t.Writer) + } + if t.Reader != nil && t.Writer == nil { + return NewStreamTransportR(t.Reader) + } + if t.Reader == nil && t.Writer != nil { + return NewStreamTransportW(t.Writer) + } + return &StreamTransport{} + } + } + if p.isReadWriter { + return NewStreamTransportRW(p.Reader.(io.ReadWriter)) + } + if p.Reader != nil && p.Writer != nil { + return NewStreamTransport(p.Reader, p.Writer) + } + if p.Reader != nil && p.Writer == nil { + return NewStreamTransportR(p.Reader) + } + if p.Reader == nil && p.Writer != nil { + return NewStreamTransportW(p.Writer) + } + return &StreamTransport{} +} + +func NewStreamTransportFactory(reader io.Reader, writer io.Writer, isReadWriter bool) *StreamTransportFactory { + return &StreamTransportFactory{Reader: reader, Writer: writer, isReadWriter: isReadWriter} +} + +func NewStreamTransport(r io.Reader, w io.Writer) *StreamTransport { + return &StreamTransport{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)} +} + +func NewStreamTransportR(r io.Reader) *StreamTransport { + return &StreamTransport{Reader: bufio.NewReader(r)} +} + +func NewStreamTransportW(w io.Writer) *StreamTransport { + return &StreamTransport{Writer: bufio.NewWriter(w)} +} + +func NewStreamTransportRW(rw io.ReadWriter) *StreamTransport { + bufrw := bufio.NewReadWriter(bufio.NewReader(rw), bufio.NewWriter(rw)) + return &StreamTransport{Reader: bufrw, Writer: bufrw, isReadWriter: true} +} + +// (The streams must already be open at construction time, so this should +// always return true.) +func (p *StreamTransport) IsOpen() bool { + return true +} + +// (The streams must already be open. This method does nothing.) +func (p *StreamTransport) Open() error { + return nil +} + +func (p *StreamTransport) Peek() bool { + return p.IsOpen() +} + +// Closes both the input and output streams. +func (p *StreamTransport) Close() error { + closedReader := false + if p.Reader != nil { + c, ok := p.Reader.(io.Closer) + if ok { + e := c.Close() + closedReader = true + if e != nil { + return e + } + } + p.Reader = nil + } + if p.Writer != nil && (!closedReader || !p.isReadWriter) { + c, ok := p.Writer.(io.Closer) + if ok { + e := c.Close() + if e != nil { + return e + } + } + p.Writer = nil + } + return nil +} + +// Reads from the underlying input stream if not null. +func (p *StreamTransport) Read(buf []byte) (int, error) { + if p.Reader == nil { + return 0, NewTTransportException(NOT_OPEN, "Cannot read from null inputStream") + } + n, err := p.Reader.Read(buf) + return n, NewTTransportExceptionFromError(err) +} + +// Writes to the underlying output stream if not null. +func (p *StreamTransport) Write(buf []byte) (int, error) { + if p.Writer == nil { + return 0, NewTTransportException(NOT_OPEN, "Cannot write to null outputStream") + } + n, err := p.Writer.Write(buf) + return n, NewTTransportExceptionFromError(err) +} + +// Flushes the underlying output stream if not null. +func (p *StreamTransport) Flush() error { + if p.Writer == nil { + return NewTTransportException(NOT_OPEN, "Cannot flush null outputStream") + } + f, ok := p.Writer.(Flusher) + if ok { + err := f.Flush() + if err != nil { + return NewTTransportExceptionFromError(err) + } + } + return nil +} diff --git a/lib/go/thrift/tcontainer.go b/lib/go/thrift/iostream_transport_test.go similarity index 82% rename from lib/go/thrift/tcontainer.go rename to lib/go/thrift/iostream_transport_test.go index 9ea3cba0..15ea2d40 100644 --- a/lib/go/thrift/tcontainer.go +++ b/lib/go/thrift/iostream_transport_test.go @@ -17,12 +17,14 @@ * under the License. */ - package thrift -type TContainer interface { - Len() int - Contains(data interface{}) bool - Equals(other interface{}) bool - CompareTo(other interface{}) (int, bool) +import ( + "bytes" + "testing" +) + +func TestStreamTransport(t *testing.T) { + trans := NewStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 1024))) + TransportTest(t, trans, trans) } diff --git a/lib/go/thrift/json_protocol.go b/lib/go/thrift/json_protocol.go new file mode 100644 index 00000000..5e8453a1 --- /dev/null +++ b/lib/go/thrift/json_protocol.go @@ -0,0 +1,556 @@ +/* + * 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 thrift + +import ( + "encoding/base64" + "fmt" +) + +const ( + THRIFT_JSON_PROTOCOL_VERSION = 1 +) + +// for references to _ParseContext see tsimplejson_protocol.go + +// JSON protocol implementation for thrift. +// +// This protocol produces/consumes a simple output format +// suitable for parsing by scripting languages. It should not be +// confused with the full-featured TJSONProtocol. +// +type TJSONProtocol struct { + *TSimpleJSONProtocol +} + +// Constructor +func NewTJSONProtocol(t TTransport) *TJSONProtocol { + v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)} + v.parseContextStack = append(v.parseContextStack, int(_CONTEXT_IN_TOPLEVEL)) + v.dumpContext = append(v.dumpContext, int(_CONTEXT_IN_TOPLEVEL)) + return v +} + +// Factory +type TJSONProtocolFactory struct{} + +func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol { + return NewTJSONProtocol(trans) +} + +func NewTJSONProtocolFactory() *TJSONProtocolFactory { + return &TJSONProtocolFactory{} +} + +func (p *TJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error { + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.WriteI32(THRIFT_JSON_PROTOCOL_VERSION); e != nil { + return e + } + if e := p.WriteString(name); e != nil { + return e + } + if e := p.WriteByte(byte(typeId)); e != nil { + return e + } + if e := p.WriteI32(seqId); e != nil { + return e + } + return nil +} + +func (p *TJSONProtocol) WriteMessageEnd() error { + return p.OutputListEnd() +} + +func (p *TJSONProtocol) WriteStructBegin(name string) error { + if e := p.OutputObjectBegin(); e != nil { + return e + } + return nil +} + +func (p *TJSONProtocol) WriteStructEnd() error { + return p.OutputObjectEnd() +} + +func (p *TJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { + if e := p.WriteI16(id); e != nil { + return e + } + if e := p.OutputObjectBegin(); e != nil { + return e + } + if e := p.WriteString(p.TypeIdToString(typeId)); e != nil { + return e + } + return nil +} + +func (p *TJSONProtocol) WriteFieldEnd() error { + return p.OutputObjectEnd() +} + +func (p *TJSONProtocol) WriteFieldStop() error { return nil } + +func (p *TJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.WriteString(p.TypeIdToString(keyType)); e != nil { + return e + } + if e := p.WriteString(p.TypeIdToString(valueType)); e != nil { + return e + } + return p.WriteI64(int64(size)) +} + +func (p *TJSONProtocol) WriteMapEnd() error { + return p.OutputListEnd() +} + +func (p *TJSONProtocol) WriteListBegin(elemType TType, size int) error { + return p.OutputElemListBegin(elemType, size) +} + +func (p *TJSONProtocol) WriteListEnd() error { + return p.OutputListEnd() +} + +func (p *TJSONProtocol) WriteSetBegin(elemType TType, size int) error { + return p.OutputElemListBegin(elemType, size) +} + +func (p *TJSONProtocol) WriteSetEnd() error { + return p.OutputListEnd() +} + +func (p *TJSONProtocol) WriteBool(b bool) error { + return p.OutputBool(b) +} + +func (p *TJSONProtocol) WriteByte(b byte) error { + return p.WriteI32(int32(b)) +} + +func (p *TJSONProtocol) WriteI16(v int16) error { + return p.WriteI32(int32(v)) +} + +func (p *TJSONProtocol) WriteI32(v int32) error { + return p.OutputI64(int64(v)) +} + +func (p *TJSONProtocol) WriteI64(v int64) error { + return p.OutputI64(int64(v)) +} + +func (p *TJSONProtocol) WriteDouble(v float64) error { + return p.OutputF64(v) +} + +func (p *TJSONProtocol) WriteString(v string) error { + return p.OutputString(v) +} + +func (p *TJSONProtocol) WriteBinary(v []byte) error { + // JSON library only takes in a string, + // not an arbitrary byte array, to ensure bytes are transmitted + // efficiently we must convert this into a valid JSON string + // therefore we use base64 encoding to avoid excessive escaping/quoting + if e := p.OutputPreValue(); e != nil { + return e + } + p.writer.Write(JSON_QUOTE_BYTES) + writer := base64.NewEncoder(base64.StdEncoding, p.writer) + if _, e := writer.Write(v); e != nil { + return NewTProtocolException(e) + } + writer.Close() + p.writer.Write(JSON_QUOTE_BYTES) + return p.OutputPostValue() +} + +// Reading methods. + +func (p *TJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { + if isNull, err := p.ParseListBegin(); isNull || err != nil { + return name, typeId, seqId, err + } + version, err := p.ReadI32() + if err != nil { + return name, typeId, seqId, err + } + if version != THRIFT_JSON_PROTOCOL_VERSION { + e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION) + return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e) + + } + if name, err = p.ReadString(); err != nil { + return name, typeId, seqId, err + } + bTypeId, err := p.ReadByte() + typeId = TMessageType(bTypeId) + if err != nil { + return name, typeId, seqId, err + } + if seqId, err = p.ReadI32(); err != nil { + return name, typeId, seqId, err + } + return name, typeId, seqId, nil +} + +func (p *TJSONProtocol) ReadMessageEnd() error { + err := p.ParseListEnd() + return err +} + +func (p *TJSONProtocol) ReadStructBegin() (name string, err error) { + _, err = p.ParseObjectStart() + return "", err +} + +func (p *TJSONProtocol) ReadStructEnd() error { + return p.ParseObjectEnd() +} + +func (p *TJSONProtocol) ReadFieldBegin() (string, TType, int16, error) { + if p.reader.Buffered() < 1 { + return "", STOP, -1, nil + } + b, _ := p.reader.Peek(1) + if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] { + return "", STOP, -1, nil + } + fieldId, err := p.ReadI16() + if err != nil { + return "", STOP, fieldId, err + } + if _, err = p.ParseObjectStart(); err != nil { + return "", STOP, fieldId, err + } + sType, err := p.ReadString() + fType := p.StringToTypeId(sType) + return "", fType, fieldId, err +} + +func (p *TJSONProtocol) ReadFieldEnd() error { + return p.ParseObjectEnd() +} + +func (p *TJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e error) { + if isNull, e := p.ParseListBegin(); isNull || e != nil { + return VOID, VOID, 0, e + } + + // read keyType + sKeyType, e := p.ReadString() + keyType = p.StringToTypeId(sKeyType) + if e != nil { + return keyType, valueType, size, e + } + + // read valueType + sValueType, e := p.ReadString() + valueType = p.StringToTypeId(sValueType) + if e != nil { + return keyType, valueType, size, e + } + + // read size + iSize, err := p.ReadI64() + size = int(iSize) + return keyType, valueType, size, err +} + +func (p *TJSONProtocol) ReadMapEnd() error { + return p.ParseListEnd() +} + +func (p *TJSONProtocol) ReadListBegin() (elemType TType, size int, e error) { + return p.ParseElemListBegin() +} + +func (p *TJSONProtocol) ReadListEnd() error { + return p.ParseListEnd() +} + +func (p *TJSONProtocol) ReadSetBegin() (elemType TType, size int, e error) { + return p.ParseElemListBegin() +} + +func (p *TJSONProtocol) ReadSetEnd() error { + return p.ParseListEnd() +} + +func (p *TJSONProtocol) ReadBool() (bool, error) { + var value bool + if err := p.ParsePreValue(); err != nil { + return value, err + } + b, _ := p.reader.Peek(len(JSON_FALSE)) + if len(b) > 0 { + switch b[0] { + case JSON_TRUE[0]: + if string(b[0:len(JSON_TRUE)]) == string(JSON_TRUE) { + p.reader.Read(b[0:len(JSON_TRUE)]) + value = true + } else { + e := fmt.Errorf("Expected \"true\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + break + case JSON_FALSE[0]: + if string(b[0:len(JSON_FALSE)]) == string(JSON_FALSE) { + p.reader.Read(b[0:len(JSON_FALSE)]) + value = false + } else { + e := fmt.Errorf("Expected \"false\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + break + case JSON_NULL[0]: + if string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { + p.reader.Read(b[0:len(JSON_NULL)]) + value = false + } else { + e := fmt.Errorf("Expected \"null\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + default: + e := fmt.Errorf("Expected \"true\", \"false\", or \"null\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + return value, p.ParsePostValue() +} + +func (p *TJSONProtocol) ReadByte() (byte, error) { + v, err := p.ReadI64() + return byte(v), err +} + +func (p *TJSONProtocol) ReadI16() (int16, error) { + v, err := p.ReadI64() + return int16(v), err +} + +func (p *TJSONProtocol) ReadI32() (int32, error) { + v, err := p.ReadI64() + return int32(v), err +} + +func (p *TJSONProtocol) ReadI64() (int64, error) { + v, _, err := p.ParseI64() + return v, err +} + +func (p *TJSONProtocol) ReadDouble() (float64, error) { + v, _, err := p.ParseF64() + return v, err +} + +func (p *TJSONProtocol) ReadString() (string, error) { + var v string + if err := p.ParsePreValue(); err != nil { + return v, err + } + b, _ := p.reader.Peek(len(JSON_NULL)) + if len(b) > 0 && b[0] == JSON_QUOTE { + p.reader.ReadByte() + value, err := p.ParseStringBody() + v = value + if err != nil { + return v, err + } + } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { + _, err := p.reader.Read(b[0:len(JSON_NULL)]) + if err != nil { + return v, NewTProtocolException(err) + } + } else { + e := fmt.Errorf("Expected a JSON string, found %s", string(b)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return v, p.ParsePostValue() +} + +func (p *TJSONProtocol) ReadBinary() ([]byte, error) { + var v []byte + if err := p.ParsePreValue(); err != nil { + return nil, err + } + b, _ := p.reader.Peek(len(JSON_NULL)) + if len(b) > 0 && b[0] == JSON_QUOTE { + p.reader.ReadByte() + value, err := p.ParseBase64EncodedBody() + v = value + if err != nil { + return v, err + } + } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { + _, err := p.reader.Read(b[0:len(JSON_NULL)]) + if err != nil { + return v, NewTProtocolException(err) + } + } else { + e := fmt.Errorf("Expected a JSON string, found %s", string(b)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return v, p.ParsePostValue() +} + +func (p *TJSONProtocol) Flush() (err error) { + return NewTProtocolException(p.writer.Flush()) +} + +func (p *TJSONProtocol) Skip(fieldType TType) (err error) { + return SkipDefaultDepth(p, fieldType) +} + +func (p *TJSONProtocol) Transport() TTransport { + return p.trans +} + +func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error { + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.WriteString(p.TypeIdToString(elemType)); e != nil { + return e + } + if e := p.WriteI64(int64(size)); e != nil { + return e + } + return nil +} + + +func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) { + if isNull, e := p.ParseListBegin(); isNull || e != nil { + return VOID, 0, e + } + sElemType, err := p.ReadString() + elemType = p.StringToTypeId(sElemType) + if err != nil { + return elemType, size, err + } + nSize, err2 := p.ReadI64() + size = int(nSize) + return elemType, size, err2 +} + +func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e error) { + if isNull, e := p.ParseListBegin(); isNull || e != nil { + return VOID, 0, e + } + sElemType, err := p.ReadString() + elemType = p.StringToTypeId(sElemType) + if err != nil { + return elemType, size, err + } + nSize, err2 := p.ReadI64() + size = int(nSize) + return elemType, size, err2 +} + +func (p *TJSONProtocol) writeElemListBegin(elemType TType, size int) error { + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.OutputString(p.TypeIdToString(elemType)); e != nil { + return e + } + if e := p.OutputI64(int64(size)); e != nil { + return e + } + return nil +} + +func (p *TJSONProtocol) TypeIdToString(fieldType TType) string { + switch byte(fieldType) { + case STOP: + return "stp" + case VOID: + return "v" + case BOOL: + return "tf" + case BYTE: + return "i8" + case DOUBLE: + return "dbl" + case I16: + return "i16" + case I32: + return "i32" + case I64: + return "i64" + case STRING: + return "str" + case STRUCT: + return "rec" + case MAP: + return "map" + case SET: + return "set" + case LIST: + return "lst" + case UTF16: + return "str" + } + return "" +} + +func (p *TJSONProtocol) StringToTypeId(fieldType string) TType { + switch fieldType { + case "stp": + return TType(STOP) + case "v": + return TType(VOID) + case "tf": + return TType(BOOL) + case "i8": + return TType(BYTE) + case "dbl": + return TType(DOUBLE) + case "16": + return TType(I16) + case "i32": + return TType(I32) + case "i64": + return TType(I64) + case "str": + return TType(STRING) + case "rec": + return TType(STRUCT) + case "map": + return TType(MAP) + case "set": + return TType(SET) + case "lst": + return TType(LIST) + case "u16": + return TType(UTF16) + } + return TType(STOP) +} diff --git a/lib/go/thrift/json_protocol_test.go b/lib/go/thrift/json_protocol_test.go new file mode 100644 index 00000000..cb626cc7 --- /dev/null +++ b/lib/go/thrift/json_protocol_test.go @@ -0,0 +1,639 @@ +/* + * 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 thrift + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "math" + "strconv" + "testing" +) + +func TestWriteJSONProtocolBool(t *testing.T) { + thetype := "boolean" + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + for _, value := range BOOL_VALUES { + if e := p.WriteBool(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := false + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadJSONProtocolBool(t *testing.T) { + thetype := "boolean" + for _, value := range BOOL_VALUES { + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + if value { + trans.Write(JSON_TRUE) + } else { + trans.Write(JSON_FALSE) + } + trans.Flush() + s := trans.String() + v, e := p.ReadBool() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteJSONProtocolByte(t *testing.T) { + thetype := "byte" + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + for _, value := range BYTE_VALUES { + if e := p.WriteByte(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := byte(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadJSONProtocolByte(t *testing.T) { + thetype := "byte" + for _, value := range BYTE_VALUES { + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + trans.WriteString(strconv.Itoa(int(value))) + trans.Flush() + s := trans.String() + v, e := p.ReadByte() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteJSONProtocolI16(t *testing.T) { + thetype := "int16" + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + for _, value := range INT16_VALUES { + if e := p.WriteI16(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := int16(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadJSONProtocolI16(t *testing.T) { + thetype := "int16" + for _, value := range INT16_VALUES { + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + trans.WriteString(strconv.Itoa(int(value))) + trans.Flush() + s := trans.String() + v, e := p.ReadI16() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteJSONProtocolI32(t *testing.T) { + thetype := "int32" + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + for _, value := range INT32_VALUES { + if e := p.WriteI32(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := int32(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadJSONProtocolI32(t *testing.T) { + thetype := "int32" + for _, value := range INT32_VALUES { + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + trans.WriteString(strconv.Itoa(int(value))) + trans.Flush() + s := trans.String() + v, e := p.ReadI32() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteJSONProtocolI64(t *testing.T) { + thetype := "int64" + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + for _, value := range INT64_VALUES { + if e := p.WriteI64(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := int64(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadJSONProtocolI64(t *testing.T) { + thetype := "int64" + for _, value := range INT64_VALUES { + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + trans.WriteString(strconv.FormatInt(value, 10)) + trans.Flush() + s := trans.String() + v, e := p.ReadI64() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteJSONProtocolDouble(t *testing.T) { + thetype := "double" + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + for _, value := range DOUBLE_VALUES { + if e := p.WriteDouble(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if math.IsInf(value, 1) { + if s != jsonQuote(JSON_INFINITY) { + t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_INFINITY)) + } + } else if math.IsInf(value, -1) { + if s != jsonQuote(JSON_NEGATIVE_INFINITY) { + t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_NEGATIVE_INFINITY)) + } + } else if math.IsNaN(value) { + if s != jsonQuote(JSON_NAN) { + t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_NAN)) + } + } else { + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := float64(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + } + trans.Reset() + } + trans.Close() +} + +func TestReadJSONProtocolDouble(t *testing.T) { + thetype := "double" + for _, value := range DOUBLE_VALUES { + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + n := NewNumericFromDouble(value) + trans.WriteString(n.String()) + trans.Flush() + s := trans.String() + v, e := p.ReadDouble() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if math.IsInf(value, 1) { + if !math.IsInf(v, 1) { + t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) + } + } else if math.IsInf(value, -1) { + if !math.IsInf(v, -1) { + t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) + } + } else if math.IsNaN(value) { + if !math.IsNaN(v) { + t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) + } + } else { + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + } + trans.Reset() + trans.Close() + } +} + +func TestWriteJSONProtocolString(t *testing.T) { + thetype := "string" + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + for _, value := range STRING_VALUES { + if e := p.WriteString(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s[0] != '"' || s[len(s)-1] != '"' { + t.Fatalf("Bad value for %s '%v', wrote '%v', expected: %v", thetype, value, s, fmt.Sprint("\"", value, "\"")) + } + v := new(string) + if err := json.Unmarshal([]byte(s), v); err != nil || *v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadJSONProtocolString(t *testing.T) { + thetype := "string" + for _, value := range STRING_VALUES { + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + trans.WriteString(jsonQuote(value)) + trans.Flush() + s := trans.String() + v, e := p.ReadString() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + v1 := new(string) + if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteJSONProtocolBinary(t *testing.T) { + thetype := "binary" + value := protocol_bdata + b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) + base64.StdEncoding.Encode(b64value, value) + b64String := string(b64value) + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + if e := p.WriteBinary(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + expectedString := fmt.Sprint("\"", b64String, "\"") + if s != expectedString { + t.Fatalf("Bad value for %s %v\n wrote: \"%v\"\nexpected: \"%v\"", thetype, value, s, expectedString) + } + v1, err := p.ReadBinary() + if err != nil { + t.Fatalf("Unable to read binary: %s", err.Error()) + } + if len(v1) != len(value) { + t.Fatalf("Invalid value for binary\nexpected: \"%v\"\n read: \"%v\"", value, v1) + } + for k, v := range value { + if v1[k] != v { + t.Fatalf("Invalid value for binary at %v\nexpected: \"%v\"\n read: \"%v\"", k, v, v1[k]) + } + } + trans.Close() +} + +func TestReadJSONProtocolBinary(t *testing.T) { + thetype := "binary" + value := protocol_bdata + b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) + base64.StdEncoding.Encode(b64value, value) + b64String := string(b64value) + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + trans.WriteString(jsonQuote(b64String)) + trans.Flush() + s := trans.String() + v, e := p.ReadBinary() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if len(v) != len(value) { + t.Fatalf("Bad value for %s value length %v, wrote: %v, received length: %v", thetype, len(value), s, len(v)) + } + for i := 0; i < len(v); i++ { + if v[i] != value[i] { + t.Fatalf("Bad value for %s at index %d value %v, wrote: %v, received: %v", thetype, i, value[i], s, v[i]) + } + } + v1 := new(string) + if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) + } + trans.Reset() + trans.Close() +} + +func TestWriteJSONProtocolList(t *testing.T) { + thetype := "list" + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + p.WriteListBegin(TType(DOUBLE), len(DOUBLE_VALUES)) + for _, value := range DOUBLE_VALUES { + if e := p.WriteDouble(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + } + p.WriteListEnd() + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) + } + str := trans.String() + str1 := new([]interface{}) + err := json.Unmarshal([]byte(str), str1) + if err != nil { + t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) + } + l := *str1 + if len(l) < 2 { + t.Fatalf("List must be at least of length two to include metadata") + } + if l[0] != "dbl" { + t.Fatal("Invalid type for list, expected: ", STRING, ", but was: ", l[0]) + } + if int(l[1].(float64)) != len(DOUBLE_VALUES) { + t.Fatal("Invalid length for list, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) + } + for k, value := range DOUBLE_VALUES { + s := l[k+2] + if math.IsInf(value, 1) { + if s.(string) != JSON_INFINITY { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_INFINITY), str) + } + } else if math.IsInf(value, 0) { + if s.(string) != JSON_NEGATIVE_INFINITY { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY), str) + } + } else if math.IsNaN(value) { + if s.(string) != JSON_NAN { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NAN), str) + } + } else { + if s.(float64) != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) + } + } + trans.Reset() + } + trans.Close() +} + +func TestWriteJSONProtocolSet(t *testing.T) { + thetype := "set" + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + p.WriteSetBegin(TType(DOUBLE), len(DOUBLE_VALUES)) + for _, value := range DOUBLE_VALUES { + if e := p.WriteDouble(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + } + p.WriteSetEnd() + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) + } + str := trans.String() + str1 := new([]interface{}) + err := json.Unmarshal([]byte(str), str1) + if err != nil { + t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) + } + l := *str1 + if len(l) < 2 { + t.Fatalf("Set must be at least of length two to include metadata") + } + if l[0] != "dbl" { + t.Fatal("Invalid type for set, expected: ", DOUBLE, ", but was: ", l[0]) + } + if int(l[1].(float64)) != len(DOUBLE_VALUES) { + t.Fatal("Invalid length for set, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) + } + for k, value := range DOUBLE_VALUES { + s := l[k+2] + if math.IsInf(value, 1) { + if s.(string) != JSON_INFINITY { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_INFINITY), str) + } + } else if math.IsInf(value, 0) { + if s.(string) != JSON_NEGATIVE_INFINITY { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY), str) + } + } else if math.IsNaN(value) { + if s.(string) != JSON_NAN { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NAN), str) + } + } else { + if s.(float64) != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) + } + } + trans.Reset() + } + trans.Close() +} + +func TestWriteJSONProtocolMap(t *testing.T) { + thetype := "map" + trans := NewTMemoryBuffer() + p := NewTJSONProtocol(trans) + p.WriteMapBegin(TType(I32), TType(DOUBLE), len(DOUBLE_VALUES)) + for k, value := range DOUBLE_VALUES { + if e := p.WriteI32(int32(k)); e != nil { + t.Fatalf("Unable to write %s key int32 value %v due to error: %s", thetype, k, e.Error()) + } + if e := p.WriteDouble(value); e != nil { + t.Fatalf("Unable to write %s value float64 value %v due to error: %s", thetype, value, e.Error()) + } + } + p.WriteMapEnd() + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) + } + str := trans.String() + if str[0] != '[' || str[len(str)-1] != ']' { + t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES) + } + expectedKeyType, expectedValueType, expectedSize, err := p.ReadMapBegin() + if err != nil { + t.Fatalf("Error while reading map begin: %s", err.Error()) + } + if expectedKeyType != I32 { + t.Fatal("Expected map key type ", I32, ", but was ", expectedKeyType) + } + if expectedValueType != DOUBLE { + t.Fatal("Expected map value type ", DOUBLE, ", but was ", expectedValueType) + } + if expectedSize != len(DOUBLE_VALUES) { + t.Fatal("Expected map size of ", len(DOUBLE_VALUES), ", but was ", expectedSize) + } + for k, value := range DOUBLE_VALUES { + ik, err := p.ReadI32() + if err != nil { + t.Fatalf("Bad key for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, ik, string(k), err.Error()) + } + if int(ik) != k { + t.Fatalf("Bad key for %s index %v, wrote: %v, expected: %v", thetype, k, ik, k) + } + dv, err := p.ReadDouble() + if err != nil { + t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, dv, value, err.Error()) + } + s := strconv.FormatFloat(dv, 'g', 10, 64) + if math.IsInf(value, 1) { + if !math.IsInf(dv, 1) { + t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_INFINITY)) + } + } else if math.IsInf(value, 0) { + if !math.IsInf(dv, 0) { + t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY)) + } + } else if math.IsNaN(value) { + if !math.IsNaN(dv) { + t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_NAN)) + } + } else { + expected := strconv.FormatFloat(value, 'g', 10, 64) + if s != expected { + t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected %v", thetype, k, value, s, expected) + } + v := float64(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + } + trans.Reset() + } + trans.Close() +} diff --git a/lib/go/thrift/memory_buffer.go b/lib/go/thrift/memory_buffer.go new file mode 100644 index 00000000..c48e0893 --- /dev/null +++ b/lib/go/thrift/memory_buffer.go @@ -0,0 +1,79 @@ +/* + * 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 thrift + +import ( + "bytes" +) + +// Memory buffer-based implementation of the TTransport interface. +type TMemoryBuffer struct { + *bytes.Buffer + size int +} + +type TMemoryBufferTransportFactory struct { + size int +} + +func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) TTransport { + if trans != nil { + t, ok := trans.(*TMemoryBuffer) + if ok && t.size > 0 { + return NewTMemoryBufferLen(t.size) + } + } + return NewTMemoryBufferLen(p.size) +} + +func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory { + return &TMemoryBufferTransportFactory{size: size} +} + +func NewTMemoryBuffer() *TMemoryBuffer { + return &TMemoryBuffer{Buffer: &bytes.Buffer{}, size: 0} +} + +func NewTMemoryBufferLen(size int) *TMemoryBuffer { + buf := make([]byte, 0, size) + return &TMemoryBuffer{Buffer: bytes.NewBuffer(buf), size: size} +} + +func (p *TMemoryBuffer) IsOpen() bool { + return true +} + +func (p *TMemoryBuffer) Open() error { + return nil +} + +func (p *TMemoryBuffer) Peek() bool { + return p.IsOpen() +} + +func (p *TMemoryBuffer) Close() error { + p.Buffer.Reset() + return nil +} + +// Flushing a memory buffer is a no-op +func (p *TMemoryBuffer) Flush() error { + return nil +} diff --git a/lib/go/thrift/tmemory_buffer_test.go b/lib/go/thrift/memory_buffer_test.go similarity index 88% rename from lib/go/thrift/tmemory_buffer_test.go rename to lib/go/thrift/memory_buffer_test.go index 5d17864b..af2e8bfe 100644 --- a/lib/go/thrift/tmemory_buffer_test.go +++ b/lib/go/thrift/memory_buffer_test.go @@ -17,14 +17,13 @@ * under the License. */ -package thrift_test +package thrift import ( - . "thrift" - "testing" + "testing" ) func TestMemoryBuffer(t *testing.T) { - trans := NewTMemoryBufferLen(1024) - TransportTest(t, trans, trans) + trans := NewTMemoryBufferLen(1024) + TransportTest(t, trans, trans) } diff --git a/lib/go/thrift/tmessagetype.go b/lib/go/thrift/messagetype.go similarity index 76% rename from lib/go/thrift/tmessagetype.go rename to lib/go/thrift/messagetype.go index b31c66cb..25ab2e98 100644 --- a/lib/go/thrift/tmessagetype.go +++ b/lib/go/thrift/messagetype.go @@ -19,16 +19,13 @@ package thrift -/** - * Message type constants in the Thrift protocol. - * - */ +// Message type constants in the Thrift protocol. type TMessageType int32 const ( - INVALID_TMESSAGE_TYPE TMessageType = 0 - CALL TMessageType = 1 - REPLY TMessageType = 2 - EXCEPTION TMessageType = 3 - ONEWAY TMessageType = 4 + INVALID_TMESSAGE_TYPE TMessageType = 0 + CALL TMessageType = 1 + REPLY TMessageType = 2 + EXCEPTION TMessageType = 3 + ONEWAY TMessageType = 4 ) diff --git a/lib/go/thrift/numeric.go b/lib/go/thrift/numeric.go new file mode 100644 index 00000000..aa8daa9b --- /dev/null +++ b/lib/go/thrift/numeric.go @@ -0,0 +1,164 @@ +/* + * 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 thrift + +import ( + "math" + "strconv" +) + +type Numeric interface { + Int64() int64 + Int32() int32 + Int16() int16 + Byte() byte + Int() int + Float64() float64 + Float32() float32 + String() string + isNull() bool +} + +type numeric struct { + iValue int64 + dValue float64 + sValue string + isNil bool +} + +var ( + INFINITY Numeric + NEGATIVE_INFINITY Numeric + NAN Numeric + ZERO Numeric + NUMERIC_NULL Numeric +) + +func NewNumericFromDouble(dValue float64) Numeric { + if math.IsInf(dValue, 1) { + return INFINITY + } + if math.IsInf(dValue, -1) { + return NEGATIVE_INFINITY + } + if math.IsNaN(dValue) { + return NAN + } + iValue := int64(dValue) + sValue := strconv.FormatFloat(dValue, 'g', 10, 64) + isNil := false + return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} +} + +func NewNumericFromI64(iValue int64) Numeric { + dValue := float64(iValue) + sValue := string(iValue) + isNil := false + return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} +} + +func NewNumericFromI32(iValue int32) Numeric { + dValue := float64(iValue) + sValue := string(iValue) + isNil := false + return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil} +} + +func NewNumericFromString(sValue string) Numeric { + if sValue == INFINITY.String() { + return INFINITY + } + if sValue == NEGATIVE_INFINITY.String() { + return NEGATIVE_INFINITY + } + if sValue == NAN.String() { + return NAN + } + iValue, _ := strconv.ParseInt(sValue, 10, 64) + dValue, _ := strconv.ParseFloat(sValue, 64) + isNil := len(sValue) == 0 + return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} +} + +func NewNumericFromJSONString(sValue string, isNull bool) Numeric { + if isNull { + return NewNullNumeric() + } + if sValue == JSON_INFINITY { + return INFINITY + } + if sValue == JSON_NEGATIVE_INFINITY { + return NEGATIVE_INFINITY + } + if sValue == JSON_NAN { + return NAN + } + iValue, _ := strconv.ParseInt(sValue, 10, 64) + dValue, _ := strconv.ParseFloat(sValue, 64) + return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNull} +} + +func NewNullNumeric() Numeric { + return &numeric{iValue: 0, dValue: 0.0, sValue: "", isNil: true} +} + +func (p *numeric) Int64() int64 { + return p.iValue +} + +func (p *numeric) Int32() int32 { + return int32(p.iValue) +} + +func (p *numeric) Int16() int16 { + return int16(p.iValue) +} + +func (p *numeric) Byte() byte { + return byte(p.iValue) +} + +func (p *numeric) Int() int { + return int(p.iValue) +} + +func (p *numeric) Float64() float64 { + return p.dValue +} + +func (p *numeric) Float32() float32 { + return float32(p.dValue) +} + +func (p *numeric) String() string { + return p.sValue +} + +func (p *numeric) isNull() bool { + return p.isNil +} + +func init() { + INFINITY = &numeric{iValue: 0, dValue: math.Inf(1), sValue: "Infinity", isNil: false} + NEGATIVE_INFINITY = &numeric{iValue: 0, dValue: math.Inf(-1), sValue: "-Infinity", isNil: false} + NAN = &numeric{iValue: 0, dValue: math.NaN(), sValue: "NaN", isNil: false} + ZERO = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: false} + NUMERIC_NULL = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: true} +} diff --git a/lib/go/thrift/tprocessor.go b/lib/go/thrift/processor.go similarity index 80% rename from lib/go/thrift/tprocessor.go rename to lib/go/thrift/processor.go index d2bb5e4b..ca0d3faf 100644 --- a/lib/go/thrift/tprocessor.go +++ b/lib/go/thrift/processor.go @@ -19,15 +19,12 @@ package thrift -/** - * A processor is a generic object which operates upon an input stream and - * writes to some output stream. - * - */ +// A processor is a generic object which operates upon an input stream and +// writes to some output stream. type TProcessor interface { - Process(in, out TProtocol) (bool, TException) + Process(in, out TProtocol) (bool, TException) } type TProcessorFunction interface { - Process(seqId int32, in, out TProtocol) (bool, TException) + Process(seqId int32, in, out TProtocol) (bool, TException) } diff --git a/lib/go/thrift/tprocessor_factory.go b/lib/go/thrift/processor_factory.go similarity index 78% rename from lib/go/thrift/tprocessor_factory.go rename to lib/go/thrift/processor_factory.go index 72681ab6..9d645df2 100644 --- a/lib/go/thrift/tprocessor_factory.go +++ b/lib/go/thrift/processor_factory.go @@ -19,44 +19,40 @@ package thrift - -/** - * The default processor factory just returns a singleton - * instance. - */ +// The default processor factory just returns a singleton +// instance. type TProcessorFactory interface { - GetProcessor(trans TTransport) TProcessor + GetProcessor(trans TTransport) TProcessor } type tProcessorFactory struct { - processor TProcessor + processor TProcessor } func NewTProcessorFactory(p TProcessor) TProcessorFactory { - return &tProcessorFactory{processor: p} + return &tProcessorFactory{processor: p} } func (p *tProcessorFactory) GetProcessor(trans TTransport) TProcessor { - return p.processor + return p.processor } - /** * The default processor factory just returns a singleton * instance. */ type TProcessorFunctionFactory interface { - GetProcessorFunction(trans TTransport) TProcessorFunction + GetProcessorFunction(trans TTransport) TProcessorFunction } type tProcessorFunctionFactory struct { - processor TProcessorFunction + processor TProcessorFunction } func NewTProcessorFunctionFactory(p TProcessorFunction) TProcessorFunctionFactory { - return &tProcessorFunctionFactory{processor: p} + return &tProcessorFunctionFactory{processor: p} } func (p *tProcessorFunctionFactory) GetProcessorFunction(trans TTransport) TProcessorFunction { - return p.processor + return p.processor } diff --git a/lib/go/thrift/protocol.go b/lib/go/thrift/protocol.go new file mode 100644 index 00000000..87ceaad2 --- /dev/null +++ b/lib/go/thrift/protocol.go @@ -0,0 +1,154 @@ +/* + * 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 thrift + +const ( + VERSION_MASK = 0xffff0000 + VERSION_1 = 0x80010000 +) + +type TProtocol interface { + WriteMessageBegin(name string, typeId TMessageType, seqid int32) error + WriteMessageEnd() error + WriteStructBegin(name string) error + WriteStructEnd() error + WriteFieldBegin(name string, typeId TType, id int16) error + WriteFieldEnd() error + WriteFieldStop() error + WriteMapBegin(keyType TType, valueType TType, size int) error + WriteMapEnd() error + WriteListBegin(elemType TType, size int) error + WriteListEnd() error + WriteSetBegin(elemType TType, size int) error + WriteSetEnd() error + WriteBool(value bool) error + WriteByte(value byte) error + WriteI16(value int16) error + WriteI32(value int32) error + WriteI64(value int64) error + WriteDouble(value float64) error + WriteString(value string) error + WriteBinary(value []byte) error + + ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err error) + ReadMessageEnd() error + ReadStructBegin() (name string, err error) + ReadStructEnd() error + ReadFieldBegin() (name string, typeId TType, id int16, err error) + ReadFieldEnd() error + ReadMapBegin() (keyType TType, valueType TType, size int, err error) + ReadMapEnd() error + ReadListBegin() (elemType TType, size int, err error) + ReadListEnd() error + ReadSetBegin() (elemType TType, size int, err error) + ReadSetEnd() error + ReadBool() (value bool, err error) + ReadByte() (value byte, err error) + ReadI16() (value int16, err error) + ReadI32() (value int32, err error) + ReadI64() (value int64, err error) + ReadDouble() (value float64, err error) + ReadString() (value string, err error) + ReadBinary() (value []byte, err error) + + Skip(fieldType TType) (err error) + Flush() (err error) + + Transport() TTransport +} + +// The maximum recursive depth the skip() function will traverse +var MaxSkipDepth = 1<<31 - 1 + +// Skips over the next data element from the provided input TProtocol object. +func SkipDefaultDepth(prot TProtocol, typeId TType) (err error) { + return Skip(prot, typeId, MaxSkipDepth) +} + +// Skips over the next data element from the provided input TProtocol object. +func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) { + switch fieldType { + case STOP: + return + case BOOL: + _, err = self.ReadBool() + return + case BYTE: + _, err = self.ReadByte() + return + case I16: + _, err = self.ReadI16() + return + case I32: + _, err = self.ReadI32() + return + case I64: + _, err = self.ReadI64() + return + case DOUBLE: + _, err = self.ReadDouble() + return + case STRING: + _, err = self.ReadString() + return + case STRUCT: + if _, err = self.ReadStructBegin(); err != nil { + return err + } + for { + _, typeId, _, _ := self.ReadFieldBegin() + if typeId == STOP { + break + } + Skip(self, typeId, maxDepth-1) + self.ReadFieldEnd() + } + return self.ReadStructEnd() + case MAP: + keyType, valueType, size, err := self.ReadMapBegin() + if err != nil { + return err + } + for i := 0; i < size; i++ { + Skip(self, keyType, maxDepth-1) + self.Skip(valueType) + } + return self.ReadMapEnd() + case SET: + elemType, size, err := self.ReadSetBegin() + if err != nil { + return err + } + for i := 0; i < size; i++ { + Skip(self, elemType, maxDepth-1) + } + return self.ReadSetEnd() + case LIST: + elemType, size, err := self.ReadListBegin() + if err != nil { + return err + } + for i := 0; i < size; i++ { + Skip(self, elemType, maxDepth-1) + } + return self.ReadListEnd() + } + return nil +} diff --git a/lib/go/thrift/protocol_exception.go b/lib/go/thrift/protocol_exception.go new file mode 100644 index 00000000..f1a164a8 --- /dev/null +++ b/lib/go/thrift/protocol_exception.go @@ -0,0 +1,77 @@ +/* + * 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 thrift + +import ( + "encoding/base64" +) + +// Thrift Protocol exception +type TProtocolException interface { + TException + TypeId() int +} + +const ( + UNKNOWN_PROTOCOL_EXCEPTION = 0 + INVALID_DATA = 1 + NEGATIVE_SIZE = 2 + SIZE_LIMIT = 3 + BAD_VERSION = 4 + NOT_IMPLEMENTED = 5 +) + +type tProtocolException struct { + typeId int + message string +} + +func (p *tProtocolException) TypeId() int { + return p.typeId +} + +func (p *tProtocolException) String() string { + return p.message +} + +func (p *tProtocolException) Error() string { + return p.message +} + +func NewTProtocolException(err error) TProtocolException { + if err == nil { + return nil + } + if e,ok := err.(TProtocolException); ok { + return e + } + if _, ok := err.(base64.CorruptInputError); ok { + return &tProtocolException{INVALID_DATA, err.Error()} + } + return &tProtocolException{UNKNOWN_PROTOCOL_EXCEPTION, err.Error()} +} + +func NewTProtocolExceptionWithType(errType int, err error) TProtocolException { + if err == nil { + return nil + } + return &tProtocolException{errType, err.Error()} +} + diff --git a/lib/go/thrift/tprotocol_factory.go b/lib/go/thrift/protocol_factory.go similarity index 88% rename from lib/go/thrift/tprotocol_factory.go rename to lib/go/thrift/protocol_factory.go index 2eed2c2c..c40f796d 100644 --- a/lib/go/thrift/tprotocol_factory.go +++ b/lib/go/thrift/protocol_factory.go @@ -19,10 +19,7 @@ package thrift -/** - * Factory interface for constructing protocol instances. - * - */ +// Factory interface for constructing protocol instances. type TProtocolFactory interface { - GetProtocol(trans TTransport) TProtocol + GetProtocol(trans TTransport) TProtocol } diff --git a/lib/go/thrift/protocol_test.go b/lib/go/thrift/protocol_test.go new file mode 100644 index 00000000..632098cc --- /dev/null +++ b/lib/go/thrift/protocol_test.go @@ -0,0 +1,458 @@ +/* + * 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 thrift + +import ( + "bytes" + "io/ioutil" + "math" + "net" + "net/http" + "testing" +) + +const PROTOCOL_BINARY_DATA_SIZE = 155 + +var ( + data string // test data for writing + protocol_bdata []byte // test data for writing; same as data + BOOL_VALUES []bool + BYTE_VALUES []byte + INT16_VALUES []int16 + INT32_VALUES []int32 + INT64_VALUES []int64 + DOUBLE_VALUES []float64 + STRING_VALUES []string +) + +func init() { + protocol_bdata = make([]byte, PROTOCOL_BINARY_DATA_SIZE) + for i := 0; i < PROTOCOL_BINARY_DATA_SIZE; i++ { + protocol_bdata[i] = byte((i + 'a') % 255) + } + data = string(protocol_bdata) + BOOL_VALUES = []bool{false, true, false, false, true} + BYTE_VALUES = []byte{117, 0, 1, 32, 127, 128, 255} + INT16_VALUES = []int16{459, 0, 1, -1, -128, 127, 32767, -32768} + INT32_VALUES = []int32{459, 0, 1, -1, -128, 127, 32767, 2147483647, -2147483535} + INT64_VALUES = []int64{459, 0, 1, -1, -128, 127, 32767, 2147483647, -2147483535, 34359738481, -35184372088719, -9223372036854775808, 9223372036854775807} + DOUBLE_VALUES = []float64{459.3, 0.0, -1.0, 1.0, 0.5, 0.3333, 3.14159, 1.537e-38, 1.673e25, 6.02214179e23, -6.02214179e23, INFINITY.Float64(), NEGATIVE_INFINITY.Float64(), NAN.Float64()} + STRING_VALUES = []string{"", "a", "st[uf]f", "st,u:ff with spaces", "stuff\twith\nescape\\characters'...\"lots{of}fun"} +} + +type HTTPEchoServer struct{} + +func (p *HTTPEchoServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { + buf, err := ioutil.ReadAll(req.Body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write(buf) + } else { + w.WriteHeader(http.StatusOK) + w.Write(buf) + } +} + +func HttpClientSetupForTest(t *testing.T) (net.Listener, net.Addr) { + addr, err := FindAvailableTCPServerPort(40000) + if err != nil { + t.Fatalf("Unable to find available tcp port addr: %s", err) + return nil, addr + } + l, err := net.Listen(addr.Network(), addr.String()) + if err != nil { + t.Fatalf("Unable to setup tcp listener on %s: %s", addr.String(), err) + return l, addr + } + go http.Serve(l, &HTTPEchoServer{}) + return l, addr +} + +func ReadWriteProtocolTest(t *testing.T, protocolFactory TProtocolFactory) { + buf := bytes.NewBuffer(make([]byte, 0, 1024)) + l, addr := HttpClientSetupForTest(t) + defer l.Close() + transports := []TTransportFactory{ + NewTMemoryBufferTransportFactory(1024), + NewStreamTransportFactory(buf, buf, true), + NewTFramedTransportFactory(NewTMemoryBufferTransportFactory(1024)), + NewTHttpPostClientTransportFactory("http://" + addr.String()), + } + for _, tf := range transports { + trans := tf.GetTransport(nil) + p := protocolFactory.GetProtocol(trans) + ReadWriteBool(t, p, trans) + trans.Close() + } + for _, tf := range transports { + trans := tf.GetTransport(nil) + p := protocolFactory.GetProtocol(trans) + ReadWriteByte(t, p, trans) + trans.Close() + } + for _, tf := range transports { + trans := tf.GetTransport(nil) + p := protocolFactory.GetProtocol(trans) + ReadWriteI16(t, p, trans) + trans.Close() + } + for _, tf := range transports { + trans := tf.GetTransport(nil) + p := protocolFactory.GetProtocol(trans) + ReadWriteI32(t, p, trans) + trans.Close() + } + for _, tf := range transports { + trans := tf.GetTransport(nil) + p := protocolFactory.GetProtocol(trans) + ReadWriteI64(t, p, trans) + trans.Close() + } + for _, tf := range transports { + trans := tf.GetTransport(nil) + p := protocolFactory.GetProtocol(trans) + ReadWriteDouble(t, p, trans) + trans.Close() + } + for _, tf := range transports { + trans := tf.GetTransport(nil) + p := protocolFactory.GetProtocol(trans) + ReadWriteString(t, p, trans) + trans.Close() + } + for _, tf := range transports { + trans := tf.GetTransport(nil) + p := protocolFactory.GetProtocol(trans) + ReadWriteBinary(t, p, trans) + trans.Close() + } + + for _, tf := range transports { + trans := tf.GetTransport(nil) + p := protocolFactory.GetProtocol(trans); + ReadWriteI64(t, p, trans); + ReadWriteDouble(t, p, trans); + ReadWriteBinary(t, p, trans); + ReadWriteByte(t, p, trans); + trans.Close() + } + +} + +func ReadWriteBool(t *testing.T, p TProtocol, trans TTransport) { + thetype := TType(BOOL) + thelen := len(BOOL_VALUES) + err := p.WriteListBegin(thetype, thelen) + if err != nil { + t.Errorf("%s: %T %T %q Error writing list begin: %q", "ReadWriteBool", p, trans, err, thetype) + } + for k, v := range BOOL_VALUES { + err = p.WriteBool(v) + if err != nil { + t.Errorf("%s: %T %T %q Error writing bool in list at index %d: %q", "ReadWriteBool", p, trans, err, k, v) + } + } + p.WriteListEnd() + if err != nil { + t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES) + } + p.Flush() + thetype2, thelen2, err := p.ReadListBegin() + if err != nil { + t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES) + } + _, ok := p.(*TSimpleJSONProtocol) + if !ok { + if thetype != thetype2 { + t.Errorf("%s: %T %T type %s != type %s", "ReadWriteBool", p, trans, thetype, thetype2) + } + if thelen != thelen2 { + t.Errorf("%s: %T %T len %s != len %s", "ReadWriteBool", p, trans, thelen, thelen2) + } + } + for k, v := range BOOL_VALUES { + value, err := p.ReadBool() + if err != nil { + t.Errorf("%s: %T %T %q Error reading bool at index %d: %q", "ReadWriteBool", p, trans, err, k, v) + } + if v != value { + t.Errorf("%s: index %d %q %q %q != %q", "ReadWriteBool", k, p, trans, v, value) + } + } + err = p.ReadListEnd() + if err != nil { + t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteBool", p, trans, err) + } +} + +func ReadWriteByte(t *testing.T, p TProtocol, trans TTransport) { + thetype := TType(BYTE) + thelen := len(BYTE_VALUES) + err := p.WriteListBegin(thetype, thelen) + if err != nil { + t.Errorf("%s: %T %T %q Error writing list begin: %q", "ReadWriteByte", p, trans, err, thetype) + } + for k, v := range BYTE_VALUES { + err = p.WriteByte(v) + if err != nil { + t.Errorf("%s: %T %T %q Error writing byte in list at index %d: %q", "ReadWriteByte", p, trans, err, k, v) + } + } + err = p.WriteListEnd() + if err != nil { + t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) + } + err = p.Flush() + if err != nil { + t.Errorf("%s: %T %T %q Error flushing list of bytes: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) + } + thetype2, thelen2, err := p.ReadListBegin() + if err != nil { + t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) + } + _, ok := p.(*TSimpleJSONProtocol) + if !ok { + if thetype != thetype2 { + t.Errorf("%s: %T %T type %s != type %s", "ReadWriteByte", p, trans, thetype, thetype2) + } + if thelen != thelen2 { + t.Errorf("%s: %T %T len %s != len %s", "ReadWriteByte", p, trans, thelen, thelen2) + } + } + for k, v := range BYTE_VALUES { + value, err := p.ReadByte() + if err != nil { + t.Errorf("%s: %T %T %q Error reading byte at index %d: %q", "ReadWriteByte", p, trans, err, k, v) + } + if v != value { + t.Errorf("%s: %T %T %d != %d", "ReadWriteByte", p, trans, v, value) + } + } + err = p.ReadListEnd() + if err != nil { + t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteByte", p, trans, err) + } +} + +func ReadWriteI16(t *testing.T, p TProtocol, trans TTransport) { + thetype := TType(I16) + thelen := len(INT16_VALUES) + p.WriteListBegin(thetype, thelen) + for _, v := range INT16_VALUES { + p.WriteI16(v) + } + p.WriteListEnd() + p.Flush() + thetype2, thelen2, err := p.ReadListBegin() + if err != nil { + t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI16", p, trans, err, INT16_VALUES) + } + _, ok := p.(*TSimpleJSONProtocol) + if !ok { + if thetype != thetype2 { + t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI16", p, trans, thetype, thetype2) + } + if thelen != thelen2 { + t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI16", p, trans, thelen, thelen2) + } + } + for k, v := range INT16_VALUES { + value, err := p.ReadI16() + if err != nil { + t.Errorf("%s: %T %T %q Error reading int16 at index %d: %q", "ReadWriteI16", p, trans, err, k, v) + } + if v != value { + t.Errorf("%s: %T %T %d != %d", "ReadWriteI16", p, trans, v, value) + } + } + err = p.ReadListEnd() + if err != nil { + t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI16", p, trans, err) + } +} + +func ReadWriteI32(t *testing.T, p TProtocol, trans TTransport) { + thetype := TType(I32) + thelen := len(INT32_VALUES) + p.WriteListBegin(thetype, thelen) + for _, v := range INT32_VALUES { + p.WriteI32(v) + } + p.WriteListEnd() + p.Flush() + thetype2, thelen2, err := p.ReadListBegin() + if err != nil { + t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI32", p, trans, err, INT32_VALUES) + } + _, ok := p.(*TSimpleJSONProtocol) + if !ok { + if thetype != thetype2 { + t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI32", p, trans, thetype, thetype2) + } + if thelen != thelen2 { + t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI32", p, trans, thelen, thelen2) + } + } + for k, v := range INT32_VALUES { + value, err := p.ReadI32() + if err != nil { + t.Errorf("%s: %T %T %q Error reading int32 at index %d: %q", "ReadWriteI32", p, trans, err, k, v) + } + if v != value { + t.Errorf("%s: %T %T %d != %d", "ReadWriteI32", p, trans, v, value) + } + } + if err != nil { + t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI32", p, trans, err) + } +} + +func ReadWriteI64(t *testing.T, p TProtocol, trans TTransport) { + thetype := TType(I64) + thelen := len(INT64_VALUES) + p.WriteListBegin(thetype, thelen) + for _, v := range INT64_VALUES { + p.WriteI64(v) + } + p.WriteListEnd() + p.Flush() + thetype2, thelen2, err := p.ReadListBegin() + if err != nil { + t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI64", p, trans, err, INT64_VALUES) + } + _, ok := p.(*TSimpleJSONProtocol) + if !ok { + if thetype != thetype2 { + t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI64", p, trans, thetype, thetype2) + } + if thelen != thelen2 { + t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI64", p, trans, thelen, thelen2) + } + } + for k, v := range INT64_VALUES { + value, err := p.ReadI64() + if err != nil { + t.Errorf("%s: %T %T %q Error reading int64 at index %d: %q", "ReadWriteI64", p, trans, err, k, v) + } + if v != value { + t.Errorf("%s: %T %T %q != %q", "ReadWriteI64", p, trans, v, value) + } + } + if err != nil { + t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI64", p, trans, err) + } +} + +func ReadWriteDouble(t *testing.T, p TProtocol, trans TTransport) { + thetype := TType(DOUBLE) + thelen := len(DOUBLE_VALUES) + p.WriteListBegin(thetype, thelen) + for _, v := range DOUBLE_VALUES { + p.WriteDouble(v) + } + p.WriteListEnd() + p.Flush() + wrotebuffer := "" + if memtrans, ok := trans.(*TMemoryBuffer); ok { + wrotebuffer = memtrans.String() + } + thetype2, thelen2, err := p.ReadListBegin() + if err != nil { + t.Errorf("%s: %T %T %q Error reading list: %q, wrote: %v", "ReadWriteDouble", p, trans, err, DOUBLE_VALUES, wrotebuffer) + } + if thetype != thetype2 { + t.Errorf("%s: %T %T type %s != type %s", "ReadWriteDouble", p, trans, thetype, thetype2) + } + if thelen != thelen2 { + t.Errorf("%s: %T %T len %s != len %s", "ReadWriteDouble", p, trans, thelen, thelen2) + } + for k, v := range DOUBLE_VALUES { + value, err := p.ReadDouble() + if err != nil { + t.Errorf("%s: %T %T %q Error reading double at index %d: %q", "ReadWriteDouble", p, trans, err, k, v) + } + if math.IsNaN(v) { + if !math.IsNaN(value) { + t.Errorf("%s: %T %T math.IsNaN(%q) != math.IsNaN(%q)", "ReadWriteDouble", p, trans, v, value) + } + } else if v != value { + t.Errorf("%s: %T %T %v != %q", "ReadWriteDouble", p, trans, v, value) + } + } + err = p.ReadListEnd() + if err != nil { + t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteDouble", p, trans, err) + } +} + +func ReadWriteString(t *testing.T, p TProtocol, trans TTransport) { + thetype := TType(STRING) + thelen := len(STRING_VALUES) + p.WriteListBegin(thetype, thelen) + for _, v := range STRING_VALUES { + p.WriteString(v) + } + p.WriteListEnd() + p.Flush() + thetype2, thelen2, err := p.ReadListBegin() + if err != nil { + t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteString", p, trans, err, STRING_VALUES) + } + _, ok := p.(*TSimpleJSONProtocol) + if !ok { + if thetype != thetype2 { + t.Errorf("%s: %T %T type %s != type %s", "ReadWriteString", p, trans, thetype, thetype2) + } + if thelen != thelen2 { + t.Errorf("%s: %T %T len %s != len %s", "ReadWriteString", p, trans, thelen, thelen2) + } + } + for k, v := range STRING_VALUES { + value, err := p.ReadString() + if err != nil { + t.Errorf("%s: %T %T %q Error reading string at index %d: %q", "ReadWriteString", p, trans, err, k, v) + } + if v != value { + t.Errorf("%s: %T %T %d != %d", "ReadWriteString", p, trans, v, value) + } + } + if err != nil { + t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteString", p, trans, err) + } +} + +func ReadWriteBinary(t *testing.T, p TProtocol, trans TTransport) { + v := protocol_bdata + p.WriteBinary(v) + p.Flush() + value, err := p.ReadBinary() + if err != nil { + t.Errorf("%s: %T %T Unable to read binary: %s", "ReadWriteBinary", p, trans, err.Error()) + } + if len(v) != len(value) { + t.Errorf("%s: %T %T len(v) != len(value)... %d != %d", "ReadWriteBinary", p, trans, len(v), len(value)) + } else { + for i := 0; i < len(v); i++ { + if v[i] != value[i] { + t.Errorf("%s: %T %T %s != %s", "ReadWriteBinary", p, trans, v, value) + } + } + } +} diff --git a/lib/go/thrift/server.go b/lib/go/thrift/server.go new file mode 100644 index 00000000..f813fa35 --- /dev/null +++ b/lib/go/thrift/server.go @@ -0,0 +1,35 @@ +/* + * 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 thrift + +type TServer interface { + ProcessorFactory() TProcessorFactory + ServerTransport() TServerTransport + InputTransportFactory() TTransportFactory + OutputTransportFactory() TTransportFactory + InputProtocolFactory() TProtocolFactory + OutputProtocolFactory() TProtocolFactory + + // Starts the server + Serve() error + // Stops the server. This is optional on a per-implementation basis. Not + // all servers are required to be cleanly stoppable. + Stop() error +} diff --git a/lib/go/thrift/server_socket.go b/lib/go/thrift/server_socket.go new file mode 100644 index 00000000..1a01095c --- /dev/null +++ b/lib/go/thrift/server_socket.go @@ -0,0 +1,107 @@ +/* + * 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 thrift + +import ( + "net" + "time" +) + +type TServerSocket struct { + listener net.Listener + addr net.Addr + clientTimeout time.Duration + interrupted bool +} + +func NewTServerSocket(listenAddr string) (*TServerSocket, error) { + return NewTServerSocketTimeout(listenAddr, 0) +} + +func NewTServerSocketTimeout(listenAddr string, clientTimeout time.Duration) (*TServerSocket, error) { + addr, err := net.ResolveTCPAddr("tcp", listenAddr) + if err != nil { + return nil, err + } + return &TServerSocket{addr: addr, clientTimeout: clientTimeout}, nil +} + +func (p *TServerSocket) Listen() error { + if p.IsListening() { + return nil + } + l, err := net.Listen(p.addr.Network(), p.addr.String()) + if err != nil { + return err + } + p.listener = l + return nil +} + +func (p *TServerSocket) Accept() (TTransport, error) { + if p.interrupted { + return nil, errTransportInterrupted + } + if p.listener == nil { + return nil, NewTTransportException(NOT_OPEN, "No underlying server socket") + } + conn, err := p.listener.Accept() + if err != nil { + return nil, NewTTransportExceptionFromError(err) + } + return NewTSocketFromConnTimeout(conn, p.clientTimeout), nil +} + +// Checks whether the socket is listening. +func (p *TServerSocket) IsListening() bool { + return p.listener != nil +} + +// Connects the socket, creating a new socket object if necessary. +func (p *TServerSocket) Open() error { + if p.IsListening() { + return NewTTransportException(ALREADY_OPEN, "Server socket already open") + } + if l, err := net.Listen(p.addr.Network(), p.addr.String()); err != nil { + return err + } else { + p.listener = l + } + return nil +} + +func (p *TServerSocket) Addr() net.Addr { + return p.addr +} + +func (p *TServerSocket) Close() error { + defer func() { + p.listener = nil + }() + if p.IsListening() { + return p.listener.Close() + } + return nil +} + +func (p *TServerSocket) Interrupt() error { + p.interrupted = true + return nil +} diff --git a/lib/go/thrift/tserver_test.go b/lib/go/thrift/server_test.go similarity index 96% rename from lib/go/thrift/tserver_test.go rename to lib/go/thrift/server_test.go index 3cbe8798..ffaf4570 100644 --- a/lib/go/thrift/tserver_test.go +++ b/lib/go/thrift/server_test.go @@ -17,10 +17,10 @@ * under the License. */ -package thrift_test +package thrift import ( - "testing" + "testing" ) func TestNothing(t *testing.T) { diff --git a/lib/go/thrift/texception.go b/lib/go/thrift/server_transport.go similarity index 62% rename from lib/go/thrift/texception.go rename to lib/go/thrift/server_transport.go index be6cbd5c..51c40b64 100644 --- a/lib/go/thrift/texception.go +++ b/lib/go/thrift/server_transport.go @@ -19,38 +19,16 @@ package thrift -import ( - "os" -) - -/** - * Generic exception class for Thrift. - * - */ - -type TException interface { - String() string -} - -type tException struct { - message string -} - -func (p *tException) String() string { - return p.message -} - -func NewTException(m string) TException { - return &tException{message: m} -} - -func NewTExceptionFromOsError(e os.Error) TException { - if e == nil { - return nil - } - t, ok := e.(TException) - if ok { - return t - } - return NewTException(e.String()) +// Server transport. Object which provides client transports. +type TServerTransport interface { + Listen() error + Accept() (TTransport, error) + Close() error + + // Optional method implementation. This signals to the server transport + // that it should break out of any accept() or listen() that it is currently + // blocked on. This method, if implemented, MUST be thread safe, as it may + // be called from a different thread context than the other TServerTransport + // methods. + Interrupt() error } diff --git a/lib/go/thrift/simple_json_protocol.go b/lib/go/thrift/simple_json_protocol.go new file mode 100644 index 00000000..9d0f68fb --- /dev/null +++ b/lib/go/thrift/simple_json_protocol.go @@ -0,0 +1,1298 @@ +/* + * 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 thrift + +import ( + "bufio" + "bytes" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "math" + "strconv" +) + +type _ParseContext int + +const ( + _CONTEXT_IN_TOPLEVEL _ParseContext = 1 + _CONTEXT_IN_LIST_FIRST _ParseContext = 2 + _CONTEXT_IN_LIST _ParseContext = 3 + _CONTEXT_IN_OBJECT_FIRST _ParseContext = 4 + _CONTEXT_IN_OBJECT_NEXT_KEY _ParseContext = 5 + _CONTEXT_IN_OBJECT_NEXT_VALUE _ParseContext = 6 +) + +func (p _ParseContext) String() string { + switch p { + case _CONTEXT_IN_TOPLEVEL: + return "TOPLEVEL" + case _CONTEXT_IN_LIST_FIRST: + return "LIST-FIRST" + case _CONTEXT_IN_LIST: + return "LIST" + case _CONTEXT_IN_OBJECT_FIRST: + return "OBJECT-FIRST" + case _CONTEXT_IN_OBJECT_NEXT_KEY: + return "OBJECT-NEXT-KEY" + case _CONTEXT_IN_OBJECT_NEXT_VALUE: + return "OBJECT-NEXT-VALUE" + } + return "UNKNOWN-PARSE-CONTEXT" +} + +// JSON protocol implementation for thrift. +// +// This protocol produces/consumes a simple output format +// suitable for parsing by scripting languages. It should not be +// confused with the full-featured TJSONProtocol. +// +type TSimpleJSONProtocol struct { + trans TTransport + + parseContextStack []int + dumpContext []int + + writer *bufio.Writer + reader *bufio.Reader +} + +// Constructor +func NewTSimpleJSONProtocol(t TTransport) *TSimpleJSONProtocol { + v := &TSimpleJSONProtocol{trans: t, + writer: bufio.NewWriter(t), + reader: bufio.NewReader(t), + } + v.parseContextStack = append(v.parseContextStack, int(_CONTEXT_IN_TOPLEVEL)) + v.dumpContext = append(v.dumpContext, int(_CONTEXT_IN_TOPLEVEL)) + return v +} + +// Factory +type TSimpleJSONProtocolFactory struct{} + +func (p *TSimpleJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol { + return NewTSimpleJSONProtocol(trans) +} + +func NewTSimpleJSONProtocolFactory() *TSimpleJSONProtocolFactory { + return &TSimpleJSONProtocolFactory{} +} + +var ( + JSON_COMMA []byte + JSON_COLON []byte + JSON_LBRACE []byte + JSON_RBRACE []byte + JSON_LBRACKET []byte + JSON_RBRACKET []byte + JSON_QUOTE byte + JSON_QUOTE_BYTES []byte + JSON_NULL []byte + JSON_TRUE []byte + JSON_FALSE []byte + JSON_INFINITY string + JSON_NEGATIVE_INFINITY string + JSON_NAN string + JSON_INFINITY_BYTES []byte + JSON_NEGATIVE_INFINITY_BYTES []byte + JSON_NAN_BYTES []byte + json_nonbase_map_elem_bytes []byte +) + +func init() { + JSON_COMMA = []byte{','} + JSON_COLON = []byte{':'} + JSON_LBRACE = []byte{'{'} + JSON_RBRACE = []byte{'}'} + JSON_LBRACKET = []byte{'['} + JSON_RBRACKET = []byte{']'} + JSON_QUOTE = '"' + JSON_QUOTE_BYTES = []byte{'"'} + JSON_NULL = []byte{'n', 'u', 'l', 'l'} + JSON_TRUE = []byte{'t', 'r', 'u', 'e'} + JSON_FALSE = []byte{'f', 'a', 'l', 's', 'e'} + JSON_INFINITY = "Infinity" + JSON_NEGATIVE_INFINITY = "-Infinity" + JSON_NAN = "NaN" + JSON_INFINITY_BYTES = []byte{'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'} + JSON_NEGATIVE_INFINITY_BYTES = []byte{'-', 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'} + JSON_NAN_BYTES = []byte{'N', 'a', 'N'} + json_nonbase_map_elem_bytes = []byte{']', ',', '['} +} + +func jsonQuote(s string) string { + b, _ := json.Marshal(s) + s1 := string(b) + return s1 +} + +func jsonUnquote(s string) (string, bool) { + s1 := new(string) + err := json.Unmarshal([]byte(s), s1) + return *s1, err == nil +} + +func mismatch(expected, actual string) error { + return fmt.Errorf("Expected '%s' but found '%s' while parsing JSON.", expected, actual) +} + +func (p *TSimpleJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error { + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.WriteString(name); e != nil { + return e + } + if e := p.WriteByte(byte(typeId)); e != nil { + return e + } + if e := p.WriteI32(seqId); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) WriteMessageEnd() error { + return p.OutputListEnd() +} + +func (p *TSimpleJSONProtocol) WriteStructBegin(name string) error { + if e := p.OutputObjectBegin(); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) WriteStructEnd() error { + return p.OutputObjectEnd() +} + +func (p *TSimpleJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { + if e := p.WriteString(name); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) WriteFieldEnd() error { + //return p.OutputListEnd() + return nil +} + +func (p *TSimpleJSONProtocol) WriteFieldStop() error { return nil } + +func (p *TSimpleJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.WriteByte(byte(keyType)); e != nil { + return e + } + if e := p.WriteByte(byte(valueType)); e != nil { + return e + } + return p.WriteI32(int32(size)) +} + +func (p *TSimpleJSONProtocol) WriteMapEnd() error { + return p.OutputListEnd() +} + +func (p *TSimpleJSONProtocol) WriteListBegin(elemType TType, size int) error { + return p.OutputElemListBegin(elemType, size) +} + +func (p *TSimpleJSONProtocol) WriteListEnd() error { + return p.OutputListEnd() +} + +func (p *TSimpleJSONProtocol) WriteSetBegin(elemType TType, size int) error { + return p.OutputElemListBegin(elemType, size) +} + +func (p *TSimpleJSONProtocol) WriteSetEnd() error { + return p.OutputListEnd() +} + +func (p *TSimpleJSONProtocol) WriteBool(b bool) error { + return p.OutputBool(b) +} + +func (p *TSimpleJSONProtocol) WriteByte(b byte) error { + return p.WriteI32(int32(b)) +} + +func (p *TSimpleJSONProtocol) WriteI16(v int16) error { + return p.WriteI32(int32(v)) +} + +func (p *TSimpleJSONProtocol) WriteI32(v int32) error { + return p.OutputI64(int64(v)) +} + +func (p *TSimpleJSONProtocol) WriteI64(v int64) error { + return p.OutputI64(int64(v)) +} + +func (p *TSimpleJSONProtocol) WriteDouble(v float64) error { + return p.OutputF64(v) +} + +func (p *TSimpleJSONProtocol) WriteString(v string) error { + return p.OutputString(v) +} + +func (p *TSimpleJSONProtocol) WriteBinary(v []byte) error { + // JSON library only takes in a string, + // not an arbitrary byte array, to ensure bytes are transmitted + // efficiently we must convert this into a valid JSON string + // therefore we use base64 encoding to avoid excessive escaping/quoting + if e := p.OutputPreValue(); e != nil { + return e + } + if _, e := p.writer.Write(JSON_QUOTE_BYTES); e != nil { + return NewTProtocolException(e) + } + writer := base64.NewEncoder(base64.StdEncoding, p.writer) + if _, e := writer.Write(v); e != nil { + return NewTProtocolException(e) + } + if e := writer.Close(); e != nil { + return NewTProtocolException(e) + } + if _, e := p.writer.Write(JSON_QUOTE_BYTES); e != nil { + return NewTProtocolException(e) + } + return p.OutputPostValue() +} + +// Reading methods. + +func (p *TSimpleJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { + if isNull, err := p.ParseListBegin(); isNull || err != nil { + return name, typeId, seqId, err + } + if name, err = p.ReadString(); err != nil { + return name, typeId, seqId, err + } + bTypeId, err := p.ReadByte() + typeId = TMessageType(bTypeId) + if err != nil { + return name, typeId, seqId, err + } + if seqId, err = p.ReadI32(); err != nil { + return name, typeId, seqId, err + } + return name, typeId, seqId, nil +} + +func (p *TSimpleJSONProtocol) ReadMessageEnd() error { + return p.ParseListEnd() +} + +func (p *TSimpleJSONProtocol) ReadStructBegin() (name string, err error) { + _, err = p.ParseObjectStart() + return "", err +} + +func (p *TSimpleJSONProtocol) ReadStructEnd() error { + return p.ParseObjectEnd() +} + +func (p *TSimpleJSONProtocol) ReadFieldBegin() (string, TType, int16, error) { + if err := p.ParsePreValue(); err != nil { + return "", STOP, 0, err + } + if p.reader.Buffered() < 1 { + return "", STOP, 0, nil + } + b, _ := p.reader.Peek(1) + if len(b) > 0 { + switch b[0] { + case JSON_RBRACE[0]: + return "", STOP, 0, nil + case JSON_QUOTE: + p.reader.ReadByte() + name, err := p.ParseStringBody() + if err != nil { + return name, STOP, 0, err + } + return name, STOP, -1, p.ParsePostValue() + /* + if err = p.ParsePostValue(); err != nil { + return name, STOP, 0, err + } + if isNull, err := p.ParseListBegin(); isNull || err != nil { + return name, STOP, 0, err + } + bType, err := p.ReadByte() + thetype := TType(bType) + if err != nil { + return name, thetype, 0, err + } + id, err := p.ReadI16() + return name, thetype, id, err + */ + } + e := fmt.Errorf("Expected \"}\" or '\"', but found: '%s'", string(b)) + return "", STOP, 0, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return "", STOP, 0, NewTProtocolException(io.EOF) +} + +func (p *TSimpleJSONProtocol) ReadFieldEnd() error { + return nil + //return p.ParseListEnd() +} + +func (p *TSimpleJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e error) { + if isNull, e := p.ParseListBegin(); isNull || e != nil { + return VOID, VOID, 0, e + } + + // read keyType + bKeyType, e := p.ReadByte() + keyType = TType(bKeyType) + if e != nil { + return keyType, valueType, size, e + } + + // read valueType + bValueType, e := p.ReadByte() + valueType = TType(bValueType) + if e != nil { + return keyType, valueType, size, e + } + + // read size + iSize, err := p.ReadI64() + size = int(iSize) + return keyType, valueType, size, err +} + +func (p *TSimpleJSONProtocol) ReadMapEnd() error { + return p.ParseListEnd() +} + +func (p *TSimpleJSONProtocol) ReadListBegin() (elemType TType, size int, e error) { + return p.ParseElemListBegin() +} + +func (p *TSimpleJSONProtocol) ReadListEnd() error { + return p.ParseListEnd() +} + +func (p *TSimpleJSONProtocol) ReadSetBegin() (elemType TType, size int, e error) { + return p.ParseElemListBegin() +} + +func (p *TSimpleJSONProtocol) ReadSetEnd() error { + return p.ParseListEnd() +} + +func (p *TSimpleJSONProtocol) ReadBool() (bool, error) { + var value bool + if err := p.ParsePreValue(); err != nil { + return value, err + } + b, _ := p.reader.Peek(len(JSON_TRUE)) + if len(b) > 0 { + switch b[0] { + case JSON_TRUE[0]: + if string(b) == string(JSON_TRUE) { + p.reader.Read(b[0:len(JSON_TRUE)]) + value = true + } else { + e := fmt.Errorf("Expected \"true\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + break + case JSON_FALSE[0]: + if string(b) == string(JSON_FALSE[:len(b)]) { + p.reader.Read(b[0:len(JSON_FALSE)]) + value = false + } else { + e := fmt.Errorf("Expected \"false\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + break + case JSON_NULL[0]: + if string(b) == string(JSON_NULL) { + p.reader.Read(b[0:len(JSON_NULL)]) + value = false + } else { + e := fmt.Errorf("Expected \"null\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + default: + e := fmt.Errorf("Expected \"true\", \"false\", or \"null\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + return value, p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) ReadByte() (byte, error) { + v, err := p.ReadI64() + return byte(v), err +} + +func (p *TSimpleJSONProtocol) ReadI16() (int16, error) { + v, err := p.ReadI64() + return int16(v), err +} + +func (p *TSimpleJSONProtocol) ReadI32() (int32, error) { + v, err := p.ReadI64() + return int32(v), err +} + +func (p *TSimpleJSONProtocol) ReadI64() (int64, error) { + v, _, err := p.ParseI64() + return v, err +} + +func (p *TSimpleJSONProtocol) ReadDouble() (float64, error) { + v, _, err := p.ParseF64() + return v, err +} + +func (p *TSimpleJSONProtocol) ReadString() (string, error) { + var v string + if err := p.ParsePreValue(); err != nil { + return v, err + } + var b []byte + if p.reader.Buffered() >= len(JSON_NULL) { + b, _ = p.reader.Peek(len(JSON_NULL)) + } else { + b, _ = p.reader.Peek(1) + } + if len(b) > 0 && b[0] == JSON_QUOTE { + p.reader.ReadByte() + value, err := p.ParseStringBody() + v = value + if err != nil { + return v, err + } + } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { + _, err := p.reader.Read(b[0:len(JSON_NULL)]) + if err != nil { + return v, NewTProtocolException(err) + } + } else { + e := fmt.Errorf("Expected a JSON string, found %s", string(b)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return v, p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) ReadBinary() ([]byte, error) { + var v []byte + if err := p.ParsePreValue(); err != nil { + return nil, err + } + b, _ := p.reader.Peek(len(JSON_NULL)) + if len(b) > 0 && b[0] == JSON_QUOTE { + p.reader.ReadByte() + value, err := p.ParseBase64EncodedBody() + v = value + if err != nil { + return v, err + } + } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { + _, err := p.reader.Read(b[0:len(JSON_NULL)]) + if err != nil { + return v, NewTProtocolException(err) + } + } else { + e := fmt.Errorf("Expected a JSON string, found %s", string(b)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return v, p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) Flush() (err error) { + return NewTProtocolException(p.writer.Flush()) +} + +func (p *TSimpleJSONProtocol) Skip(fieldType TType) (err error) { + return SkipDefaultDepth(p, fieldType) +} + +func (p *TSimpleJSONProtocol) Transport() TTransport { + return p.trans +} + +func (p *TSimpleJSONProtocol) OutputPreValue() error { + cxt := _ParseContext(p.dumpContext[len(p.dumpContext)-1]) + switch cxt { + case _CONTEXT_IN_LIST, _CONTEXT_IN_OBJECT_NEXT_KEY: + if _, e := p.writer.Write(JSON_COMMA); e != nil { + return NewTProtocolException(e) + } + break + case _CONTEXT_IN_OBJECT_NEXT_VALUE: + if _, e := p.writer.Write(JSON_COLON); e != nil { + return NewTProtocolException(e) + } + break + } + return nil +} + +func (p *TSimpleJSONProtocol) OutputPostValue() error { + cxt := _ParseContext(p.dumpContext[len(p.dumpContext)-1]) + switch cxt { + case _CONTEXT_IN_LIST_FIRST: + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_LIST)) + break + case _CONTEXT_IN_OBJECT_FIRST: + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) + break + case _CONTEXT_IN_OBJECT_NEXT_KEY: + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) + break + case _CONTEXT_IN_OBJECT_NEXT_VALUE: + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_KEY)) + break + } + return nil +} + +func (p *TSimpleJSONProtocol) OutputBool(value bool) error { + if e := p.OutputPreValue(); e != nil { + return e + } + var v string + if value { + v = string(JSON_TRUE) + } else { + v = string(JSON_FALSE) + } + switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) { + case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: + v = jsonQuote(v) + default: + } + if e := p.OutputStringData(v); e != nil { + return e + } + return p.OutputPostValue() +} + +func (p *TSimpleJSONProtocol) OutputNull() error { + if e := p.OutputPreValue(); e != nil { + return e + } + if _, e := p.writer.Write(JSON_NULL); e != nil { + return NewTProtocolException(e) + } + return p.OutputPostValue() +} + +func (p *TSimpleJSONProtocol) OutputF64(value float64) error { + if e := p.OutputPreValue(); e != nil { + return e + } + var v string + if math.IsNaN(value) { + v = string(JSON_QUOTE) + JSON_NAN + string(JSON_QUOTE) + } else if math.IsInf(value, 1) { + v = string(JSON_QUOTE) + JSON_INFINITY + string(JSON_QUOTE) + } else if math.IsInf(value, -1) { + v = string(JSON_QUOTE) + JSON_NEGATIVE_INFINITY + string(JSON_QUOTE) + } else { + v = strconv.FormatFloat(value, 'g', -1, 64) + switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) { + case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: + v = string(JSON_QUOTE) + v + string(JSON_QUOTE) + default: + } + } + if e := p.OutputStringData(v); e != nil { + return e + } + return p.OutputPostValue() +} + +func (p *TSimpleJSONProtocol) OutputI64(value int64) error { + if e := p.OutputPreValue(); e != nil { + return e + } + v := strconv.FormatInt(value, 10) + switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) { + case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: + v = jsonQuote(v) + default: + } + if e := p.OutputStringData(v); e != nil { + return e + } + return p.OutputPostValue() +} + +func (p *TSimpleJSONProtocol) OutputString(s string) error { + if e := p.OutputPreValue(); e != nil { + return e + } + if e := p.OutputStringData(jsonQuote(s)); e != nil { + return e + } + return p.OutputPostValue() +} + +func (p *TSimpleJSONProtocol) OutputStringData(s string) error { + _, e := p.writer.Write([]byte(s)) + return NewTProtocolException(e) +} + +func (p *TSimpleJSONProtocol) OutputObjectBegin() error { + if e := p.OutputPreValue(); e != nil { + return e + } + if _, e := p.writer.Write(JSON_LBRACE); e != nil { + return NewTProtocolException(e) + } + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_FIRST)) + return nil +} + +func (p *TSimpleJSONProtocol) OutputObjectEnd() error { + if _, e := p.writer.Write(JSON_RBRACE); e != nil { + return NewTProtocolException(e) + } + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + if e := p.OutputPostValue(); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) OutputListBegin() error { + if e := p.OutputPreValue(); e != nil { + return e + } + if _, e := p.writer.Write(JSON_LBRACKET); e != nil { + return NewTProtocolException(e) + } + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_LIST_FIRST)) + return nil +} + +func (p *TSimpleJSONProtocol) OutputListEnd() error { + if _, e := p.writer.Write(JSON_RBRACKET); e != nil { + return NewTProtocolException(e) + } + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + if e := p.OutputPostValue(); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) OutputElemListBegin(elemType TType, size int) error { + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.WriteByte(byte(elemType)); e != nil { + return e + } + if e := p.WriteI64(int64(size)); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) ParsePreValue() error { + if e := p.readNonSignificantWhitespace(); e != nil { + return NewTProtocolException(e) + } + cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) + if p.reader.Buffered() < 1 { + return nil + } + b, _ := p.reader.Peek(1) + switch cxt { + case _CONTEXT_IN_LIST: + if len(b) > 0 { + switch b[0] { + case JSON_RBRACKET[0]: + return nil + case JSON_COMMA[0]: + p.reader.ReadByte() + if e := p.readNonSignificantWhitespace(); e != nil { + return NewTProtocolException(e) + } + return nil + default: + e := fmt.Errorf("Expected \"]\" or \",\" in list context, but found \"%s\"", string(b)) + return NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + break + case _CONTEXT_IN_OBJECT_NEXT_KEY: + if len(b) > 0 { + switch b[0] { + case JSON_RBRACE[0]: + return nil + case JSON_COMMA[0]: + p.reader.ReadByte() + if e := p.readNonSignificantWhitespace(); e != nil { + return NewTProtocolException(e) + } + return nil + default: + e := fmt.Errorf("Expected \"}\" or \",\" in object context, but found \"%s\"", string(b)) + return NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + break + case _CONTEXT_IN_OBJECT_NEXT_VALUE: + if len(b) > 0 { + switch b[0] { + case JSON_COLON[0]: + p.reader.ReadByte() + if e := p.readNonSignificantWhitespace(); e != nil { + return NewTProtocolException(e) + } + return nil + default: + e := fmt.Errorf("Expected \":\" in object context, but found \"%s\"", string(b)) + return NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + break + } + return nil +} + +func (p *TSimpleJSONProtocol) ParsePostValue() error { + if e := p.readNonSignificantWhitespace(); e != nil { + return NewTProtocolException(e) + } + cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) + switch cxt { + case _CONTEXT_IN_LIST_FIRST: + p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] + p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_LIST)) + break + case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: + p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] + p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) + break + case _CONTEXT_IN_OBJECT_NEXT_VALUE: + p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] + p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_NEXT_KEY)) + break + } + return nil +} + +func (p *TSimpleJSONProtocol) readNonSignificantWhitespace() error { + for p.reader.Buffered() > 0 { + b, _ := p.reader.Peek(1) + if len(b) < 1 { + return nil + } + switch b[0] { + case ' ', '\r', '\n', '\t': + p.reader.ReadByte() + continue + default: + break + } + break + } + return nil +} + +func (p *TSimpleJSONProtocol) ParseStringBody() (string, error) { + line, err := p.reader.ReadString(JSON_QUOTE) + if err != nil { + return "", NewTProtocolException(err) + } + l := len(line) + // count number of escapes to see if we need to keep going + i := 1 + for ; i < l; i++ { + if line[l-i-1] != '\\' { + break + } + } + if i&0x01 == 1 { + v, ok := jsonUnquote(string(JSON_QUOTE) + line) + if !ok { + return "", NewTProtocolException(err) + } + return v, nil + } + s, err := p.ParseQuotedStringBody() + if err != nil { + return "", NewTProtocolException(err) + } + str := string(JSON_QUOTE) + line + s + v, ok := jsonUnquote(str) + if !ok { + e := fmt.Errorf("Unable to parse as JSON string %s", str) + return "", NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return v, nil +} + +func (p *TSimpleJSONProtocol) ParseQuotedStringBody() (string, error) { + line, err := p.reader.ReadString(JSON_QUOTE) + if err != nil { + return "", NewTProtocolException(err) + } + l := len(line) + // count number of escapes to see if we need to keep going + i := 1 + for ; i < l; i++ { + if line[l-i-1] != '\\' { + break + } + } + if i&0x01 == 1 { + return line, nil + } + s, err := p.ParseQuotedStringBody() + if err != nil { + return "", NewTProtocolException(err) + } + v := line + s + return v, nil +} + +func (p *TSimpleJSONProtocol) ParseBase64EncodedBody() ([]byte, error) { + line, err := p.reader.ReadBytes(JSON_QUOTE) + if err != nil { + return line, NewTProtocolException(err) + } + line2 := line[0 : len(line)-1] + l := len(line2) + output := make([]byte, base64.StdEncoding.DecodedLen(l)) + n, err := base64.StdEncoding.Decode(output, line2) + return output[0:n], NewTProtocolException(err) +} + +func (p *TSimpleJSONProtocol) ParseI64() (int64, bool, error) { + if err := p.ParsePreValue(); err != nil { + return 0, false, err + } + var value int64 + var isnull bool + b, _ := p.reader.Peek(len(JSON_NULL)) + if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) { + p.reader.Read(b[0:len(JSON_NULL)]) + isnull = true + } else { + num, err := p.readNumeric() + isnull = (num == nil) + if !isnull { + value = num.Int64() + } + if err != nil { + return value, isnull, err + } + } + return value, isnull, p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) ParseF64() (float64, bool, error) { + if err := p.ParsePreValue(); err != nil { + return 0, false, err + } + var value float64 + var isnull bool + b, _ := p.reader.Peek(len(JSON_NULL)) + if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) { + p.reader.Read(b[0:len(JSON_NULL)]) + isnull = true + } else { + num, err := p.readNumeric() + isnull = (num == nil) + if !isnull { + value = num.Float64() + } + if err != nil { + return value, isnull, err + } + } + return value, isnull, p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) ParseObjectStart() (bool, error) { + if err := p.ParsePreValue(); err != nil { + return false, err + } + var b []byte + if p.reader.Buffered() >= len(JSON_NULL) { + b, _ = p.reader.Peek(len(JSON_NULL)) + } else if p.reader.Buffered() >= 1 { + b, _ = p.reader.Peek(1) + } + if len(b) > 0 && b[0] == JSON_LBRACE[0] { + p.reader.ReadByte() + p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_FIRST)) + return false, nil + } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { + return true, nil + } + e := fmt.Errorf("Expected '{' or null, but found '%s'", string(b)) + return false, NewTProtocolExceptionWithType(INVALID_DATA, e) +} + +func (p *TSimpleJSONProtocol) ParseObjectEnd() error { + if isNull, err := p.readIfNull(); isNull || err != nil { + return err + } + cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) + if cxt != _CONTEXT_IN_OBJECT_FIRST && cxt != _CONTEXT_IN_OBJECT_NEXT_KEY { + e := fmt.Errorf("Expected to be in the Object Context, but not in Object Context") + return NewTProtocolExceptionWithType(INVALID_DATA, e) + } + line, err := p.reader.ReadString(JSON_RBRACE[0]) + if err != nil { + return NewTProtocolException(err) + } + for _, char := range line { + switch char { + default: + e := fmt.Errorf("Expecting end of object \"}\", but found: \"%s\"", line) + return NewTProtocolExceptionWithType(INVALID_DATA, e) + case ' ', '\n', '\r', '\t', '}': + break + } + } + p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] + return p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) ParseListBegin() (isNull bool, err error) { + if e := p.ParsePreValue(); e != nil { + return false, e + } + var b []byte + if p.reader.Buffered() >= len(JSON_NULL) { + b, err = p.reader.Peek(len(JSON_NULL)) + } else { + b, err = p.reader.Peek(1) + } + if err != nil { + return false, err + } + if len(b) >= 1 && b[0] == JSON_LBRACKET[0] { + p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_LIST_FIRST)) + p.reader.ReadByte() + isNull = false + } else if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) { + isNull = true + } else { + err = fmt.Errorf("Expected \"null\" or \"[\", received %q", b) + } + return isNull, NewTProtocolExceptionWithType(INVALID_DATA, err) +} + +func (p *TSimpleJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) { + if isNull, e := p.ParseListBegin(); isNull || e != nil { + return VOID, 0, e + } + bElemType, err := p.ReadByte() + elemType = TType(bElemType) + if err != nil { + return elemType, size, err + } + nSize, err2 := p.ReadI64() + size = int(nSize) + return elemType, size, err2 +} + +func (p *TSimpleJSONProtocol) ParseListEnd() error { + if isNull, err := p.readIfNull(); isNull || err != nil { + return err + } + if _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) != _CONTEXT_IN_LIST { + e := fmt.Errorf("Expected to be in the List Context, but not in List Context") + return NewTProtocolExceptionWithType(INVALID_DATA, e) + } + line, err := p.reader.ReadString(JSON_RBRACKET[0]) + if err != nil { + return NewTProtocolException(err) + } + for _, char := range line { + switch char { + default: + e := fmt.Errorf("Expecting end of list \"]\", but found: \"", line, "\"") + return NewTProtocolExceptionWithType(INVALID_DATA, e) + case ' ', '\n', '\r', '\t', rune(JSON_RBRACKET[0]): + break + } + } + p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] + return p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) readSingleValue() (interface{}, TType, error) { + e := p.readNonSignificantWhitespace() + if e != nil { + return nil, VOID, NewTProtocolException(e) + } + b, e := p.reader.Peek(10) + if len(b) > 0 { + c := b[0] + switch c { + case JSON_NULL[0]: + buf := make([]byte, len(JSON_NULL)) + _, e := p.reader.Read(buf) + if e != nil { + return nil, VOID, NewTProtocolException(e) + } + if string(JSON_NULL) != string(buf) { + e = mismatch(string(JSON_NULL), string(buf)) + return nil, VOID, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return nil, VOID, nil + case JSON_QUOTE: + p.reader.ReadByte() + v, e := p.ParseStringBody() + if e != nil { + return v, UTF8, NewTProtocolException(e) + } + if v == JSON_INFINITY { + return INFINITY, DOUBLE, nil + } else if v == JSON_NEGATIVE_INFINITY { + return NEGATIVE_INFINITY, DOUBLE, nil + } else if v == JSON_NAN { + return NAN, DOUBLE, nil + } + return v, UTF8, nil + case JSON_TRUE[0]: + buf := make([]byte, len(JSON_TRUE)) + _, e := p.reader.Read(buf) + if e != nil { + return true, BOOL, NewTProtocolException(e) + } + if string(JSON_TRUE) != string(buf) { + e := mismatch(string(JSON_TRUE), string(buf)) + return true, BOOL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return true, BOOL, nil + case JSON_FALSE[0]: + buf := make([]byte, len(JSON_FALSE)) + _, e := p.reader.Read(buf) + if e != nil { + return false, BOOL, NewTProtocolException(e) + } + if string(JSON_FALSE) != string(buf) { + e := mismatch(string(JSON_FALSE), string(buf)) + return false, BOOL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return false, BOOL, nil + case JSON_LBRACKET[0]: + _, e := p.reader.ReadByte() + return make([]interface{}, 0), LIST, NewTProtocolException(e) + case JSON_LBRACE[0]: + _, e := p.reader.ReadByte() + return make(map[string]interface{}), STRUCT, NewTProtocolException(e) + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E', '.', '+', '-', JSON_INFINITY[0], JSON_NAN[0]: + // assume numeric + v, e := p.readNumeric() + return v, DOUBLE, e + default: + e := fmt.Errorf("Expected element in list but found '%s' while parsing JSON.", string(c)) + return nil, VOID, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + e = fmt.Errorf("Cannot read a single element while parsing JSON.") + return nil, VOID, NewTProtocolExceptionWithType(INVALID_DATA, e) + +} + +func (p *TSimpleJSONProtocol) readIfNull() (bool, error) { + cont := true + for p.reader.Buffered() > 0 && cont { + b, _ := p.reader.Peek(1) + if len(b) < 1 { + return false, nil + } + switch b[0] { + default: + return false, nil + case JSON_NULL[0]: + cont = false + break + case ' ', '\n', '\r', '\t': + p.reader.ReadByte() + break + } + } + if p.reader.Buffered() == 0 { + return false, nil + } + b, _ := p.reader.Peek(len(JSON_NULL)) + if string(b) == string(JSON_NULL) { + p.reader.Read(b[0:len(JSON_NULL)]) + return true, nil + } + return false, nil +} + +func (p *TSimpleJSONProtocol) readQuoteIfNext() { + if p.reader.Buffered() < 1 { + return + } + b, _ := p.reader.Peek(1) + if len(b) > 0 && b[0] == JSON_QUOTE { + p.reader.ReadByte() + } +} + +func (p *TSimpleJSONProtocol) readNumeric() (Numeric, error) { + isNull, err := p.readIfNull() + if isNull || err != nil { + return NUMERIC_NULL, err + } + hasDecimalPoint := false + nextCanBeSign := true + hasE := false + MAX_LEN := 40 + buf := bytes.NewBuffer(make([]byte, 0, MAX_LEN)) + continueFor := true + inQuotes := false + for continueFor { + c, err := p.reader.ReadByte() + if err != nil { + if err == io.EOF { + break + } + return NUMERIC_NULL, NewTProtocolException(err) + } + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + buf.WriteByte(c) + nextCanBeSign = false + case '.': + if hasDecimalPoint { + e := fmt.Errorf("Unable to parse number with multiple decimal points '%s.'", buf.String()) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + if hasE { + e := fmt.Errorf("Unable to parse number with decimal points in the exponent '%s.'", buf.String()) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + buf.WriteByte(c) + hasDecimalPoint, nextCanBeSign = true, false + case 'e', 'E': + if hasE { + e := fmt.Errorf("Unable to parse number with multiple exponents '%s%c'", buf.String(), c) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + buf.WriteByte(c) + hasE, nextCanBeSign = true, true + case '-', '+': + if !nextCanBeSign { + e := fmt.Errorf("Negative sign within number") + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + buf.WriteByte(c) + nextCanBeSign = false + case ' ', 0, '\t', '\n', '\r', JSON_RBRACE[0], JSON_RBRACKET[0], JSON_COMMA[0], JSON_COLON[0]: + p.reader.UnreadByte() + continueFor = false + case JSON_NAN[0]: + if buf.Len() == 0 { + buffer := make([]byte, len(JSON_NAN)) + buffer[0] = c + _, e := p.reader.Read(buffer[1:]) + if e != nil { + return NUMERIC_NULL, NewTProtocolException(e) + } + if JSON_NAN != string(buffer) { + e := mismatch(JSON_NAN, string(buffer)) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + if inQuotes { + p.readQuoteIfNext() + } + return NAN, nil + } else { + e := fmt.Errorf("Unable to parse number starting with character '%c'", c) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + case JSON_INFINITY[0]: + if buf.Len() == 0 || (buf.Len() == 1 && buf.Bytes()[0] == '+') { + buffer := make([]byte, len(JSON_INFINITY)) + buffer[0] = c + _, e := p.reader.Read(buffer[1:]) + if e != nil { + return NUMERIC_NULL, NewTProtocolException(e) + } + if JSON_INFINITY != string(buffer) { + e := mismatch(JSON_INFINITY, string(buffer)) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + if inQuotes { + p.readQuoteIfNext() + } + return INFINITY, nil + } else if buf.Len() == 1 && buf.Bytes()[0] == JSON_NEGATIVE_INFINITY[0] { + buffer := make([]byte, len(JSON_NEGATIVE_INFINITY)) + buffer[0] = JSON_NEGATIVE_INFINITY[0] + buffer[1] = c + _, e := p.reader.Read(buffer[2:]) + if e != nil { + return NUMERIC_NULL, NewTProtocolException(e) + } + if JSON_NEGATIVE_INFINITY != string(buffer) { + e := mismatch(JSON_NEGATIVE_INFINITY, string(buffer)) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + if inQuotes { + p.readQuoteIfNext() + } + return NEGATIVE_INFINITY, nil + } else { + e := fmt.Errorf("Unable to parse number starting with character '%c' due to existing buffer %s", c, buf.String()) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + case JSON_QUOTE: + if !inQuotes { + inQuotes = true + } else { + break + } + default: + e := fmt.Errorf("Unable to parse number starting with character '%c'", c) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + if buf.Len() == 0 { + e := fmt.Errorf("Unable to parse number from empty string ''") + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return NewNumericFromJSONString(buf.String(), false), nil +} diff --git a/lib/go/thrift/simple_json_protocol_test.go b/lib/go/thrift/simple_json_protocol_test.go new file mode 100644 index 00000000..87a5c64b --- /dev/null +++ b/lib/go/thrift/simple_json_protocol_test.go @@ -0,0 +1,632 @@ +/* + * 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 thrift + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "math" + "strconv" + "strings" + "testing" +) + +func TestWriteSimpleJSONProtocolBool(t *testing.T) { + thetype := "boolean" + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + for _, value := range BOOL_VALUES { + if e := p.WriteBool(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := false + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadSimpleJSONProtocolBool(t *testing.T) { + thetype := "boolean" + for _, value := range BOOL_VALUES { + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + if value { + trans.Write(JSON_TRUE) + } else { + trans.Write(JSON_FALSE) + } + trans.Flush() + s := trans.String() + v, e := p.ReadBool() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteSimpleJSONProtocolByte(t *testing.T) { + thetype := "byte" + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + for _, value := range BYTE_VALUES { + if e := p.WriteByte(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := byte(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadSimpleJSONProtocolByte(t *testing.T) { + thetype := "byte" + for _, value := range BYTE_VALUES { + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + trans.WriteString(strconv.Itoa(int(value))) + trans.Flush() + s := trans.String() + v, e := p.ReadByte() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteSimpleJSONProtocolI16(t *testing.T) { + thetype := "int16" + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + for _, value := range INT16_VALUES { + if e := p.WriteI16(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := int16(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadSimpleJSONProtocolI16(t *testing.T) { + thetype := "int16" + for _, value := range INT16_VALUES { + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + trans.WriteString(strconv.Itoa(int(value))) + trans.Flush() + s := trans.String() + v, e := p.ReadI16() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteSimpleJSONProtocolI32(t *testing.T) { + thetype := "int32" + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + for _, value := range INT32_VALUES { + if e := p.WriteI32(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := int32(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadSimpleJSONProtocolI32(t *testing.T) { + thetype := "int32" + for _, value := range INT32_VALUES { + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + trans.WriteString(strconv.Itoa(int(value))) + trans.Flush() + s := trans.String() + v, e := p.ReadI32() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteSimpleJSONProtocolI64(t *testing.T) { + thetype := "int64" + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + for _, value := range INT64_VALUES { + if e := p.WriteI64(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := int64(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadSimpleJSONProtocolI64(t *testing.T) { + thetype := "int64" + for _, value := range INT64_VALUES { + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + trans.WriteString(strconv.FormatInt(value, 10)) + trans.Flush() + s := trans.String() + v, e := p.ReadI64() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteSimpleJSONProtocolDouble(t *testing.T) { + thetype := "double" + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + for _, value := range DOUBLE_VALUES { + if e := p.WriteDouble(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if math.IsInf(value, 1) { + if s != jsonQuote(JSON_INFINITY) { + t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_INFINITY)) + } + } else if math.IsInf(value, -1) { + if s != jsonQuote(JSON_NEGATIVE_INFINITY) { + t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_NEGATIVE_INFINITY)) + } + } else if math.IsNaN(value) { + if s != jsonQuote(JSON_NAN) { + t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_NAN)) + } + } else { + if s != fmt.Sprint(value) { + t.Fatalf("Bad value for %s %v: %s", thetype, value, s) + } + v := float64(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + } + trans.Reset() + } + trans.Close() +} + +func TestReadSimpleJSONProtocolDouble(t *testing.T) { + thetype := "double" + for _, value := range DOUBLE_VALUES { + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + n := NewNumericFromDouble(value) + trans.WriteString(n.String()) + trans.Flush() + s := trans.String() + v, e := p.ReadDouble() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if math.IsInf(value, 1) { + if !math.IsInf(v, 1) { + t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) + } + } else if math.IsInf(value, -1) { + if !math.IsInf(v, -1) { + t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) + } + } else if math.IsNaN(value) { + if !math.IsNaN(v) { + t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) + } + } else { + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + } + trans.Reset() + trans.Close() + } +} + +func TestWriteSimpleJSONProtocolString(t *testing.T) { + thetype := "string" + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + for _, value := range STRING_VALUES { + if e := p.WriteString(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s[0] != '"' || s[len(s)-1] != '"' { + t.Fatalf("Bad value for %s '%v', wrote '%v', expected: %v", thetype, value, s, fmt.Sprint("\"", value, "\"")) + } + v := new(string) + if err := json.Unmarshal([]byte(s), v); err != nil || *v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v) + } + trans.Reset() + } + trans.Close() +} + +func TestReadSimpleJSONProtocolString(t *testing.T) { + thetype := "string" + for _, value := range STRING_VALUES { + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + trans.WriteString(jsonQuote(value)) + trans.Flush() + s := trans.String() + v, e := p.ReadString() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if v != value { + t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) + } + v1 := new(string) + if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) + } + trans.Reset() + trans.Close() + } +} + +func TestWriteSimpleJSONProtocolBinary(t *testing.T) { + thetype := "binary" + value := protocol_bdata + b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) + base64.StdEncoding.Encode(b64value, value) + b64String := string(b64value) + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + if e := p.WriteBinary(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) + } + s := trans.String() + if s != fmt.Sprint("\"", b64String, "\"") { + t.Fatalf("Bad value for %s %v\n wrote: %v\nexpected: %v", thetype, value, s, "\""+b64String+"\"") + } + v1 := new(string) + if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) + } + trans.Close() +} + +func TestReadSimpleJSONProtocolBinary(t *testing.T) { + thetype := "binary" + value := protocol_bdata + b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) + base64.StdEncoding.Encode(b64value, value) + b64String := string(b64value) + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + trans.WriteString(jsonQuote(b64String)) + trans.Flush() + s := trans.String() + v, e := p.ReadBinary() + if e != nil { + t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) + } + if len(v) != len(value) { + t.Fatalf("Bad value for %s value length %v, wrote: %v, received length: %v", thetype, len(value), s, len(v)) + } + for i := 0; i < len(v); i++ { + if v[i] != value[i] { + t.Fatalf("Bad value for %s at index %d value %v, wrote: %v, received: %v", thetype, i, value[i], s, v[i]) + } + } + v1 := new(string) + if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) + } + trans.Reset() + trans.Close() +} + +func TestWriteSimpleJSONProtocolList(t *testing.T) { + thetype := "list" + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + p.WriteListBegin(TType(DOUBLE), len(DOUBLE_VALUES)) + for _, value := range DOUBLE_VALUES { + if e := p.WriteDouble(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + } + p.WriteListEnd() + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) + } + str := trans.String() + str1 := new([]interface{}) + err := json.Unmarshal([]byte(str), str1) + if err != nil { + t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) + } + l := *str1 + if len(l) < 2 { + t.Fatalf("List must be at least of length two to include metadata") + } + if int(l[0].(float64)) != DOUBLE { + t.Fatal("Invalid type for list, expected: ", DOUBLE, ", but was: ", l[0]) + } + if int(l[1].(float64)) != len(DOUBLE_VALUES) { + t.Fatal("Invalid length for list, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) + } + for k, value := range DOUBLE_VALUES { + s := l[k+2] + if math.IsInf(value, 1) { + if s.(string) != JSON_INFINITY { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_INFINITY), str) + } + } else if math.IsInf(value, 0) { + if s.(string) != JSON_NEGATIVE_INFINITY { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY), str) + } + } else if math.IsNaN(value) { + if s.(string) != JSON_NAN { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NAN), str) + } + } else { + if s.(float64) != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) + } + } + trans.Reset() + } + trans.Close() +} + +func TestWriteSimpleJSONProtocolSet(t *testing.T) { + thetype := "set" + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + p.WriteSetBegin(TType(DOUBLE), len(DOUBLE_VALUES)) + for _, value := range DOUBLE_VALUES { + if e := p.WriteDouble(value); e != nil { + t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) + } + } + p.WriteSetEnd() + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) + } + str := trans.String() + str1 := new([]interface{}) + err := json.Unmarshal([]byte(str), str1) + if err != nil { + t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) + } + l := *str1 + if len(l) < 2 { + t.Fatalf("Set must be at least of length two to include metadata") + } + if int(l[0].(float64)) != DOUBLE { + t.Fatal("Invalid type for set, expected: ", DOUBLE, ", but was: ", l[0]) + } + if int(l[1].(float64)) != len(DOUBLE_VALUES) { + t.Fatal("Invalid length for set, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) + } + for k, value := range DOUBLE_VALUES { + s := l[k+2] + if math.IsInf(value, 1) { + if s.(string) != JSON_INFINITY { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_INFINITY), str) + } + } else if math.IsInf(value, 0) { + if s.(string) != JSON_NEGATIVE_INFINITY { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY), str) + } + } else if math.IsNaN(value) { + if s.(string) != JSON_NAN { + t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NAN), str) + } + } else { + if s.(float64) != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) + } + } + trans.Reset() + } + trans.Close() +} + +func TestWriteSimpleJSONProtocolMap(t *testing.T) { + thetype := "map" + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + p.WriteMapBegin(TType(I32), TType(DOUBLE), len(DOUBLE_VALUES)) + for k, value := range DOUBLE_VALUES { + if e := p.WriteI32(int32(k)); e != nil { + t.Fatalf("Unable to write %s key int32 value %v due to error: %s", thetype, k, e.Error()) + } + if e := p.WriteDouble(value); e != nil { + t.Fatalf("Unable to write %s value float64 value %v due to error: %s", thetype, value, e.Error()) + } + } + p.WriteMapEnd() + if e := p.Flush(); e != nil { + t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) + } + str := trans.String() + if str[0] != '[' || str[len(str)-1] != ']' { + t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES) + } + l := strings.Split(str[1:len(str)-1], ",") + if len(l) < 3 { + t.Fatal("Expected list of at least length 3 for map for metadata, but was of length ", len(l)) + } + expectedKeyType, _ := strconv.Atoi(l[0]) + expectedValueType, _ := strconv.Atoi(l[1]) + expectedSize, _ := strconv.Atoi(l[2]) + if expectedKeyType != I32 { + t.Fatal("Expected map key type ", I32, ", but was ", l[0]) + } + if expectedValueType != DOUBLE { + t.Fatal("Expected map value type ", DOUBLE, ", but was ", l[1]) + } + if expectedSize != len(DOUBLE_VALUES) { + t.Fatal("Expected map size of ", len(DOUBLE_VALUES), ", but was ", l[2]) + } + for k, value := range DOUBLE_VALUES { + strk := l[k*2+3] + strv := l[k*2+4] + ik, err := strconv.Atoi(strk) + if err != nil { + t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, strk, string(k), err.Error()) + } + if ik != k { + t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v", thetype, k, strk, k) + } + s := strv + if math.IsInf(value, 1) { + if s != jsonQuote(JSON_INFINITY) { + t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_INFINITY)) + } + } else if math.IsInf(value, 0) { + if s != jsonQuote(JSON_NEGATIVE_INFINITY) { + t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY)) + } + } else if math.IsNaN(value) { + if s != jsonQuote(JSON_NAN) { + t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_NAN)) + } + } else { + expected := strconv.FormatFloat(value, 'g', 10, 64) + if s != expected { + t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected %v", thetype, k, value, s, expected) + } + v := float64(0) + if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { + t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) + } + } + trans.Reset() + } + trans.Close() +} diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go new file mode 100644 index 00000000..17be8d8d --- /dev/null +++ b/lib/go/thrift/simple_server.go @@ -0,0 +1,164 @@ +/* + * 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 thrift + +import ( + "log" +) + +// Simple, non-concurrent server for testing. +type TSimpleServer struct { + stopped bool + + processorFactory TProcessorFactory + serverTransport TServerTransport + inputTransportFactory TTransportFactory + outputTransportFactory TTransportFactory + inputProtocolFactory TProtocolFactory + outputProtocolFactory TProtocolFactory +} + +func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer { + return NewTSimpleServerFactory2(NewTProcessorFactory(processor), serverTransport) +} + +func NewTSimpleServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer { + return NewTSimpleServerFactory4(NewTProcessorFactory(processor), + serverTransport, + transportFactory, + protocolFactory, + ) +} + +func NewTSimpleServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer { + return NewTSimpleServerFactory6(NewTProcessorFactory(processor), + serverTransport, + inputTransportFactory, + outputTransportFactory, + inputProtocolFactory, + outputProtocolFactory, + ) +} + +func NewTSimpleServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TSimpleServer { + return NewTSimpleServerFactory6(processorFactory, + serverTransport, + NewTTransportFactory(), + NewTTransportFactory(), + NewTBinaryProtocolFactoryDefault(), + NewTBinaryProtocolFactoryDefault(), + ) +} + +func NewTSimpleServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer { + return NewTSimpleServerFactory6(processorFactory, + serverTransport, + transportFactory, + transportFactory, + protocolFactory, + protocolFactory, + ) +} + +func NewTSimpleServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer { + return &TSimpleServer{processorFactory: processorFactory, + serverTransport: serverTransport, + inputTransportFactory: inputTransportFactory, + outputTransportFactory: outputTransportFactory, + inputProtocolFactory: inputProtocolFactory, + outputProtocolFactory: outputProtocolFactory, + } +} + +func (p *TSimpleServer) ProcessorFactory() TProcessorFactory { + return p.processorFactory +} + +func (p *TSimpleServer) ServerTransport() TServerTransport { + return p.serverTransport +} + +func (p *TSimpleServer) InputTransportFactory() TTransportFactory { + return p.inputTransportFactory +} + +func (p *TSimpleServer) OutputTransportFactory() TTransportFactory { + return p.outputTransportFactory +} + +func (p *TSimpleServer) InputProtocolFactory() TProtocolFactory { + return p.inputProtocolFactory +} + +func (p *TSimpleServer) OutputProtocolFactory() TProtocolFactory { + return p.outputProtocolFactory +} + +func (p *TSimpleServer) Serve() error { + p.stopped = false + err := p.serverTransport.Listen() + if err != nil { + return err + } + for !p.stopped { + client, err := p.serverTransport.Accept() + if err != nil { + return err + } + if client != nil { + if err := p.processRequest(client); err != nil { + log.Println("error processing request:", err) + } + } + } + return nil +} + +func (p *TSimpleServer) Stop() error { + p.stopped = true + p.serverTransport.Interrupt() + return nil +} + +func (p *TSimpleServer) processRequest(client TTransport) error { + processor := p.processorFactory.GetProcessor(client) + inputTransport := p.inputTransportFactory.GetTransport(client) + outputTransport := p.outputTransportFactory.GetTransport(client) + inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport) + outputProtocol := p.outputProtocolFactory.GetProtocol(outputTransport) + if inputTransport != nil { + defer inputTransport.Close() + } + if outputTransport != nil { + defer outputTransport.Close() + } + for { + ok, err := processor.Process(inputProtocol, outputProtocol) + if err, ok := err.(TTransportException); ok && err.TypeId() == END_OF_FILE{ + return nil + } else if err != nil { + return err + } + if !ok || !inputProtocol.Transport().Peek() { + break + } + } + return nil +} diff --git a/lib/go/thrift/socket.go b/lib/go/thrift/socket.go new file mode 100644 index 00000000..a381ea25 --- /dev/null +++ b/lib/go/thrift/socket.go @@ -0,0 +1,159 @@ +/* + * 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 thrift + +import ( + "net" + "time" +) + +type TSocket struct { + conn net.Conn + addr net.Addr + timeout time.Duration +} + +// NewTSocket creates a net.Conn-backed TTransport, given a host and port +// +// Example: +// trans, err := thrift.NewTSocket("localhost:9090") +func NewTSocket(hostPort string) (*TSocket, error) { + return NewTSocketTimeout(hostPort, 0) +} + +// NewTSocketTimeout creates a net.Conn-backed TTransport, given a host and port +// it also accepts a timeout as a time.Duration +func NewTSocketTimeout(hostPort string, timeout time.Duration) (*TSocket, error) { + //conn, err := net.DialTimeout(network, address, timeout) + addr, err := net.ResolveTCPAddr("tcp", hostPort) + if err != nil { + return nil, err + } + return NewTSocketFromAddrTimeout(addr, timeout), nil +} + +// Creates a TSocket from a net.Addr +func NewTSocketFromAddrTimeout(addr net.Addr, timeout time.Duration) *TSocket { + return &TSocket{addr: addr, timeout: timeout} +} + +// Creates a TSocket from an existing net.Conn +func NewTSocketFromConnTimeout(conn net.Conn, timeout time.Duration) *TSocket { + return &TSocket{conn: conn, addr: conn.RemoteAddr(), timeout: timeout} +} + +// Sets the socket timeout +func (p *TSocket) SetTimeout(timeout time.Duration) error { + p.timeout = timeout + return nil +} + +func (p *TSocket) pushDeadline(read, write bool) { + var t time.Time + if p.timeout > 0 { + t = time.Now().Add(time.Duration(p.timeout)) + } + if read && write { + p.conn.SetDeadline(t) + } else if read { + p.conn.SetReadDeadline(t) + } else if write { + p.conn.SetWriteDeadline(t) + } +} + +// Connects the socket, creating a new socket object if necessary. +func (p *TSocket) Open() error { + if p.IsOpen() { + return NewTTransportException(ALREADY_OPEN, "Socket already connected.") + } + if p.addr == nil { + return NewTTransportException(NOT_OPEN, "Cannot open nil address.") + } + if len(p.addr.Network()) == 0 { + return NewTTransportException(NOT_OPEN, "Cannot open bad network name.") + } + if len(p.addr.String()) == 0 { + return NewTTransportException(NOT_OPEN, "Cannot open bad address.") + } + var err error + if p.conn, err = net.DialTimeout(p.addr.Network(), p.addr.String(), p.timeout); err != nil { + return NewTTransportException(NOT_OPEN, err.Error()) + } + return nil +} + +// Retreive the underlying net.Conn +func (p *TSocket) Conn() net.Conn { + return p.conn +} + +// Returns true if the connection is open +func (p *TSocket) IsOpen() bool { + if p.conn == nil { + return false + } + return true +} + +// Closes the socket. +func (p *TSocket) Close() error { + // Close the socket + if p.conn != nil { + err := p.conn.Close() + if err != nil { + return err + } + p.conn = nil + } + return nil +} + +func (p *TSocket) Read(buf []byte) (int, error) { + if !p.IsOpen() { + return 0, NewTTransportException(NOT_OPEN, "Connection not open") + } + p.pushDeadline(true, false) + n, err := p.conn.Read(buf) + return n, NewTTransportExceptionFromError(err) +} + +func (p *TSocket) Write(buf []byte) (int, error) { + if !p.IsOpen() { + return 0, NewTTransportException(NOT_OPEN, "Connection not open") + } + p.pushDeadline(false, true) + return p.conn.Write(buf) +} + +func (p *TSocket) Peek() bool { + return p.IsOpen() +} + +func (p *TSocket) Flush() error { + return nil +} + +func (p *TSocket) Interrupt() error { + if !p.IsOpen() { + return nil + } + return p.conn.Close() +} diff --git a/lib/go/thrift/tapplication_exception.go b/lib/go/thrift/tapplication_exception.go deleted file mode 100644 index 6b7a75d5..00000000 --- a/lib/go/thrift/tapplication_exception.go +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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 thrift - -import ( - "os" -) - -const ( - UNKNOWN_APPLICATION_EXCEPTION = 0 - UNKNOWN_METHOD = 1 - INVALID_MESSAGE_TYPE_EXCEPTION = 2 - WRONG_METHOD_NAME = 3 - BAD_SEQUENCE_ID = 4 - MISSING_RESULT = 5 - INTERNAL_ERROR = 6 - PROTOCOL_ERROR = 7 - INVALID_TRANSFORM = 8 - INVALID_PROTOCOL = 9 - UNSUPPORTED_CLIENT_TYPE = 10 -) - - -/** - * Application level exception - * - */ -type TApplicationException interface { - TException - TypeId() int32 - Read(iprot TProtocol) (TApplicationException, os.Error) - Write(oprot TProtocol) os.Error -} - -type tApplicationException struct { - TException - type_ int32 -} - -func NewTApplicationExceptionDefault() TApplicationException { - return NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, "UNKNOWN") -} - -func NewTApplicationExceptionType(type_ int32) TApplicationException { - return NewTApplicationException(type_, "UNKNOWN") -} - -func NewTApplicationException(type_ int32, message string) TApplicationException { - return &tApplicationException{TException: NewTException(message), type_: type_} -} - -func NewTApplicationExceptionMessage(message string) TApplicationException { - return NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, message) -} - -func (p *tApplicationException) TypeId() int32 { - return p.type_ -} - -func (p *tApplicationException) Read(iprot TProtocol) (error TApplicationException, err os.Error) { - _, err = iprot.ReadStructBegin() - if err != nil { - return - } - - message := "" - type_ := int32(UNKNOWN_APPLICATION_EXCEPTION) - - for { - _, ttype, id, err := iprot.ReadFieldBegin() - if err != nil { - return - } - if ttype == STOP { - break - } - switch id { - case 1: - if ttype == STRING { - message, err = iprot.ReadString() - if err != nil { - return - } - } else { - err = SkipDefaultDepth(iprot, ttype) - if err != nil { - return - } - } - break - case 2: - if ttype == I32 { - type_, err = iprot.ReadI32() - if err != nil { - return - } - } else { - err = SkipDefaultDepth(iprot, ttype) - if err != nil { - return - } - } - break - default: - err = SkipDefaultDepth(iprot, ttype) - if err != nil { - return - } - break - } - err = iprot.ReadFieldEnd() - if err != nil { - return - } - } - err = iprot.ReadStructEnd() - error = NewTApplicationException(type_, message) - return -} - -func (p *tApplicationException) Write(oprot TProtocol) (err os.Error) { - err = oprot.WriteStructBegin("TApplicationException") - if len(p.String()) > 0 { - err = oprot.WriteFieldBegin("message", STRING, 1) - if err != nil { - return - } - err = oprot.WriteString(p.String()) - if err != nil { - return - } - err = oprot.WriteFieldEnd() - if err != nil { - return - } - } - err = oprot.WriteFieldBegin("type", I32, 2) - if err != nil { - return - } - err = oprot.WriteI32(p.type_) - if err != nil { - return - } - err = oprot.WriteFieldEnd() - if err != nil { - return - } - err = oprot.WriteFieldStop() - if err != nil { - return - } - err = oprot.WriteStructEnd() - return -} diff --git a/lib/go/thrift/tbase.go b/lib/go/thrift/tbase.go deleted file mode 100644 index adc52d00..00000000 --- a/lib/go/thrift/tbase.go +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 thrift - -/** - * Generic base interface for generated Thrift objects. - * - */ -type TBase interface { - - /** - * Reads the TObject from the given input protocol - * - * @param iprot Input protocol - */ - Read(iprot TProtocol) (err TException) - - /** - * Writes the objects out to the protocol - * - * @param oprot Output protocol - */ - Write(oprot TProtocol) (err TException) - - /** - * Check if a field is currently set or unset. - * - * @param field - */ - IsSet(field TField) bool - - /** - * Get a field's value by field variable. Primitive types will be wrapped in - * the appropriate "boxed" types. - * - * @param field - */ - FieldValue(field TField) interface{} - - /** - * Set a field's value by field variable. Primitive types must be "boxed" in - * the appropriate object wrapper type. - * - * @param field - */ - SetFieldValue(field TField, value interface{}) - - DeepCopy() TBase -} diff --git a/lib/go/thrift/tbinary_protocol.go b/lib/go/thrift/tbinary_protocol.go deleted file mode 100644 index 1c88da64..00000000 --- a/lib/go/thrift/tbinary_protocol.go +++ /dev/null @@ -1,493 +0,0 @@ -/* - * 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 thrift - -import ( - "encoding/binary" - "math" - "strings" - "io" -) - -type TBinaryProtocol struct { - //TProtocolBase; - trans TTransport - _StrictRead bool - _StrictWrite bool - _ReadLength int - _CheckReadLength bool -} - -type TBinaryProtocolFactory struct { - _StrictRead bool - _StrictWrite bool -} - -func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol { - return NewTBinaryProtocol(t, false, true) -} - -func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol { - //return &TBinaryProtocol{TProtocolBase:TProtocolBase{trans:t}, _StrictRead:strictRead, _StrictWrite:strictWrite, _ReadLength:0, _CheckReadLength:false}; - return &TBinaryProtocol{trans: t, _StrictRead: strictRead, _StrictWrite: strictWrite, _ReadLength: 0, _CheckReadLength: false} -} - -func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory { - return NewTBinaryProtocolFactory(false, true) -} - -func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory { - return &TBinaryProtocolFactory{_StrictRead: strictRead, _StrictWrite: strictWrite} -} - -func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol { - return NewTBinaryProtocol(t, p._StrictRead, p._StrictWrite) -} - -/** - * Writing Methods - */ - -func (p *TBinaryProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) TProtocolException { - if p._StrictWrite { - version := uint32(VERSION_1) | uint32(typeId) - e := p.WriteI32(int32(version)) - if e != nil { - return e - } - e = p.WriteString(name) - if e != nil { - return e - } - e = p.WriteI32(seqId) - return e - } else { - e := p.WriteString(name) - if e != nil { - return e - } - e = p.WriteByte(byte(typeId)) - if e != nil { - return e - } - e = p.WriteI32(seqId) - return e - } - return nil -} - -func (p *TBinaryProtocol) WriteMessageEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) WriteStructBegin(name string) TProtocolException { - return nil -} - -func (p *TBinaryProtocol) WriteStructEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException { - e := p.WriteByte(byte(typeId)) - if e != nil { - return e - } - e = p.WriteI16(id) - return e -} - -func (p *TBinaryProtocol) WriteFieldEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) WriteFieldStop() TProtocolException { - e := p.WriteByte(STOP) - return e -} - -func (p *TBinaryProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException { - e := p.WriteByte(byte(keyType)) - if e != nil { - return e - } - e = p.WriteByte(byte(valueType)) - if e != nil { - return e - } - e = p.WriteI32(int32(size)) - return e -} - -func (p *TBinaryProtocol) WriteMapEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) WriteListBegin(elemType TType, size int) TProtocolException { - e := p.WriteByte(byte(elemType)) - if e != nil { - return e - } - e = p.WriteI32(int32(size)) - return e -} - -func (p *TBinaryProtocol) WriteListEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) WriteSetBegin(elemType TType, size int) TProtocolException { - e := p.WriteByte(byte(elemType)) - if e != nil { - return e - } - e = p.WriteI32(int32(size)) - return e -} - -func (p *TBinaryProtocol) WriteSetEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) WriteBool(value bool) TProtocolException { - if value { - return p.WriteByte(1) - } - return p.WriteByte(0) -} - -func (p *TBinaryProtocol) WriteByte(value byte) TProtocolException { - v := []byte{value} - _, e := p.trans.Write(v) - return NewTProtocolExceptionFromOsError(e) -} - -func (p *TBinaryProtocol) WriteI16(value int16) TProtocolException { - h := byte(0xff & (value >> 8)) - l := byte(0xff & value) - v := []byte{h, l} - _, e := p.trans.Write(v) - return NewTProtocolExceptionFromOsError(e) -} - -func (p *TBinaryProtocol) WriteI32(value int32) TProtocolException { - a := byte(0xff & (value >> 24)) - b := byte(0xff & (value >> 16)) - c := byte(0xff & (value >> 8)) - d := byte(0xff & value) - v := []byte{a, b, c, d} - _, e := p.trans.Write(v) - return NewTProtocolExceptionFromOsError(e) -} - -func (p *TBinaryProtocol) WriteI64(value int64) TProtocolException { - a := byte(0xff & (value >> 56)) - b := byte(0xff & (value >> 48)) - c := byte(0xff & (value >> 40)) - d := byte(0xff & (value >> 32)) - e := byte(0xff & (value >> 24)) - f := byte(0xff & (value >> 16)) - g := byte(0xff & (value >> 8)) - h := byte(0xff & value) - v := []byte{a, b, c, d, e, f, g, h} - _, err := p.trans.Write(v) - return NewTProtocolExceptionFromOsError(err) -} - -func (p *TBinaryProtocol) WriteDouble(value float64) TProtocolException { - return p.WriteI64(int64(math.Float64bits(value))) -} - -func (p *TBinaryProtocol) WriteString(value string) TProtocolException { - return p.WriteBinaryFromReader(strings.NewReader(value), len(value)) -} - -func (p *TBinaryProtocol) WriteBinary(value []byte) TProtocolException { - e := p.WriteI32(int32(len(value))) - if e != nil { - return e - } - _, err := p.trans.Write(value) - return NewTProtocolExceptionFromOsError(err) -} - -func (p *TBinaryProtocol) WriteBinaryFromReader(reader io.Reader, size int) TProtocolException { - e := p.WriteI32(int32(size)) - if e != nil { - return e - } - _, err := io.Copyn(p.trans, reader, int64(size)) - return NewTProtocolExceptionFromOsError(err) -} - - -/** - * Reading methods - */ - -func (p *TBinaryProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) { - size, e := p.ReadI32() - if e != nil { - return "", typeId, 0, NewTProtocolExceptionFromOsError(e) - } - if size < 0 { - typeId = TMessageType(size & 0x0ff) - version := int64(int64(size) & VERSION_MASK) - if version != VERSION_1 { - return name, typeId, seqId, NewTProtocolException(BAD_VERSION, "Bad version in ReadMessageBegin") - } - name, e = p.ReadString() - if e != nil { - return name, typeId, seqId, NewTProtocolExceptionFromOsError(e) - } - seqId, e = p.ReadI32() - if e != nil { - return name, typeId, seqId, NewTProtocolExceptionFromOsError(e) - } - return name, typeId, seqId, nil - } - if p._StrictRead { - return name, typeId, seqId, NewTProtocolException(BAD_VERSION, "Missing version in ReadMessageBegin") - } - name, e2 := p.readStringBody(int(size)) - if e2 != nil { - return name, typeId, seqId, e2 - } - b, e3 := p.ReadByte() - if e3 != nil { - return name, typeId, seqId, e3 - } - typeId = TMessageType(b) - seqId, e4 := p.ReadI32() - if e4 != nil { - return name, typeId, seqId, e4 - } - return name, typeId, seqId, nil -} - -func (p *TBinaryProtocol) ReadMessageEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) ReadStructBegin() (name string, err TProtocolException) { - return -} - -func (p *TBinaryProtocol) ReadStructEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) ReadFieldBegin() (name string, typeId TType, seqId int16, err TProtocolException) { - t, err := p.ReadByte() - typeId = TType(t) - if err != nil { - return name, typeId, seqId, err - } - if t != STOP { - seqId, err = p.ReadI16() - } - return name, typeId, seqId, err -} - -func (p *TBinaryProtocol) ReadFieldEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) ReadMapBegin() (kType, vType TType, size int, err TProtocolException) { - k, e := p.ReadByte() - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - kType = TType(k) - v, e := p.ReadByte() - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - vType = TType(v) - size32, e := p.ReadI32() - size = int(size32) - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - return kType, vType, size, nil -} - -func (p *TBinaryProtocol) ReadMapEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) ReadListBegin() (elemType TType, size int, err TProtocolException) { - b, e := p.ReadByte() - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - elemType = TType(b) - size32, e := p.ReadI32() - size = int(size32) - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - return elemType, size, nil -} - -func (p *TBinaryProtocol) ReadListEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) ReadSetBegin() (elemType TType, size int, err TProtocolException) { - b, e := p.ReadByte() - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - elemType = TType(b) - size32, e := p.ReadI32() - size = int(size32) - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - return elemType, size, nil -} - -func (p *TBinaryProtocol) ReadSetEnd() TProtocolException { - return nil -} - -func (p *TBinaryProtocol) ReadBool() (bool, TProtocolException) { - b, e := p.ReadByte() - v := true - if b != 1 { - v = false - } - return v, e -} - -func (p *TBinaryProtocol) ReadByte() (value byte, err TProtocolException) { - buf := []byte{0} - err = p.readAll(buf) - return buf[0], err -} - -func (p *TBinaryProtocol) ReadI16() (value int16, err TProtocolException) { - buf := []byte{0, 0} - err = p.readAll(buf) - value = int16(binary.BigEndian.Uint16(buf)) - return value, err -} - -func (p *TBinaryProtocol) ReadI32() (value int32, err TProtocolException) { - buf := []byte{0, 0, 0, 0} - err = p.readAll(buf) - value = int32(binary.BigEndian.Uint32(buf)) - return value, err -} - -func (p *TBinaryProtocol) ReadI64() (value int64, err TProtocolException) { - buf := []byte{0, 0, 0, 0, 0, 0, 0, 0} - err = p.readAll(buf) - value = int64(binary.BigEndian.Uint64(buf)) - return value, err -} - -func (p *TBinaryProtocol) ReadDouble() (value float64, err TProtocolException) { - buf := []byte{0, 0, 0, 0, 0, 0, 0, 0} - err = p.readAll(buf) - value = math.Float64frombits(binary.BigEndian.Uint64(buf)) - return value, err -} - -func (p *TBinaryProtocol) ReadString() (value string, err TProtocolException) { - size, e := p.ReadI32() - if e != nil { - return "", e - } - return p.readStringBody(int(size)) -} - -func (p *TBinaryProtocol) ReadBinary() ([]byte, TProtocolException) { - size, e := p.ReadI32() - if e != nil { - return nil, e - } - isize := int(size) - e = p.checkReadLength(isize) - if e != nil { - return nil, e - } - buf := make([]byte, isize) - _, err := p.trans.ReadAll(buf) - return buf, NewTProtocolExceptionFromOsError(err) -} - -func (p *TBinaryProtocol) Flush() (err TProtocolException) { - return NewTProtocolExceptionFromOsError(p.trans.Flush()) -} - -func (p *TBinaryProtocol) Skip(fieldType TType) (err TProtocolException) { - return SkipDefaultDepth(p, fieldType) -} - -func (p *TBinaryProtocol) Transport() TTransport { - return p.trans -} - -func (p *TBinaryProtocol) readAll(buf []byte) TProtocolException { - e := p.checkReadLength(len(buf)) - if e != nil { - return e - } - _, err := p.trans.ReadAll(buf) - return NewTProtocolExceptionFromOsError(err) -} - -func (p *TBinaryProtocol) setReadLength(readLength int) { - p._ReadLength = readLength - p._CheckReadLength = true -} - -func (p *TBinaryProtocol) checkReadLength(length int) TProtocolException { - if p._CheckReadLength { - p._ReadLength = p._ReadLength - length - if p._ReadLength < 0 { - return NewTProtocolException(UNKNOWN_PROTOCOL_EXCEPTION, "Message length exceeded: "+string(length)) - } - } - return nil -} - -func (p *TBinaryProtocol) readStringBody(size int) (value string, err TProtocolException) { - if size < 0 { - return "", nil - } - err = p.checkReadLength(size) - if err != nil { - return "", err - } - isize := int(size) - buf := make([]byte, isize) - _, e := p.trans.ReadAll(buf) - return string(buf), NewTProtocolExceptionFromOsError(e) -} diff --git a/lib/go/thrift/tcompact_protocol.go b/lib/go/thrift/tcompact_protocol.go deleted file mode 100644 index 9b780f7d..00000000 --- a/lib/go/thrift/tcompact_protocol.go +++ /dev/null @@ -1,856 +0,0 @@ -/* - * 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 thrift - -import ( - "container/vector" - "encoding/binary" - "fmt" - "math" - "os" - "strings" -) - -const ( - COMPACT_PROTOCOL_ID = 0x082 - COMPACT_VERSION = 1 - COMPACT_VERSION_MASK = 0x1f - COMPACT_TYPE_MASK = 0x0E0 - COMPACT_TYPE_SHIFT_AMOUNT = 5 -) - -type TCompactType byte - -const ( - COMPACT_BOOLEAN_TRUE = 0x01 - COMPACT_BOOLEAN_FALSE = 0x02 - COMPACT_BYTE = 0x03 - COMPACT_I16 = 0x04 - COMPACT_I32 = 0x05 - COMPACT_I64 = 0x06 - COMPACT_DOUBLE = 0x07 - COMPACT_BINARY = 0x08 - COMPACT_LIST = 0x09 - COMPACT_SET = 0x0A - COMPACT_MAP = 0x0B - COMPACT_STRUCT = 0x0C -) - -var ( - _TTypeToCompactType []TCompactType - _TSTOP TField -) - -func init() { - _TSTOP = NewTField("", STOP, 0) - _TTypeToCompactType = make([]TCompactType, int(UTF16)+1) - _TTypeToCompactType[int(STOP)] = STOP - _TTypeToCompactType[int(BOOL)] = COMPACT_BOOLEAN_TRUE - _TTypeToCompactType[int(BYTE)] = COMPACT_BYTE - _TTypeToCompactType[int(I16)] = COMPACT_I16 - _TTypeToCompactType[int(I32)] = COMPACT_I32 - _TTypeToCompactType[int(I64)] = COMPACT_I64 - _TTypeToCompactType[int(DOUBLE)] = COMPACT_DOUBLE - _TTypeToCompactType[int(STRING)] = COMPACT_BINARY - _TTypeToCompactType[int(LIST)] = COMPACT_LIST - _TTypeToCompactType[int(SET)] = COMPACT_SET - _TTypeToCompactType[int(MAP)] = COMPACT_MAP - _TTypeToCompactType[int(STRUCT)] = COMPACT_STRUCT -} - -type TCompactProtocolFactory struct{} - -func NewTCompactProtocolFactory() *TCompactProtocolFactory { - return &TCompactProtocolFactory{} -} - -func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol { - return NewTCompactProtocol(trans) -} - -type TCompactProtocol struct { - trans TTransport - - /** - * Used to keep track of the last field for the current and previous structs, - * so we can do the delta stuff. - */ - lastField *vector.IntVector - lastFieldId int - - /** - * If we encounter a boolean field begin, save the TField here so it can - * have the value incorporated. - */ - booleanField TField - - /** - * If we read a field header, and it's a boolean field, save the boolean - * value here so that readBool can use it. - */ - boolValue bool - boolValueIsNotNull bool -} - -/** - * Create a TCompactProtocol. - * - * @param transport the TTransport object to read from or write to. - */ -func NewTCompactProtocol(trans TTransport) *TCompactProtocol { - return &TCompactProtocol{trans: trans, lastField: &vector.IntVector{}} -} - - -// -// Public Writing methods. -// - -/** - * Write a message header to the wire. Compact Protocol messages contain the - * protocol version so we can migrate forwards in the future if need be. - */ -func (p *TCompactProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) TProtocolException { - _, err := p.writeByteDirect(COMPACT_PROTOCOL_ID) - if err != nil { - return NewTProtocolExceptionFromOsError(err) - } - _, err = p.writeByteDirect((COMPACT_VERSION & COMPACT_VERSION_MASK) | ((byte(typeId) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK)) - if err != nil { - return NewTProtocolExceptionFromOsError(err) - } - _, err = p.writeVarint32(seqid) - if err != nil { - return NewTProtocolExceptionFromOsError(err) - } - e := p.WriteString(name) - return e - -} - -func (p *TCompactProtocol) WriteMessageEnd() TProtocolException { return nil } - -/** - * Write a struct begin. This doesn't actually put anything on the wire. We - * use it as an opportunity to put special placeholder markers on the field - * stack so we can get the field id deltas correct. - */ -func (p *TCompactProtocol) WriteStructBegin(name string) TProtocolException { - p.lastField.Push(p.lastFieldId) - p.lastFieldId = 0 - return nil -} - -/** - * Write a struct end. This doesn't actually put anything on the wire. We use - * this as an opportunity to pop the last field from the current struct off - * of the field stack. - */ -func (p *TCompactProtocol) WriteStructEnd() TProtocolException { - p.lastFieldId = p.lastField.Pop() - return nil -} - -func (p *TCompactProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException { - if typeId == BOOL { - // we want to possibly include the value, so we'll wait. - p.booleanField = NewTField(name, typeId, int(id)) - return nil - } - _, err := p.writeFieldBeginInternal(name, typeId, id, 0xFF) - return NewTProtocolExceptionFromOsError(err) -} - - -/** - * The workhorse of writeFieldBegin. It has the option of doing a - * 'type override' of the type header. This is used specifically in the - * boolean field case. - */ -func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id int16, typeOverride byte) (int, os.Error) { - // short lastField = lastField_.pop(); - - // if there's a type override, use that. - var typeToWrite byte - if typeOverride == 0xFF { - typeToWrite = byte(p.getCompactType(typeId)) - } else { - typeToWrite = typeOverride - } - // check if we can use delta encoding for the field id - fieldId := int(id) - written := 0 - if fieldId > p.lastFieldId && fieldId-p.lastFieldId <= 15 { - // write them together - written, err := p.writeByteDirect(byte((fieldId-p.lastFieldId)<<4) | typeToWrite) - if err != nil { - return written, err - } - } else { - // write them separate - n, err := p.writeByteDirect(typeToWrite) - if err != nil { - return n, err - } - err = p.WriteI16(id) - written = n + 2 - if err != nil { - return written, err - } - } - - p.lastFieldId = fieldId - // p.lastField.Push(field.id); - return written, nil -} - - -func (p *TCompactProtocol) WriteFieldEnd() TProtocolException { return nil } - -func (p *TCompactProtocol) WriteFieldStop() TProtocolException { - _, err := p.writeByteDirect(STOP) - return NewTProtocolExceptionFromOsError(err) -} - -func (p *TCompactProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException { - if size == 0 { - _, err := p.writeByteDirect(0) - return NewTProtocolExceptionFromOsError(err) - } - _, err := p.writeVarint32(int32(size)) - if err != nil { - return NewTProtocolExceptionFromOsError(err) - } - _, err = p.writeByteDirect(byte(p.getCompactType(keyType))<<4 | byte(p.getCompactType(valueType))) - return NewTProtocolExceptionFromOsError(err) -} - -func (p *TCompactProtocol) WriteMapEnd() TProtocolException { return nil } - -/** - * Write a list header. - */ -func (p *TCompactProtocol) WriteListBegin(elemType TType, size int) TProtocolException { - _, err := p.writeCollectionBegin(elemType, size) - return NewTProtocolExceptionFromOsError(err) -} - -func (p *TCompactProtocol) WriteListEnd() TProtocolException { return nil } - -/** - * Write a set header. - */ -func (p *TCompactProtocol) WriteSetBegin(elemType TType, size int) TProtocolException { - _, err := p.writeCollectionBegin(elemType, size) - return NewTProtocolExceptionFromOsError(err) -} - -func (p *TCompactProtocol) WriteSetEnd() TProtocolException { return nil } - -func (p *TCompactProtocol) WriteBool(value bool) TProtocolException { - v := byte(COMPACT_BOOLEAN_FALSE) - if value { - v = byte(COMPACT_BOOLEAN_TRUE) - } - if p.booleanField != nil { - // we haven't written the field header yet - _, err := p.writeFieldBeginInternal(p.booleanField.Name(), p.booleanField.TypeId(), int16(p.booleanField.Id()), v) - p.booleanField = nil - return NewTProtocolExceptionFromOsError(err) - } - // we're not part of a field, so just write the value. - _, err := p.writeByteDirect(v) - return NewTProtocolExceptionFromOsError(err) -} - -/** - * Write a byte. Nothing to see here! - */ -func (p *TCompactProtocol) WriteByte(value byte) TProtocolException { - _, err := p.writeByteDirect(value) - return NewTProtocolExceptionFromOsError(err) -} - -/** - * Write an I16 as a zigzag varint. - */ -func (p *TCompactProtocol) WriteI16(value int16) TProtocolException { - _, err := p.writeVarint32(p.int32ToZigzag(int32(value))) - return NewTProtocolExceptionFromOsError(err) -} - -/** - * Write an i32 as a zigzag varint. - */ -func (p *TCompactProtocol) WriteI32(value int32) TProtocolException { - _, err := p.writeVarint32(p.int32ToZigzag(value)) - return NewTProtocolExceptionFromOsError(err) -} - -/** - * Write an i64 as a zigzag varint. - */ -func (p *TCompactProtocol) WriteI64(value int64) TProtocolException { - _, err := p.writeVarint64(p.int64ToZigzag(value)) - return NewTProtocolExceptionFromOsError(err) -} - -/** - * Write a double to the wire as 8 bytes. - */ -func (p *TCompactProtocol) WriteDouble(value float64) TProtocolException { - buf := make([]byte, 8) - binary.LittleEndian.PutUint64(buf, math.Float64bits(value)) - _, err := p.trans.Write(buf) - return NewTProtocolExceptionFromOsError(err) -} - -/** - * Write a string to the wire with a varint size preceeding. - */ -func (p *TCompactProtocol) WriteString(value string) TProtocolException { - buf := make([]byte, len(value)) - strings.NewReader(value).Read(buf) - return p.WriteBinary(buf) -} - -/** - * Write a byte array, using a varint for the size. - */ -func (p *TCompactProtocol) WriteBinary(bin []byte) TProtocolException { - _, e := p.writeVarint32(int32(len(bin))) - if e != nil { - return NewTProtocolExceptionFromOsError(e) - } - if len(bin) > 0 { - _, e = p.trans.Write(bin) - return NewTProtocolExceptionFromOsError(e) - } - return nil -} - - -// -// Reading methods. -// - -/** - * Read a message header. - */ -func (p *TCompactProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) { - protocolId, err := p.ReadByte() - if protocolId != COMPACT_PROTOCOL_ID { - s := fmt.Sprintf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId) - return "", typeId, seqId, NewTProtocolException(BAD_VERSION, s) - } - versionAndType, err := p.ReadByte() - version := versionAndType & COMPACT_VERSION_MASK - typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & 0x03) - if err != nil { - return - } - if version != COMPACT_VERSION { - s := fmt.Sprintf("Expected version %02x but got %02x", COMPACT_VERSION, version) - err = NewTProtocolException(BAD_VERSION, s) - return - } - seqId, e := p.readVarint32() - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - name, err = p.ReadString() - return -} - -func (p *TCompactProtocol) ReadMessageEnd() TProtocolException { return nil } - -/** - * Read a struct begin. There's nothing on the wire for this, but it is our - * opportunity to push a new struct begin marker onto the field stack. - */ -func (p *TCompactProtocol) ReadStructBegin() (name string, err TProtocolException) { - p.lastField.Push(p.lastFieldId) - p.lastFieldId = 0 - return -} - -/** - * Doesn't actually consume any wire data, just removes the last field for - * this struct from the field stack. - */ -func (p *TCompactProtocol) ReadStructEnd() TProtocolException { - // consume the last field we read off the wire. - p.lastFieldId = p.lastField.Pop() - return nil -} - -/** - * Read a field header off the wire. - */ -func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err TProtocolException) { - t, err := p.ReadByte() - if err != nil { - return - } - - // if it's a stop, then we can return immediately, as the struct is over. - if (t & 0x0f) == STOP { - return _TSTOP.Name(), _TSTOP.TypeId(), int16(_TSTOP.Id()), nil - } - - // mask off the 4 MSB of the type header. it could contain a field id delta. - modifier := int16((t & 0xf0) >> 4) - if modifier == 0 { - // not a delta. look ahead for the zigzag varint field id. - id, err = p.ReadI16() - if err != nil { - return - } - } else { - // has a delta. add the delta to the last read field id. - id = int16(p.lastFieldId) + modifier - } - typeId, e := p.getTType(TCompactType(t & 0x0f)) - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - - // if this happens to be a boolean field, the value is encoded in the type - if p.isBoolType(t) { - // save the boolean value in a special instance variable. - p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE) - p.boolValueIsNotNull = true - } - - // push the new field onto the field stack so we can keep the deltas going. - p.lastFieldId = int(id) - return -} - -func (p *TCompactProtocol) ReadFieldEnd() TProtocolException { return nil } - -/** - * Read a map header off the wire. If the size is zero, skip reading the key - * and value type. This means that 0-length maps will yield TMaps without the - * "correct" types. - */ -func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err TProtocolException) { - size32, e := p.readVarint32() - size = int(size32) - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - keyAndValueType := byte(STOP) - if size != 0 { - keyAndValueType, err = p.ReadByte() - if err != nil { - return - } - } - keyType, _ = p.getTType(TCompactType(keyAndValueType >> 4)) - valueType, _ = p.getTType(TCompactType(keyAndValueType & 0xf)) - return -} - -func (p *TCompactProtocol) ReadMapEnd() TProtocolException { return nil } - -/** - * Read a list header off the wire. If the list size is 0-14, the size will - * be packed into the element type header. If it's a longer list, the 4 MSB - * of the element type header will be 0xF, and a varint will follow with the - * true size. - */ -func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err TProtocolException) { - size_and_type, err := p.ReadByte() - if err != nil { - return - } - size = int((size_and_type >> 4) & 0x0f) - if size == 15 { - size2, e := p.readVarint32() - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - size = int(size2) - } - elemType, e := p.getTType(TCompactType(size_and_type)) - if e != nil { - err = NewTProtocolExceptionFromOsError(e) - return - } - return -} - -func (p *TCompactProtocol) ReadListEnd() TProtocolException { return nil } - -/** - * Read a set header off the wire. If the set size is 0-14, the size will - * be packed into the element type header. If it's a longer set, the 4 MSB - * of the element type header will be 0xF, and a varint will follow with the - * true size. - */ -func (p *TCompactProtocol) ReadSetBegin() (elemType TType, size int, err TProtocolException) { - return p.ReadListBegin() -} - -func (p *TCompactProtocol) ReadSetEnd() TProtocolException { return nil } - -/** - * Read a boolean off the wire. If this is a boolean field, the value should - * already have been read during readFieldBegin, so we'll just consume the - * pre-stored value. Otherwise, read a byte. - */ -func (p *TCompactProtocol) ReadBool() (value bool, err TProtocolException) { - if p.boolValueIsNotNull { - p.boolValueIsNotNull = false - return p.boolValue, nil - } - v, err := p.ReadByte() - return v == COMPACT_BOOLEAN_TRUE, err -} - -/** - * Read a single byte off the wire. Nothing interesting here. - */ -func (p *TCompactProtocol) ReadByte() (value byte, err TProtocolException) { - buf := []byte{0} - _, e := p.trans.ReadAll(buf) - if e != nil { - return 0, NewTProtocolExceptionFromOsError(e) - } - return buf[0], nil -} - -/** - * Read an i16 from the wire as a zigzag varint. - */ -func (p *TCompactProtocol) ReadI16() (value int16, err TProtocolException) { - v, err := p.ReadI32() - return int16(v), err -} - -/** - * Read an i32 from the wire as a zigzag varint. - */ -func (p *TCompactProtocol) ReadI32() (value int32, err TProtocolException) { - v, e := p.readVarint32() - if e != nil { - return 0, NewTProtocolExceptionFromOsError(e) - } - value = p.zigzagToInt32(v) - return value, nil -} - -/** - * Read an i64 from the wire as a zigzag varint. - */ -func (p *TCompactProtocol) ReadI64() (value int64, err TProtocolException) { - v, e := p.readVarint64() - if e != nil { - return 0, NewTProtocolExceptionFromOsError(e) - } - value = p.zigzagToInt64(v) - return value, nil -} - -/** - * No magic here - just read a double off the wire. - */ -func (p *TCompactProtocol) ReadDouble() (value float64, err TProtocolException) { - longBits := make([]byte, 8) - _, e := p.trans.ReadAll(longBits) - if e != nil { - return 0.0, NewTProtocolExceptionFromOsError(e) - } - return math.Float64frombits(p.bytesToUint64(longBits)), nil -} - -/** - * Reads a []byte (via readBinary), and then UTF-8 decodes it. - */ -func (p *TCompactProtocol) ReadString() (value string, err TProtocolException) { - v, e := p.ReadBinary() - return string(v), NewTProtocolExceptionFromOsError(e) -} - -/** - * Read a []byte from the wire. - */ -func (p *TCompactProtocol) ReadBinary() (value []byte, err TProtocolException) { - length, e := p.readVarint32() - if e != nil { - return []byte{}, NewTProtocolExceptionFromOsError(e) - } - if length == 0 { - return []byte{}, nil - } - - buf := make([]byte, length) - p.trans.ReadAll(buf) - return buf, nil -} - -func (p *TCompactProtocol) Flush() (err TProtocolException) { - return NewTProtocolExceptionFromOsError(p.trans.Flush()) -} - -func (p *TCompactProtocol) Skip(fieldType TType) (err TProtocolException) { - return SkipDefaultDepth(p, fieldType) -} - -func (p *TCompactProtocol) Transport() TTransport { - return p.trans -} - -// -// Internal writing methods -// - -/** - * Abstract method for writing the start of lists and sets. List and sets on - * the wire differ only by the type indicator. - */ -func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, os.Error) { - if size <= 14 { - return p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType)))) - } - n, err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType))) - if err != nil { - return n, err - } - m, err := p.writeVarint32(int32(size)) - return n + m, err -} - -/** - * Write an i32 as a varint. Results in 1-5 bytes on the wire. - * TODO(pomack): make a permanent buffer like writeVarint64? - */ -func (p *TCompactProtocol) writeVarint32(n int32) (int, os.Error) { - i32buf := make([]byte, 5) - idx := 0 - for { - if (n & ^0x7F) == 0 { - i32buf[idx] = byte(n) - idx++ - // p.writeByteDirect(byte(n)); - break - // return; - } else { - i32buf[idx] = byte((n & 0x7F) | 0x80) - idx++ - // p.writeByteDirect(byte(((n & 0x7F) | 0x80))); - u := uint32(n) - n = int32(u >> 7) - } - } - return p.trans.Write(i32buf[0:idx]) -} - -/** - * Write an i64 as a varint. Results in 1-10 bytes on the wire. - */ -func (p *TCompactProtocol) writeVarint64(n int64) (int, os.Error) { - varint64out := make([]byte, 10) - idx := 0 - for { - if (n & ^0x7F) == 0 { - varint64out[idx] = byte(n) - idx++ - break - } else { - varint64out[idx] = byte((n & 0x7F) | 0x80) - idx++ - u := uint64(n) - n = int64(u >> 7) - } - } - return p.trans.Write(varint64out[0:idx]) -} - -/** - * Convert l into a zigzag long. This allows negative numbers to be - * represented compactly as a varint. - */ -func (p *TCompactProtocol) int64ToZigzag(l int64) int64 { - return (l << 1) ^ (l >> 63) -} - -/** - * Convert l into a zigzag long. This allows negative numbers to be - * represented compactly as a varint. - */ -func (p *TCompactProtocol) int32ToZigzag(n int32) int32 { - return (n << 1) ^ (n >> 31) -} - -func (p *TCompactProtocol) fixedUint64ToBytes(n uint64, buf []byte) { - binary.LittleEndian.PutUint64(buf, n) -} - -func (p *TCompactProtocol) fixedInt64ToBytes(n int64, buf []byte) { - binary.LittleEndian.PutUint64(buf, uint64(n)) -} - -/** - * Writes a byte without any possiblity of all that field header nonsense. - * Used internally by other writing methods that know they need to write a byte. - */ -func (p *TCompactProtocol) writeByteDirect(b byte) (int, os.Error) { - return p.trans.Write([]byte{b}) -} - -/** - * Writes a byte without any possiblity of all that field header nonsense. - */ -func (p *TCompactProtocol) writeIntAsByteDirect(n int) (int, os.Error) { - return p.writeByteDirect(byte(n)) -} - - -// -// Internal reading methods -// - -/** - * Read an i32 from the wire as a varint. The MSB of each byte is set - * if there is another byte to follow. This can read up to 5 bytes. - */ -func (p *TCompactProtocol) readVarint32() (int32, os.Error) { - // if the wire contains the right stuff, this will just truncate the i64 we - // read and get us the right sign. - v, err := p.readVarint64() - return int32(v), err -} - - -/** - * Read an i64 from the wire as a proper varint. The MSB of each byte is set - * if there is another byte to follow. This can read up to 10 bytes. - */ -func (p *TCompactProtocol) readVarint64() (int64, os.Error) { - shift := uint(0) - result := int64(0) - for { - b, err := p.ReadByte() - if err != nil { - return 0, err - } - result |= int64(b&0x7f) << shift - if (b & 0x80) != 0x80 { - break - } - shift += 7 - } - return result, nil -} - - -// -// encoding helpers -// - -/** - * Convert from zigzag int to int. - */ -func (p *TCompactProtocol) zigzagToInt32(n int32) int32 { - u := uint32(n) - return int32(u>>1) ^ -(n & 1) -} - -/** - * Convert from zigzag long to long. - */ -func (p *TCompactProtocol) zigzagToInt64(n int64) int64 { - u := uint64(n) - return int64(u>>1) ^ -(n & 1) -} - -/** - * Note that it's important that the mask bytes are long literals, - * otherwise they'll default to ints, and when you shift an int left 56 bits, - * you just get a messed up int. - */ -func (p *TCompactProtocol) bytesToInt64(b []byte) int64 { - return int64(binary.LittleEndian.Uint64(b)) -} - -/** - * Note that it's important that the mask bytes are long literals, - * otherwise they'll default to ints, and when you shift an int left 56 bits, - * you just get a messed up int. - */ -func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 { - return binary.LittleEndian.Uint64(b) -} - -// -// type testing and converting -// - -func (p *TCompactProtocol) isBoolType(b byte) bool { - return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE -} - -/** - * Given a TCompactType constant, convert it to its corresponding - * TType value. - */ -func (p *TCompactProtocol) getTType(t TCompactType) (TType, os.Error) { - switch byte(t) & 0x0f { - case STOP: - return STOP, nil - case COMPACT_BOOLEAN_FALSE: - case COMPACT_BOOLEAN_TRUE: - return BOOL, nil - case COMPACT_BYTE: - return BYTE, nil - case COMPACT_I16: - return I16, nil - case COMPACT_I32: - return I32, nil - case COMPACT_I64: - return I64, nil - case COMPACT_DOUBLE: - return DOUBLE, nil - case COMPACT_BINARY: - return STRING, nil - case COMPACT_LIST: - return LIST, nil - case COMPACT_SET: - return SET, nil - case COMPACT_MAP: - return MAP, nil - case COMPACT_STRUCT: - return STRUCT, nil - } - return STOP, NewTException("don't know what type: " + string(t&0x0f)) -} - -/** - * Given a TType value, find the appropriate TCompactProtocol.Types constant. - */ -func (p *TCompactProtocol) getCompactType(t TType) TCompactType { - return _TTypeToCompactType[int(t)] -} diff --git a/lib/go/thrift/tcompact_protocol_test.go b/lib/go/thrift/tcompact_protocol_test.go deleted file mode 100644 index da0e39cc..00000000 --- a/lib/go/thrift/tcompact_protocol_test.go +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 thrift_test - -import ( - . "thrift" - "testing" - //"bytes"; -) - -func TestReadWriteCompactProtocol(t *testing.T) { - ReadWriteProtocolTest(t, NewTCompactProtocolFactory()) - /* - transports := []TTransport{ - NewTMemoryBuffer(), - NewTIOStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 16384))), - NewTFramedTransport(NewTMemoryBuffer()), - } - for _, trans := range transports { - p := NewTCompactProtocol(trans); - ReadWriteBool(t, p, trans); - p = NewTCompactProtocol(trans); - ReadWriteByte(t, p, trans); - p = NewTCompactProtocol(trans); - ReadWriteI16(t, p, trans); - p = NewTCompactProtocol(trans); - ReadWriteI32(t, p, trans); - p = NewTCompactProtocol(trans); - ReadWriteI64(t, p, trans); - p = NewTCompactProtocol(trans); - ReadWriteDouble(t, p, trans); - p = NewTCompactProtocol(trans); - ReadWriteString(t, p, trans); - p = NewTCompactProtocol(trans); - ReadWriteBinary(t, p, trans); - trans.Close(); - } - */ -} diff --git a/lib/go/thrift/tcompare.go b/lib/go/thrift/tcompare.go deleted file mode 100644 index 01fef447..00000000 --- a/lib/go/thrift/tcompare.go +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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 thrift - -func CompareInt(i, j int) int { - if i > j { - return 1 - } - if i < j { - return -1 - } - return 0 -} - -func CompareInt16(i, j int16) int { - if i > j { - return 1 - } - if i < j { - return -1 - } - return 0 -} - -func CompareInt32(i, j int32) int { - if i > j { - return 1 - } - if i < j { - return -1 - } - return 0 -} - -func CompareInt64(i, j int32) int { - if i > j { - return 1 - } - if i < j { - return -1 - } - return 0 -} - -func CompareStringArray(i, j []string) int { - if cmp := CompareInt(len(i), len(j)); cmp != 0 { - return cmp - } - size := len(i) - for k := 0; k < size; k++ { - if cmp := CompareString(i[k], j[k]); cmp != 0 { - return cmp - } - } - return 0 -} - -func CompareString(i, j string) int { - if i > j { - return 1 - } - if i < j { - return -1 - } - return 0 -} - -func CompareFloat(i, j float32) int { - if i > j { - return 1 - } - if i < j { - return -1 - } - return 0 -} - -func CompareDouble(i, j float64) int { - if i > j { - return 1 - } - if i < j { - return -1 - } - return 0 -} - -func CompareByte(i, j byte) int { - if i > j { - return 1 - } - if i < j { - return -1 - } - return 0 -} - -func CompareBool(i, j bool) int { - if i { - if j { - return 0 - } - return 1 - } - if j { - return -1 - } - return 0 -} diff --git a/lib/go/thrift/tfield.go b/lib/go/thrift/tfield.go deleted file mode 100644 index 31d9b891..00000000 --- a/lib/go/thrift/tfield.go +++ /dev/null @@ -1,281 +0,0 @@ -/* - * 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 thrift - -import ( - "sort" -) - -/** - * Helper class that encapsulates field metadata. - * - */ -type TField interface { - Name() string - TypeId() TType - Id() int - String() string - CompareTo(other interface{}) (int, bool) - Equals(other interface{}) bool -} - -type tField struct { - name string - typeId TType - id int -} - -func NewTFieldDefault() TField { - return ANONYMOUS_FIELD -} - -func NewTField(n string, t TType, i int) TField { - return &tField{name: n, typeId: t, id: i} -} - -func (p *tField) Name() string { - if p == nil { - return "" - } - return p.name -} - -func (p *tField) TypeId() TType { - if p == nil { - return TType(VOID) - } - return p.typeId -} - -func (p *tField) Id() int { - if p == nil { - return -1 - } - return p.id -} - -func (p *tField) String() string { - if p == nil { - return "" - } - return "" -} - -func (p *tField) CompareTo(other interface{}) (int, bool) { - if other == nil { - return 1, true - } - if data, ok := other.(TField); ok { - if p.Id() != data.Id() { - return CompareInt(p.Id(), data.Id()), true - } - if p.TypeId() != data.TypeId() { - return CompareByte(byte(p.TypeId()), byte(data.TypeId())), true - } - return CompareString(p.Name(), data.Name()), true - } - return 0, false -} - -func (p *tField) Equals(other interface{}) bool { - if p == nil { - return other == nil - } - if other == nil { - return false - } - if data, ok := other.(TField); ok { - return p.TypeId() == data.TypeId() && p.Id() == data.Id() - } - return false -} - -var ANONYMOUS_FIELD TField - -type tFieldArray []TField - -func (p tFieldArray) Len() int { - return len(p) -} - -func (p tFieldArray) Less(i, j int) bool { - return p[i].Id() < p[j].Id() -} - -func (p tFieldArray) Swap(i, j int) { - p[i], p[j] = p[j], p[i] -} - -type TFieldContainer interface { - TContainer - FieldNameFromFieldId(id int) string - FieldIdFromFieldName(name string) int - FieldFromFieldId(id int) TField - FieldFromFieldName(name string) TField - At(i int) TField - Iter() <-chan TField -} - -type tFieldContainer struct { - fields []TField - nameToFieldMap map[string]TField - idToFieldMap map[int]TField -} - -func NewTFieldContainer(fields []TField) TFieldContainer { - sortedFields := make([]TField, len(fields)) - nameToFieldMap := make(map[string]TField) - idToFieldMap := make(map[int]TField) - for i, field := range fields { - sortedFields[i] = field - idToFieldMap[field.Id()] = field - if field.Name() != "" { - nameToFieldMap[field.Name()] = field - } - } - sort.Sort(tFieldArray(sortedFields)) - return &tFieldContainer{ - fields: fields, - nameToFieldMap: nameToFieldMap, - idToFieldMap: idToFieldMap, - } -} - -func (p *tFieldContainer) FieldNameFromFieldId(id int) string { - if field, ok := p.idToFieldMap[id]; ok { - return field.Name() - } - return "" -} - -func (p *tFieldContainer) FieldIdFromFieldName(name string) int { - if field, ok := p.nameToFieldMap[name]; ok { - return field.Id() - } - return -1 -} - -func (p *tFieldContainer) FieldFromFieldId(id int) TField { - if field, ok := p.idToFieldMap[id]; ok { - return field - } - return ANONYMOUS_FIELD -} - -func (p *tFieldContainer) FieldFromFieldName(name string) TField { - if field, ok := p.nameToFieldMap[name]; ok { - return field - } - return ANONYMOUS_FIELD -} - -func (p *tFieldContainer) Len() int { - return len(p.fields) -} - -func (p *tFieldContainer) At(i int) TField { - return p.FieldFromFieldId(i) -} - -func (p *tFieldContainer) Contains(data interface{}) bool { - if i, ok := data.(int); ok { - for _, field := range p.fields { - if field.Id() == i { - return true - } - } - } else if i, ok := data.(int16); ok { - for _, field := range p.fields { - if field.Id() == int(i) { - return true - } - } - } else if s, ok := data.(string); ok { - for _, field := range p.fields { - if field.Name() == s { - return true - } - } - } else if f, ok := data.(TField); ok { - for _, field := range p.fields { - if field.Equals(f) { - return true - } - } - } - return false -} - -func (p *tFieldContainer) Equals(other interface{}) bool { - if other == nil { - return false - } - if data, ok := other.(TFieldContainer); ok { - if p.Len() != data.Len() { - return false - } - for _, field := range p.fields { - if !data.Contains(field) { - return false - } - } - return true - } - return false -} - -func (p *tFieldContainer) CompareTo(other interface{}) (int, bool) { - if other == nil { - return 1, true - } - if data, ok := other.(TFieldContainer); ok { - cont, ok2 := data.(*tFieldContainer) - if ok2 && p == cont { - return 0, true - } - if cmp := CompareInt(p.Len(), data.Len()); cmp != 0 { - return cmp, true - } - for _, field := range p.fields { - if cmp, ok3 := field.CompareTo(data.At(field.Id())); !ok3 || cmp != 0 { - return cmp, ok3 - } - } - return 0, true - } - return 0, false -} - -func (p *tFieldContainer) Iter() <-chan TField { - c := make(chan TField) - go p.iterate(c) - return c -} - -func (p *tFieldContainer) iterate(c chan<- TField) { - for _, v := range p.fields { - c <- v - } - close(c) -} - -func init() { - ANONYMOUS_FIELD = NewTField("", STOP, 0) -} diff --git a/lib/go/thrift/tframed_transport.go b/lib/go/thrift/tframed_transport.go deleted file mode 100644 index 52049cbc..00000000 --- a/lib/go/thrift/tframed_transport.go +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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 thrift - -import ( - "encoding/binary" - "bytes" - "os" -) - - -type TFramedTransport struct { - transport TTransport - writeBuffer *bytes.Buffer - readBuffer *bytes.Buffer -} - -type tFramedTransportFactory struct { - factory TTransportFactory -} - -func NewTFramedTransportFactory(factory TTransportFactory) TTransportFactory { - return &tFramedTransportFactory{factory: factory} -} - -func (p *tFramedTransportFactory) GetTransport(base TTransport) TTransport { - return NewTFramedTransport(p.factory.GetTransport(base)) -} - -func NewTFramedTransport(transport TTransport) *TFramedTransport { - writeBuf := make([]byte, 0, 1024) - readBuf := make([]byte, 0, 1024) - return &TFramedTransport{transport: transport, writeBuffer: bytes.NewBuffer(writeBuf), readBuffer: bytes.NewBuffer(readBuf)} -} - -func (p *TFramedTransport) Open() os.Error { - return p.transport.Open() -} - -func (p *TFramedTransport) IsOpen() bool { - return p.transport.IsOpen() -} - -func (p *TFramedTransport) Peek() bool { - return p.transport.Peek() -} - -func (p *TFramedTransport) Close() os.Error { - return p.transport.Close() -} - -func (p *TFramedTransport) Read(buf []byte) (int, os.Error) { - if p.readBuffer.Len() > 0 { - got, err := p.readBuffer.Read(buf) - if got > 0 { - return got, NewTTransportExceptionFromOsError(err) - } - } - - // Read another frame of data - p.readFrame() - - got, err := p.readBuffer.Read(buf) - return got, NewTTransportExceptionFromOsError(err) -} - -func (p *TFramedTransport) ReadAll(buf []byte) (int, os.Error) { - return ReadAllTransport(p, buf) -} - -func (p *TFramedTransport) Write(buf []byte) (int, os.Error) { - n, err := p.writeBuffer.Write(buf) - return n, NewTTransportExceptionFromOsError(err) -} - -func (p *TFramedTransport) Flush() os.Error { - size := p.writeBuffer.Len() - buf := []byte{0, 0, 0, 0} - binary.BigEndian.PutUint32(buf, uint32(size)) - _, err := p.transport.Write(buf) - if err != nil { - return NewTTransportExceptionFromOsError(err) - } - if size > 0 { - n, err := p.writeBuffer.WriteTo(p.transport) - if err != nil { - print("Error while flushing write buffer of size ", size, " to transport, only wrote ", n, " bytes: ", err.String(), "\n") - return NewTTransportExceptionFromOsError(err) - } - } - err = p.transport.Flush() - return NewTTransportExceptionFromOsError(err) -} - -func (p *TFramedTransport) readFrame() (int, os.Error) { - buf := []byte{0, 0, 0, 0} - _, err := p.transport.ReadAll(buf) - if err != nil { - return 0, err - } - size := int(binary.BigEndian.Uint32(buf)) - if size < 0 { - // TODO(pomack) log error - return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "Read a negative frame size ("+string(size)+")") - } - if size == 0 { - return 0, nil - } - buf2 := make([]byte, size) - n, err := p.transport.ReadAll(buf2) - if err != nil { - return n, err - } - p.readBuffer = bytes.NewBuffer(buf2) - return size, nil -} diff --git a/lib/go/thrift/thttp_client.go b/lib/go/thrift/thttp_client.go deleted file mode 100644 index 2ec4b28e..00000000 --- a/lib/go/thrift/thttp_client.go +++ /dev/null @@ -1,148 +0,0 @@ -/* - * 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 thrift - -import ( - "bytes" - "http" - "os" - "strconv" - "url" -) - - -type THttpClient struct { - response *http.Response - url *url.URL - requestBuffer *bytes.Buffer - nsecConnectTimeout int64 - nsecReadTimeout int64 -} - -type THttpClientTransportFactory struct { - url string - isPost bool -} - -func (p *THttpClientTransportFactory) GetTransport(trans TTransport) TTransport { - if trans != nil { - t, ok := trans.(*THttpClient) - if ok && t.url != nil { - if t.requestBuffer != nil { - t2, _ := NewTHttpPostClient(t.url.String()) - return t2 - } - t2, _ := NewTHttpClient(t.url.String()) - return t2 - } - } - if p.isPost { - s, _ := NewTHttpPostClient(p.url) - return s - } - s, _ := NewTHttpClient(p.url) - return s -} - -func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory { - return &THttpClientTransportFactory{url: url, isPost: false} -} - -func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory { - return &THttpClientTransportFactory{url: url, isPost: true} -} - - -func NewTHttpClient(urlstr string) (TTransport, os.Error) { - parsedURL, err := url.Parse(urlstr) - if err != nil { - return nil, err - } - response, err := http.Get(urlstr) - if err != nil { - return nil, err - } - return &THttpClient{response: response, url: parsedURL}, nil -} - -func NewTHttpPostClient(urlstr string) (TTransport, os.Error) { - parsedURL, err := url.Parse(urlstr) - if err != nil { - return nil, err - } - buf := make([]byte, 0, 1024) - return &THttpClient{url: parsedURL, requestBuffer: bytes.NewBuffer(buf)}, nil -} - -func (p *THttpClient) Open() os.Error { - // do nothing - return nil -} - -func (p *THttpClient) IsOpen() bool { - return p.response != nil || p.requestBuffer != nil -} - -func (p *THttpClient) Peek() bool { - return p.IsOpen() -} - -func (p *THttpClient) Close() os.Error { - if p.response != nil && p.response.Body != nil { - err := p.response.Body.Close() - p.response = nil - return err - } - if p.requestBuffer != nil { - p.requestBuffer.Reset() - p.requestBuffer = nil - } - return nil -} - -func (p *THttpClient) Read(buf []byte) (int, os.Error) { - if p.response == nil { - return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.") - } - n, err := p.response.Body.Read(buf) - return n, NewTTransportExceptionFromOsError(err) -} - -func (p *THttpClient) ReadAll(buf []byte) (int, os.Error) { - return ReadAllTransport(p, buf) -} - -func (p *THttpClient) Write(buf []byte) (int, os.Error) { - n, err := p.requestBuffer.Write(buf) - return n, err -} - -func (p *THttpClient) Flush() os.Error { - response, err := http.Post(p.url.String(), "application/x-thrift", p.requestBuffer) - if err != nil { - return NewTTransportExceptionFromOsError(err) - } - if response.StatusCode != http.StatusOK { - // TODO(pomack) log bad response - return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "HTTP Response code: "+ strconv.Itoa(response.StatusCode)) - } - p.response = response - return nil -} diff --git a/lib/go/thrift/tiostream_transport.go b/lib/go/thrift/tiostream_transport.go deleted file mode 100644 index 5c4beeac..00000000 --- a/lib/go/thrift/tiostream_transport.go +++ /dev/null @@ -1,231 +0,0 @@ -/* - * 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 thrift - -import ( - "bufio" - "io" - "os" -) - -/** - * This is the most commonly used base transport. It takes an InputStream - * and an OutputStream and uses those to perform all transport operations. - * This allows for compatibility with all the nice constructs Java already - * has to provide a variety of types of streams. - * - */ -type TIOStreamTransport struct { - Reader io.Reader - Writer io.Writer - IsReadWriter bool -} - -type TIOStreamTransportFactory struct { - Reader io.Reader - Writer io.Writer - IsReadWriter bool -} - -func (p *TIOStreamTransportFactory) GetTransport(trans TTransport) TTransport { - if trans != nil { - t, ok := trans.(*TIOStreamTransport) - if ok { - if t.IsReadWriter { - return NewTIOStreamTransportRW(t.Reader.(io.ReadWriter)) - } - if t.Reader != nil && t.Writer != nil { - return NewTIOStreamTransportRAndW(t.Reader, t.Writer) - } - if t.Reader != nil && t.Writer == nil { - return NewTIOStreamTransportR(t.Reader) - } - if t.Reader == nil && t.Writer != nil { - return NewTIOStreamTransportW(t.Writer) - } - return NewTIOStreamTransportDefault() - } - } - if p.IsReadWriter { - return NewTIOStreamTransportRW(p.Reader.(io.ReadWriter)) - } - if p.Reader != nil && p.Writer != nil { - return NewTIOStreamTransportRAndW(p.Reader, p.Writer) - } - if p.Reader != nil && p.Writer == nil { - return NewTIOStreamTransportR(p.Reader) - } - if p.Reader == nil && p.Writer != nil { - return NewTIOStreamTransportW(p.Writer) - } - return NewTIOStreamTransportDefault() -} - -func NewTIOStreamTransportFactory(reader io.Reader, writer io.Writer, isReadWriter bool) *TIOStreamTransportFactory { - return &TIOStreamTransportFactory{Reader: reader, Writer: writer, IsReadWriter: isReadWriter} -} - - -/** - * Subclasses can invoke the default constructor and then assign the input - * streams in the open method. - */ -func NewTIOStreamTransportDefault() *TIOStreamTransport { - return &TIOStreamTransport{} -} - -/** - * Input stream constructor. - * - * @param is Input stream to read from - */ -func NewTIOStreamTransportR(r io.Reader) *TIOStreamTransport { - return &TIOStreamTransport{Reader: bufio.NewReader(r)} -} - -/** - * Output stream constructor. - * - * @param os Output stream to read from - */ -func NewTIOStreamTransportW(w io.Writer) *TIOStreamTransport { - return &TIOStreamTransport{Writer: bufio.NewWriter(w)} -} - -/** - * Two-way stream constructor. - * - * @param is Input stream to read from - * @param os Output stream to read from - */ -func NewTIOStreamTransportRAndW(r io.Reader, w io.Writer) *TIOStreamTransport { - return &TIOStreamTransport{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)} -} - -/** - * Two-way stream constructor. - * - * @param is Input stream to read from - * @param os Output stream to read from - */ -func NewTIOStreamTransportRW(rw io.ReadWriter) *TIOStreamTransport { - // bufio has a bug where once a Reader hits EOF, a new Write never brings the reader out of EOF - // even if reader and writer use the same underlier - //bufrw := bufio.NewReadWriter(bufio.NewReader(rw), bufio.NewWriter(rw)); - return &TIOStreamTransport{Reader: rw, Writer: rw, IsReadWriter: true} -} - -/** - * The streams must already be open at construction time, so this should - * always return true. - * - * @return true - */ -func (p *TIOStreamTransport) IsOpen() bool { - return true -} - -/** - * The streams must already be open. This method does nothing. - */ -func (p *TIOStreamTransport) Open() os.Error { - return nil -} - -func (p *TIOStreamTransport) Peek() bool { - return p.IsOpen() -} - -/** - * Closes both the input and output streams. - */ -func (p *TIOStreamTransport) Close() os.Error { - closedReader := false - if p.Reader != nil { - c, ok := p.Reader.(io.Closer) - if ok { - e := c.Close() - closedReader = true - if e != nil { - LOGGER.Print("Error closing input stream.", e) - } - } - p.Reader = nil - } - if p.Writer != nil && (!closedReader || !p.IsReadWriter) { - c, ok := p.Writer.(io.Closer) - if ok { - e := c.Close() - if e != nil { - LOGGER.Print("Error closing output stream.", e) - } - } - p.Writer = nil - } - return nil -} - -/** - * Reads from the underlying input stream if not null. - */ -func (p *TIOStreamTransport) Read(buf []byte) (int, os.Error) { - if p.Reader == nil { - return 0, NewTTransportException(NOT_OPEN, "Cannot read from null inputStream") - } - n, err := p.Reader.Read(buf) - return n, NewTTransportExceptionFromOsError(err) -} - -func (p *TIOStreamTransport) ReadAll(buf []byte) (int, os.Error) { - return ReadAllTransport(p, buf) -} - - -/** - * Writes to the underlying output stream if not null. - */ -func (p *TIOStreamTransport) Write(buf []byte) (int, os.Error) { - if p.Writer == nil { - LOGGER.Print("Could not write to iostream as Writer is null\n") - return 0, NewTTransportException(NOT_OPEN, "Cannot write to null outputStream") - } - n, err := p.Writer.Write(buf) - if n == 0 || err != nil { - LOGGER.Print("Error writing to iostream, only wrote ", n, " bytes: ", err.String(), "\n") - } - return n, NewTTransportExceptionFromOsError(err) -} - -/** - * Flushes the underlying output stream if not null. - */ -func (p *TIOStreamTransport) Flush() os.Error { - if p.Writer == nil { - return NewTTransportException(NOT_OPEN, "Cannot flush null outputStream") - } - f, ok := p.Writer.(Flusher) - if ok { - err := f.Flush() - if err != nil { - return NewTTransportExceptionFromOsError(err) - } - } - return nil -} diff --git a/lib/go/thrift/tiostream_transport_test.go b/lib/go/thrift/tiostream_transport_test.go deleted file mode 100644 index a7425c75..00000000 --- a/lib/go/thrift/tiostream_transport_test.go +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 thrift_test - -import ( - . "thrift" - "testing" - "bytes" -) - -func TestIOStreamTransport(t *testing.T) { - trans := NewTIOStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 1024))) - TransportTest(t, trans, trans) -} diff --git a/lib/go/thrift/tjson_protocol.go b/lib/go/thrift/tjson_protocol.go deleted file mode 100644 index 45ab7000..00000000 --- a/lib/go/thrift/tjson_protocol.go +++ /dev/null @@ -1,537 +0,0 @@ -/* - * 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 thrift - -import ( - "encoding/base64" - "fmt" -) - -const ( - THRIFT_JSON_PROTOCOL_VERSION = 1 -) - -// for references to _ParseContext see tsimplejson_protocol.go - -/** - * JSON protocol implementation for thrift. - * - * This protocol produces/consumes a simple output format - * suitable for parsing by scripting languages. It should not be - * confused with the full-featured TJSONProtocol. - * - */ -type TJSONProtocol struct { - *TSimpleJSONProtocol -} - -/** - * Constructor - */ -func NewTJSONProtocol(t TTransport) *TJSONProtocol { - v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)} - v.parseContextStack.Push(int(_CONTEXT_IN_TOPLEVEL)) - v.dumpContext.Push(int(_CONTEXT_IN_TOPLEVEL)) - return v -} - -/** - * Factory - */ -type TJSONProtocolFactory struct{} - -func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol { - return NewTJSONProtocol(trans) -} - -func NewTJSONProtocolFactory() *TJSONProtocolFactory { - return &TJSONProtocolFactory{} -} - - -func (p *TJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) TProtocolException { - if e := p.OutputListBegin(); e != nil { - return e - } - if e := p.WriteI32(THRIFT_JSON_PROTOCOL_VERSION); e != nil { - return e - } - if e := p.WriteString(name); e != nil { - return e - } - if e := p.WriteByte(byte(typeId)); e != nil { - return e - } - if e := p.WriteI32(seqId); e != nil { - return e - } - return nil -} - -func (p *TJSONProtocol) WriteMessageEnd() TProtocolException { - return p.OutputListEnd() -} - -func (p *TJSONProtocol) WriteStructBegin(name string) TProtocolException { - if e := p.OutputObjectBegin(); e != nil { - return e - } - return nil -} - -func (p *TJSONProtocol) WriteStructEnd() TProtocolException { - return p.OutputObjectEnd() -} - -func (p *TJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException { - if e := p.WriteI16(id); e != nil { - return e - } - if e := p.OutputObjectBegin(); e != nil { - return e - } - if e := p.WriteString(p.TypeIdToString(typeId)); e != nil { - return e - } - return nil -} - -func (p *TJSONProtocol) WriteFieldEnd() TProtocolException { - return p.OutputObjectEnd() -} - -func (p *TJSONProtocol) WriteFieldStop() TProtocolException { return nil } - -func (p *TJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException { - if e := p.OutputListBegin(); e != nil { - return e - } - if e := p.WriteString(p.TypeIdToString(keyType)); e != nil { - return e - } - if e := p.WriteString(p.TypeIdToString(valueType)); e != nil { - return e - } - return p.WriteI64(int64(size)) -} - -func (p *TJSONProtocol) WriteMapEnd() TProtocolException { - return p.OutputListEnd() -} - -func (p *TJSONProtocol) WriteListBegin(elemType TType, size int) TProtocolException { - return p.OutputElemListBegin(elemType, size) -} - -func (p *TJSONProtocol) WriteListEnd() TProtocolException { - return p.OutputListEnd() -} - -func (p *TJSONProtocol) WriteSetBegin(elemType TType, size int) TProtocolException { - return p.OutputElemListBegin(elemType, size) -} - -func (p *TJSONProtocol) WriteSetEnd() TProtocolException { - return p.OutputListEnd() -} - -func (p *TJSONProtocol) WriteBool(b bool) TProtocolException { - return p.OutputBool(b) -} - -func (p *TJSONProtocol) WriteByte(b byte) TProtocolException { - return p.WriteI32(int32(b)) -} - -func (p *TJSONProtocol) WriteI16(v int16) TProtocolException { - return p.WriteI32(int32(v)) -} - -func (p *TJSONProtocol) WriteI32(v int32) TProtocolException { - return p.OutputI64(int64(v)) -} - -func (p *TJSONProtocol) WriteI64(v int64) TProtocolException { - return p.OutputI64(int64(v)) -} - -func (p *TJSONProtocol) WriteDouble(v float64) TProtocolException { - return p.OutputF64(v) -} - -func (p *TJSONProtocol) WriteString(v string) TProtocolException { - return p.OutputString(v) -} - -func (p *TJSONProtocol) WriteBinary(v []byte) TProtocolException { - // JSON library only takes in a string, - // not an arbitrary byte array, to ensure bytes are transmitted - // efficiently we must convert this into a valid JSON string - // therefore we use base64 encoding to avoid excessive escaping/quoting - if e := p.OutputPreValue(); e != nil { - return e - } - p.writer.Write(JSON_QUOTE_BYTES) - writer := base64.NewEncoder(base64.StdEncoding, p.writer) - if _, e := writer.Write(v); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - writer.Close() - p.writer.Write(JSON_QUOTE_BYTES) - return p.OutputPostValue() -} - -/** - * Reading methods. - */ - -func (p *TJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) { - if isNull, err := p.ParseListBegin(); isNull || err != nil { - return name, typeId, seqId, err - } - version, err := p.ReadI32() - if err != nil { - return name, typeId, seqId, err - } - if version != THRIFT_JSON_PROTOCOL_VERSION { - return name, typeId, seqId, NewTProtocolException(INVALID_DATA, fmt.Sprint("Unknown Protocol version ", version, ", expected version ", THRIFT_JSON_PROTOCOL_VERSION, "\n")) - } - if name, err = p.ReadString(); err != nil { - return name, typeId, seqId, err - } - bTypeId, err := p.ReadByte() - typeId = TMessageType(bTypeId) - if err != nil { - return name, typeId, seqId, err - } - if seqId, err = p.ReadI32(); err != nil { - return name, typeId, seqId, err - } - return name, typeId, seqId, nil -} - -func (p *TJSONProtocol) ReadMessageEnd() TProtocolException { - err := p.ParseListEnd() - return err -} - -func (p *TJSONProtocol) ReadStructBegin() (name string, err TProtocolException) { - _, err = p.ParseObjectStart() - return "", err -} - -func (p *TJSONProtocol) ReadStructEnd() TProtocolException { - return p.ParseObjectEnd() -} - -func (p *TJSONProtocol) ReadFieldBegin() (string, TType, int16, TProtocolException) { - if p.reader.Buffered() < 1 { - return "", STOP, -1, nil - } - b, _ := p.reader.Peek(1) - if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] { - return "", STOP, -1, nil - } - fieldId, err := p.ReadI16() - if err != nil { - return "", STOP, fieldId, err - } - if _, err = p.ParseObjectStart(); err != nil { - return "", STOP, fieldId, err - } - sType, err := p.ReadString() - fType := p.StringToTypeId(sType) - return "", fType, fieldId, err -} - -func (p *TJSONProtocol) ReadFieldEnd() TProtocolException { - return p.ParseObjectEnd() -} - -func (p *TJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e TProtocolException) { - if isNull, e := p.ParseListBegin(); isNull || e != nil { - return VOID, VOID, 0, e - } - - // read keyType - sKeyType, e := p.ReadString() - keyType = p.StringToTypeId(sKeyType) - if e != nil { - return keyType, valueType, size, e - } - - // read valueType - sValueType, e := p.ReadString() - valueType = p.StringToTypeId(sValueType) - if e != nil { - return keyType, valueType, size, e - } - - // read size - iSize, err := p.ReadI64() - size = int(iSize) - return keyType, valueType, size, err -} - -func (p *TJSONProtocol) ReadMapEnd() TProtocolException { - return p.ParseListEnd() -} - -func (p *TJSONProtocol) ReadListBegin() (elemType TType, size int, e TProtocolException) { - return p.ParseElemListBegin() -} - -func (p *TJSONProtocol) ReadListEnd() TProtocolException { - return p.ParseListEnd() -} - -func (p *TJSONProtocol) ReadSetBegin() (elemType TType, size int, e TProtocolException) { - return p.ParseElemListBegin() -} - -func (p *TJSONProtocol) ReadSetEnd() TProtocolException { - return p.ParseListEnd() -} - -func (p *TJSONProtocol) ReadBool() (bool, TProtocolException) { - var value bool - if err := p.ParsePreValue(); err != nil { - return value, err - } - b, _ := p.reader.Peek(len(JSON_FALSE)) - if len(b) > 0 { - switch b[0] { - case JSON_TRUE[0]: - if string(b[0:len(JSON_TRUE)]) == string(JSON_TRUE) { - p.reader.Read(b[0:len(JSON_TRUE)]) - value = true - } else { - return value, NewTProtocolException(INVALID_DATA, "Expected \"true\" but found: "+string(b)) - } - break - case JSON_FALSE[0]: - if string(b[0:len(JSON_FALSE)]) == string(JSON_FALSE) { - p.reader.Read(b[0:len(JSON_FALSE)]) - value = false - } else { - return value, NewTProtocolException(INVALID_DATA, "Expected \"false\" but found: "+string(b)) - } - break - case JSON_NULL[0]: - if string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { - p.reader.Read(b[0:len(JSON_NULL)]) - value = false - } else { - return value, NewTProtocolException(INVALID_DATA, "Expected \"null\" but found: "+string(b)) - } - default: - return value, NewTProtocolException(INVALID_DATA, "Expected \"true\", \"false\", or \"null\" but found: "+string(b)) - } - } - return value, p.ParsePostValue() -} - -func (p *TJSONProtocol) ReadByte() (byte, TProtocolException) { - v, err := p.ReadI64() - return byte(v), err -} - -func (p *TJSONProtocol) ReadI16() (int16, TProtocolException) { - v, err := p.ReadI64() - return int16(v), err -} - -func (p *TJSONProtocol) ReadI32() (int32, TProtocolException) { - v, err := p.ReadI64() - return int32(v), err -} - -func (p *TJSONProtocol) ReadI64() (int64, TProtocolException) { - v, _, err := p.ParseI64() - return v, err -} - -func (p *TJSONProtocol) ReadDouble() (float64, TProtocolException) { - v, _, err := p.ParseF64() - return v, err -} - -func (p *TJSONProtocol) ReadString() (string, TProtocolException) { - var v string - if err := p.ParsePreValue(); err != nil { - return v, err - } - b, _ := p.reader.Peek(len(JSON_NULL)) - if len(b) > 0 && b[0] == JSON_QUOTE { - p.reader.ReadByte() - value, err := p.ParseStringBody() - v = value - if err != nil { - return v, err - } - } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { - _, err := p.reader.Read(b[0:len(JSON_NULL)]) - if err != nil { - return v, NewTProtocolExceptionFromOsError(err) - } - } else { - return v, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected a JSON string, found ", string(b))) - } - return v, p.ParsePostValue() -} - -func (p *TJSONProtocol) ReadBinary() ([]byte, TProtocolException) { - var v []byte - if err := p.ParsePreValue(); err != nil { - return nil, err - } - b, _ := p.reader.Peek(len(JSON_NULL)) - if len(b) > 0 && b[0] == JSON_QUOTE { - p.reader.ReadByte() - value, err := p.ParseBase64EncodedBody() - v = value - if err != nil { - return v, err - } - } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { - _, err := p.reader.Read(b[0:len(JSON_NULL)]) - if err != nil { - return v, NewTProtocolExceptionFromOsError(err) - } - } else { - return v, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected a JSON string, found ", string(b))) - } - return v, p.ParsePostValue() -} - -func (p *TJSONProtocol) Flush() (err TProtocolException) { - return NewTProtocolExceptionFromOsError(p.writer.Flush()) -} - -func (p *TJSONProtocol) Skip(fieldType TType) (err TProtocolException) { - return SkipDefaultDepth(p, fieldType) -} - -func (p *TJSONProtocol) Transport() TTransport { - return p.trans -} - -func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e TProtocolException) { - if isNull, e := p.ParseListBegin(); isNull || e != nil { - return VOID, 0, e - } - sElemType, err := p.ReadString() - elemType = p.StringToTypeId(sElemType) - if err != nil { - return elemType, size, err - } - nSize, err2 := p.ReadI64() - size = int(nSize) - return elemType, size, err2 -} - -func (p *TJSONProtocol) writeElemListBegin(elemType TType, size int) TProtocolException { - if e := p.OutputListBegin(); e != nil { - return e - } - if e := p.OutputString(p.TypeIdToString(elemType)); e != nil { - return e - } - if e := p.OutputI64(int64(size)); e != nil { - return e - } - return nil -} - -func (p *TJSONProtocol) TypeIdToString(fieldType TType) string { - switch byte(fieldType) { - case STOP: - return "stp" - case VOID: - return "v" - case BOOL: - return "tf" - case BYTE: - return "i8" - case DOUBLE: - return "dbl" - case I16: - return "i16" - case I32: - return "i32" - case I64: - return "i64" - case STRING: - return "str" - case STRUCT: - return "rec" - case MAP: - return "map" - case SET: - return "set" - case LIST: - return "lst" - case ENUM: - return "i32" - case UTF16: - return "str" - case GENERIC: - return "gen" - } - return "" -} - -func (p *TJSONProtocol) StringToTypeId(fieldType string) TType { - switch fieldType { - case "stp": - return TType(STOP) - case "v": - return TType(VOID) - case "tf": - return TType(BOOL) - case "i8": - return TType(BYTE) - case "dbl": - return TType(DOUBLE) - case "16": - return TType(I16) - case "i32": - return TType(I32) - case "i64": - return TType(I64) - case "str": - return TType(STRING) - case "rec": - return TType(STRUCT) - case "map": - return TType(MAP) - case "set": - return TType(SET) - case "lst": - return TType(LIST) - case "enm": - return TType(ENUM) - case "u16": - return TType(UTF16) - case "gen": - return TType(GENERIC) - } - return TType(STOP) -} diff --git a/lib/go/thrift/tjson_protocol_test.go b/lib/go/thrift/tjson_protocol_test.go deleted file mode 100644 index 60f0f2e6..00000000 --- a/lib/go/thrift/tjson_protocol_test.go +++ /dev/null @@ -1,674 +0,0 @@ -/* - * 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 thrift_test - -import ( - . "thrift" - "encoding/base64" - "fmt" - "json" - "math" - "strconv" - "testing" -) - -func TestWriteJSONProtocolBool(t *testing.T) { - thetype := "boolean" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - for _, value := range BOOL_VALUES { - if e := p.WriteBool(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := false - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadJSONProtocolBool(t *testing.T) { - thetype := "boolean" - for _, value := range BOOL_VALUES { - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - if value { - trans.Write(JSON_TRUE) - } else { - trans.Write(JSON_FALSE) - } - trans.Flush() - s := trans.String() - v, e := p.ReadBool() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteJSONProtocolByte(t *testing.T) { - thetype := "byte" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - for _, value := range BYTE_VALUES { - if e := p.WriteByte(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := byte(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadJSONProtocolByte(t *testing.T) { - thetype := "byte" - for _, value := range BYTE_VALUES { - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() - s := trans.String() - v, e := p.ReadByte() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteJSONProtocolI16(t *testing.T) { - thetype := "int16" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - for _, value := range INT16_VALUES { - if e := p.WriteI16(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := int16(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadJSONProtocolI16(t *testing.T) { - thetype := "int16" - for _, value := range INT16_VALUES { - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() - s := trans.String() - v, e := p.ReadI16() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteJSONProtocolI32(t *testing.T) { - thetype := "int32" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - for _, value := range INT32_VALUES { - if e := p.WriteI32(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := int32(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadJSONProtocolI32(t *testing.T) { - thetype := "int32" - for _, value := range INT32_VALUES { - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() - s := trans.String() - v, e := p.ReadI32() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteJSONProtocolI64(t *testing.T) { - thetype := "int64" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - for _, value := range INT64_VALUES { - if e := p.WriteI64(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := int64(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadJSONProtocolI64(t *testing.T) { - thetype := "int64" - for _, value := range INT64_VALUES { - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - trans.WriteString(strconv.Itoa64(value)) - trans.Flush() - s := trans.String() - v, e := p.ReadI64() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteJSONProtocolDouble(t *testing.T) { - thetype := "double" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - for _, value := range DOUBLE_VALUES { - if e := p.WriteDouble(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if math.IsInf(value, 1) { - if s != JsonQuote(JSON_INFINITY) { - t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_INFINITY)) - } - } else if math.IsInf(value, -1) { - if s != JsonQuote(JSON_NEGATIVE_INFINITY) { - t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_NEGATIVE_INFINITY)) - } - } else if math.IsNaN(value) { - if s != JsonQuote(JSON_NAN) { - t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_NAN)) - } - } else { - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := float64(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - } - trans.Reset() - } - trans.Close() -} - -func TestReadJSONProtocolDouble(t *testing.T) { - thetype := "double" - for _, value := range DOUBLE_VALUES { - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - n := NewNumericFromDouble(value) - trans.WriteString(n.String()) - trans.Flush() - s := trans.String() - v, e := p.ReadDouble() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if math.IsInf(value, 1) { - if !math.IsInf(v, 1) { - t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) - } - } else if math.IsInf(value, -1) { - if !math.IsInf(v, -1) { - t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) - } - } else if math.IsNaN(value) { - if !math.IsNaN(v) { - t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) - } - } else { - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - } - trans.Reset() - trans.Close() - } -} - -func TestWriteJSONProtocolString(t *testing.T) { - thetype := "string" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - for _, value := range STRING_VALUES { - if e := p.WriteString(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s[0] != '"' || s[len(s)-1] != '"' { - t.Fatalf("Bad value for %s '%v', wrote '%v', expected: %v", thetype, value, s, fmt.Sprint("\"", value, "\"")) - } - v := new(string) - if err := json.Unmarshal([]byte(s), v); err != nil || *v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadJSONProtocolString(t *testing.T) { - thetype := "string" - for _, value := range STRING_VALUES { - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - trans.WriteString(JsonQuote(value)) - trans.Flush() - s := trans.String() - v, e := p.ReadString() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - v1 := new(string) - if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteJSONProtocolBinary(t *testing.T) { - thetype := "binary" - value := protocol_bdata - b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) - base64.StdEncoding.Encode(b64value, value) - b64String := string(b64value) - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - if e := p.WriteBinary(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - expectedString := fmt.Sprint("\"", b64String, "\"") - if s != expectedString { - t.Fatalf("Bad value for %s %v\n wrote: \"%v\"\nexpected: \"%v\"", thetype, value, s, expectedString) - } - v1, err := p.ReadBinary() - if err != nil { - t.Fatalf("Unable to read binary: %s", err.String()) - } - if len(v1) != len(value) { - t.Fatalf("Invalid value for binary\nexpected: \"%v\"\n read: \"%v\"", value, v1) - } - for k, v := range value { - if v1[k] != v { - t.Fatalf("Invalid value for binary at %v\nexpected: \"%v\"\n read: \"%v\"", k, v, v1[k]) - } - } - trans.Close() -} - -func TestReadJSONProtocolBinary(t *testing.T) { - thetype := "binary" - value := protocol_bdata - b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) - base64.StdEncoding.Encode(b64value, value) - b64String := string(b64value) - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - trans.WriteString(JsonQuote(b64String)) - trans.Flush() - s := trans.String() - v, e := p.ReadBinary() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if len(v) != len(value) { - t.Fatalf("Bad value for %s value length %v, wrote: %v, received length: %v", thetype, len(value), s, len(v)) - } - for i := 0; i < len(v); i++ { - if v[i] != value[i] { - t.Fatalf("Bad value for %s at index %d value %v, wrote: %v, received: %v", thetype, i, value[i], s, v[i]) - } - } - v1 := new(string) - if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) - } - trans.Reset() - trans.Close() -} - -func TestWriteJSONProtocolList(t *testing.T) { - thetype := "list" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - p.WriteListBegin(TType(DOUBLE), len(DOUBLE_VALUES)) - for _, value := range DOUBLE_VALUES { - if e := p.WriteDouble(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - } - p.WriteListEnd() - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String()) - } - str := trans.String() - str1 := new([]interface{}) - err := json.Unmarshal([]byte(str), str1) - if err != nil { - t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) - } - l := *str1 - if len(l) < 2 { - t.Fatalf("List must be at least of length two to include metadata") - } - if int(l[0].(float64)) != DOUBLE { - t.Fatal("Invalid type for list, expected: ", DOUBLE, ", but was: ", l[0]) - } - if int(l[1].(float64)) != len(DOUBLE_VALUES) { - t.Fatal("Invalid length for list, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) - } - for k, value := range DOUBLE_VALUES { - s := l[k+2] - if math.IsInf(value, 1) { - if s.(string) != JSON_INFINITY { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_INFINITY), str) - } - } else if math.IsInf(value, 0) { - if s.(string) != JSON_NEGATIVE_INFINITY { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY), str) - } - } else if math.IsNaN(value) { - if s.(string) != JSON_NAN { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NAN), str) - } - } else { - if s.(float64) != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) - } - } - trans.Reset() - } - trans.Close() -} - -func TestWriteJSONProtocolSet(t *testing.T) { - thetype := "set" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - p.WriteSetBegin(TType(DOUBLE), len(DOUBLE_VALUES)) - for _, value := range DOUBLE_VALUES { - if e := p.WriteDouble(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - } - p.WriteSetEnd() - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String()) - } - str := trans.String() - str1 := new([]interface{}) - err := json.Unmarshal([]byte(str), str1) - if err != nil { - t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) - } - l := *str1 - if len(l) < 2 { - t.Fatalf("Set must be at least of length two to include metadata") - } - if int(l[0].(float64)) != DOUBLE { - t.Fatal("Invalid type for set, expected: ", DOUBLE, ", but was: ", l[0]) - } - if int(l[1].(float64)) != len(DOUBLE_VALUES) { - t.Fatal("Invalid length for set, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) - } - for k, value := range DOUBLE_VALUES { - s := l[k+2] - if math.IsInf(value, 1) { - if s.(string) != JSON_INFINITY { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_INFINITY), str) - } - } else if math.IsInf(value, 0) { - if s.(string) != JSON_NEGATIVE_INFINITY { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY), str) - } - } else if math.IsNaN(value) { - if s.(string) != JSON_NAN { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NAN), str) - } - } else { - if s.(float64) != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) - } - } - trans.Reset() - } - trans.Close() -} - -func TestWriteJSONProtocolMap(t *testing.T) { - thetype := "map" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - p.WriteMapBegin(TType(I32), TType(DOUBLE), len(DOUBLE_VALUES)) - for k, value := range DOUBLE_VALUES { - if e := p.WriteI32(int32(k)); e != nil { - t.Fatalf("Unable to write %s key int32 value %v due to error: %s", thetype, k, e.String()) - } - if e := p.WriteDouble(value); e != nil { - t.Fatalf("Unable to write %s value float64 value %v due to error: %s", thetype, value, e.String()) - } - } - p.WriteMapEnd() - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String()) - } - str := trans.String() - if str[0] != '[' || str[len(str)-1] != ']' { - t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES) - } - expectedKeyType, expectedValueType, expectedSize, err := p.ReadMapBegin() - if err != nil { - t.Fatalf("Error while reading map begin: %s", err.String()) - } - if expectedKeyType != I32 { - t.Fatal("Expected map key type ", I32, ", but was ", expectedKeyType) - } - if expectedValueType != DOUBLE { - t.Fatal("Expected map value type ", DOUBLE, ", but was ", expectedValueType) - } - if expectedSize != len(DOUBLE_VALUES) { - t.Fatal("Expected map size of ", len(DOUBLE_VALUES), ", but was ", expectedSize) - } - for k, value := range DOUBLE_VALUES { - ik, err := p.ReadI32() - if err != nil { - t.Fatalf("Bad key for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, ik, string(k), err.String()) - } - if int(ik) != k { - t.Fatalf("Bad key for %s index %v, wrote: %v, expected: %v", thetype, k, ik, k) - } - dv, err := p.ReadDouble() - if err != nil { - t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, dv, value, err.String()) - } - s := strconv.Ftoa64(dv, 'g', 10) - if math.IsInf(value, 1) { - if !math.IsInf(dv, 1) { - t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_INFINITY)) - } - } else if math.IsInf(value, 0) { - if !math.IsInf(dv, 0) { - t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY)) - } - } else if math.IsNaN(value) { - if !math.IsNaN(dv) { - t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_NAN)) - } - } else { - expected := strconv.Ftoa64(value, 'g', 10) - if s != expected { - t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected %v", thetype, k, value, s, expected) - } - v := float64(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - } - trans.Reset() - } - trans.Close() -} - - -func TestReadWriteJSONStruct(t *testing.T) { - thetype := "struct" - trans := NewTMemoryBuffer() - p := NewTJSONProtocol(trans) - orig := NewWork() - orig.Num1 = 25 - orig.Num2 = 102 - orig.Op = ADD - orig.Comment = "Add: 25 + 102" - if e := orig.Write(p); e != nil { - t.Fatalf("Unable to write %s value %#v due to error: %s", thetype, orig, e.String()) - } - p.Flush() - t.Log("Memory buffer contents: ", trans.String()) - expectedString := "{\"1\":{\"i32\":25},\"2\":{\"i32\":102},\"3\":{\"i32\":1},\"4\":{\"str\":\"Add: 25 + 102\"}}" - if expectedString != trans.String() { - t.Fatalf("Expected JSON Struct with value %#v but have %#v", expectedString, trans.String()) - } - read := NewWork() - e := read.Read(p) - t.Logf("Read %s value: %#v", thetype, read) - if e != nil { - t.Fatalf("Unable to read %s due to error: %s", thetype, e.String()) - } - if !orig.Equals(read) { - t.Fatalf("Original Write != Read: %#v != %#v ", orig, read) - } -} - -func TestReadWriteJSONProtocol(t *testing.T) { - ReadWriteProtocolTest(t, NewTJSONProtocolFactory()) -} diff --git a/lib/go/thrift/tlist.go b/lib/go/thrift/tlist.go deleted file mode 100644 index 778fc3b6..00000000 --- a/lib/go/thrift/tlist.go +++ /dev/null @@ -1,222 +0,0 @@ -/* - * 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 thrift - -import ( - "container/vector" -) - -/** - * Helper class that encapsulates list metadata. - * - */ -type TList interface { - TContainer - ElemType() TType - At(i int) interface{} - Set(i int, data interface{}) - Push(data interface{}) - Pop() interface{} - Swap(i, j int) - Insert(i int, data interface{}) - Delete(i int) - Less(i, j int) bool - Iter() <-chan interface{} -} - -type tList struct { - elemType TType - l *vector.Vector -} - -func NewTList(t TType, s int) TList { - var v vector.Vector - return &tList{elemType: t, l: v.Resize(s, s)} -} - -func NewTListDefault() TList { - var v vector.Vector - return &tList{elemType: TType(STOP), l: &v} -} - -func (p *tList) ElemType() TType { - return p.elemType -} - -func (p *tList) Len() int { - return p.l.Len() -} - -func (p *tList) At(i int) interface{} { - return p.l.At(i) -} - -func (p *tList) Set(i int, data interface{}) { - if p.elemType.IsEmptyType() { - p.elemType = TypeFromValue(data) - } - if data, ok := p.elemType.CoerceData(data); ok { - p.l.Set(i, data) - } -} - -func (p *tList) Push(data interface{}) { - if p.elemType.IsEmptyType() { - p.elemType = TypeFromValue(data) - } - data, ok := p.elemType.CoerceData(data) - if ok { - p.l.Push(data) - } -} - -func (p *tList) Pop() interface{} { - return p.l.Pop() -} - -func (p *tList) Swap(i, j int) { - p.l.Swap(i, j) -} - -func (p *tList) Insert(i int, data interface{}) { - p.l.Insert(i, data) -} - -func (p *tList) Delete(i int) { - p.l.Delete(i) -} - -func (p *tList) Contains(data interface{}) bool { - return p.indexOf(data) >= 0 -} - -func (p *tList) Less(i, j int) bool { - return p.l.Less(i, j) -} - -func (p *tList) Iter() <-chan interface{} { - c := make(chan interface{}) - go p.iterate(c) - return c -} - -func (p *tList) iterate(c chan<- interface{}) { - for _, elem := range *p.l { - c <- elem - } - close(c) -} - -func (p *tList) indexOf(data interface{}) int { - if data == nil { - size := p.l.Len() - for i := 0; i < size; i++ { - if p.l.At(i) == nil { - return i - } - } - return -1 - } - data, ok := p.elemType.CoerceData(data) - if data == nil || !ok { - return -1 - } - size := p.l.Len() - if p.elemType.IsBaseType() || p.elemType.IsEnum() { - for i := 0; i < size; i++ { - if data == p.l.At(i) { - return i - } - } - return -1 - } - if cmp, ok := data.(EqualsOtherInterface); ok { - for i := 0; i < size; i++ { - if cmp.Equals(p.l.At(i)) { - return i - } - } - return -1 - } - switch p.elemType { - case MAP: - if cmp, ok := data.(EqualsMap); ok { - for i := 0; i < size; i++ { - v := p.l.At(i) - if v == nil { - continue - } - if cmp.Equals(v.(TMap)) { - return i - } - } - return -1 - } - case SET: - if cmp, ok := data.(EqualsSet); ok { - for i := 0; i < size; i++ { - v := p.l.At(i) - if v == nil { - continue - } - if cmp.Equals(v.(TSet)) { - return i - } - } - return -1 - } - case LIST: - if cmp, ok := data.(EqualsList); ok { - for i := 0; i < size; i++ { - v := p.l.At(i) - if v == nil { - continue - } - if cmp.Equals(v.(TList)) { - return i - } - } - return -1 - } - case STRUCT: - if cmp, ok := data.(EqualsStruct); ok { - for i := 0; i < size; i++ { - v := p.l.At(i) - if v == nil { - continue - } - if cmp.Equals(v.(TStruct)) { - return i - } - } - return -1 - } - } - return -1 -} - -func (p *tList) Equals(other interface{}) bool { - c, cok := p.CompareTo(other) - return cok && c == 0 -} - -func (p *tList) CompareTo(other interface{}) (int, bool) { - return TType(LIST).Compare(p, other) -} diff --git a/lib/go/thrift/tmap.go b/lib/go/thrift/tmap.go deleted file mode 100644 index d042f05e..00000000 --- a/lib/go/thrift/tmap.go +++ /dev/null @@ -1,763 +0,0 @@ -/* - * 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 thrift - -import ( - "container/list" - "reflect" -) - -/** - * Helper class that encapsulates map metadata. - * - */ -type TMap interface { - KeyType() TType - ValueType() TType - Len() int - Set(key, value interface{}) - Get(key interface{}) (interface{}, bool) - Contains(key interface{}) bool - Iter() <-chan TMapElem - KeyIter() <-chan interface{} - ValueIter() <-chan interface{} - Keys() []interface{} - Values() []interface{} - Less(other interface{}) bool - Equals(other interface{}) bool - CompareTo(other interface{}) (int, bool) -} - -type TMapElem interface { - Key() interface{} - Value() interface{} -} - -type tMap struct { - keyType TType - valueType TType - size int - l *list.List - b map[bool]interface{} - i08 map[byte]interface{} - i16 map[int16]interface{} - i32 map[int32]interface{} - i64 map[int64]interface{} - f64 map[float64]interface{} - s map[string]interface{} -} - -type tMapElem struct { - key interface{} - value interface{} -} - -func (p *tMapElem) Key() interface{} { - return p.key -} - -func (p *tMapElem) Value() interface{} { - return p.value -} - -func NewTMapElem(k, v interface{}) TMapElem { - return &tMapElem{key: k, value: v} -} - -func NewTMap(k, v TType, s int) TMap { - return &tMap{keyType: k, valueType: v, size: s, l: list.New()} -} - -func NewTMapDefault() TMap { - return NewTMap(STOP, STOP, 0) -} - -func (p *tMap) KeyType() TType { - return p.keyType -} - -func (p *tMap) ValueType() TType { - return p.valueType -} - -func (p *tMap) Len() int { - if p.l.Len() != 0 { - return p.l.Len() - } - switch p.KeyType() { - case STOP, VOID: - return 0 - case BOOL: - return len(p.b) - case BYTE: - return len(p.i08) - case I16: - return len(p.i16) - case I32: - return len(p.i32) - case I64: - return len(p.i64) - case DOUBLE: - return len(p.f64) - case STRING, UTF8, UTF16: - return len(p.s) - default: - return p.size - } - return p.size -} - -func (p *tMap) Get(key interface{}) (interface{}, bool) { - if p.KeyType().IsEmptyType() { - return nil, false - } - if key == nil { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - e := elem.Value.(TMapElem) - k := e.Key() - if k == nil { - return e.Value(), true - } - } - return nil, false - } - useKey, ok := p.KeyType().CoerceData(key) - if !ok { - return nil, false - } - switch p.KeyType() { - case STOP, VOID: - // if here, then we don't have a key type yet and key is not nil - // so this is pretty much an empty map - return nil, false - case BOOL: - m := p.b - if m == nil { - return nil, false - } - if v, ok := m[useKey.(bool)]; ok { - return v, true - } - return nil, true - case BYTE: - m := p.i08 - if v, ok := m[useKey.(byte)]; ok { - return v, true - } - return nil, false - case DOUBLE: - m := p.f64 - if m == nil { - return nil, false - } - if v, ok := m[useKey.(float64)]; ok { - return v, true - } - return nil, false - case I16: - m := p.i16 - if m == nil { - return nil, false - } - if v, ok := m[useKey.(int16)]; ok { - return v, true - } - return nil, false - case I32: - m := p.i32 - if m == nil { - return nil, false - } - if v, ok := m[useKey.(int32)]; ok { - return v, true - } - return nil, false - case I64: - m := p.i64 - if m == nil { - return nil, false - } - if v, ok := m[useKey.(int64)]; ok { - return v, true - } - return nil, false - case STRING, UTF8, UTF16: - // TODO(pomack) properly handle ENUM - m := p.s - if m == nil { - return nil, false - } - if v, ok := m[useKey.(string)]; ok { - return v, true - } - return nil, false - case STRUCT: - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - e := elem.Value.(TMapElem) - k := e.Key() - if k == nil { - continue - } - structkey, ok := k.(TStruct) - if ok { - if structkey.Equals(useKey.(TStruct)) { - return e.Value(), true - } - continue - } - if reflect.DeepEqual(useKey, k) { - return e.Value(), true - } - } - return nil, false - case MAP: - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - e := elem.Value.(TMapElem) - k := e.Key() - if k == nil { - continue - } - mapkey, ok := k.(TMap) - if ok { - if mapkey.Equals(useKey.(TMap)) { - return e.Value(), true - } - continue - } - if reflect.DeepEqual(useKey, k) { - return e.Value(), true - } - } - return nil, false - case SET: - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - e := elem.Value.(TMapElem) - k := e.Key() - if k == nil { - continue - } - setkey, ok := k.(TSet) - if ok { - if setkey.Equals(useKey.(TSet)) { - return e.Value(), true - } - continue - } - if reflect.DeepEqual(useKey, k) { - return e.Value(), true - } - } - return nil, false - case LIST: - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - e := elem.Value.(TMapElem) - k := e.Key() - if k == nil { - continue - } - listkey, ok := k.(TList) - if ok { - if listkey.Equals(useKey.(TList)) { - return e.Value(), true - } - continue - } - if reflect.DeepEqual(useKey, k) { - return e.Value(), true - } - } - return nil, false - default: - panic("Invalid Thrift element type") - } - return nil, false -} - - -func (p *tMap) Set(key, value interface{}) { - if p.KeyType() == STOP || p.KeyType() == VOID { - p.keyType = TypeFromValue(key) - } - coercedKey, ok := p.KeyType().CoerceData(key) - if !ok { - return - } - if p.ValueType() == STOP || p.ValueType() == VOID { - p.valueType = TypeFromValue(value) - } - coercedValue, ok := p.ValueType().CoerceData(value) - if !ok { - return - } - newElem := NewTMapElem(coercedKey, coercedValue) - if !p.KeyType().IsBaseType() { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - k := elem.Value.(TMapElem).Key() - if cmp, ok := p.KeyType().Compare(coercedKey, k); ok && cmp >= 0 { - if cmp == 0 { - p.l.InsertAfter(newElem, elem) - p.l.Remove(elem) - return - } - p.l.InsertBefore(newElem, elem) - return - } - } - p.l.PushBack(newElem) - return - } - if key == nil { - return - } - switch p.KeyType() { - case STOP, VOID: - // if here, then we don't have a key type yet and key is not nil - // so this is pretty much an empty map - return - case BOOL: - if p.b == nil { - p.b = make(map[bool]interface{}) - } - b := coercedKey.(bool) - p.b[b] = value - case BYTE: - if p.i08 == nil { - p.i08 = make(map[byte]interface{}) - } - b := coercedKey.(byte) - p.i08[b] = value - case DOUBLE: - if p.f64 == nil { - p.f64 = make(map[float64]interface{}) - } - b := coercedKey.(float64) - p.f64[b] = value - case I16: - if p.i16 == nil { - p.i16 = make(map[int16]interface{}) - } - b := coercedKey.(int16) - p.i16[b] = value - case I32: - if p.i32 == nil { - p.i32 = make(map[int32]interface{}) - } - b := coercedKey.(int32) - p.i32[b] = value - case I64: - if p.i64 == nil { - p.i64 = make(map[int64]interface{}) - } - b := coercedKey.(int64) - p.i64[b] = value - case STRING, UTF8, UTF16: - if p.s == nil { - p.s = make(map[string]interface{}) - } - b := coercedKey.(string) - p.s[b] = value - case STRUCT, MAP, SET, LIST: - panic("Should never be here") - default: - panic("Should never be here") - } -} - -func (p *tMap) Contains(key interface{}) bool { - coercedKey, ok := p.KeyType().CoerceData(key) - if !ok { - return false - } - if coercedKey == nil { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - k := elem.Value.(TMapElem).Key() - if k == nil { - return true - } - } - return false - } - if !ok { - return false - } - switch p.KeyType() { - case STOP: - // if here, then we don't have a key type yet and key is not nil - // so this is pretty much an empty map - return false - case VOID: - // if here, then we don't have a key type yet and key is not nil - // so this is pretty much an empty map - return false - case BOOL: - m := p.b - if m == nil { - return false - } - _, ok := m[coercedKey.(bool)] - return ok - case BYTE: - m := p.i08 - _, ok := m[coercedKey.(byte)] - return ok - case DOUBLE: - m := p.f64 - if m == nil { - return false - } - _, ok := m[coercedKey.(float64)] - return ok - case I16: - m := p.i16 - if m == nil { - return false - } - _, ok := m[coercedKey.(int16)] - return ok - case I32: - m := p.i32 - if m == nil { - return false - } - _, ok := m[coercedKey.(int32)] - return ok - case I64: - m := p.i64 - if m == nil { - return false - } - _, ok := m[coercedKey.(int64)] - return ok - case STRING, UTF8, UTF16: - // TODO(pomack) properly handle ENUM - m := p.s - if m == nil { - return false - } - _, ok := m[coercedKey.(string)] - return ok - case STRUCT: - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - e := elem.Value.(TMapElem) - k := e.Key() - if k == nil { - continue - } - structkey, ok := k.(TStruct) - if ok { - if structkey.Equals(coercedKey.(TStruct)) { - return true - } - continue - } - if reflect.DeepEqual(coercedKey, k) { - return true - } - } - return false - case MAP: - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - e := elem.Value.(TMapElem) - k := e.Key() - if k == nil { - continue - } - mapkey, ok := k.(TMap) - if ok { - if mapkey.Equals(coercedKey.(TMap)) { - return true - } - continue - } - } - return false - case SET: - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - e := elem.Value.(TMapElem) - k := e.Key() - if k == nil { - continue - } - setkey, ok := k.(TSet) - if ok { - if setkey.Equals(coercedKey.(TSet)) { - return true - } - continue - } - } - return false - case LIST: - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - e := elem.Value.(TMapElem) - k := e.Key() - if k == nil { - continue - } - listkey, ok := k.(TList) - if ok { - if listkey.Equals(coercedKey.(TList)) { - return true - } - continue - } - } - return false - default: - panic("Invalid Thrift element type") - } - return false -} - -// Iterate over all elements; driver for range -func (p *tMap) iterate(c chan<- TMapElem) { - switch p.KeyType() { - case STOP, VOID: - close(c) - case BOOL: - for k, v := range p.b { - c <- NewTMapElem(k, v) - } - close(c) - case BYTE: - for k, v := range p.i08 { - c <- NewTMapElem(k, v) - } - close(c) - case I16: - for k, v := range p.i16 { - c <- NewTMapElem(k, v) - } - close(c) - case I32: - for k, v := range p.i32 { - c <- NewTMapElem(k, v) - } - close(c) - case I64: - for k, v := range p.i64 { - c <- NewTMapElem(k, v) - } - close(c) - case DOUBLE: - for k, v := range p.f64 { - c <- NewTMapElem(k, v) - } - close(c) - case STRING, UTF8, UTF16: - for k, v := range p.s { - c <- NewTMapElem(k, v) - } - close(c) - case STRUCT: - for v := p.l.Front(); v != nil; v = v.Next() { - c <- v.Value.(TMapElem) - } - close(c) - case LIST: - for v := p.l.Front(); v != nil; v = v.Next() { - c <- v.Value.(TMapElem) - } - close(c) - case SET: - for v := p.l.Front(); v != nil; v = v.Next() { - c <- v.Value.(TMapElem) - } - close(c) - default: - panic("Invalid Thrift type") - } -} - -// Channel iterator for range. -func (p *tMap) Iter() <-chan TMapElem { - c := make(chan TMapElem) - go p.iterate(c) - return c -} - -// Iterate over all keys; driver for range -func (p *tMap) iterateKeys(c chan<- interface{}) { - switch p.KeyType() { - case STOP, VOID: - close(c) - case BOOL: - for k, _ := range p.b { - c <- k - } - close(c) - case BYTE: - for k, _ := range p.i08 { - c <- k - } - close(c) - case I16: - for k, _ := range p.i16 { - c <- k - } - close(c) - case I32: - for k, _ := range p.i32 { - c <- k - } - close(c) - case I64: - for k, _ := range p.i64 { - c <- k - } - close(c) - case DOUBLE: - for k, _ := range p.f64 { - c <- k - } - close(c) - case STRING, UTF8, UTF16: - for k, _ := range p.s { - c <- k - } - close(c) - case STRUCT: - for v := p.l.Front(); v != nil; v = v.Next() { - c <- v.Value.(TMapElem).Key() - } - close(c) - case LIST: - for v := p.l.Front(); v != nil; v = v.Next() { - c <- v.Value.(TMapElem).Key() - } - close(c) - case SET: - for v := p.l.Front(); v != nil; v = v.Next() { - c <- v.Value.(TMapElem).Key() - } - close(c) - default: - panic("Invalid Thrift type") - } -} - -func (p *tMap) KeyIter() <-chan interface{} { - c := make(chan interface{}) - go p.iterateKeys(c) - return c -} - -// Iterate over all values; driver for range -func (p *tMap) iterateValues(c chan<- interface{}) { - switch p.KeyType() { - case STOP, VOID: - close(c) - case BOOL: - for _, v := range p.b { - c <- v - } - close(c) - case BYTE: - for _, v := range p.i08 { - c <- v - } - close(c) - case I16: - for _, v := range p.i16 { - c <- v - } - close(c) - case I32: - for _, v := range p.i32 { - c <- v - } - close(c) - case I64: - for _, v := range p.i64 { - c <- v - } - close(c) - case DOUBLE: - for _, v := range p.f64 { - c <- v - } - close(c) - case STRING, UTF8, UTF16: - for _, v := range p.s { - c <- v - } - close(c) - case STRUCT: - for v := p.l.Front(); v != nil; v = v.Next() { - c <- v.Value.(TMapElem).Value() - } - close(c) - case LIST: - for v := p.l.Front(); v != nil; v = v.Next() { - c <- v.Value.(TMapElem).Value() - } - close(c) - case SET: - for v := p.l.Front(); v != nil; v = v.Next() { - c <- v.Value.(TMapElem).Value() - } - close(c) - default: - panic("Invalid Thrift type") - } -} - -func (p *tMap) ValueIter() <-chan interface{} { - c := make(chan interface{}) - go p.iterateValues(c) - return c -} - - -func (p *tMap) Less(other interface{}) bool { - cmp, ok := p.CompareTo(other) - return ok && cmp > 0 -} - -func (p *tMap) Equals(other interface{}) bool { - c, cok := p.CompareTo(other) - return cok && c == 0 -} - -func (p *tMap) CompareTo(other interface{}) (int, bool) { - return TType(MAP).Compare(p, other) -} - -func (p *tMap) Keys() []interface{} { - size := p.Len() - values := make([]interface{}, size, size) - i := 0 - for k := range p.KeyIter() { - values[i] = k - i++ - } - return values -} - -func (p *tMap) Values() []interface{} { - size := p.Len() - values := make([]interface{}, size, size) - i := 0 - for v := range p.ValueIter() { - values[i] = v - i++ - } - return values -} diff --git a/lib/go/thrift/tmemory_buffer.go b/lib/go/thrift/tmemory_buffer.go deleted file mode 100644 index 69b794e2..00000000 --- a/lib/go/thrift/tmemory_buffer.go +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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 thrift - -import ( - "bytes" - "io" - "os" -) - -/** - * Memory buffer-based implementation of the TTransport interface. - * - */ -type TMemoryBuffer struct { - buf *bytes.Buffer - size int -} - -type TMemoryBufferTransportFactory struct { - size int -} - -func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) TTransport { - if trans != nil { - t, ok := trans.(*TMemoryBuffer) - if ok && t.size > 0 { - return NewTMemoryBufferLen(t.size) - } - } - return NewTMemoryBufferLen(p.size) -} - -func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory { - return &TMemoryBufferTransportFactory{size: size} -} - -func NewTMemoryBuffer() *TMemoryBuffer { - return &TMemoryBuffer{buf: &bytes.Buffer{}, size: 0} -} - -func NewTMemoryBufferLen(size int) *TMemoryBuffer { - buf := make([]byte, 0, size) - return &TMemoryBuffer{buf: bytes.NewBuffer(buf), size: size} -} - -func (p *TMemoryBuffer) IsOpen() bool { - return true -} - -func (p *TMemoryBuffer) Open() os.Error { - return nil -} - -func (p *TMemoryBuffer) Peek() bool { - return p.IsOpen() -} - -func (p *TMemoryBuffer) Close() os.Error { - p.buf.Reset() - return nil -} - -func (p *TMemoryBuffer) Read(buf []byte) (int, os.Error) { - return p.buf.Read(buf) -} - -func (p *TMemoryBuffer) ReadAll(buf []byte) (int, os.Error) { - return ReadAllTransport(p, buf) -} - -func (p *TMemoryBuffer) ReadByte() (byte, os.Error) { - return p.buf.ReadByte() -} - -func (p *TMemoryBuffer) ReadFrom(r io.Reader) (int64, os.Error) { - return p.buf.ReadFrom(r) -} - -func (p *TMemoryBuffer) Write(buf []byte) (int, os.Error) { - return p.buf.Write(buf) -} - -func (p *TMemoryBuffer) WriteString(buf string) (int, os.Error) { - return p.buf.WriteString(buf) -} - -func (p *TMemoryBuffer) WriteTo(w io.Writer) (int64, os.Error) { - return p.buf.WriteTo(w) -} - -func (p *TMemoryBuffer) Flush() os.Error { - return nil -} - -func (p *TMemoryBuffer) Reset() { - p.buf.Reset() -} - -func (p *TMemoryBuffer) Bytes() []byte { - return p.buf.Bytes() -} - -func (p *TMemoryBuffer) Len() int { - return p.buf.Len() -} - -func (p *TMemoryBuffer) String() string { - return p.buf.String() -} diff --git a/lib/go/thrift/tmessage.go b/lib/go/thrift/tmessage.go deleted file mode 100644 index c768cb4b..00000000 --- a/lib/go/thrift/tmessage.go +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 thrift - -/** - * Helper class that encapsulates struct metadata. - * - */ -type TMessage interface { - Name() string - TypeId() TMessageType - SeqId() int - Equals(other TMessage) bool -} -type tMessage struct { - name string - typeId TMessageType - seqid int -} - -func NewTMessageDefault() TMessage { - return NewTMessage("", STOP, 0) -} - -func NewTMessage(n string, t TMessageType, s int) TMessage { - return &tMessage{name: n, typeId: t, seqid: s} -} - -func (p *tMessage) Name() string { - return p.name -} - -func (p *tMessage) TypeId() TMessageType { - return p.typeId -} - -func (p *tMessage) SeqId() int { - return p.seqid -} - -func (p *tMessage) String() string { - return "" -} - -func (p *tMessage) Equals(other TMessage) bool { - return p.name == other.Name() && p.typeId == other.TypeId() && p.seqid == other.SeqId() -} - -var EMPTY_MESSAGE TMessage - -func init() { - EMPTY_MESSAGE = NewTMessageDefault() -} diff --git a/lib/go/thrift/tnonblocking_server.go b/lib/go/thrift/tnonblocking_server.go deleted file mode 100644 index e234c5a5..00000000 --- a/lib/go/thrift/tnonblocking_server.go +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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 thrift - -import ( - "os" -) - -/** - * A nonblocking TServer implementation. This allows for fairness amongst all - * connected clients in terms of invocations. - * - * This server is inherently single-threaded. If you want a limited thread pool - * coupled with invocation-fairness, see THsHaServer. - * - * To use this server, you MUST use a TFramedTransport at the outermost - * transport, otherwise this server will be unable to determine when a whole - * method call has been read off the wire. Clients must also use TFramedTransport. - */ -type TNonblockingServer struct { - /** Flag for stopping the server */ - stopped bool - - processorFactory TProcessorFactory - serverTransport TServerTransport - inputTransportFactory TTransportFactory - outputTransportFactory TTransportFactory - inputProtocolFactory TProtocolFactory - outputProtocolFactory TProtocolFactory -} - - -func NewTNonblockingServer2(processor TProcessor, serverTransport TServerTransport) *TNonblockingServer { - return NewTNonblockingServerFactory2(NewTProcessorFactory(processor), serverTransport) -} - -func NewTNonblockingServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TNonblockingServer { - return NewTNonblockingServerFactory4(NewTProcessorFactory(processor), - serverTransport, - transportFactory, - protocolFactory, - ) -} - -func NewTNonblockingServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TNonblockingServer { - return NewTNonblockingServerFactory6(NewTProcessorFactory(processor), - serverTransport, - inputTransportFactory, - outputTransportFactory, - inputProtocolFactory, - outputProtocolFactory, - ) -} - -func NewTNonblockingServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TNonblockingServer { - return NewTNonblockingServerFactory6(processorFactory, - serverTransport, - NewTTransportFactory(), - NewTTransportFactory(), - NewTBinaryProtocolFactoryDefault(), - NewTBinaryProtocolFactoryDefault(), - ) -} - -func NewTNonblockingServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TNonblockingServer { - return NewTNonblockingServerFactory6(processorFactory, - serverTransport, - transportFactory, - transportFactory, - protocolFactory, - protocolFactory, - ) -} - -func NewTNonblockingServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TNonblockingServer { - return &TNonblockingServer{processorFactory: processorFactory, - serverTransport: serverTransport, - inputTransportFactory: inputTransportFactory, - outputTransportFactory: outputTransportFactory, - inputProtocolFactory: inputProtocolFactory, - outputProtocolFactory: outputProtocolFactory, - } -} - -func (p *TNonblockingServer) ProcessorFactory() TProcessorFactory { - return p.processorFactory -} - -func (p *TNonblockingServer) ServerTransport() TServerTransport { - return p.serverTransport -} - -func (p *TNonblockingServer) InputTransportFactory() TTransportFactory { - return p.inputTransportFactory -} - -func (p *TNonblockingServer) OutputTransportFactory() TTransportFactory { - return p.outputTransportFactory -} - -func (p *TNonblockingServer) InputProtocolFactory() TProtocolFactory { - return p.inputProtocolFactory -} - -func (p *TNonblockingServer) OutputProtocolFactory() TProtocolFactory { - return p.outputProtocolFactory -} - -func (p *TNonblockingServer) Serve() os.Error { - p.stopped = false - err := p.serverTransport.Listen() - if err != nil { - return err - } - for !p.stopped { - client, err := p.serverTransport.Accept() - if err != nil { - return err - } - if client != nil { - go p.processRequest(client) - } - } - return nil -} - -func (p *TNonblockingServer) Stop() os.Error { - p.stopped = true - p.serverTransport.Interrupt() - return nil -} - -func (p *TNonblockingServer) IsStopped() bool { - return p.stopped -} - -func (p *TNonblockingServer) processRequest(client TTransport) { - processor := p.processorFactory.GetProcessor(client) - inputTransport := p.inputTransportFactory.GetTransport(client) - outputTransport := p.outputTransportFactory.GetTransport(client) - inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport) - outputProtocol := p.outputProtocolFactory.GetProtocol(outputTransport) - if inputTransport != nil { - defer inputTransport.Close() - } - if outputTransport != nil { - defer outputTransport.Close() - } - for { - ok, e := processor.Process(inputProtocol, outputProtocol) - if e != nil { - if !p.stopped { - // TODO(pomack) log error - break - } - } - if !ok { - break - } - } -} diff --git a/lib/go/thrift/tnonblocking_server_socket.go b/lib/go/thrift/tnonblocking_server_socket.go deleted file mode 100644 index 3c9dbaa9..00000000 --- a/lib/go/thrift/tnonblocking_server_socket.go +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 thrift - -import ( - "net" - "os" -) - -/** - * Socket implementation of the TTransport interface. To be commented soon! - */ -type TNonblockingServerSocket struct { - listener net.Listener - addr net.Addr - /** - * Socket timeout - */ - nsecTimeout int64 -} - -type TNonblockingServerSocketTransportFactory struct { - addr net.Addr -} - -func (p *TNonblockingServerSocketTransportFactory) GetTransport(trans TTransport) TTransport { - if trans != nil { - t, ok := trans.(*TNonblockingServerSocket) - if ok && t.addr != nil { - s, _ := NewTNonblockingServerSocketAddr(t.addr) - s.SetTimeout(t.nsecTimeout) - return s - } - } - s, _ := NewTNonblockingServerSocketAddr(p.addr) - return s -} - -func NewTNonblockingServerSocketTransportFactory(addr net.Addr) *TNonblockingServerSocketTransportFactory { - return &TNonblockingServerSocketTransportFactory{addr: addr} -} - - -func NewTNonblockingServerSocketListener(listener net.Listener) (*TNonblockingServerSocket, TTransportException) { - s := &TNonblockingServerSocket{listener: listener, addr: listener.Addr()} - return s, nil -} - -func NewTNonblockingServerSocketAddr(addr net.Addr) (*TNonblockingServerSocket, TTransportException) { - s := &TNonblockingServerSocket{addr: addr} - return s, nil -} - -func (p *TNonblockingServerSocket) Listen() os.Error { - return p.Open() -} - -/** - * Sets the socket timeout - * - * @param timeout Nanoseconds timeout - */ -func (p *TNonblockingServerSocket) SetTimeout(nsecTimeout int64) os.Error { - p.nsecTimeout = nsecTimeout - return nil -} - -/** - * Checks whether the socket is connected. - */ -func (p *TNonblockingServerSocket) IsOpen() bool { - return p.listener != nil -} - -/** - * Connects the socket, creating a new socket object if necessary. - */ -func (p *TNonblockingServerSocket) Open() os.Error { - if !p.IsOpen() { - l, err := net.Listen(p.addr.Network(), p.addr.String()) - if err != nil { - return err - } - p.listener = l - return nil - } - return NewTTransportException(ALREADY_OPEN, "Server socket already open") -} - -/** - * Perform a nonblocking read into buffer. - */ -func (p *TNonblockingServerSocket) Read(buf []byte) (int, os.Error) { - return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TNonblockingServerSocket.Read([]byte) is not implemented") -} - -func (p *TNonblockingServerSocket) ReadAll(buf []byte) (int, os.Error) { - return ReadAllTransport(p, buf) -} - -/** - * Perform a nonblocking write of the data in buffer; - */ -func (p *TNonblockingServerSocket) Write(buf []byte) (int, os.Error) { - return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TNonblockingServerSocket.Write([]byte) is not implemented") -} - -/** - * Flushes the underlying output stream if not null. - */ -func (p *TNonblockingServerSocket) Flush() os.Error { - return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TNonblockingServerSocket.Flush() is not implemented") -} - -func (p *TNonblockingServerSocket) Addr() net.Addr { - return p.addr -} - -func (p *TNonblockingServerSocket) Accept() (TTransport, os.Error) { - if !p.IsOpen() { - return nil, NewTTransportException(NOT_OPEN, "No underlying server socket") - } - conn, err := p.listener.Accept() - if err != nil { - return nil, NewTTransportExceptionFromOsError(err) - } - conn.SetTimeout(p.nsecTimeout) - return NewTSocketConn(conn) -} - -func (p *TNonblockingServerSocket) Peek() bool { - return p.IsOpen() -} - -/** - * Closes the socket. - */ -func (p *TNonblockingServerSocket) Close() (err os.Error) { - if p.IsOpen() { - err := p.listener.Close() - if err != nil { - return NewTTransportExceptionFromOsError(err) - } - p.listener = nil - } - return nil -} - -func (p *TNonblockingServerSocket) Interrupt() os.Error { - // probably not right - return p.Close() -} diff --git a/lib/go/thrift/tnonblocking_socket.go b/lib/go/thrift/tnonblocking_socket.go deleted file mode 100644 index 9b175b87..00000000 --- a/lib/go/thrift/tnonblocking_socket.go +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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 thrift - -import ( - "net" - "os" -) - -/** - * Socket implementation of the TTransport interface. To be commented soon! - */ -type TNonblockingSocket struct { - conn net.Conn - addr net.Addr - /** - * Socket timeout - */ - nsecTimeout int64 -} - -type TNonblockingSocketTransportFactory struct { - addr net.Addr -} - -func (p *TNonblockingSocketTransportFactory) GetTransport(trans TTransport) TTransport { - if trans != nil { - t, ok := trans.(*TNonblockingSocket) - if ok { - s, _ := NewTNonblockingSocketAddr(t.addr) - s.SetTimeout(t.nsecTimeout) - return s - } - } - s, _ := NewTNonblockingSocketAddr(p.addr) - return s -} - -func NewTNonblockingSocketTransportFactory(addr net.Addr) *TNonblockingSocketTransportFactory { - return &TNonblockingSocketTransportFactory{addr: addr} -} - -func NewTNonblockingSocketConn(conn net.Conn) (*TNonblockingSocket, TTransportException) { - s := &TNonblockingSocket{conn: conn, addr: conn.RemoteAddr()} - return s, nil -} - -func NewTNonblockingSocketAddr(addr net.Addr) (*TNonblockingSocket, TTransportException) { - s := &TNonblockingSocket{addr: addr} - return s, nil -} - -/** - * Sets the socket timeout - * - * @param nsecTimeout Nanoseconds timeout - */ -func (p *TNonblockingSocket) SetTimeout(nsecTimeout int64) os.Error { - p.nsecTimeout = nsecTimeout - if p.IsOpen() { - if err := p.conn.SetTimeout(nsecTimeout); err != nil { - LOGGER.Print("Could not set socket timeout.", err) - return err - } - } - return nil -} - -/** - * Checks whether the socket is connected. - */ -func (p *TNonblockingSocket) IsOpen() bool { - return p.conn != nil -} - -/** - * Connects the socket, creating a new socket object if necessary. - */ -func (p *TNonblockingSocket) Open() os.Error { - if p.IsOpen() { - return NewTTransportException(ALREADY_OPEN, "Socket already connected.") - } - if p.addr == nil { - return NewTTransportException(NOT_OPEN, "Cannot open nil address.") - } - if len(p.addr.Network()) == 0 { - return NewTTransportException(NOT_OPEN, "Cannot open bad network name.") - } - if len(p.addr.String()) == 0 { - return NewTTransportException(NOT_OPEN, "Cannot open bad address.") - } - - var err os.Error - if p.conn, err = net.Dial(p.addr.Network(), p.addr.String()); err != nil { - LOGGER.Print("Could not open socket", err.String()) - return NewTTransportException(NOT_OPEN, err.String()) - } - if p.conn != nil { - p.conn.SetTimeout(p.nsecTimeout) - } - return nil -} - -/** - * Perform a nonblocking read into buffer. - */ -func (p *TNonblockingSocket) Read(buf []byte) (int, os.Error) { - if !p.IsOpen() { - return 0, NewTTransportException(NOT_OPEN, "Connection not open") - } - n, err := p.conn.Read(buf) - return n, NewTTransportExceptionFromOsError(err) -} - - -func (p *TNonblockingSocket) ReadAll(buf []byte) (int, os.Error) { - return ReadAllTransport(p, buf) -} - -/** - * Perform a nonblocking write of the data in buffer; - */ -func (p *TNonblockingSocket) Write(buf []byte) (int, os.Error) { - if !p.IsOpen() { - return 0, NewTTransportException(NOT_OPEN, "Connection not open") - } - return p.conn.Write(buf) -} - -/** - * Flushes the underlying output stream if not null. - */ -func (p *TNonblockingSocket) Flush() os.Error { - if !p.IsOpen() { - return NewTTransportException(NOT_OPEN, "Connection not open") - } - f, ok := p.conn.(Flusher) - if ok { - err := f.Flush() - if err != nil { - return NewTTransportExceptionFromOsError(err) - } - } - return nil -} - -func (p *TNonblockingSocket) Addr() net.Addr { - return p.addr -} - -func (p *TNonblockingSocket) Peek() bool { - return p.IsOpen() -} - -/** - * Closes the socket. - */ -func (p *TNonblockingSocket) Close() os.Error { - if p.conn != nil { - if err := p.conn.Close(); err != nil { - LOGGER.Print("Could not close socket.", err.String()) - return err - } - p.conn = nil - } - return nil -} - -func (p *TNonblockingSocket) Interrupt() os.Error { - if !p.IsOpen() { - return nil - } - // TODO(pomack) fix Interrupt as it is probably not right - return p.Close() -} diff --git a/lib/go/thrift/tnonblocking_transport_test.go b/lib/go/thrift/tnonblocking_transport_test.go deleted file mode 100644 index 7d019dbd..00000000 --- a/lib/go/thrift/tnonblocking_transport_test.go +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 thrift_test - -import ( - . "thrift" - "testing" - "net" -) - -func TestNonblockingTransportServerToClient(t *testing.T) { - - addr, err := FindAvailableTCPServerPort(40000) - if err != nil { - t.Fatalf("Unable to find available tcp port addr: %s", err) - } - trans1, err := NewTNonblockingServerSocketAddr(addr) - if err != nil { - t.Fatalf("Unable to setup server socket listener: %s", err) - } - trans1.Open() - trans2, err := NewTNonblockingSocketAddr(addr) - if err != nil { - t.Fatalf("Unable to setup client socket: %s", err) - } - trans1.SetTimeout(10) - trans2.SetTimeout(10) - err = trans2.Open() - if err != nil { - t.Fatalf("Unable to connect client to server: %s", err) - } - s, err := trans1.Accept() - if err != nil { - t.Fatalf("Unable to accept client connection from server: %s", err) - } - //s.SetTimeout(10) - TransportTest(t, NewTFramedTransport(s), NewTFramedTransport(trans2)) - trans1.Close() -} - -func TestNonblockingTransportClientToServer(t *testing.T) { - addr, err := FindAvailableTCPServerPort(40000) - if err != nil { - t.Fatalf("Unable to find available tcp port addr: %s", err) - } - l, err := net.Listen(addr.Network(), addr.String()) - if err != nil { - t.Fatalf("Unable to setup listener: %s", err) - } - trans1, err := NewTNonblockingServerSocketListener(l) - if err != nil { - t.Fatalf("Unable to setup server socket listener: %s", err) - } - trans2, err := NewTNonblockingSocketAddr(l.Addr()) - if err != nil { - t.Fatalf("Unable to setup client socket: %s", err) - } - trans1.SetTimeout(10) - trans2.SetTimeout(10) - err = trans2.Open() - if err != nil { - t.Fatalf("Unable to connect client to server: %s", err) - } - s, err := trans1.Accept() - if err != nil { - t.Fatalf("Unable to accept client connection from server: %s", err) - } - //s.SetTimeout(10) - TransportTest(t, NewTFramedTransport(trans2), NewTFramedTransport(s)) - trans1.Close() -} diff --git a/lib/go/thrift/tnumeric.go b/lib/go/thrift/tnumeric.go deleted file mode 100644 index b1f65084..00000000 --- a/lib/go/thrift/tnumeric.go +++ /dev/null @@ -1,165 +0,0 @@ -/* - * 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 thrift - -import ( - "math" - "strconv" -) - -type Numeric interface { - Int64() int64 - Int32() int32 - Int16() int16 - Byte() byte - Int() int - Float64() float64 - Float32() float32 - String() string - isNull() bool -} - -type numeric struct { - iValue int64 - dValue float64 - sValue string - isNil bool -} - -var ( - INFINITY Numeric - NEGATIVE_INFINITY Numeric - NAN Numeric - ZERO Numeric - NUMERIC_NULL Numeric -) - -func NewNumericFromDouble(dValue float64) Numeric { - if math.IsInf(dValue, 1) { - return INFINITY - } - if math.IsInf(dValue, -1) { - return NEGATIVE_INFINITY - } - if math.IsNaN(dValue) { - return NAN - } - iValue := int64(dValue) - sValue := strconv.Ftoa64(dValue, 'g', 10) - isNil := false - return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} -} - -func NewNumericFromI64(iValue int64) Numeric { - dValue := float64(iValue) - sValue := string(iValue) - isNil := false - return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} -} - -func NewNumericFromI32(iValue int32) Numeric { - dValue := float64(iValue) - sValue := string(iValue) - isNil := false - return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil} -} - -func NewNumericFromString(sValue string) Numeric { - if sValue == INFINITY.String() { - return INFINITY - } - if sValue == NEGATIVE_INFINITY.String() { - return NEGATIVE_INFINITY - } - if sValue == NAN.String() { - return NAN - } - iValue, _ := strconv.Atoi64(sValue) - dValue, _ := strconv.Atof64(sValue) - isNil := len(sValue) == 0 - return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} -} - -func NewNumericFromJSONString(sValue string, isNull bool) Numeric { - if isNull { - return NewNullNumeric() - } - if sValue == JSON_INFINITY { - return INFINITY - } - if sValue == JSON_NEGATIVE_INFINITY { - return NEGATIVE_INFINITY - } - if sValue == JSON_NAN { - return NAN - } - iValue, _ := strconv.Atoi64(sValue) - dValue, _ := strconv.Atof64(sValue) - return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNull} -} - -func NewNullNumeric() Numeric { - return &numeric{iValue: 0, dValue: 0.0, sValue: "", isNil: true} -} - -func (p *numeric) Int64() int64 { - return p.iValue -} - -func (p *numeric) Int32() int32 { - return int32(p.iValue) -} - -func (p *numeric) Int16() int16 { - return int16(p.iValue) -} - -func (p *numeric) Byte() byte { - return byte(p.iValue) -} - -func (p *numeric) Int() int { - return int(p.iValue) -} - -func (p *numeric) Float64() float64 { - return p.dValue -} - -func (p *numeric) Float32() float32 { - return float32(p.dValue) -} - -func (p *numeric) String() string { - return p.sValue -} - -func (p *numeric) isNull() bool { - return p.isNil -} - -func init() { - INFINITY = &numeric{iValue: 0, dValue: math.Inf(1), sValue: "Infinity", isNil: false} - NEGATIVE_INFINITY = &numeric{iValue: 0, dValue: math.Inf(-1), sValue: "-Infinity", isNil: false} - NAN = &numeric{iValue: 0, dValue: math.NaN(), sValue: "NaN", isNil: false} - ZERO = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: false} - NUMERIC_NULL = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: true} -} diff --git a/lib/go/thrift/tprotocol.go b/lib/go/thrift/tprotocol.go deleted file mode 100644 index dcb27a89..00000000 --- a/lib/go/thrift/tprotocol.go +++ /dev/null @@ -1,201 +0,0 @@ -/* - * 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 thrift - - -const ( - VERSION_MASK = 0xffff0000 - VERSION_1 = 0x80010000 -) - -type EmptyInterface interface{} - -type TProtocol interface { - WriteMessageBegin(name string, typeId TMessageType, seqid int32) TProtocolException - WriteMessageEnd() TProtocolException - WriteStructBegin(name string) TProtocolException - WriteStructEnd() TProtocolException - WriteFieldBegin(name string, typeId TType, id int16) TProtocolException - WriteFieldEnd() TProtocolException - WriteFieldStop() TProtocolException - WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException - WriteMapEnd() TProtocolException - WriteListBegin(elemType TType, size int) TProtocolException - WriteListEnd() TProtocolException - WriteSetBegin(elemType TType, size int) TProtocolException - WriteSetEnd() TProtocolException - WriteBool(value bool) TProtocolException - WriteByte(value byte) TProtocolException - WriteI16(value int16) TProtocolException - WriteI32(value int32) TProtocolException - WriteI64(value int64) TProtocolException - WriteDouble(value float64) TProtocolException - WriteString(value string) TProtocolException - WriteBinary(value []byte) TProtocolException - - ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err TProtocolException) - ReadMessageEnd() TProtocolException - ReadStructBegin() (name string, err TProtocolException) - ReadStructEnd() TProtocolException - ReadFieldBegin() (name string, typeId TType, id int16, err TProtocolException) - ReadFieldEnd() TProtocolException - ReadMapBegin() (keyType TType, valueType TType, size int, err TProtocolException) - ReadMapEnd() TProtocolException - ReadListBegin() (elemType TType, size int, err TProtocolException) - ReadListEnd() TProtocolException - ReadSetBegin() (elemType TType, size int, err TProtocolException) - ReadSetEnd() TProtocolException - ReadBool() (value bool, err TProtocolException) - ReadByte() (value byte, err TProtocolException) - ReadI16() (value int16, err TProtocolException) - ReadI32() (value int32, err TProtocolException) - ReadI64() (value int64, err TProtocolException) - ReadDouble() (value float64, err TProtocolException) - ReadString() (value string, err TProtocolException) - ReadBinary() (value []byte, err TProtocolException) - - Skip(fieldType TType) (err TProtocolException) - Flush() (err TProtocolException) - - Transport() TTransport -} - -/** - * The maximum recursive depth the skip() function will traverse before - * throwing a TException. - */ -var ( - MaxSkipDepth = 1<<31 - 1 -) - -/** - * Specifies the maximum recursive depth that the skip function will - * traverse before throwing a TException. This is a global setting, so - * any call to skip in this JVM will enforce this value. - * - * @param depth the maximum recursive depth. A value of 2 would allow - * the skip function to skip a structure or collection with basic children, - * but it would not permit skipping a struct that had a field containing - * a child struct. A value of 1 would only allow skipping of simple - * types and empty structs/collections. - */ -func SetMaxSkipDepth(depth int) { - MaxSkipDepth = depth -} - -/** - * Skips over the next data element from the provided input TProtocol object. - * - * @param prot the protocol object to read from - * @param type the next value will be intepreted as this TType value. - */ -func SkipDefaultDepth(prot TProtocol, typeId TType) (err TProtocolException) { - return Skip(prot, typeId, MaxSkipDepth) -} - -/** - * Skips over the next data element from the provided input TProtocol object. - * - * @param prot the protocol object to read from - * @param type the next value will be intepreted as this TType value. - * @param maxDepth this function will only skip complex objects to this - * recursive depth, to prevent Java stack overflow. - */ -func Skip(self TProtocol, fieldType TType, maxDepth int) (err TProtocolException) { - switch fieldType { - case STOP: - return - case BOOL: - _, err = self.ReadBool() - return - case BYTE: - _, err = self.ReadByte() - return - case I16: - _, err = self.ReadI16() - return - case I32: - _, err = self.ReadI32() - return - case I64: - _, err = self.ReadI64() - return - case DOUBLE: - _, err = self.ReadDouble() - return - case STRING: - _, err = self.ReadString() - return - case STRUCT: - { - _, err = self.ReadStructBegin() - if err != nil { - return - } - for { - _, typeId, _, _ := self.ReadFieldBegin() - if typeId == STOP { - break - } - Skip(self, typeId, maxDepth-1) - self.ReadFieldEnd() - } - return self.ReadStructEnd() - } - case MAP: - { - keyType, valueType, l, err := self.ReadMapBegin() - if err != nil { - return err - } - size := int(l) - for i := 0; i < size; i++ { - Skip(self, keyType, maxDepth-1) - self.Skip(valueType) - } - return self.ReadMapEnd() - } - case SET: - { - elemType, l, err := self.ReadSetBegin() - if err != nil { - return err - } - size := int(l) - for i := 0; i < size; i++ { - Skip(self, elemType, maxDepth-1) - } - return self.ReadSetEnd() - } - case LIST: - { - elemType, l, err := self.ReadListBegin() - if err != nil { - return err - } - size := int(l) - for i := 0; i < size; i++ { - Skip(self, elemType, maxDepth-1) - } - return self.ReadListEnd() - } - } - return nil -} diff --git a/lib/go/thrift/tprotocol_exception.go b/lib/go/thrift/tprotocol_exception.go deleted file mode 100644 index 2dac97e2..00000000 --- a/lib/go/thrift/tprotocol_exception.go +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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 thrift - -import ( - "encoding/base64" - "os" -) - -/** - * Protocol exceptions. - * - */ -type TProtocolException interface { - TException - TypeId() int -} - -const ( - UNKNOWN_PROTOCOL_EXCEPTION = 0 - INVALID_DATA = 1 - NEGATIVE_SIZE = 2 - SIZE_LIMIT = 3 - BAD_VERSION = 4 - NOT_IMPLEMENTED = 5 -) - -type tProtocolException struct { - typeId int - message string -} - -func (p *tProtocolException) TypeId() int { - return p.typeId -} - -func (p *tProtocolException) String() string { - return p.message -} - -func NewTProtocolExceptionDefault() TProtocolException { - return NewTProtocolExceptionDefaultType(UNKNOWN_PROTOCOL_EXCEPTION) -} - -func NewTProtocolExceptionDefaultType(t int) TProtocolException { - return NewTProtocolException(t, "") -} - -func NewTProtocolExceptionDefaultString(m string) TProtocolException { - return NewTProtocolException(UNKNOWN_PROTOCOL_EXCEPTION, m) -} - -func NewTProtocolException(t int, m string) TProtocolException { - return &tProtocolException{typeId: t, message: m} -} - -func NewTProtocolExceptionReadField(fieldId int, fieldName string, structName string, e TProtocolException) TProtocolException { - t := e.TypeId() - if t == UNKNOWN_PROTOCOL_EXCEPTION { - t = INVALID_DATA - } - return NewTProtocolException(t, "Unable to read field "+string(fieldId)+" ("+fieldName+") in "+structName+" due to: "+e.String()) -} - -func NewTProtocolExceptionWriteField(fieldId int, fieldName string, structName string, e TProtocolException) TProtocolException { - t := e.TypeId() - if t == UNKNOWN_PROTOCOL_EXCEPTION { - t = INVALID_DATA - } - return NewTProtocolException(t, "Unable to write field "+string(fieldId)+" ("+fieldName+") in "+structName+" due to: "+e.String()) -} - -func NewTProtocolExceptionReadStruct(structName string, e TProtocolException) TProtocolException { - t := e.TypeId() - if t == UNKNOWN_PROTOCOL_EXCEPTION { - t = INVALID_DATA - } - return NewTProtocolException(t, "Unable to read struct "+structName+" due to: "+e.String()) -} - -func NewTProtocolExceptionWriteStruct(structName string, e TProtocolException) TProtocolException { - t := e.TypeId() - if t == UNKNOWN_PROTOCOL_EXCEPTION { - t = INVALID_DATA - } - return NewTProtocolException(t, "Unable to write struct "+structName+" due to: "+e.String()) -} - -func NewTProtocolExceptionFromOsError(e os.Error) TProtocolException { - if e == nil { - return nil - } - if t, ok := e.(TProtocolException); ok { - return t - } - if te, ok := e.(TTransportException); ok { - return NewTProtocolExceptionFromTransportException(te) - } - if _, ok := e.(base64.CorruptInputError); ok { - return NewTProtocolException(INVALID_DATA, e.String()) - } - return NewTProtocolExceptionDefaultString(e.String()) -} - -func NewTProtocolExceptionFromTransportException(e TTransportException) TProtocolException { - if e == nil { - return nil - } - if t, ok := e.(TProtocolException); ok { - return t - } - return NewTProtocolExceptionDefaultString(e.String()) -} diff --git a/lib/go/thrift/tprotocol_test.go b/lib/go/thrift/tprotocol_test.go deleted file mode 100644 index 71ef8e9b..00000000 --- a/lib/go/thrift/tprotocol_test.go +++ /dev/null @@ -1,1825 +0,0 @@ -/* - * 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 thrift_test - -import ( - . "thrift" - "testing" - "http" - "math" - "net" - "io/ioutil" - "os" - "bytes" - "fmt" -) - -const PROTOCOL_BINARY_DATA_SIZE = 155 - -var ( - data string // test data for writing - protocol_bdata []byte // test data for writing; same as data - BOOL_VALUES []bool - BYTE_VALUES []byte - INT16_VALUES []int16 - INT32_VALUES []int32 - INT64_VALUES []int64 - DOUBLE_VALUES []float64 - STRING_VALUES []string -) - - -func init() { - protocol_bdata = make([]byte, PROTOCOL_BINARY_DATA_SIZE) - for i := 0; i < PROTOCOL_BINARY_DATA_SIZE; i++ { - protocol_bdata[i] = byte((i + 'a') % 255) - } - data = string(protocol_bdata) - BOOL_VALUES = []bool{false, true, false, false, true} - BYTE_VALUES = []byte{117, 0, 1, 32, 127, 128, 255} - INT16_VALUES = []int16{459, 0, 1, -1, -128, 127, 32767, -32768} - INT32_VALUES = []int32{459, 0, 1, -1, -128, 127, 32767, 2147483647, -2147483535} - INT64_VALUES = []int64{459, 0, 1, -1, -128, 127, 32767, 2147483647, -2147483535, 34359738481, -35184372088719, -9223372036854775808, 9223372036854775807} - DOUBLE_VALUES = []float64{459.3, 0.0, -1.0, 1.0, 0.5, 0.3333, 3.14159, 1.537e-38, 1.673e25, 6.02214179e23, -6.02214179e23, INFINITY.Float64(), NEGATIVE_INFINITY.Float64(), NAN.Float64()} - STRING_VALUES = []string{"", "a", "st[uf]f", "st,u:ff with spaces", "stuff\twith\nescape\\characters'...\"lots{of}fun"} -} - -type HTTPEchoServer struct{} - -func (p *HTTPEchoServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { - buf, err := ioutil.ReadAll(req.Body) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write(buf) - } else { - w.WriteHeader(http.StatusOK) - w.Write(buf) - } -} - -func HttpClientSetupForTest(t *testing.T) (net.Listener, net.Addr) { - addr, err := FindAvailableTCPServerPort(40000) - if err != nil { - t.Fatalf("Unable to find available tcp port addr: %s", err) - return nil, addr - } - l, err := net.Listen(addr.Network(), addr.String()) - if err != nil { - t.Fatalf("Unable to setup tcp listener on %s: %s", addr.String(), err) - return l, addr - } - go http.Serve(l, &HTTPEchoServer{}) - return l, addr -} - - -func ReadWriteProtocolTest(t *testing.T, protocolFactory TProtocolFactory) { - buf := bytes.NewBuffer(make([]byte, 0, 1024)) - l, addr := HttpClientSetupForTest(t) - defer l.Close() - transports := []TTransportFactory{ - NewTMemoryBufferTransportFactory(1024), - NewTIOStreamTransportFactory(buf, buf, true), - NewTFramedTransportFactory(NewTMemoryBufferTransportFactory(1024)), - NewTHttpPostClientTransportFactory("http://" + addr.String()), - } - for _, tf := range transports { - trans := tf.GetTransport(nil) - p := protocolFactory.GetProtocol(trans) - ReadWriteBool(t, p, trans) - trans.Close() - } - for _, tf := range transports { - trans := tf.GetTransport(nil) - p := protocolFactory.GetProtocol(trans) - ReadWriteByte(t, p, trans) - trans.Close() - } - for _, tf := range transports { - trans := tf.GetTransport(nil) - p := protocolFactory.GetProtocol(trans) - ReadWriteI16(t, p, trans) - trans.Close() - } - for _, tf := range transports { - trans := tf.GetTransport(nil) - p := protocolFactory.GetProtocol(trans) - ReadWriteI32(t, p, trans) - trans.Close() - } - for _, tf := range transports { - trans := tf.GetTransport(nil) - p := protocolFactory.GetProtocol(trans) - ReadWriteI64(t, p, trans) - trans.Close() - } - for _, tf := range transports { - trans := tf.GetTransport(nil) - p := protocolFactory.GetProtocol(trans) - ReadWriteDouble(t, p, trans) - trans.Close() - } - for _, tf := range transports { - trans := tf.GetTransport(nil) - p := protocolFactory.GetProtocol(trans) - ReadWriteString(t, p, trans) - trans.Close() - } - for _, tf := range transports { - trans := tf.GetTransport(nil) - p := protocolFactory.GetProtocol(trans) - ReadWriteBinary(t, p, trans) - trans.Close() - } - for _, tf := range transports { - trans := tf.GetTransport(nil) - p := protocolFactory.GetProtocol(trans) - ReadWriteWork(t, p, trans) - trans.Close() - } - for _, tf := range transports { - trans := tf.GetTransport(nil) - p := protocolFactory.GetProtocol(trans) - ReadWriteCalculate(t, p, trans) - trans.Close() - } - - // this test doesn't work in all cases due to EOF issues between - // buffer read and buffer write when using the same bufio for both - //for _, tf := range transports { - // trans := tf.GetTransport(nil) - // p := GetProtocol(trans); - // ReadWriteI64(t, p, trans); - // ReadWriteDouble(t, p, trans); - // ReadWriteBinary(t, p, trans); - // ReadWriteByte(t, p, trans); - // trans.Close() - //} - -} - -func ReadWriteBool(t *testing.T, p TProtocol, trans TTransport) { - thetype := TType(BOOL) - thelen := len(BOOL_VALUES) - err := p.WriteListBegin(thetype, thelen) - if err != nil { - t.Errorf("%s: %T %T %q Error writing list begin: %q", "ReadWriteBool", p, trans, err, thetype) - } - for k, v := range BOOL_VALUES { - err = p.WriteBool(v) - if err != nil { - t.Errorf("%s: %T %T %q Error writing bool in list at index %d: %q", "ReadWriteBool", p, trans, err, k, v) - } - } - p.WriteListEnd() - if err != nil { - t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES) - } - p.Flush() - thetype2, thelen2, err := p.ReadListBegin() - if err != nil { - t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES) - } - _, ok := p.(*TSimpleJSONProtocol) - if !ok { - if thetype != thetype2 { - t.Errorf("%s: %T %T type %s != type %s", "ReadWriteBool", p, trans, thetype, thetype2) - } - if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteBool", p, trans, thelen, thelen2) - } - } - for k, v := range BOOL_VALUES { - value, err := p.ReadBool() - if err != nil { - t.Errorf("%s: %T %T %q Error reading bool at index %d: %q", "ReadWriteBool", p, trans, err, k, v) - } - if v != value { - t.Errorf("%s: index %d %q %q %q != %q", "ReadWriteBool", k, p, trans, v, value) - } - } - err = p.ReadListEnd() - if err != nil { - t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteBool", p, trans, err) - } -} - -func ReadWriteByte(t *testing.T, p TProtocol, trans TTransport) { - thetype := TType(BYTE) - thelen := len(BYTE_VALUES) - err := p.WriteListBegin(thetype, thelen) - if err != nil { - t.Errorf("%s: %T %T %q Error writing list begin: %q", "ReadWriteByte", p, trans, err, thetype) - } - for k, v := range BYTE_VALUES { - err = p.WriteByte(v) - if err != nil { - t.Errorf("%s: %T %T %q Error writing byte in list at index %d: %q", "ReadWriteByte", p, trans, err, k, v) - } - } - err = p.WriteListEnd() - if err != nil { - t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) - } - err = p.Flush() - if err != nil { - t.Errorf("%s: %T %T %q Error flushing list of bytes: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) - } - thetype2, thelen2, err := p.ReadListBegin() - if err != nil { - t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) - } - _, ok := p.(*TSimpleJSONProtocol) - if !ok { - if thetype != thetype2 { - t.Errorf("%s: %T %T type %s != type %s", "ReadWriteByte", p, trans, thetype, thetype2) - } - if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteByte", p, trans, thelen, thelen2) - } - } - for k, v := range BYTE_VALUES { - value, err := p.ReadByte() - if err != nil { - t.Errorf("%s: %T %T %q Error reading byte at index %d: %q", "ReadWriteByte", p, trans, err, k, v) - } - if v != value { - t.Errorf("%s: %T %T %d != %d", "ReadWriteByte", p, trans, v, value) - } - } - err = p.ReadListEnd() - if err != nil { - t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteByte", p, trans, err) - } -} - -func ReadWriteI16(t *testing.T, p TProtocol, trans TTransport) { - thetype := TType(I16) - thelen := len(INT16_VALUES) - p.WriteListBegin(thetype, thelen) - for _, v := range INT16_VALUES { - p.WriteI16(v) - } - p.WriteListEnd() - p.Flush() - thetype2, thelen2, err := p.ReadListBegin() - if err != nil { - t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI16", p, trans, err, INT16_VALUES) - } - _, ok := p.(*TSimpleJSONProtocol) - if !ok { - if thetype != thetype2 { - t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI16", p, trans, thetype, thetype2) - } - if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI16", p, trans, thelen, thelen2) - } - } - for k, v := range INT16_VALUES { - value, err := p.ReadI16() - if err != nil { - t.Errorf("%s: %T %T %q Error reading int16 at index %d: %q", "ReadWriteI16", p, trans, err, k, v) - } - if v != value { - t.Errorf("%s: %T %T %d != %d", "ReadWriteI16", p, trans, v, value) - } - } - err = p.ReadListEnd() - if err != nil { - t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI16", p, trans, err) - } -} - -func ReadWriteI32(t *testing.T, p TProtocol, trans TTransport) { - thetype := TType(I32) - thelen := len(INT32_VALUES) - p.WriteListBegin(thetype, thelen) - for _, v := range INT32_VALUES { - p.WriteI32(v) - } - p.WriteListEnd() - p.Flush() - thetype2, thelen2, err := p.ReadListBegin() - if err != nil { - t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI32", p, trans, err, INT32_VALUES) - } - _, ok := p.(*TSimpleJSONProtocol) - if !ok { - if thetype != thetype2 { - t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI32", p, trans, thetype, thetype2) - } - if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI32", p, trans, thelen, thelen2) - } - } - for k, v := range INT32_VALUES { - value, err := p.ReadI32() - if err != nil { - t.Errorf("%s: %T %T %q Error reading int32 at index %d: %q", "ReadWriteI32", p, trans, err, k, v) - } - if v != value { - t.Errorf("%s: %T %T %d != %d", "ReadWriteI32", p, trans, v, value) - } - } - if err != nil { - t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI32", p, trans, err) - } -} - -func ReadWriteI64(t *testing.T, p TProtocol, trans TTransport) { - thetype := TType(I64) - thelen := len(INT64_VALUES) - p.WriteListBegin(thetype, thelen) - for _, v := range INT64_VALUES { - p.WriteI64(v) - } - p.WriteListEnd() - p.Flush() - thetype2, thelen2, err := p.ReadListBegin() - if err != nil { - t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI64", p, trans, err, INT64_VALUES) - } - _, ok := p.(*TSimpleJSONProtocol) - if !ok { - if thetype != thetype2 { - t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI64", p, trans, thetype, thetype2) - } - if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI64", p, trans, thelen, thelen2) - } - } - for k, v := range INT64_VALUES { - value, err := p.ReadI64() - if err != nil { - t.Errorf("%s: %T %T %q Error reading int64 at index %d: %q", "ReadWriteI64", p, trans, err, k, v) - } - if v != value { - t.Errorf("%s: %T %T %q != %q", "ReadWriteI64", p, trans, v, value) - } - } - if err != nil { - t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI64", p, trans, err) - } -} - -func ReadWriteDouble(t *testing.T, p TProtocol, trans TTransport) { - thetype := TType(DOUBLE) - thelen := len(DOUBLE_VALUES) - p.WriteListBegin(thetype, thelen) - for _, v := range DOUBLE_VALUES { - p.WriteDouble(v) - } - p.WriteListEnd() - p.Flush() - wrotebuffer := "" - if memtrans, ok := trans.(*TMemoryBuffer); ok { - wrotebuffer = memtrans.String() - } - thetype2, thelen2, err := p.ReadListBegin() - if err != nil { - t.Errorf("%s: %T %T %q Error reading list: %q, wrote: %v", "ReadWriteDouble", p, trans, err, DOUBLE_VALUES, wrotebuffer) - } - if thetype != thetype2 { - t.Errorf("%s: %T %T type %s != type %s", "ReadWriteDouble", p, trans, thetype, thetype2) - } - if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteDouble", p, trans, thelen, thelen2) - } - for k, v := range DOUBLE_VALUES { - value, err := p.ReadDouble() - if err != nil { - t.Errorf("%s: %T %T %q Error reading double at index %d: %q", "ReadWriteDouble", p, trans, err, k, v) - } - if math.IsNaN(v) { - if !math.IsNaN(value) { - t.Errorf("%s: %T %T math.IsNaN(%q) != math.IsNaN(%q)", "ReadWriteDouble", p, trans, v, value) - } - } else if v != value { - t.Errorf("%s: %T %T %v != %q", "ReadWriteDouble", p, trans, v, value) - } - } - err = p.ReadListEnd() - if err != nil { - t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteDouble", p, trans, err) - } -} - -func ReadWriteString(t *testing.T, p TProtocol, trans TTransport) { - thetype := TType(STRING) - thelen := len(STRING_VALUES) - p.WriteListBegin(thetype, thelen) - for _, v := range STRING_VALUES { - p.WriteString(v) - } - p.WriteListEnd() - p.Flush() - thetype2, thelen2, err := p.ReadListBegin() - if err != nil { - t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteString", p, trans, err, STRING_VALUES) - } - _, ok := p.(*TSimpleJSONProtocol) - if !ok { - if thetype != thetype2 { - t.Errorf("%s: %T %T type %s != type %s", "ReadWriteString", p, trans, thetype, thetype2) - } - if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteString", p, trans, thelen, thelen2) - } - } - for k, v := range STRING_VALUES { - value, err := p.ReadString() - if err != nil { - t.Errorf("%s: %T %T %q Error reading string at index %d: %q", "ReadWriteString", p, trans, err, k, v) - } - if v != value { - t.Errorf("%s: %T %T %d != %d", "ReadWriteString", p, trans, v, value) - } - } - if err != nil { - t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteString", p, trans, err) - } -} - - -func ReadWriteBinary(t *testing.T, p TProtocol, trans TTransport) { - v := protocol_bdata - p.WriteBinary(v) - p.Flush() - value, err := p.ReadBinary() - if err != nil { - t.Errorf("%s: %T %T Unable to read binary: %s", "ReadWriteBinary", p, trans, err.String()) - } - if len(v) != len(value) { - t.Errorf("%s: %T %T len(v) != len(value)... %d != %d", "ReadWriteBinary", p, trans, len(v), len(value)) - } else { - for i := 0; i < len(v); i++ { - if v[i] != value[i] { - t.Errorf("%s: %T %T %s != %s", "ReadWriteBinary", p, trans, v, value) - } - } - } -} - - -func ReadWriteWork(t *testing.T, p TProtocol, trans TTransport) { - thetype := "struct" - orig := NewWork() - orig.Num1 = 25 - orig.Num2 = 102 - orig.Op = ADD - orig.Comment = "Add: 25 + 102" - return - if e := orig.Write(p); e != nil { - t.Fatalf("Unable to write %s value %#v due to error: %s", thetype, orig, e.String()) - } - read := NewWork() - e := read.Read(p) - if e != nil { - t.Fatalf("Unable to read %s due to error: %s", thetype, e.String()) - } - if !orig.Equals(read) { - t.Fatalf("Original Write != Read: %#v != %#v ", orig, read) - } -} - - -func ReadWriteCalculate(t *testing.T, p TProtocol, trans TTransport) { - messageName := "calculate" - logid := int32(12) - seqId := int32(35) - w := NewWork() - w.Num1 = 25 - w.Num2 = 102 - w.Op = ADD - w.Comment = "Add: 25 + 102" - - args31 := NewCalculateArgs() - args31.Logid = logid - args31.W = w - p.WriteMessageBegin(messageName, CALL, seqId) - if err := args31.Write(p); err != nil { - t.Fatalf("%s: %T %T Unable to write message: %s", messageName, p, trans, err.String()) - } - p.WriteMessageEnd() - p.Transport().Flush() - - name, ttype, seqid, err1 := p.ReadMessageBegin() - if err1 != nil { - t.Fatalf("%s: %T %T Unable to read message begin: %s", messageName, p, trans, err1.String()) - } - if name != messageName { - t.Errorf("%s: %T %T Expected message named \"%s\", but was: \"%s\"", messageName, p, trans, messageName, name) - } - if ttype != CALL { - t.Errorf("%s: %T %T Expected message type \"%s\", but was: \"%s\"", messageName, p, trans, CALL, ttype) - } - if seqid != seqId { - t.Errorf("%s: %T %T Expected message type \"%s\", but was: \"%s\"", messageName, p, trans, seqId, seqid) - } - calcArgs := NewCalculateArgs() - err2 := calcArgs.Read(p) - if !args31.Equals(calcArgs) { - //cmp1, _ := args31.W.CompareTo(calcArgs.W) - cmp2, ok := args31.CompareTo(calcArgs) - t.Errorf("%s: %T %T Calculate args not as expected, %T vs %T, cmp: %#v, ok: %#v, equals: %#v", messageName, p, trans, args31, calcArgs, cmp2, ok, args31.Equals(calcArgs)) - } - if err2 != nil { - t.Fatalf("%s: %T %T Unable to read message end: %s", messageName, p, trans, err2.String()) - } - err3 := p.ReadMessageEnd() - if err3 != nil { - t.Fatalf("%s: %T %T Unable to read message end: %s", messageName, p, trans, err3.String()) - } -} - - -/** - *You can define enums, which are just 32 bit integers. Values are optional - *and start at 1 if not supplied, C style again. - */ -type Operation int - -const ( - ADD Operation = 1 - SUBTRACT Operation = 2 - MULTIPLY Operation = 3 - DIVIDE Operation = 4 -) - -func (p Operation) String() string { - switch p { - case ADD: - return "ADD" - case SUBTRACT: - return "SUBTRACT" - case MULTIPLY: - return "MULTIPLY" - case DIVIDE: - return "DIVIDE" - } - return "" -} - -func FromOperationString(s string) Operation { - switch s { - case "ADD": - return ADD - case "SUBTRACT": - return SUBTRACT - case "MULTIPLY": - return MULTIPLY - case "DIVIDE": - return DIVIDE - } - return Operation(-10000) -} - -func (p Operation) Value() int { - return int(p) -} - -func (p Operation) IsEnum() bool { - return true -} - -/** - *Thrift lets you do typedefs to get pretty names for your types. Standard - *C style here. - */ -type MyInteger int32 - -const INT32CONSTANT = 9853 - -var MAPCONSTANT TMap -/** - * Structs are the basic complex data structures. They are comprised of fields - * which each have an integer identifier, a type, a symbolic name, and an - * optional default value. - * - * Fields can be declared "optional", which ensures they will not be included - * in the serialized output if they aren't set. Note that this requires some - * manual management in some languages. - * - * Attributes: - * - Num1 - * - Num2 - * - Op - * - Comment - */ -type Work struct { - TStruct - _ interface{} "num1" // nil # 0 - Num1 int32 "num1" // 1 - Num2 int32 "num2" // 2 - Op Operation "op" // 3 - Comment string "comment" // 4 -} - -func NewWork() *Work { - output := &Work{ - TStruct: NewTStruct("Work", []TField{ - NewTField("num1", I32, 1), - NewTField("num2", I32, 2), - NewTField("op", I32, 3), - NewTField("comment", STRING, 4), - }), - } - { - output.Num1 = 0 - } - return output -} - -func (p *Work) Read(iprot TProtocol) (err TProtocolException) { - _, err = iprot.ReadStructBegin() - if err != nil { - return NewTProtocolExceptionReadStruct(p.ThriftName(), err) - } - for { - fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() - if fieldId < 0 { - fieldId = int16(p.FieldIdFromFieldName(fieldName)) - } else if fieldName == "" { - fieldName = p.FieldNameFromFieldId(int(fieldId)) - } - if fieldTypeId == GENERIC { - fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId() - } - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - if fieldTypeId == STOP { - break - } - if fieldId == 1 || fieldName == "num1" { - if fieldTypeId == I32 { - err = p.ReadField1(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else if fieldTypeId == VOID { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else { - err = p.ReadField1(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - } else if fieldId == 2 || fieldName == "num2" { - if fieldTypeId == I32 { - err = p.ReadField2(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else if fieldTypeId == VOID { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else { - err = p.ReadField2(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - } else if fieldId == 3 || fieldName == "op" { - if fieldTypeId == I32 { - err = p.ReadField3(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else if fieldTypeId == VOID { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else { - err = p.ReadField3(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - } else if fieldId == 4 || fieldName == "comment" { - if fieldTypeId == STRING { - err = p.ReadField4(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else if fieldTypeId == VOID { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else { - err = p.ReadField4(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - } else { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - err = iprot.ReadFieldEnd() - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - err = iprot.ReadStructEnd() - if err != nil { - return NewTProtocolExceptionReadStruct(p.ThriftName(), err) - } - return err -} - -func (p *Work) ReadField1(iprot TProtocol) (err TProtocolException) { - v4, err5 := iprot.ReadI32() - if err5 != nil { - return NewTProtocolExceptionReadField(1, "num1", p.ThriftName(), err5) - } - p.Num1 = v4 - return err -} - -func (p *Work) ReadFieldNum1(iprot TProtocol) TProtocolException { - return p.ReadField1(iprot) -} - -func (p *Work) ReadField2(iprot TProtocol) (err TProtocolException) { - v6, err7 := iprot.ReadI32() - if err7 != nil { - return NewTProtocolExceptionReadField(2, "num2", p.ThriftName(), err7) - } - p.Num2 = v6 - return err -} - -func (p *Work) ReadFieldNum2(iprot TProtocol) TProtocolException { - return p.ReadField2(iprot) -} - -func (p *Work) ReadField3(iprot TProtocol) (err TProtocolException) { - v8, err9 := iprot.ReadI32() - if err9 != nil { - return NewTProtocolExceptionReadField(3, "op", p.ThriftName(), err9) - } - p.Op = Operation(v8) - return err -} - -func (p *Work) ReadFieldOp(iprot TProtocol) TProtocolException { - return p.ReadField3(iprot) -} - -func (p *Work) ReadField4(iprot TProtocol) (err TProtocolException) { - v10, err11 := iprot.ReadString() - if err11 != nil { - return NewTProtocolExceptionReadField(4, "comment", p.ThriftName(), err11) - } - p.Comment = v10 - return err -} - -func (p *Work) ReadFieldComment(iprot TProtocol) TProtocolException { - return p.ReadField4(iprot) -} - -func (p *Work) Write(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteStructBegin("Work") - if err != nil { - return NewTProtocolExceptionWriteStruct(p.ThriftName(), err) - } - err = p.WriteField1(oprot) - if err != nil { - return err - } - err = p.WriteField2(oprot) - if err != nil { - return err - } - err = p.WriteField3(oprot) - if err != nil { - return err - } - err = p.WriteField4(oprot) - if err != nil { - return err - } - err = oprot.WriteFieldStop() - if err != nil { - return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err) - } - err = oprot.WriteStructEnd() - if err != nil { - return NewTProtocolExceptionWriteStruct(p.ThriftName(), err) - } - return err -} - -func (p *Work) WriteField1(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteFieldBegin("num1", I32, 1) - if err != nil { - return NewTProtocolExceptionWriteField(1, "num1", p.ThriftName(), err) - } - err = oprot.WriteI32(int32(p.Num1)) - if err != nil { - return NewTProtocolExceptionWriteField(1, "num1", p.ThriftName(), err) - } - err = oprot.WriteFieldEnd() - if err != nil { - return NewTProtocolExceptionWriteField(1, "num1", p.ThriftName(), err) - } - return err -} - -func (p *Work) WriteFieldNum1(oprot TProtocol) TProtocolException { - return p.WriteField1(oprot) -} - -func (p *Work) WriteField2(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteFieldBegin("num2", I32, 2) - if err != nil { - return NewTProtocolExceptionWriteField(2, "num2", p.ThriftName(), err) - } - err = oprot.WriteI32(int32(p.Num2)) - if err != nil { - return NewTProtocolExceptionWriteField(2, "num2", p.ThriftName(), err) - } - err = oprot.WriteFieldEnd() - if err != nil { - return NewTProtocolExceptionWriteField(2, "num2", p.ThriftName(), err) - } - return err -} - -func (p *Work) WriteFieldNum2(oprot TProtocol) TProtocolException { - return p.WriteField2(oprot) -} - -func (p *Work) WriteField3(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteFieldBegin("op", I32, 3) - if err != nil { - return NewTProtocolExceptionWriteField(3, "op", p.ThriftName(), err) - } - err = oprot.WriteI32(int32(p.Op)) - if err != nil { - return NewTProtocolExceptionWriteField(3, "op", p.ThriftName(), err) - } - err = oprot.WriteFieldEnd() - if err != nil { - return NewTProtocolExceptionWriteField(3, "op", p.ThriftName(), err) - } - return err -} - -func (p *Work) WriteFieldOp(oprot TProtocol) TProtocolException { - return p.WriteField3(oprot) -} - -func (p *Work) WriteField4(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteFieldBegin("comment", STRING, 4) - if err != nil { - return NewTProtocolExceptionWriteField(4, "comment", p.ThriftName(), err) - } - err = oprot.WriteString(string(p.Comment)) - if err != nil { - return NewTProtocolExceptionWriteField(4, "comment", p.ThriftName(), err) - } - err = oprot.WriteFieldEnd() - if err != nil { - return NewTProtocolExceptionWriteField(4, "comment", p.ThriftName(), err) - } - return err -} - -func (p *Work) WriteFieldComment(oprot TProtocol) TProtocolException { - return p.WriteField4(oprot) -} - -func (p *Work) TStructName() string { - return "Work" -} - -func (p *Work) ThriftName() string { - return "Work" -} - -func (p *Work) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("Work(%+v)", *p) -} - -func (p *Work) CompareTo(other interface{}) (int, bool) { - if other == nil { - return 1, true - } - data, ok := other.(*Work) - if !ok { - return 0, false - } - if p.Num1 != data.Num1 { - if p.Num1 < data.Num1 { - return -1, true - } - return 1, true - } - if p.Num2 != data.Num2 { - if p.Num2 < data.Num2 { - return -1, true - } - return 1, true - } - if p.Op != data.Op { - if p.Op < data.Op { - return -1, true - } - return 1, true - } - if p.Comment != data.Comment { - if p.Comment < data.Comment { - return -1, true - } - return 1, true - } - return 0, true -} - -func (p *Work) AttributeByFieldId(id int) interface{} { - switch id { - default: - return nil - case 1: - return p.Num1 - case 2: - return p.Num2 - case 3: - return p.Op - case 4: - return p.Comment - } - return nil -} - -func (p *Work) TStructFields() TFieldContainer { - return NewTFieldContainer([]TField{ - NewTField("num1", I32, 1), - NewTField("num2", I32, 2), - NewTField("op", I32, 3), - NewTField("comment", STRING, 4), - }) -} - - -type ICalculator interface { - /** - * Parameters: - * - Key - */ - Calculate(logid int32, w *Work) (retval30 int32, ouch *InvalidOperation, err os.Error) -} - -type CalculatorClient struct { - Transport TTransport - ProtocolFactory TProtocolFactory - InputProtocol TProtocol - OutputProtocol TProtocol - SeqId int32 -} - -func NewCalculatorClientFactory(t TTransport, f TProtocolFactory) *CalculatorClient { - return &CalculatorClient{Transport: t, - ProtocolFactory: f, - InputProtocol: f.GetProtocol(t), - OutputProtocol: f.GetProtocol(t), - SeqId: 0, - } -} - -func NewCalculatorClientProtocol(t TTransport, iprot TProtocol, oprot TProtocol) *CalculatorClient { - return &CalculatorClient{Transport: t, - ProtocolFactory: nil, - InputProtocol: iprot, - OutputProtocol: oprot, - SeqId: 0, - } -} - - -/** - * Parameters: - * - Logid - * - W - */ -func (p *CalculatorClient) Calculate(logid int32, w *Work) (retval30 int32, ouch *InvalidOperation, err os.Error) { - err = p.SendCalculate(logid, w) - if err != nil { - return - } - return p.RecvCalculate() -} - -func (p *CalculatorClient) SendCalculate(logid int32, w *Work) (err os.Error) { - oprot := p.OutputProtocol - if oprot != nil { - oprot = p.ProtocolFactory.GetProtocol(p.Transport) - p.OutputProtocol = oprot - } - oprot.WriteMessageBegin("calculate", CALL, p.SeqId) - args31 := NewCalculateArgs() - args31.Logid = logid - args31.W = w - err = args31.Write(oprot) - oprot.WriteMessageEnd() - oprot.Transport().Flush() - return -} - - -func (p *CalculatorClient) RecvCalculate() (value int32, ouch *InvalidOperation, err os.Error) { - iprot := p.InputProtocol - if iprot == nil { - iprot = p.ProtocolFactory.GetProtocol(p.Transport) - p.InputProtocol = iprot - } - _, mTypeId, _, err := iprot.ReadMessageBegin() - if err != nil { - return - } - if mTypeId == EXCEPTION { - error33 := NewTApplicationExceptionDefault() - error34, err := error33.Read(iprot) - if err != nil { - return - } - if err = iprot.ReadMessageEnd(); err != nil { - return - } - err = error34 - return - } - result32 := NewCalculateResult() - err = result32.Read(iprot) - iprot.ReadMessageEnd() - value = result32.Success - if result32.Ouch != nil { - ouch = result32.Ouch - } - return -} - - -/** - * Attributes: - * - Logid - * - W - */ -type CalculateArgs struct { - TStruct - _ interface{} "logid" // nil # 0 - Logid int32 "logid" // 1 - W *Work "w" // 2 -} - -func NewCalculateArgs() *CalculateArgs { - output := &CalculateArgs{ - TStruct: NewTStruct("calculate_args", []TField{ - NewTField("logid", I32, 1), - NewTField("w", STRUCT, 2), - }), - } - { - } - return output -} - -func (p *CalculateArgs) Read(iprot TProtocol) (err TProtocolException) { - _, err = iprot.ReadStructBegin() - if err != nil { - return NewTProtocolExceptionReadStruct(p.ThriftName(), err) - } - for { - fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() - if fieldId < 0 { - fieldId = int16(p.FieldIdFromFieldName(fieldName)) - } else if fieldName == "" { - fieldName = p.FieldNameFromFieldId(int(fieldId)) - } - if fieldTypeId == GENERIC { - fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId() - } - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - if fieldTypeId == STOP { - break - } - if fieldId == 1 || fieldName == "logid" { - if fieldTypeId == I32 { - err = p.ReadField1(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else if fieldTypeId == VOID { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else { - err = p.ReadField1(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - } else if fieldId == 2 || fieldName == "w" { - if fieldTypeId == STRUCT { - err = p.ReadField2(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else if fieldTypeId == VOID { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else { - err = p.ReadField2(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - } else { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - err = iprot.ReadFieldEnd() - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - err = iprot.ReadStructEnd() - if err != nil { - return NewTProtocolExceptionReadStruct(p.ThriftName(), err) - } - return err -} - -func (p *CalculateArgs) ReadField1(iprot TProtocol) (err TProtocolException) { - v47, err48 := iprot.ReadI32() - if err48 != nil { - return NewTProtocolExceptionReadField(1, "logid", p.ThriftName(), err48) - } - p.Logid = v47 - return err -} - -func (p *CalculateArgs) ReadFieldLogid(iprot TProtocol) TProtocolException { - return p.ReadField1(iprot) -} - -func (p *CalculateArgs) ReadField2(iprot TProtocol) (err TProtocolException) { - p.W = NewWork() - err51 := p.W.Read(iprot) - if err51 != nil { - return NewTProtocolExceptionReadStruct("p.WWork", err51) - } - return err -} - -func (p *CalculateArgs) ReadFieldW(iprot TProtocol) TProtocolException { - return p.ReadField2(iprot) -} - -func (p *CalculateArgs) Write(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteStructBegin("calculate_args") - if err != nil { - return NewTProtocolExceptionWriteStruct(p.ThriftName(), err) - } - err = p.WriteField1(oprot) - if err != nil { - return err - } - err = p.WriteField2(oprot) - if err != nil { - return err - } - err = oprot.WriteFieldStop() - if err != nil { - return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err) - } - err = oprot.WriteStructEnd() - if err != nil { - return NewTProtocolExceptionWriteStruct(p.ThriftName(), err) - } - return err -} - -func (p *CalculateArgs) WriteField1(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteFieldBegin("logid", I32, 1) - if err != nil { - return NewTProtocolExceptionWriteField(1, "logid", p.ThriftName(), err) - } - err = oprot.WriteI32(int32(p.Logid)) - if err != nil { - return NewTProtocolExceptionWriteField(1, "logid", p.ThriftName(), err) - } - err = oprot.WriteFieldEnd() - if err != nil { - return NewTProtocolExceptionWriteField(1, "logid", p.ThriftName(), err) - } - return err -} - -func (p *CalculateArgs) WriteFieldLogid(oprot TProtocol) TProtocolException { - return p.WriteField1(oprot) -} - -func (p *CalculateArgs) WriteField2(oprot TProtocol) (err TProtocolException) { - if p.W != nil { - err = oprot.WriteFieldBegin("w", STRUCT, 2) - if err != nil { - return NewTProtocolExceptionWriteField(2, "w", p.ThriftName(), err) - } - err = p.W.Write(oprot) - if err != nil { - return NewTProtocolExceptionWriteStruct("Work", err) - } - err = oprot.WriteFieldEnd() - if err != nil { - return NewTProtocolExceptionWriteField(2, "w", p.ThriftName(), err) - } - } - return err -} - -func (p *CalculateArgs) WriteFieldW(oprot TProtocol) TProtocolException { - return p.WriteField2(oprot) -} - -func (p *CalculateArgs) TStructName() string { - return "CalculateArgs" -} - -func (p *CalculateArgs) ThriftName() string { - return "calculate_args" -} - -func (p *CalculateArgs) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("CalculateArgs(%+v)", *p) -} - -func (p *CalculateArgs) CompareTo(other interface{}) (int, bool) { - if other == nil { - return 1, true - } - data, ok := other.(*CalculateArgs) - if !ok { - return 0, false - } - if p.Logid != data.Logid { - if p.Logid < data.Logid { - return -1, true - } - return 1, true - } - if cmp, ok := p.W.CompareTo(data.W); !ok || cmp != 0 { - return cmp, ok - } - return 0, true -} - -func (p *CalculateArgs) AttributeByFieldId(id int) interface{} { - switch id { - default: - return nil - case 1: - return p.Logid - case 2: - return p.W - } - return nil -} - -func (p *CalculateArgs) TStructFields() TFieldContainer { - return NewTFieldContainer([]TField{ - NewTField("logid", I32, 1), - NewTField("w", STRUCT, 2), - }) -} - -/** - * Attributes: - * - Success - * - Ouch - */ -type CalculateResult struct { - TStruct - Success int32 "success" // 0 - Ouch *InvalidOperation "ouch" // 1 -} - -func NewCalculateResult() *CalculateResult { - output := &CalculateResult{ - TStruct: NewTStruct("calculate_result", []TField{ - NewTField("success", I32, 0), - NewTField("ouch", STRUCT, 1), - }), - } - { - } - return output -} - -func (p *CalculateResult) Read(iprot TProtocol) (err TProtocolException) { - _, err = iprot.ReadStructBegin() - if err != nil { - return NewTProtocolExceptionReadStruct(p.ThriftName(), err) - } - for { - fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() - if fieldId < 0 { - fieldId = int16(p.FieldIdFromFieldName(fieldName)) - } else if fieldName == "" { - fieldName = p.FieldNameFromFieldId(int(fieldId)) - } - if fieldTypeId == GENERIC { - fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId() - } - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - if fieldTypeId == STOP { - break - } - if fieldId == 0 || fieldName == "success" { - if fieldTypeId == I32 { - err = p.ReadField0(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else if fieldTypeId == VOID { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else { - err = p.ReadField0(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - } else if fieldId == 1 || fieldName == "ouch" { - if fieldTypeId == STRUCT { - err = p.ReadField1(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else if fieldTypeId == VOID { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else { - err = p.ReadField1(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - } else { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - err = iprot.ReadFieldEnd() - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - err = iprot.ReadStructEnd() - if err != nil { - return NewTProtocolExceptionReadStruct(p.ThriftName(), err) - } - return err -} - -func (p *CalculateResult) ReadField0(iprot TProtocol) (err TProtocolException) { - v52, err53 := iprot.ReadI32() - if err53 != nil { - return NewTProtocolExceptionReadField(0, "success", p.ThriftName(), err53) - } - p.Success = v52 - return err -} - -func (p *CalculateResult) ReadFieldSuccess(iprot TProtocol) TProtocolException { - return p.ReadField0(iprot) -} - -func (p *CalculateResult) ReadField1(iprot TProtocol) (err TProtocolException) { - p.Ouch = NewInvalidOperation() - err56 := p.Ouch.Read(iprot) - if err56 != nil { - return NewTProtocolExceptionReadStruct("p.OuchInvalidOperation", err56) - } - return err -} - -func (p *CalculateResult) ReadFieldOuch(iprot TProtocol) TProtocolException { - return p.ReadField1(iprot) -} - -func (p *CalculateResult) Write(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteStructBegin("calculate_result") - if err != nil { - return NewTProtocolExceptionWriteStruct(p.ThriftName(), err) - } - err = p.WriteField0(oprot) - if err != nil { - return err - } - err = p.WriteField1(oprot) - if err != nil { - return err - } - err = oprot.WriteFieldStop() - if err != nil { - return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err) - } - err = oprot.WriteStructEnd() - if err != nil { - return NewTProtocolExceptionWriteStruct(p.ThriftName(), err) - } - return err -} - -func (p *CalculateResult) WriteField0(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteFieldBegin("success", I32, 0) - if err != nil { - return NewTProtocolExceptionWriteField(0, "success", p.ThriftName(), err) - } - err = oprot.WriteI32(int32(p.Success)) - if err != nil { - return NewTProtocolExceptionWriteField(0, "success", p.ThriftName(), err) - } - err = oprot.WriteFieldEnd() - if err != nil { - return NewTProtocolExceptionWriteField(0, "success", p.ThriftName(), err) - } - return err -} - -func (p *CalculateResult) WriteFieldSuccess(oprot TProtocol) TProtocolException { - return p.WriteField0(oprot) -} - -func (p *CalculateResult) WriteField1(oprot TProtocol) (err TProtocolException) { - if p.Ouch != nil { - err = oprot.WriteFieldBegin("ouch", STRUCT, 1) - if err != nil { - return NewTProtocolExceptionWriteField(1, "ouch", p.ThriftName(), err) - } - err = p.Ouch.Write(oprot) - if err != nil { - return NewTProtocolExceptionWriteStruct("InvalidOperation", err) - } - err = oprot.WriteFieldEnd() - if err != nil { - return NewTProtocolExceptionWriteField(1, "ouch", p.ThriftName(), err) - } - } - return err -} - -func (p *CalculateResult) WriteFieldOuch(oprot TProtocol) TProtocolException { - return p.WriteField1(oprot) -} - -func (p *CalculateResult) TStructName() string { - return "CalculateResult" -} - -func (p *CalculateResult) ThriftName() string { - return "calculate_result" -} - -func (p *CalculateResult) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("CalculateResult(%+v)", *p) -} - -func (p *CalculateResult) CompareTo(other interface{}) (int, bool) { - if other == nil { - return 1, true - } - data, ok := other.(*CalculateResult) - if !ok { - return 0, false - } - if p.Success != data.Success { - if p.Success < data.Success { - return -1, true - } - return 1, true - } - if cmp, ok := p.Ouch.CompareTo(data.Ouch); !ok || cmp != 0 { - return cmp, ok - } - return 0, true -} - -func (p *CalculateResult) AttributeByFieldId(id int) interface{} { - switch id { - default: - return nil - case 0: - return p.Success - case 1: - return p.Ouch - } - return nil -} - -func (p *CalculateResult) TStructFields() TFieldContainer { - return NewTFieldContainer([]TField{ - NewTField("success", I32, 0), - NewTField("ouch", STRUCT, 1), - }) -} - - -/** - * Structs can also be exceptions, if they are nasty. - * - * Attributes: - * - What - * - Why - */ -type InvalidOperation struct { - TStruct - _ interface{} "what" // nil # 0 - What int32 "what" // 1 - Why string "why" // 2 -} - -func NewInvalidOperation() *InvalidOperation { - output := &InvalidOperation{ - TStruct: NewTStruct("InvalidOperation", []TField{ - NewTField("what", I32, 1), - NewTField("why", STRING, 2), - }), - } - { - } - return output -} - -func (p *InvalidOperation) Read(iprot TProtocol) (err TProtocolException) { - _, err = iprot.ReadStructBegin() - if err != nil { - return NewTProtocolExceptionReadStruct(p.ThriftName(), err) - } - for { - fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() - if fieldId < 0 { - fieldId = int16(p.FieldIdFromFieldName(fieldName)) - } else if fieldName == "" { - fieldName = p.FieldNameFromFieldId(int(fieldId)) - } - if fieldTypeId == GENERIC { - fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId() - } - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - if fieldTypeId == STOP { - break - } - if fieldId == 1 || fieldName == "what" { - if fieldTypeId == I32 { - err = p.ReadField1(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else if fieldTypeId == VOID { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else { - err = p.ReadField1(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - } else if fieldId == 2 || fieldName == "why" { - if fieldTypeId == STRING { - err = p.ReadField2(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else if fieldTypeId == VOID { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } else { - err = p.ReadField2(iprot) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - } else { - err = iprot.Skip(fieldTypeId) - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - err = iprot.ReadFieldEnd() - if err != nil { - return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err) - } - } - err = iprot.ReadStructEnd() - if err != nil { - return NewTProtocolExceptionReadStruct(p.ThriftName(), err) - } - return err -} - -func (p *InvalidOperation) ReadField1(iprot TProtocol) (err TProtocolException) { - v12, err13 := iprot.ReadI32() - if err13 != nil { - return NewTProtocolExceptionReadField(1, "what", p.ThriftName(), err13) - } - p.What = v12 - return err -} - -func (p *InvalidOperation) ReadFieldWhat(iprot TProtocol) TProtocolException { - return p.ReadField1(iprot) -} - -func (p *InvalidOperation) ReadField2(iprot TProtocol) (err TProtocolException) { - v14, err15 := iprot.ReadString() - if err15 != nil { - return NewTProtocolExceptionReadField(2, "why", p.ThriftName(), err15) - } - p.Why = v14 - return err -} - -func (p *InvalidOperation) ReadFieldWhy(iprot TProtocol) TProtocolException { - return p.ReadField2(iprot) -} - -func (p *InvalidOperation) Write(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteStructBegin("InvalidOperation") - if err != nil { - return NewTProtocolExceptionWriteStruct(p.ThriftName(), err) - } - err = p.WriteField1(oprot) - if err != nil { - return err - } - err = p.WriteField2(oprot) - if err != nil { - return err - } - err = oprot.WriteFieldStop() - if err != nil { - return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err) - } - err = oprot.WriteStructEnd() - if err != nil { - return NewTProtocolExceptionWriteStruct(p.ThriftName(), err) - } - return err -} - -func (p *InvalidOperation) WriteField1(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteFieldBegin("what", I32, 1) - if err != nil { - return NewTProtocolExceptionWriteField(1, "what", p.ThriftName(), err) - } - err = oprot.WriteI32(int32(p.What)) - if err != nil { - return NewTProtocolExceptionWriteField(1, "what", p.ThriftName(), err) - } - err = oprot.WriteFieldEnd() - if err != nil { - return NewTProtocolExceptionWriteField(1, "what", p.ThriftName(), err) - } - return err -} - -func (p *InvalidOperation) WriteFieldWhat(oprot TProtocol) TProtocolException { - return p.WriteField1(oprot) -} - -func (p *InvalidOperation) WriteField2(oprot TProtocol) (err TProtocolException) { - err = oprot.WriteFieldBegin("why", STRING, 2) - if err != nil { - return NewTProtocolExceptionWriteField(2, "why", p.ThriftName(), err) - } - err = oprot.WriteString(string(p.Why)) - if err != nil { - return NewTProtocolExceptionWriteField(2, "why", p.ThriftName(), err) - } - err = oprot.WriteFieldEnd() - if err != nil { - return NewTProtocolExceptionWriteField(2, "why", p.ThriftName(), err) - } - return err -} - -func (p *InvalidOperation) WriteFieldWhy(oprot TProtocol) TProtocolException { - return p.WriteField2(oprot) -} - -func (p *InvalidOperation) TStructName() string { - return "InvalidOperation" -} - -func (p *InvalidOperation) ThriftName() string { - return "InvalidOperation" -} - -func (p *InvalidOperation) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("InvalidOperation(%+v)", *p) -} - -func (p *InvalidOperation) CompareTo(other interface{}) (int, bool) { - if other == nil { - return 1, true - } - data, ok := other.(*InvalidOperation) - if !ok { - return 0, false - } - if p.What != data.What { - if p.What < data.What { - return -1, true - } - return 1, true - } - if p.Why != data.Why { - if p.Why < data.Why { - return -1, true - } - return 1, true - } - return 0, true -} - -func (p *InvalidOperation) AttributeByFieldId(id int) interface{} { - switch id { - default: - return nil - case 1: - return p.What - case 2: - return p.Why - } - return nil -} - -func (p *InvalidOperation) TStructFields() TFieldContainer { - return NewTFieldContainer([]TField{ - NewTField("what", I32, 1), - NewTField("why", STRING, 2), - }) -} diff --git a/lib/go/thrift/transport.go b/lib/go/thrift/transport.go new file mode 100644 index 00000000..44823dd5 --- /dev/null +++ b/lib/go/thrift/transport.go @@ -0,0 +1,46 @@ +/* + * 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 thrift + +import ( + "errors" + "io" +) + +var errTransportInterrupted = errors.New("Transport Interrupted") + +type Flusher interface { + Flush() (err error) +} + +// Encapsulates the I/O layer +type TTransport interface { + io.ReadWriteCloser + Flusher + + // Opens the transport for communication + Open() error + + // Returns true if the transport is open + IsOpen() bool + + // Returns true if there is more data to be read or the remote side is still open + Peek() bool +} diff --git a/lib/go/thrift/transport_exception.go b/lib/go/thrift/transport_exception.go new file mode 100644 index 00000000..dbab4d97 --- /dev/null +++ b/lib/go/thrift/transport_exception.go @@ -0,0 +1,68 @@ +/* + * 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 thrift + +import ( + "io" +) + +// Thrift Transport exception +type TTransportException interface { + TException + TypeId() int +} + +const ( + UNKNOWN_TRANSPORT_EXCEPTION = 0 + NOT_OPEN = 1 + ALREADY_OPEN = 2 + TIMED_OUT = 3 + END_OF_FILE = 4 +) + +type tTransportException struct { + typeId int + message string +} + +func (p *tTransportException) TypeId() int { + return p.typeId +} + +func (p *tTransportException) Error() string { + return p.message +} + +func NewTTransportException(t int, m string) TTransportException { + return &tTransportException{typeId: t, message: m} +} + +func NewTTransportExceptionFromError(e error) TTransportException { + if e == nil { + return nil + } + if t, ok := e.(TTransportException); ok { + return t + } + if e == io.EOF { + return NewTTransportException(END_OF_FILE, e.Error()) + } + return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, e.Error()) +} diff --git a/lib/go/thrift/ttransport_factory.go b/lib/go/thrift/transport_factory.go similarity index 68% rename from lib/go/thrift/ttransport_factory.go rename to lib/go/thrift/transport_factory.go index 4ab4dbea..533d1b43 100644 --- a/lib/go/thrift/ttransport_factory.go +++ b/lib/go/thrift/transport_factory.go @@ -19,29 +19,21 @@ package thrift -/** - * Factory class used to create wrapped instance of Transports. - * This is used primarily in servers, which get Transports from - * a ServerTransport and then may want to mutate them (i.e. create - * a BufferedTransport from the underlying base transport) - * - */ +// Factory class used to create wrapped instance of Transports. +// This is used primarily in servers, which get Transports from +// a ServerTransport and then may want to mutate them (i.e. create +// a BufferedTransport from the underlying base transport) type TTransportFactory interface { - GetTransport(trans TTransport) TTransport + GetTransport(trans TTransport) TTransport } type tTransportFactory struct{} -/** - * Return a wrapped instance of the base Transport. - * - * @param trans The base transport - * @return Wrapped Transport - */ +// Return a wrapped instance of the base Transport. func (p *tTransportFactory) GetTransport(trans TTransport) TTransport { - return trans + return trans } func NewTTransportFactory() TTransportFactory { - return &tTransportFactory{} + return &tTransportFactory{} } diff --git a/lib/go/thrift/transport_test.go b/lib/go/thrift/transport_test.go new file mode 100644 index 00000000..c9f1d56c --- /dev/null +++ b/lib/go/thrift/transport_test.go @@ -0,0 +1,120 @@ +/* + * 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 thrift + +import ( + "io" + "net" + "strconv" + "testing" +) + +const TRANSPORT_BINARY_DATA_SIZE = 4096 + +var ( + transport_bdata []byte // test data for writing; same as data +) + +func init() { + transport_bdata = make([]byte, TRANSPORT_BINARY_DATA_SIZE) + for i := 0; i < TRANSPORT_BINARY_DATA_SIZE; i++ { + transport_bdata[i] = byte((i + 'a') % 255) + } +} + +func TransportTest(t *testing.T, writeTrans TTransport, readTrans TTransport) { + buf := make([]byte, TRANSPORT_BINARY_DATA_SIZE) + if !writeTrans.IsOpen() { + t.Fatalf("Transport %T not open: %s", writeTrans, writeTrans) + } + if !readTrans.IsOpen() { + t.Fatalf("Transport %T not open: %s", readTrans, readTrans) + } + _, err := writeTrans.Write(transport_bdata) + if err != nil { + t.Fatalf("Transport %T cannot write binary data of length %d: %s", writeTrans, len(transport_bdata), err) + } + err = writeTrans.Flush() + if err != nil { + t.Fatalf("Transport %T cannot flush write of binary data: %s", writeTrans, err) + } + n, err := io.ReadFull(readTrans, buf) + if err != nil { + t.Errorf("Transport %T cannot read binary data of length %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, err) + } + if n != TRANSPORT_BINARY_DATA_SIZE { + t.Errorf("Transport %T read only %d instead of %d bytes of binary data", readTrans, n, TRANSPORT_BINARY_DATA_SIZE) + } + for k, v := range buf { + if v != transport_bdata[k] { + t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k) + } + } + _, err = writeTrans.Write(transport_bdata) + if err != nil { + t.Fatalf("Transport %T cannot write binary data 2 of length %d: %s", writeTrans, len(transport_bdata), err) + } + err = writeTrans.Flush() + if err != nil { + t.Fatalf("Transport %T cannot flush write binary data 2: %s", writeTrans, err) + } + buf = make([]byte, TRANSPORT_BINARY_DATA_SIZE) + read := 1 + for n = 0; n < TRANSPORT_BINARY_DATA_SIZE && read != 0; { + read, err = readTrans.Read(buf[n:]) + if err != nil { + t.Errorf("Transport %T cannot read binary data 2 of total length %d from offset %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, n, err) + } + n += read + } + if n != TRANSPORT_BINARY_DATA_SIZE { + t.Errorf("Transport %T read only %d instead of %d bytes of binary data 2", readTrans, n, TRANSPORT_BINARY_DATA_SIZE) + } + for k, v := range buf { + if v != transport_bdata[k] { + t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k) + } + } +} + +func CloseTransports(t *testing.T, readTrans TTransport, writeTrans TTransport) { + err := readTrans.Close() + if err != nil { + t.Errorf("Transport %T cannot close read transport: %s", readTrans, err) + } + if writeTrans != readTrans { + err = writeTrans.Close() + if err != nil { + t.Errorf("Transport %T cannot close write transport: %s", writeTrans, err) + } + } +} + +func FindAvailableTCPServerPort(startPort int) (net.Addr, error) { + for i := startPort; i < 65535; i++ { + s := "127.0.0.1:" + strconv.Itoa(i) + l, err := net.Listen("tcp", s) + if err == nil { + l.Close() + return net.ResolveTCPAddr("tcp", s) + } + } + return nil, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "Could not find available server port") +} diff --git a/lib/go/thrift/tserver.go b/lib/go/thrift/tserver.go deleted file mode 100644 index 6bc3167e..00000000 --- a/lib/go/thrift/tserver.go +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 thrift - -import ( - "os" -) - -type TServer interface { - /** - * Core processor - */ - ProcessorFactory() TProcessorFactory - /** - * Server transport - */ - ServerTransport() TServerTransport - /** - * Input Transport Factory - */ - InputTransportFactory() TTransportFactory - /** - * Output Transport Factory - */ - OutputTransportFactory() TTransportFactory - /** - * Input Protocol Factory - */ - InputProtocolFactory() TProtocolFactory - /** - * Output Protocol Factory - */ - OutputProtocolFactory() TProtocolFactory - - /** - * The run method fires up the server and gets things going. - */ - Serve() os.Error - /** - * Stop the server. This is optional on a per-implementation basis. Not - * all servers are required to be cleanly stoppable. - */ - Stop() os.Error -} diff --git a/lib/go/thrift/tserver_socket.go b/lib/go/thrift/tserver_socket.go deleted file mode 100644 index dc3e7489..00000000 --- a/lib/go/thrift/tserver_socket.go +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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 thrift - -import ( - "net" - "os" -) - - -type TServerSocket struct { - /** - * Underlying socket conection object - */ - conn net.Conn - /** - * Underlying socket conection object - */ - listener net.Listener - - /** - * Address to listen on - */ - addr net.Addr - - /** - * Client timeout in nanoseconds - */ - nsecClientTimeout int64 -} - -type TServerSocketTransportFactory struct { - addr net.Addr - nsecClientTimeout int64 -} - -func (p *TServerSocketTransportFactory) GetTransport(trans TTransport) TTransport { - if trans != nil { - t, ok := trans.(*TServerSocket) - if ok && t.addr != nil { - s, _ := NewTServerSocketAddrTimeout(t.addr, t.nsecClientTimeout) - return s - } - } - s, _ := NewTServerSocketAddrTimeout(p.addr, p.nsecClientTimeout) - return s -} - -func NewTServerSocketTransportFactory(addr net.Addr, nsecClientTimeout int64) *TServerSocketTransportFactory { - return &TServerSocketTransportFactory{addr: addr, nsecClientTimeout: nsecClientTimeout} -} - -func NewTServerSocketConn(conn net.Conn) *TServerSocket { - return NewTServerSocketConnTimeout(conn, 0) -} - -func NewTServerSocketConnTimeout(conn net.Conn, nsecClientTimeout int64) *TServerSocket { - v := &TServerSocket{conn: conn, addr: conn.LocalAddr(), nsecClientTimeout: nsecClientTimeout} - conn.SetTimeout(nsecClientTimeout) - return v -} - -func NewTServerSocketAddr(addr net.Addr) (*TServerSocket, TTransportException) { - return NewTServerSocketAddrTimeout(addr, 0) -} - -func NewTServerSocketAddrTimeout(addr net.Addr, nsecClientTimeout int64) (*TServerSocket, TTransportException) { - s := &TServerSocket{addr: addr, nsecClientTimeout: nsecClientTimeout} - return s, nil -} - -func (p *TServerSocket) Listen() (err os.Error) { - if p.listener == nil { - if p.listener, err = net.Listen("tcp", p.addr.String()); err != nil { - return err - } - } - return nil -} - -func (p *TServerSocket) Accept() (TTransport, os.Error) { - if p.listener == nil { - if err := p.Listen(); err != nil { - return nil, NewTTransportExceptionFromOsError(err) - } - if p.listener == nil { - return nil, NewTTransportException(NOT_OPEN, "No underlying server socket") - } - } - conn, err := p.listener.Accept() - if err != nil { - return nil, NewTTransportExceptionFromOsError(err) - } - conn.SetTimeout(p.nsecClientTimeout) - return NewTSocketConn(conn) -} - -/** - * Checks whether the socket is connected. - */ -func (p *TServerSocket) IsOpen() bool { - return p.listener != nil -} - -/** - * Connects the socket, creating a new socket object if necessary. - */ -func (p *TServerSocket) Open() os.Error { - if !p.IsOpen() { - l, err := net.Listen(p.addr.Network(), p.addr.String()) - if err != nil { - return err - } - p.listener = l - return nil - } - return NewTTransportException(ALREADY_OPEN, "Server socket already open") -} - -/** - * Perform a nonblocking read into buffer. - */ -func (p *TServerSocket) Read(buf []byte) (int, os.Error) { - return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Read([]byte) is not implemented") -} - -func (p *TServerSocket) ReadAll(buf []byte) (int, os.Error) { - return ReadAllTransport(p, buf) -} - -/** - * Perform a nonblocking write of the data in buffer; - */ -func (p *TServerSocket) Write(buf []byte) (int, os.Error) { - return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Write([]byte) is not implemented") -} - -/** - * Flushes the underlying output stream if not null. - */ -func (p *TServerSocket) Flush() os.Error { - return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Flush() is not implemented") -} - -func (p *TServerSocket) Addr() net.Addr { - return p.addr -} - -func (p *TServerSocket) Peek() bool { - return p.IsOpen() -} - -/** - * Closes the socket. - */ -func (p *TServerSocket) Close() (err os.Error) { - if p.IsOpen() { - err := p.listener.Close() - if err != nil { - return NewTTransportExceptionFromOsError(err) - } - p.listener = nil - } - if p.conn != nil { - err := p.conn.Close() - if err != nil { - return NewTTransportExceptionFromOsError(err) - } - p.conn = nil - } - return nil -} - -func (p *TServerSocket) Interrupt() os.Error { - // TODO(pomack) fix Interrupt as it is probably not right - return NewTTransportExceptionFromOsError(p.Close()) -} diff --git a/lib/go/thrift/tserver_transport.go b/lib/go/thrift/tserver_transport.go deleted file mode 100644 index ef3a462e..00000000 --- a/lib/go/thrift/tserver_transport.go +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 thrift - -import "os" - -/** - * Server transport. Object which provides client transports. - * - */ -type TServerTransport interface { - Listen() os.Error - Accept() (TTransport, os.Error) - Close() os.Error - - /** - * Optional method implementation. This signals to the server transport - * that it should break out of any accept() or listen() that it is currently - * blocked on. This method, if implemented, MUST be thread safe, as it may - * be called from a different thread context than the other TServerTransport - * methods. - */ - Interrupt() os.Error -} diff --git a/lib/go/thrift/tset.go b/lib/go/thrift/tset.go deleted file mode 100644 index f8681098..00000000 --- a/lib/go/thrift/tset.go +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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 thrift - -import ( - "container/list" -) - -/** - * Helper class that encapsulates set metadata. - * - */ -type TSet interface { - TContainer - ElemType() TType - Add(data interface{}) - Remove(data interface{}) - Less(other interface{}) bool - Front() *list.Element - Back() *list.Element - Values() []interface{} -} - -type tSet struct { - elemType TType - size int - l *list.List -} - -func NewTSet(t TType, s int) TSet { - return &tSet{elemType: t, size: s, l: list.New()} -} - -func NewTSetDefault() TSet { - return NewTSet(STOP, 0) -} - -func (p *tSet) ElemType() TType { - return p.elemType -} - -func (p *tSet) Front() *list.Element { - return p.l.Front() -} - -func (p *tSet) Back() *list.Element { - return p.l.Back() -} - -func (p *tSet) Len() int { - if p.l.Len() != 0 { - return p.l.Len() - } - return p.size -} - -func (p *tSet) Contains(data interface{}) bool { - return p.find(data) != nil -} - -func (p *tSet) Add(other interface{}) { - if data, ok := p.elemType.CoerceData(other); ok { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - if cmp, ok := p.elemType.Compare(data, elem.Value); ok && cmp >= 0 { - if cmp > 0 { - p.l.InsertBefore(data, elem) - } - return - } - } - } -} - -func (p *tSet) Remove(data interface{}) { - elem := p.find(data) - if elem != nil { - p.l.Remove(elem) - } -} - -func (p *tSet) Less(other interface{}) bool { - cmp, ok := p.CompareTo(other) - return ok && cmp > 0 -} - -func (p *tSet) Equals(other interface{}) bool { - c, cok := p.CompareTo(other) - return cok && c == 0 -} - -func (p *tSet) CompareTo(other interface{}) (int, bool) { - return TType(SET).Compare(p, other) -} - -func (p *tSet) find(data interface{}) *list.Element { - if data == nil { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - if elem.Value == nil { - return elem - } - } - return nil - } - data, ok := p.elemType.CoerceData(data) - if data == nil || !ok { - return nil - } - if p.elemType.IsBaseType() || p.elemType.IsEnum() { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - if data == elem.Value { - return elem - } - } - return nil - } - if cmp, ok := data.(EqualsOtherInterface); ok { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - if cmp.Equals(elem.Value) { - return elem - } - } - return nil - } - switch p.elemType { - case MAP: - if cmp, ok := data.(EqualsMap); ok { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - v := elem.Value - if v == nil { - continue - } - if cmp.Equals(v.(TMap)) { - return elem - } - } - return nil - } - case SET: - if cmp, ok := data.(EqualsSet); ok { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - v := elem.Value - if v == nil { - continue - } - if cmp.Equals(v.(TSet)) { - return elem - } - } - return nil - } - case LIST: - if cmp, ok := data.(EqualsList); ok { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - v := elem.Value - if v == nil { - continue - } - if cmp.Equals(v.(TList)) { - return elem - } - } - return nil - } - case STRUCT: - if cmp, ok := data.(EqualsStruct); ok { - for elem := p.l.Front(); elem != nil; elem = elem.Next() { - v := elem.Value - if v == nil { - continue - } - if cmp.Equals(v.(TStruct)) { - return elem - } - } - return nil - } - } - return nil -} - -func (p *tSet) Values() []interface{} { - size := p.l.Len() - values := make([]interface{}, size, size) - i := 0 - for v := p.l.Front(); v != nil; v = v.Next() { - values[i] = v.Value - i++ - } - return values -} diff --git a/lib/go/thrift/tsimple_json_protocol.go b/lib/go/thrift/tsimple_json_protocol.go deleted file mode 100644 index 569dd9cc..00000000 --- a/lib/go/thrift/tsimple_json_protocol.go +++ /dev/null @@ -1,1281 +0,0 @@ -/* - * 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 thrift - -import ( - "bufio" - "bytes" - "container/vector" - "encoding/base64" - "fmt" - "io" - "json" - "math" - "os" - "strconv" - "strings" -) - -type _ParseContext int - -const ( - _CONTEXT_IN_TOPLEVEL _ParseContext = 1 - _CONTEXT_IN_LIST_FIRST _ParseContext = 2 - _CONTEXT_IN_LIST _ParseContext = 3 - _CONTEXT_IN_OBJECT_FIRST _ParseContext = 4 - _CONTEXT_IN_OBJECT_NEXT_KEY _ParseContext = 5 - _CONTEXT_IN_OBJECT_NEXT_VALUE _ParseContext = 6 -) - -func (p _ParseContext) String() string { - switch p { - case _CONTEXT_IN_TOPLEVEL: - return "TOPLEVEL" - case _CONTEXT_IN_LIST_FIRST: - return "LIST-FIRST" - case _CONTEXT_IN_LIST: - return "LIST" - case _CONTEXT_IN_OBJECT_FIRST: - return "OBJECT-FIRST" - case _CONTEXT_IN_OBJECT_NEXT_KEY: - return "OBJECT-NEXT-KEY" - case _CONTEXT_IN_OBJECT_NEXT_VALUE: - return "OBJECT-NEXT-VALUE" - } - return "UNKNOWN-PARSE-CONTEXT" -} - -/** - * JSON protocol implementation for thrift. - * - * This protocol produces/consumes a simple output format - * suitable for parsing by scripting languages. It should not be - * confused with the full-featured TJSONProtocol. - * - */ -type TSimpleJSONProtocol struct { - //TProtocolBase; - trans TTransport - - /** - * Stack of nested contexts that we may be in. - */ - parseContextStack vector.IntVector - /** - * Stack of nested contexts that we may be in. - */ - dumpContext vector.IntVector - - /** - * Current context that we are in - */ - writer TTransport - reader *bufio.Reader -} - -/** - * Constructor - */ -func NewTSimpleJSONProtocol(t TTransport) *TSimpleJSONProtocol { - v := &TSimpleJSONProtocol{trans: t, - writer: t, - reader: bufio.NewReader(t), - } - v.parseContextStack.Push(int(_CONTEXT_IN_TOPLEVEL)) - v.dumpContext.Push(int(_CONTEXT_IN_TOPLEVEL)) - return v -} - -/** - * Factory - */ -type TSimpleJSONProtocolFactory struct{} - -func (p *TSimpleJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol { - return NewTSimpleJSONProtocol(trans) -} - -func NewTSimpleJSONProtocolFactory() *TSimpleJSONProtocolFactory { - return &TSimpleJSONProtocolFactory{} -} - -var ( - JSON_COMMA []byte - JSON_COLON []byte - JSON_LBRACE []byte - JSON_RBRACE []byte - JSON_LBRACKET []byte - JSON_RBRACKET []byte - JSON_QUOTE byte - JSON_QUOTE_BYTES []byte - JSON_NULL []byte - JSON_TRUE []byte - JSON_FALSE []byte - JSON_INFINITY string - JSON_NEGATIVE_INFINITY string - JSON_NAN string - JSON_INFINITY_BYTES []byte - JSON_NEGATIVE_INFINITY_BYTES []byte - JSON_NAN_BYTES []byte - json_nonbase_map_elem_bytes []byte -) - -func init() { - JSON_COMMA = []byte{','} - JSON_COLON = []byte{':'} - JSON_LBRACE = []byte{'{'} - JSON_RBRACE = []byte{'}'} - JSON_LBRACKET = []byte{'['} - JSON_RBRACKET = []byte{']'} - JSON_QUOTE = '"' - JSON_QUOTE_BYTES = []byte{'"'} - JSON_NULL = []byte{'n', 'u', 'l', 'l'} - JSON_TRUE = []byte{'t', 'r', 'u', 'e'} - JSON_FALSE = []byte{'f', 'a', 'l', 's', 'e'} - JSON_INFINITY = "Infinity" - JSON_NEGATIVE_INFINITY = "-Infinity" - JSON_NAN = "NaN" - JSON_INFINITY_BYTES = []byte{'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'} - JSON_NEGATIVE_INFINITY_BYTES = []byte{'-', 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'} - JSON_NAN_BYTES = []byte{'N', 'a', 'N'} - json_nonbase_map_elem_bytes = []byte{']', ',', '['} -} - -func JsonQuote(s string) string { - b, _ := json.Marshal(s) - s1 := string(b) - return s1 -} - -func JsonUnquote(s string) (string, bool) { - s1 := new(string) - err := json.Unmarshal([]byte(s), s1) - return *s1, err == nil -} - - -func (p *TSimpleJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) TProtocolException { - if e := p.OutputListBegin(); e != nil { - return e - } - if e := p.WriteString(name); e != nil { - return e - } - if e := p.WriteByte(byte(typeId)); e != nil { - return e - } - if e := p.WriteI32(seqId); e != nil { - return e - } - return nil -} - -func (p *TSimpleJSONProtocol) WriteMessageEnd() TProtocolException { - return p.OutputListEnd() -} - -func (p *TSimpleJSONProtocol) WriteStructBegin(name string) TProtocolException { - if e := p.OutputObjectBegin(); e != nil { - return e - } - return nil -} - -func (p *TSimpleJSONProtocol) WriteStructEnd() TProtocolException { - return p.OutputObjectEnd() -} - -func (p *TSimpleJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException { - if e := p.WriteString(name); e != nil { - return e - } - return nil - /* - if e := p.OutputListBegin(); e != nil { - return e - } - if e := p.WriteByte(byte(typeId)); e != nil { - return e - } - return p.WriteI16(id) - */ -} - -func (p *TSimpleJSONProtocol) WriteFieldEnd() TProtocolException { - //return p.OutputListEnd() - return nil -} - -func (p *TSimpleJSONProtocol) WriteFieldStop() TProtocolException { return nil } - -func (p *TSimpleJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException { - if e := p.OutputListBegin(); e != nil { - return e - } - if e := p.WriteByte(byte(keyType)); e != nil { - return e - } - if e := p.WriteByte(byte(valueType)); e != nil { - return e - } - return p.WriteI32(int32(size)) -} - -func (p *TSimpleJSONProtocol) WriteMapEnd() TProtocolException { - return p.OutputListEnd() -} - -func (p *TSimpleJSONProtocol) WriteListBegin(elemType TType, size int) TProtocolException { - return p.OutputElemListBegin(elemType, size) -} - -func (p *TSimpleJSONProtocol) WriteListEnd() TProtocolException { - return p.OutputListEnd() -} - -func (p *TSimpleJSONProtocol) WriteSetBegin(elemType TType, size int) TProtocolException { - return p.OutputElemListBegin(elemType, size) -} - -func (p *TSimpleJSONProtocol) WriteSetEnd() TProtocolException { - return p.OutputListEnd() -} - -func (p *TSimpleJSONProtocol) WriteBool(b bool) TProtocolException { - return p.OutputBool(b) -} - -func (p *TSimpleJSONProtocol) WriteByte(b byte) TProtocolException { - return p.WriteI32(int32(b)) -} - -func (p *TSimpleJSONProtocol) WriteI16(v int16) TProtocolException { - return p.WriteI32(int32(v)) -} - -func (p *TSimpleJSONProtocol) WriteI32(v int32) TProtocolException { - return p.OutputI64(int64(v)) -} - -func (p *TSimpleJSONProtocol) WriteI64(v int64) TProtocolException { - return p.OutputI64(int64(v)) -} - -func (p *TSimpleJSONProtocol) WriteDouble(v float64) TProtocolException { - return p.OutputF64(v) -} - -func (p *TSimpleJSONProtocol) WriteString(v string) TProtocolException { - return p.OutputString(v) -} - -func (p *TSimpleJSONProtocol) WriteBinary(v []byte) TProtocolException { - // JSON library only takes in a string, - // not an arbitrary byte array, to ensure bytes are transmitted - // efficiently we must convert this into a valid JSON string - // therefore we use base64 encoding to avoid excessive escaping/quoting - if e := p.OutputPreValue(); e != nil { - return e - } - if _, e := p.writer.Write(JSON_QUOTE_BYTES); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - writer := base64.NewEncoder(base64.StdEncoding, p.writer) - if _, e := writer.Write(v); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - if e := writer.Close(); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - if _, e := p.writer.Write(JSON_QUOTE_BYTES); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - return p.OutputPostValue() -} - -/** - * Reading methods. - */ - -func (p *TSimpleJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) { - if isNull, err := p.ParseListBegin(); isNull || err != nil { - return name, typeId, seqId, err - } - if name, err = p.ReadString(); err != nil { - return name, typeId, seqId, err - } - bTypeId, err := p.ReadByte() - typeId = TMessageType(bTypeId) - if err != nil { - return name, typeId, seqId, err - } - if seqId, err = p.ReadI32(); err != nil { - return name, typeId, seqId, err - } - return name, typeId, seqId, nil -} - -func (p *TSimpleJSONProtocol) ReadMessageEnd() TProtocolException { - return p.ParseListEnd() -} - -func (p *TSimpleJSONProtocol) ReadStructBegin() (name string, err TProtocolException) { - _, err = p.ParseObjectStart() - return "", err -} - -func (p *TSimpleJSONProtocol) ReadStructEnd() TProtocolException { - return p.ParseObjectEnd() -} - -func (p *TSimpleJSONProtocol) ReadFieldBegin() (string, TType, int16, TProtocolException) { - if err := p.ParsePreValue(); err != nil { - return "", STOP, 0, err - } - if p.reader.Buffered() < 1 { - return "", STOP, 0, nil - } - b, _ := p.reader.Peek(1) - if len(b) > 0 { - switch b[0] { - case JSON_RBRACE[0]: - return "", STOP, 0, nil - case JSON_QUOTE: - p.reader.ReadByte() - name, err := p.ParseStringBody() - if err != nil { - return name, STOP, 0, err - } - return name, GENERIC, -1, p.ParsePostValue() - /* - if err = p.ParsePostValue(); err != nil { - return name, STOP, 0, err - } - if isNull, err := p.ParseListBegin(); isNull || err != nil { - return name, STOP, 0, err - } - bType, err := p.ReadByte() - thetype := TType(bType) - if err != nil { - return name, thetype, 0, err - } - id, err := p.ReadI16() - return name, thetype, id, err - */ - } - return "", STOP, 0, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \"}\" or '\"', but found: '", string(b), "'")) - } - return "", STOP, 0, NewTProtocolExceptionFromOsError(os.EOF) -} - -func (p *TSimpleJSONProtocol) ReadFieldEnd() TProtocolException { - return nil - //return p.ParseListEnd() -} - -func (p *TSimpleJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e TProtocolException) { - if isNull, e := p.ParseListBegin(); isNull || e != nil { - return VOID, VOID, 0, e - } - - // read keyType - bKeyType, e := p.ReadByte() - keyType = TType(bKeyType) - if e != nil { - return keyType, valueType, size, e - } - - // read valueType - bValueType, e := p.ReadByte() - valueType = TType(bValueType) - if e != nil { - return keyType, valueType, size, e - } - - // read size - iSize, err := p.ReadI64() - size = int(iSize) - return keyType, valueType, size, err -} - -func (p *TSimpleJSONProtocol) ReadMapEnd() TProtocolException { - return p.ParseListEnd() -} - -func (p *TSimpleJSONProtocol) ReadListBegin() (elemType TType, size int, e TProtocolException) { - return p.ParseElemListBegin() -} - -func (p *TSimpleJSONProtocol) ReadListEnd() TProtocolException { - return p.ParseListEnd() -} - -func (p *TSimpleJSONProtocol) ReadSetBegin() (elemType TType, size int, e TProtocolException) { - return p.ParseElemListBegin() -} - -func (p *TSimpleJSONProtocol) ReadSetEnd() TProtocolException { - return p.ParseListEnd() -} - -func (p *TSimpleJSONProtocol) ReadBool() (bool, TProtocolException) { - var value bool - if err := p.ParsePreValue(); err != nil { - return value, err - } - b, _ := p.reader.Peek(len(JSON_FALSE)) - if len(b) > 0 { - switch b[0] { - case JSON_TRUE[0]: - if string(b[0:len(JSON_TRUE)]) == string(JSON_TRUE) { - p.reader.Read(b[0:len(JSON_TRUE)]) - value = true - } else { - return value, NewTProtocolException(INVALID_DATA, "Expected \"true\" but found: "+string(b)) - } - break - case JSON_FALSE[0]: - if string(b[0:len(JSON_FALSE)]) == string(JSON_FALSE) { - p.reader.Read(b[0:len(JSON_FALSE)]) - value = false - } else { - return value, NewTProtocolException(INVALID_DATA, "Expected \"false\" but found: "+string(b)) - } - break - case JSON_NULL[0]: - if string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { - p.reader.Read(b[0:len(JSON_NULL)]) - value = false - } else { - return value, NewTProtocolException(INVALID_DATA, "Expected \"null\" but found: "+string(b)) - } - default: - return value, NewTProtocolException(INVALID_DATA, "Expected \"true\", \"false\", or \"null\" but found: "+string(b)) - } - } - return value, p.ParsePostValue() -} - -func (p *TSimpleJSONProtocol) ReadByte() (byte, TProtocolException) { - v, err := p.ReadI64() - return byte(v), err -} - -func (p *TSimpleJSONProtocol) ReadI16() (int16, TProtocolException) { - v, err := p.ReadI64() - return int16(v), err -} - -func (p *TSimpleJSONProtocol) ReadI32() (int32, TProtocolException) { - v, err := p.ReadI64() - return int32(v), err -} - -func (p *TSimpleJSONProtocol) ReadI64() (int64, TProtocolException) { - v, _, err := p.ParseI64() - return v, err -} - -func (p *TSimpleJSONProtocol) ReadDouble() (float64, TProtocolException) { - v, _, err := p.ParseF64() - return v, err -} - -func (p *TSimpleJSONProtocol) ReadString() (string, TProtocolException) { - var v string - if err := p.ParsePreValue(); err != nil { - return v, err - } - b, _ := p.reader.Peek(len(JSON_NULL)) - if len(b) > 0 && b[0] == JSON_QUOTE { - p.reader.ReadByte() - value, err := p.ParseStringBody() - v = value - if err != nil { - return v, err - } - } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { - _, err := p.reader.Read(b[0:len(JSON_NULL)]) - if err != nil { - return v, NewTProtocolExceptionFromOsError(err) - } - } else { - return v, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected a JSON string, found ", string(b))) - } - return v, p.ParsePostValue() -} - -func (p *TSimpleJSONProtocol) ReadBinary() ([]byte, TProtocolException) { - var v []byte - if err := p.ParsePreValue(); err != nil { - return nil, err - } - b, _ := p.reader.Peek(len(JSON_NULL)) - if len(b) > 0 && b[0] == JSON_QUOTE { - p.reader.ReadByte() - value, err := p.ParseBase64EncodedBody() - v = value - if err != nil { - return v, err - } - } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { - _, err := p.reader.Read(b[0:len(JSON_NULL)]) - if err != nil { - return v, NewTProtocolExceptionFromOsError(err) - } - } else { - return v, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected a JSON string, found ", string(b))) - } - return v, p.ParsePostValue() -} - -func (p *TSimpleJSONProtocol) Flush() (err TProtocolException) { - return NewTProtocolExceptionFromOsError(p.writer.Flush()) -} - -func (p *TSimpleJSONProtocol) Skip(fieldType TType) (err TProtocolException) { - return SkipDefaultDepth(p, fieldType) -} - -func (p *TSimpleJSONProtocol) Transport() TTransport { - return p.trans -} - - -func (p *TSimpleJSONProtocol) OutputPreValue() TProtocolException { - cxt := _ParseContext(p.dumpContext.Last()) - switch cxt { - case _CONTEXT_IN_LIST, _CONTEXT_IN_OBJECT_NEXT_KEY: - if _, e := p.writer.Write(JSON_COMMA); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - break - case _CONTEXT_IN_OBJECT_NEXT_VALUE: - if _, e := p.writer.Write(JSON_COLON); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - break - } - return nil -} - -func (p *TSimpleJSONProtocol) OutputPostValue() TProtocolException { - cxt := _ParseContext(p.dumpContext.Last()) - switch cxt { - case _CONTEXT_IN_LIST_FIRST: - p.dumpContext.Pop() - p.dumpContext.Push(int(_CONTEXT_IN_LIST)) - break - case _CONTEXT_IN_OBJECT_FIRST: - p.dumpContext.Pop() - p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) - break - case _CONTEXT_IN_OBJECT_NEXT_KEY: - p.dumpContext.Pop() - p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) - break - case _CONTEXT_IN_OBJECT_NEXT_VALUE: - p.dumpContext.Pop() - p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_NEXT_KEY)) - break - } - return nil -} - -func (p *TSimpleJSONProtocol) OutputBool(value bool) TProtocolException { - if e := p.OutputPreValue(); e != nil { - return e - } - var v string - if value { - v = string(JSON_TRUE) - } else { - v = string(JSON_FALSE) - } - switch _ParseContext(p.dumpContext.Last()) { - case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: - v = JsonQuote(v) - default: - } - if e := p.OutputStringData(v); e != nil { - return e - } - return p.OutputPostValue() -} - -func (p *TSimpleJSONProtocol) OutputNull() TProtocolException { - if e := p.OutputPreValue(); e != nil { - return e - } - if _, e := p.writer.Write(JSON_NULL); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - return p.OutputPostValue() -} - -func (p *TSimpleJSONProtocol) OutputF64(value float64) TProtocolException { - if e := p.OutputPreValue(); e != nil { - return e - } - var v string - if math.IsNaN(value) { - v = string(JSON_QUOTE) + JSON_NAN + string(JSON_QUOTE) - } else if math.IsInf(value, 1) { - v = string(JSON_QUOTE) + JSON_INFINITY + string(JSON_QUOTE) - } else if math.IsInf(value, -1) { - v = string(JSON_QUOTE) + JSON_NEGATIVE_INFINITY + string(JSON_QUOTE) - } else { - v = strconv.Ftoa64(value, 'g', -1) - switch _ParseContext(p.dumpContext.Last()) { - case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: - v = string(JSON_QUOTE) + v + string(JSON_QUOTE) - default: - } - } - if e := p.OutputStringData(v); e != nil { - return e - } - return p.OutputPostValue() -} - -func (p *TSimpleJSONProtocol) OutputI64(value int64) TProtocolException { - if e := p.OutputPreValue(); e != nil { - return e - } - v := strconv.Itoa64(value) - switch _ParseContext(p.dumpContext.Last()) { - case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: - v = JsonQuote(v) - default: - } - if e := p.OutputStringData(v); e != nil { - return e - } - return p.OutputPostValue() -} - -func (p *TSimpleJSONProtocol) OutputString(s string) TProtocolException { - if e := p.OutputPreValue(); e != nil { - return e - } - if e := p.OutputStringData(JsonQuote(s)); e != nil { - return e - } - return p.OutputPostValue() -} - -func (p *TSimpleJSONProtocol) OutputStringData(s string) TProtocolException { - _, e := io.Copyn(p.writer, strings.NewReader(s), int64(len(s))) - return NewTProtocolExceptionFromOsError(e) -} - -func (p *TSimpleJSONProtocol) OutputObjectBegin() TProtocolException { - if e := p.OutputPreValue(); e != nil { - return e - } - if _, e := p.writer.Write(JSON_LBRACE); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_FIRST)) - return nil -} - -func (p *TSimpleJSONProtocol) OutputObjectEnd() TProtocolException { - if _, e := p.writer.Write(JSON_RBRACE); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - p.dumpContext.Pop() - if e := p.OutputPostValue(); e != nil { - return e - } - return nil -} - -func (p *TSimpleJSONProtocol) OutputListBegin() TProtocolException { - if e := p.OutputPreValue(); e != nil { - return e - } - if _, e := p.writer.Write(JSON_LBRACKET); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - p.dumpContext.Push(int(_CONTEXT_IN_LIST_FIRST)) - return nil -} - -func (p *TSimpleJSONProtocol) OutputListEnd() TProtocolException { - if _, e := p.writer.Write(JSON_RBRACKET); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - p.dumpContext.Pop() - if e := p.OutputPostValue(); e != nil { - return e - } - return nil -} - -func (p *TSimpleJSONProtocol) OutputElemListBegin(elemType TType, size int) TProtocolException { - if e := p.OutputListBegin(); e != nil { - return e - } - if e := p.WriteByte(byte(elemType)); e != nil { - return e - } - if e := p.WriteI64(int64(size)); e != nil { - return e - } - return nil -} - -func (p *TSimpleJSONProtocol) ParsePreValue() TProtocolException { - if e := p.readNonSignificantWhitespace(); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - cxt := _ParseContext(p.parseContextStack.Last()) - if p.reader.Buffered() < 1 { - return nil - } - b, _ := p.reader.Peek(1) - switch cxt { - case _CONTEXT_IN_LIST: - if len(b) > 0 { - switch b[0] { - case JSON_RBRACKET[0]: - return nil - case JSON_COMMA[0]: - p.reader.ReadByte() - if e := p.readNonSignificantWhitespace(); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - return nil - default: - return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \"]\" or \",\" in list context, but found \"", string(b), "\"")) - } - } - break - case _CONTEXT_IN_OBJECT_NEXT_KEY: - if len(b) > 0 { - switch b[0] { - case JSON_RBRACE[0]: - return nil - case JSON_COMMA[0]: - p.reader.ReadByte() - if e := p.readNonSignificantWhitespace(); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - return nil - default: - return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \"}\" or \",\" in object context, but found \"", string(b), "\"")) - } - } - break - case _CONTEXT_IN_OBJECT_NEXT_VALUE: - if len(b) > 0 { - switch b[0] { - case JSON_COLON[0]: - p.reader.ReadByte() - if e := p.readNonSignificantWhitespace(); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - return nil - default: - return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \":\" in object context, but found \"", string(b), "\"")) - } - } - break - } - return nil -} - -func (p *TSimpleJSONProtocol) ParsePostValue() TProtocolException { - if e := p.readNonSignificantWhitespace(); e != nil { - return NewTProtocolExceptionFromOsError(e) - } - cxt := _ParseContext(p.parseContextStack.Last()) - switch cxt { - case _CONTEXT_IN_LIST_FIRST: - p.parseContextStack.Pop() - p.parseContextStack.Push(int(_CONTEXT_IN_LIST)) - break - case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: - p.parseContextStack.Pop() - p.parseContextStack.Push(int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) - break - case _CONTEXT_IN_OBJECT_NEXT_VALUE: - p.parseContextStack.Pop() - p.parseContextStack.Push(int(_CONTEXT_IN_OBJECT_NEXT_KEY)) - break - } - return nil -} - -func (p *TSimpleJSONProtocol) readNonSignificantWhitespace() os.Error { - for p.reader.Buffered() > 0 { - b, _ := p.reader.Peek(1) - if len(b) < 1 { - return nil - } - switch b[0] { - case ' ', '\r', '\n', '\t': - p.reader.ReadByte() - continue - default: - break - } - break - } - return nil -} - -func (p *TSimpleJSONProtocol) ParseStringBody() (string, TProtocolException) { - line, err := p.reader.ReadString(JSON_QUOTE) - if err != nil { - return "", NewTProtocolExceptionFromOsError(err) - } - l := len(line) - // count number of escapes to see if we need to keep going - i := 1 - for ; i < l; i++ { - if line[l-i-1] != '\\' { - break - } - } - if i&0x01 == 1 { - v, ok := JsonUnquote(string(JSON_QUOTE) + line) - if !ok { - return "", NewTProtocolExceptionFromOsError(err) - } - return v, nil - } - s, err := p.ParseQuotedStringBody() - if err != nil { - return "", NewTProtocolExceptionFromOsError(err) - } - str := string(JSON_QUOTE) + line + s - v, ok := JsonUnquote(str) - if !ok { - return "", NewTProtocolException(INVALID_DATA, "Unable to parse as JSON string "+str) - } - return v, nil -} - -func (p *TSimpleJSONProtocol) ParseQuotedStringBody() (string, TProtocolException) { - line, err := p.reader.ReadString(JSON_QUOTE) - if err != nil { - return "", NewTProtocolExceptionFromOsError(err) - } - l := len(line) - // count number of escapes to see if we need to keep going - i := 1 - for ; i < l; i++ { - if line[l-i-1] != '\\' { - break - } - } - if i&0x01 == 1 { - return line, nil - } - s, err := p.ParseQuotedStringBody() - if err != nil { - return "", NewTProtocolExceptionFromOsError(err) - } - v := line + s - return v, nil -} - -func (p *TSimpleJSONProtocol) ParseBase64EncodedBody() ([]byte, TProtocolException) { - line, err := p.reader.ReadBytes(JSON_QUOTE) - if err != nil { - return line, NewTProtocolExceptionFromOsError(err) - } - line2 := line[0 : len(line)-1] - l := len(line2) - output := make([]byte, base64.StdEncoding.DecodedLen(l)) - n, err := base64.StdEncoding.Decode(output, line2) - return output[0:n], NewTProtocolExceptionFromOsError(err) -} - -func (p *TSimpleJSONProtocol) ParseI64() (int64, bool, TProtocolException) { - if err := p.ParsePreValue(); err != nil { - return 0, false, err - } - var value int64 - var isnull bool - b, _ := p.reader.Peek(len(JSON_NULL)) - if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) { - p.reader.Read(b[0:len(JSON_NULL)]) - isnull = true - } else { - num, err := p.readNumeric() - isnull = (num == nil) - if !isnull { - value = num.Int64() - } - if err != nil { - return value, isnull, err - } - } - return value, isnull, p.ParsePostValue() -} - -func (p *TSimpleJSONProtocol) ParseF64() (float64, bool, TProtocolException) { - if err := p.ParsePreValue(); err != nil { - return 0, false, err - } - var value float64 - var isnull bool - b, _ := p.reader.Peek(len(JSON_NULL)) - if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) { - p.reader.Read(b[0:len(JSON_NULL)]) - isnull = true - } else { - num, err := p.readNumeric() - isnull = (num == nil) - if !isnull { - value = num.Float64() - } - if err != nil { - return value, isnull, err - } - } - return value, isnull, p.ParsePostValue() -} - -func (p *TSimpleJSONProtocol) ParseObjectStart() (bool, TProtocolException) { - if err := p.ParsePreValue(); err != nil { - return false, err - } - b, _ := p.reader.Peek(len(JSON_NULL)) - if len(b) > 0 && b[0] == JSON_LBRACE[0] { - p.reader.ReadByte() - p.parseContextStack.Push(int(_CONTEXT_IN_OBJECT_FIRST)) - return false, nil - } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) { - return true, nil - } - return false, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected '{' or null, but found '", string(b), "'")) -} - -func (p *TSimpleJSONProtocol) ParseObjectEnd() TProtocolException { - if isNull, err := p.readIfNull(); isNull || err != nil { - return err - } - cxt := _ParseContext(p.parseContextStack.Last()) - if cxt != _CONTEXT_IN_OBJECT_FIRST && cxt != _CONTEXT_IN_OBJECT_NEXT_KEY { - return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected to be in the Object Context, but not in Object Context")) - } - line, err := p.reader.ReadString(JSON_RBRACE[0]) - if err != nil { - return NewTProtocolExceptionFromOsError(err) - } - for _, char := range line { - switch char { - default: - return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expecting end of object \"}\", but found: \"", line, "\"")) - case ' ', '\n', '\r', '\t', '}': - break - } - } - p.parseContextStack.Pop() - return p.ParsePostValue() -} - -func (p *TSimpleJSONProtocol) ParseListBegin() (bool, TProtocolException) { - if e := p.ParsePreValue(); e != nil { - return false, e - } - b, e := p.reader.Peek(len(JSON_NULL)) - if e == nil && len(b) >= 1 && b[0] == JSON_LBRACKET[0] { - p.parseContextStack.Push(int(_CONTEXT_IN_LIST_FIRST)) - p.reader.ReadByte() - return false, nil - } else if e == nil && len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) { - return true, nil - } - return false, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Expected 'null' or '{', received '%q'", b)) -} - -func (p *TSimpleJSONProtocol) ParseElemListBegin() (elemType TType, size int, e TProtocolException) { - if isNull, e := p.ParseListBegin(); isNull || e != nil { - return VOID, 0, e - } - bElemType, err := p.ReadByte() - elemType = TType(bElemType) - if err != nil { - return elemType, size, err - } - nSize, err2 := p.ReadI64() - size = int(nSize) - return elemType, size, err2 -} - -func (p *TSimpleJSONProtocol) ParseListEnd() TProtocolException { - if isNull, err := p.readIfNull(); isNull || err != nil { - return err - } - if _ParseContext(p.parseContextStack.Last()) != _CONTEXT_IN_LIST { - return NewTProtocolException(INVALID_DATA, "Expected to be in the List Context, but not in List Context") - } - line, err := p.reader.ReadString(JSON_RBRACKET[0]) - if err != nil { - return NewTProtocolExceptionFromOsError(err) - } - for _, char := range line { - switch char { - default: - return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expecting end of list \"]\", but found: \"", line, "\"")) - case ' ', '\n', '\r', '\t', int(JSON_RBRACKET[0]): - break - } - } - p.parseContextStack.Pop() - return p.ParsePostValue() -} - -func (p *TSimpleJSONProtocol) readSingleValue() (interface{}, TType, TProtocolException) { - e := p.readNonSignificantWhitespace() - if e != nil { - return nil, VOID, NewTProtocolExceptionFromOsError(e) - } - b, e := p.reader.Peek(10) - if len(b) > 0 { - c := b[0] - switch c { - case JSON_NULL[0]: - buf := make([]byte, len(JSON_NULL)) - _, e := p.reader.Read(buf) - if e != nil { - return nil, VOID, NewTProtocolExceptionFromOsError(e) - } - if string(JSON_NULL) != string(buf) { - e := NewTProtocolException(INVALID_DATA, "Expected '"+string(JSON_NULL)+"' but found '"+string(buf)+"' while parsing JSON.") - return nil, VOID, e - } - return nil, VOID, nil - case JSON_QUOTE: - p.reader.ReadByte() - v, e := p.ParseStringBody() - if e != nil { - return v, UTF8, NewTProtocolExceptionFromOsError(e) - } - if v == JSON_INFINITY { - return INFINITY, DOUBLE, nil - } else if v == JSON_NEGATIVE_INFINITY { - return NEGATIVE_INFINITY, DOUBLE, nil - } else if v == JSON_NAN { - return NAN, DOUBLE, nil - } - return v, UTF8, nil - case JSON_TRUE[0]: - buf := make([]byte, len(JSON_TRUE)) - _, e := p.reader.Read(buf) - if e != nil { - return true, BOOL, NewTProtocolExceptionFromOsError(e) - } - if string(JSON_TRUE) != string(buf) { - e := NewTProtocolException(INVALID_DATA, "Expected '"+string(JSON_TRUE)+"' but found '"+string(buf)+"' while parsing JSON.") - return true, BOOL, NewTProtocolExceptionFromOsError(e) - } - return true, BOOL, nil - case JSON_FALSE[0]: - buf := make([]byte, len(JSON_FALSE)) - _, e := p.reader.Read(buf) - if e != nil { - return false, BOOL, NewTProtocolExceptionFromOsError(e) - } - if string(JSON_FALSE) != string(buf) { - e := NewTProtocolException(INVALID_DATA, "Expected '"+string(JSON_FALSE)+"' but found '"+string(buf)+"' while parsing JSON.") - return false, BOOL, NewTProtocolExceptionFromOsError(e) - } - return false, BOOL, nil - case JSON_LBRACKET[0]: - _, e := p.reader.ReadByte() - return make([]interface{}, 0), LIST, NewTProtocolExceptionFromOsError(e) - case JSON_LBRACE[0]: - _, e := p.reader.ReadByte() - return make(map[string]interface{}), STRUCT, NewTProtocolExceptionFromOsError(e) - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E', '.', '+', '-', JSON_INFINITY[0], JSON_NAN[0]: - // assume numeric - v, e := p.readNumeric() - return v, DOUBLE, e - default: - return nil, VOID, NewTProtocolException(INVALID_DATA, "Expected element in list but found '"+string(c)+"' while parsing JSON.") - } - } - return nil, VOID, NewTProtocolException(INVALID_DATA, "Cannot read a single element while parsing JSON.") - -} - - -func (p *TSimpleJSONProtocol) readIfNull() (bool, TProtocolException) { - cont := true - for p.reader.Buffered() > 0 && cont { - b, _ := p.reader.Peek(1) - if len(b) < 1 { - return false, nil - } - switch b[0] { - default: - return false, nil - case JSON_NULL[0]: - cont = false - break - case ' ', '\n', '\r', '\t': - p.reader.ReadByte() - break - } - } - if p.reader.Buffered() == 0 { - return false, nil - } - b, _ := p.reader.Peek(len(JSON_NULL)) - if string(b) == string(JSON_NULL) { - p.reader.Read(b[0:len(JSON_NULL)]) - return true, nil - } - return false, nil -} - -func (p *TSimpleJSONProtocol) readQuoteIfNext() { - if p.reader.Buffered() < 1 { - return - } - b, _ := p.reader.Peek(1) - if len(b) > 0 && b[0] == JSON_QUOTE { - p.reader.ReadByte() - } -} - -func (p *TSimpleJSONProtocol) readNumeric() (Numeric, TProtocolException) { - isNull, err := p.readIfNull() - if isNull || err != nil { - return NUMERIC_NULL, err - } - hasDecimalPoint := false - nextCanBeSign := true - hasE := false - MAX_LEN := 40 - buf := bytes.NewBuffer(make([]byte, 0, MAX_LEN)) - continueFor := true - inQuotes := false - for continueFor { - c, err := p.reader.ReadByte() - if err != nil { - if err == os.EOF { - break - } - return NUMERIC_NULL, NewTProtocolExceptionFromOsError(err) - } - switch c { - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - buf.WriteByte(c) - nextCanBeSign = false - case '.': - if hasDecimalPoint { - return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number with multiple decimal points '%s.'", buf.String())) - } - if hasE { - return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number with decimal points in the exponent '%s.'", buf.String())) - } - buf.WriteByte(c) - hasDecimalPoint, nextCanBeSign = true, false - case 'e', 'E': - if hasE { - return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number with multiple exponents '%s%c'", buf.String(), c)) - } - buf.WriteByte(c) - hasE, nextCanBeSign = true, true - case '-', '+': - if !nextCanBeSign { - return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprint("Negative sign within number")) - } - buf.WriteByte(c) - nextCanBeSign = false - case ' ', 0, '\t', '\n', '\r', JSON_RBRACE[0], JSON_RBRACKET[0], JSON_COMMA[0], JSON_COLON[0]: - p.reader.UnreadByte() - continueFor = false - case JSON_NAN[0]: - if buf.Len() == 0 { - buffer := make([]byte, len(JSON_NAN)) - buffer[0] = c - _, e := p.reader.Read(buffer[1:]) - if e != nil { - return NUMERIC_NULL, NewTProtocolExceptionFromOsError(e) - } - if JSON_NAN != string(buffer) { - e := NewTProtocolException(INVALID_DATA, "Expected '"+JSON_NAN+"' but found '"+string(buffer)+"' while parsing JSON.") - return NUMERIC_NULL, e - } - if inQuotes { - p.readQuoteIfNext() - } - return NAN, nil - } else { - return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number starting with character '%c'", c)) - } - case JSON_INFINITY[0]: - if buf.Len() == 0 || (buf.Len() == 1 && buf.Bytes()[0] == '+') { - buffer := make([]byte, len(JSON_INFINITY)) - buffer[0] = c - _, e := p.reader.Read(buffer[1:]) - if e != nil { - return NUMERIC_NULL, NewTProtocolExceptionFromOsError(e) - } - if JSON_INFINITY != string(buffer) { - e := NewTProtocolException(INVALID_DATA, "Expected '"+JSON_INFINITY+"' but found '"+string(buffer)+"' while parsing JSON.") - return NUMERIC_NULL, e - } - if inQuotes { - p.readQuoteIfNext() - } - return INFINITY, nil - } else if buf.Len() == 1 && buf.Bytes()[0] == JSON_NEGATIVE_INFINITY[0] { - buffer := make([]byte, len(JSON_NEGATIVE_INFINITY)) - buffer[0] = JSON_NEGATIVE_INFINITY[0] - buffer[1] = c - _, e := p.reader.Read(buffer[2:]) - if e != nil { - return NUMERIC_NULL, NewTProtocolExceptionFromOsError(e) - } - if JSON_NEGATIVE_INFINITY != string(buffer) { - e := NewTProtocolException(INVALID_DATA, "Expected '"+JSON_NEGATIVE_INFINITY+"' but found '"+string(buffer)+"' while parsing JSON.") - return NUMERIC_NULL, e - } - if inQuotes { - p.readQuoteIfNext() - } - return NEGATIVE_INFINITY, nil - } else { - return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number starting with character '%c' due to existing buffer %s", c, buf.String())) - } - case JSON_QUOTE: - if !inQuotes { - inQuotes = true - } else { - break - } - default: - return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number starting with character '%c'", c)) - } - } - if buf.Len() == 0 { - return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprint("Unable to parse number from empty string ''")) - } - return NewNumericFromJSONString(buf.String(), false), nil -} diff --git a/lib/go/thrift/tsimple_json_protocol_test.go b/lib/go/thrift/tsimple_json_protocol_test.go deleted file mode 100644 index f6f5f489..00000000 --- a/lib/go/thrift/tsimple_json_protocol_test.go +++ /dev/null @@ -1,662 +0,0 @@ -/* - * 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 thrift_test - -import ( - . "thrift" - "encoding/base64" - "fmt" - "json" - "math" - "strconv" - "strings" - "testing" -) - -func TestWriteSimpleJSONProtocolBool(t *testing.T) { - thetype := "boolean" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - for _, value := range BOOL_VALUES { - if e := p.WriteBool(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := false - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadSimpleJSONProtocolBool(t *testing.T) { - thetype := "boolean" - for _, value := range BOOL_VALUES { - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - if value { - trans.Write(JSON_TRUE) - } else { - trans.Write(JSON_FALSE) - } - trans.Flush() - s := trans.String() - v, e := p.ReadBool() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteSimpleJSONProtocolByte(t *testing.T) { - thetype := "byte" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - for _, value := range BYTE_VALUES { - if e := p.WriteByte(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := byte(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadSimpleJSONProtocolByte(t *testing.T) { - thetype := "byte" - for _, value := range BYTE_VALUES { - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() - s := trans.String() - v, e := p.ReadByte() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteSimpleJSONProtocolI16(t *testing.T) { - thetype := "int16" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - for _, value := range INT16_VALUES { - if e := p.WriteI16(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := int16(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadSimpleJSONProtocolI16(t *testing.T) { - thetype := "int16" - for _, value := range INT16_VALUES { - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() - s := trans.String() - v, e := p.ReadI16() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteSimpleJSONProtocolI32(t *testing.T) { - thetype := "int32" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - for _, value := range INT32_VALUES { - if e := p.WriteI32(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := int32(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadSimpleJSONProtocolI32(t *testing.T) { - thetype := "int32" - for _, value := range INT32_VALUES { - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() - s := trans.String() - v, e := p.ReadI32() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteSimpleJSONProtocolI64(t *testing.T) { - thetype := "int64" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - for _, value := range INT64_VALUES { - if e := p.WriteI64(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := int64(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadSimpleJSONProtocolI64(t *testing.T) { - thetype := "int64" - for _, value := range INT64_VALUES { - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - trans.WriteString(strconv.Itoa64(value)) - trans.Flush() - s := trans.String() - v, e := p.ReadI64() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteSimpleJSONProtocolDouble(t *testing.T) { - thetype := "double" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - for _, value := range DOUBLE_VALUES { - if e := p.WriteDouble(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if math.IsInf(value, 1) { - if s != JsonQuote(JSON_INFINITY) { - t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_INFINITY)) - } - } else if math.IsInf(value, -1) { - if s != JsonQuote(JSON_NEGATIVE_INFINITY) { - t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_NEGATIVE_INFINITY)) - } - } else if math.IsNaN(value) { - if s != JsonQuote(JSON_NAN) { - t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_NAN)) - } - } else { - if s != fmt.Sprint(value) { - t.Fatalf("Bad value for %s %v: %s", thetype, value, s) - } - v := float64(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - } - trans.Reset() - } - trans.Close() -} - -func TestReadSimpleJSONProtocolDouble(t *testing.T) { - thetype := "double" - for _, value := range DOUBLE_VALUES { - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - n := NewNumericFromDouble(value) - trans.WriteString(n.String()) - trans.Flush() - s := trans.String() - v, e := p.ReadDouble() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if math.IsInf(value, 1) { - if !math.IsInf(v, 1) { - t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) - } - } else if math.IsInf(value, -1) { - if !math.IsInf(v, -1) { - t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) - } - } else if math.IsNaN(value) { - if !math.IsNaN(v) { - t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) - } - } else { - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - } - trans.Reset() - trans.Close() - } -} - -func TestWriteSimpleJSONProtocolString(t *testing.T) { - thetype := "string" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - for _, value := range STRING_VALUES { - if e := p.WriteString(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s[0] != '"' || s[len(s)-1] != '"' { - t.Fatalf("Bad value for %s '%v', wrote '%v', expected: %v", thetype, value, s, fmt.Sprint("\"", value, "\"")) - } - v := new(string) - if err := json.Unmarshal([]byte(s), v); err != nil || *v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v) - } - trans.Reset() - } - trans.Close() -} - -func TestReadSimpleJSONProtocolString(t *testing.T) { - thetype := "string" - for _, value := range STRING_VALUES { - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - trans.WriteString(JsonQuote(value)) - trans.Flush() - s := trans.String() - v, e := p.ReadString() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if v != value { - t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) - } - v1 := new(string) - if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) - } - trans.Reset() - trans.Close() - } -} - -func TestWriteSimpleJSONProtocolBinary(t *testing.T) { - thetype := "binary" - value := protocol_bdata - b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) - base64.StdEncoding.Encode(b64value, value) - b64String := string(b64value) - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - if e := p.WriteBinary(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String()) - } - s := trans.String() - if s != fmt.Sprint("\"", b64String, "\"") { - t.Fatalf("Bad value for %s %v\n wrote: %v\nexpected: %v", thetype, value, s, "\""+b64String+"\"") - } - v1 := new(string) - if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) - } - trans.Close() -} - -func TestReadSimpleJSONProtocolBinary(t *testing.T) { - thetype := "binary" - value := protocol_bdata - b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) - base64.StdEncoding.Encode(b64value, value) - b64String := string(b64value) - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - trans.WriteString(JsonQuote(b64String)) - trans.Flush() - s := trans.String() - v, e := p.ReadBinary() - if e != nil { - t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String()) - } - if len(v) != len(value) { - t.Fatalf("Bad value for %s value length %v, wrote: %v, received length: %v", thetype, len(value), s, len(v)) - } - for i := 0; i < len(v); i++ { - if v[i] != value[i] { - t.Fatalf("Bad value for %s at index %d value %v, wrote: %v, received: %v", thetype, i, value[i], s, v[i]) - } - } - v1 := new(string) - if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) - } - trans.Reset() - trans.Close() -} - -func TestWriteSimpleJSONProtocolList(t *testing.T) { - thetype := "list" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - p.WriteListBegin(TType(DOUBLE), len(DOUBLE_VALUES)) - for _, value := range DOUBLE_VALUES { - if e := p.WriteDouble(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - } - p.WriteListEnd() - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String()) - } - str := trans.String() - str1 := new([]interface{}) - err := json.Unmarshal([]byte(str), str1) - if err != nil { - t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) - } - l := *str1 - if len(l) < 2 { - t.Fatalf("List must be at least of length two to include metadata") - } - if int(l[0].(float64)) != DOUBLE { - t.Fatal("Invalid type for list, expected: ", DOUBLE, ", but was: ", l[0]) - } - if int(l[1].(float64)) != len(DOUBLE_VALUES) { - t.Fatal("Invalid length for list, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) - } - for k, value := range DOUBLE_VALUES { - s := l[k+2] - if math.IsInf(value, 1) { - if s.(string) != JSON_INFINITY { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_INFINITY), str) - } - } else if math.IsInf(value, 0) { - if s.(string) != JSON_NEGATIVE_INFINITY { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY), str) - } - } else if math.IsNaN(value) { - if s.(string) != JSON_NAN { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NAN), str) - } - } else { - if s.(float64) != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) - } - } - trans.Reset() - } - trans.Close() -} - -func TestWriteSimpleJSONProtocolSet(t *testing.T) { - thetype := "set" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - p.WriteSetBegin(TType(DOUBLE), len(DOUBLE_VALUES)) - for _, value := range DOUBLE_VALUES { - if e := p.WriteDouble(value); e != nil { - t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String()) - } - } - p.WriteSetEnd() - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String()) - } - str := trans.String() - str1 := new([]interface{}) - err := json.Unmarshal([]byte(str), str1) - if err != nil { - t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) - } - l := *str1 - if len(l) < 2 { - t.Fatalf("Set must be at least of length two to include metadata") - } - if int(l[0].(float64)) != DOUBLE { - t.Fatal("Invalid type for set, expected: ", DOUBLE, ", but was: ", l[0]) - } - if int(l[1].(float64)) != len(DOUBLE_VALUES) { - t.Fatal("Invalid length for set, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) - } - for k, value := range DOUBLE_VALUES { - s := l[k+2] - if math.IsInf(value, 1) { - if s.(string) != JSON_INFINITY { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_INFINITY), str) - } - } else if math.IsInf(value, 0) { - if s.(string) != JSON_NEGATIVE_INFINITY { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY), str) - } - } else if math.IsNaN(value) { - if s.(string) != JSON_NAN { - t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NAN), str) - } - } else { - if s.(float64) != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) - } - } - trans.Reset() - } - trans.Close() -} - -func TestWriteSimpleJSONProtocolMap(t *testing.T) { - thetype := "map" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - p.WriteMapBegin(TType(I32), TType(DOUBLE), len(DOUBLE_VALUES)) - for k, value := range DOUBLE_VALUES { - if e := p.WriteI32(int32(k)); e != nil { - t.Fatalf("Unable to write %s key int32 value %v due to error: %s", thetype, k, e.String()) - } - if e := p.WriteDouble(value); e != nil { - t.Fatalf("Unable to write %s value float64 value %v due to error: %s", thetype, value, e.String()) - } - } - p.WriteMapEnd() - if e := p.Flush(); e != nil { - t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String()) - } - str := trans.String() - if str[0] != '[' || str[len(str)-1] != ']' { - t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES) - } - l := strings.Split(str[1:len(str)-1], ",") - if len(l) < 3 { - t.Fatal("Expected list of at least length 3 for map for metadata, but was of length ", len(l)) - } - expectedKeyType, _ := strconv.Atoi(l[0]) - expectedValueType, _ := strconv.Atoi(l[1]) - expectedSize, _ := strconv.Atoi(l[2]) - if expectedKeyType != I32 { - t.Fatal("Expected map key type ", I32, ", but was ", l[0]) - } - if expectedValueType != DOUBLE { - t.Fatal("Expected map value type ", DOUBLE, ", but was ", l[1]) - } - if expectedSize != len(DOUBLE_VALUES) { - t.Fatal("Expected map size of ", len(DOUBLE_VALUES), ", but was ", l[2]) - } - for k, value := range DOUBLE_VALUES { - strk := l[k*2+3] - strv := l[k*2+4] - ik, err := strconv.Atoi(strk) - if err != nil { - t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, strk, string(k), err.String()) - } - if ik != k { - t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v", thetype, k, strk, k) - } - s := strv - if math.IsInf(value, 1) { - if s != JsonQuote(JSON_INFINITY) { - t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_INFINITY)) - } - } else if math.IsInf(value, 0) { - if s != JsonQuote(JSON_NEGATIVE_INFINITY) { - t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY)) - } - } else if math.IsNaN(value) { - if s != JsonQuote(JSON_NAN) { - t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_NAN)) - } - } else { - expected := strconv.Ftoa64(value, 'g', 10) - if s != expected { - t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected %v", thetype, k, value, s, expected) - } - v := float64(0) - if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { - t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) - } - } - trans.Reset() - } - trans.Close() -} - - -func TestReadWriteSimpleJSONStruct(t *testing.T) { - thetype := "struct" - trans := NewTMemoryBuffer() - p := NewTSimpleJSONProtocol(trans) - orig := NewWork() - orig.Num1 = 25 - orig.Num2 = 102 - orig.Op = ADD - orig.Comment = "Add: 25 + 102" - if e := orig.Write(p); e != nil { - t.Fatalf("Unable to write %s value %#v due to error: %s", thetype, orig, e.String()) - } - t.Log("Memory buffer contents: ", trans.String()) - read := NewWork() - e := read.Read(p) - t.Logf("Read %s value: %#v", thetype, read) - if e != nil { - t.Fatalf("Unable to read %s due to error: %s", thetype, e.String()) - } - if !orig.Equals(read) { - t.Fatalf("Original Write != Read: %#v != %#v ", orig, read) - } -} - -func TestReadWriteSimpleJSONProtocol(t *testing.T) { - ReadWriteProtocolTest(t, NewTSimpleJSONProtocolFactory()) -} diff --git a/lib/go/thrift/tsimple_server.go b/lib/go/thrift/tsimple_server.go deleted file mode 100644 index 6c7d656e..00000000 --- a/lib/go/thrift/tsimple_server.go +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 thrift - -import ( - "os" -) - - -/** - * Simple singlethreaded server for testing. - * - */ -type TSimpleServer struct { - stopped bool - - processorFactory TProcessorFactory - serverTransport TServerTransport - inputTransportFactory TTransportFactory - outputTransportFactory TTransportFactory - inputProtocolFactory TProtocolFactory - outputProtocolFactory TProtocolFactory -} - -func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer { - return NewTSimpleServerFactory2(NewTProcessorFactory(processor), serverTransport) -} - -func NewTSimpleServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer { - return NewTSimpleServerFactory4(NewTProcessorFactory(processor), - serverTransport, - transportFactory, - protocolFactory, - ) -} - -func NewTSimpleServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer { - return NewTSimpleServerFactory6(NewTProcessorFactory(processor), - serverTransport, - inputTransportFactory, - outputTransportFactory, - inputProtocolFactory, - outputProtocolFactory, - ) -} - -func NewTSimpleServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TSimpleServer { - return NewTSimpleServerFactory6(processorFactory, - serverTransport, - NewTTransportFactory(), - NewTTransportFactory(), - NewTBinaryProtocolFactoryDefault(), - NewTBinaryProtocolFactoryDefault(), - ) -} - -func NewTSimpleServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer { - return NewTSimpleServerFactory6(processorFactory, - serverTransport, - transportFactory, - transportFactory, - protocolFactory, - protocolFactory, - ) -} - -func NewTSimpleServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer { - return &TSimpleServer{processorFactory: processorFactory, - serverTransport: serverTransport, - inputTransportFactory: inputTransportFactory, - outputTransportFactory: outputTransportFactory, - inputProtocolFactory: inputProtocolFactory, - outputProtocolFactory: outputProtocolFactory, - } -} - -func (p *TSimpleServer) ProcessorFactory() TProcessorFactory { - return p.processorFactory -} - -func (p *TSimpleServer) ServerTransport() TServerTransport { - return p.serverTransport -} - -func (p *TSimpleServer) InputTransportFactory() TTransportFactory { - return p.inputTransportFactory -} - -func (p *TSimpleServer) OutputTransportFactory() TTransportFactory { - return p.outputTransportFactory -} - -func (p *TSimpleServer) InputProtocolFactory() TProtocolFactory { - return p.inputProtocolFactory -} - -func (p *TSimpleServer) OutputProtocolFactory() TProtocolFactory { - return p.outputProtocolFactory -} - -func (p *TSimpleServer) Serve() os.Error { - p.stopped = false - err := p.serverTransport.Listen() - if err != nil { - return err - } - for !p.stopped { - client, err := p.serverTransport.Accept() - if err != nil { - return err - } - if client != nil { - p.processRequest(client) - } - } - return nil -} - -func (p *TSimpleServer) Stop() os.Error { - p.stopped = true - p.serverTransport.Interrupt() - return nil -} - -func (p *TSimpleServer) processRequest(client TTransport) { - processor := p.processorFactory.GetProcessor(client) - inputTransport := p.inputTransportFactory.GetTransport(client) - outputTransport := p.outputTransportFactory.GetTransport(client) - inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport) - outputProtocol := p.outputProtocolFactory.GetProtocol(outputTransport) - if inputTransport != nil { - defer inputTransport.Close() - } - if outputTransport != nil { - defer outputTransport.Close() - } - for { - ok, e := processor.Process(inputProtocol, outputProtocol) - if e != nil { - if !p.stopped { - // TODO(pomack) log error - break - } - } - if !ok { - break - } - } -} diff --git a/lib/go/thrift/tsocket.go b/lib/go/thrift/tsocket.go deleted file mode 100644 index 3fc62537..00000000 --- a/lib/go/thrift/tsocket.go +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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 thrift - -import ( - "net" - "os" - "bytes" -) - -/** - * Socket implementation of the TTransport interface. To be commented soon! - * - */ -type TSocket struct { - writeBuffer *bytes.Buffer - /** - * Wrapped Socket object - */ - conn net.Conn - /** - * Remote Addr - */ - addr net.Addr - /** - * Socket timeout in nanoseconds - */ - nsecTimeout int64 -} - -/** - * Constructor that takes an already created socket. - * - * @param socket Already created socket object - * @throws TTransportException if there is an error setting up the streams - */ -func NewTSocketConn(connection net.Conn) (*TSocket, TTransportException) { - address := connection.RemoteAddr() - if address == nil { - address = connection.LocalAddr() - } - p := &TSocket{conn: connection, addr: address, nsecTimeout: 0, writeBuffer: bytes.NewBuffer(make([]byte, 0, 4096))} - return p, nil -} - -/** - * Creates a new unconnected socket that will connect to the given host - * on the given port. - * - * @param host Remote host - * @param port Remote port - */ -func NewTSocketAddr(address net.Addr) *TSocket { - return NewTSocket(address, 0) -} - -/** - * Creates a new unconnected socket that will connect to the given host - * on the given port. - * - * @param host Remote host - * @param port Remote port - * @param nsecTimeout Socket timeout - */ -func NewTSocket(address net.Addr, nsecTimeout int64) *TSocket { - sock := &TSocket{addr: address, nsecTimeout: nsecTimeout, writeBuffer: bytes.NewBuffer(make([]byte, 0, 4096))} - return sock -} - -/** - * Sets the socket timeout - * - * @param timeout Nanoseconds timeout - */ -func (p *TSocket) SetTimeout(nsecTimeout int64) os.Error { - p.nsecTimeout = nsecTimeout - if p.IsOpen() { - if err := p.conn.SetTimeout(nsecTimeout); err != nil { - LOGGER.Print("Could not set socket timeout.", err) - return err - } - } - return nil -} - -/** - * Returns a reference to the underlying socket. - */ -func (p *TSocket) Conn() net.Conn { - return p.conn -} - -/** - * Checks whether the socket is connected. - */ -func (p *TSocket) IsOpen() bool { - if p.conn == nil { - return false - } - return true -} - -/** - * Connects the socket, creating a new socket object if necessary. - */ -func (p *TSocket) Open() os.Error { - if p.IsOpen() { - return NewTTransportException(ALREADY_OPEN, "Socket already connected.") - } - if p.addr == nil { - return NewTTransportException(NOT_OPEN, "Cannot open nil address.") - } - if len(p.addr.Network()) == 0 { - return NewTTransportException(NOT_OPEN, "Cannot open bad network name.") - } - if len(p.addr.String()) == 0 { - return NewTTransportException(NOT_OPEN, "Cannot open bad address.") - } - var err os.Error - if p.conn, err = net.Dial(p.addr.Network(), p.addr.String()); err != nil { - LOGGER.Print("Could not open socket", err.String()) - return NewTTransportException(NOT_OPEN, err.String()) - } - if p.conn != nil { - p.conn.SetTimeout(p.nsecTimeout) - } - return nil -} - -/** - * Closes the socket. - */ -func (p *TSocket) Close() os.Error { - // Close the socket - if p.conn != nil { - err := p.conn.Close() - if err != nil { - LOGGER.Print("Could not close socket. ", err.String()) - return err - } - p.conn = nil - } - return nil -} - - -func (p *TSocket) Read(buf []byte) (int, os.Error) { - if !p.IsOpen() { - return 0, NewTTransportException(NOT_OPEN, "Connection not open") - } - n, err := p.conn.Read(buf) - return n, NewTTransportExceptionFromOsError(err) -} - - -func (p *TSocket) ReadAll(buf []byte) (int, os.Error) { - return ReadAllTransport(p, buf) -} - -func (p *TSocket) Write(buf []byte) (int, os.Error) { - if !p.IsOpen() { - return 0, NewTTransportException(NOT_OPEN, "Connection not open") - } - p.writeBuffer.Write(buf) - return len(buf), nil -} - -func (p *TSocket) Peek() bool { - return p.IsOpen() -} - -func (p *TSocket) Flush() os.Error { - if !p.IsOpen() { - return NewTTransportException(NOT_OPEN, "Connection not open") - } - _, err := p.writeBuffer.WriteTo(p.conn) - return NewTTransportExceptionFromOsError(err) -} - -func (p *TSocket) Interrupt() os.Error { - if !p.IsOpen() { - return nil - } - // TODO(pomack) fix Interrupt as this is probably wrong - return p.conn.Close() -} diff --git a/lib/go/thrift/tstruct.go b/lib/go/thrift/tstruct.go deleted file mode 100644 index 5eaffae0..00000000 --- a/lib/go/thrift/tstruct.go +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 thrift - -/** - * Helper class that encapsulates struct metadata. - * - */ -type TStruct interface { - TFieldContainer - TStructName() string - ThriftName() string - TStructFields() TFieldContainer - String() string - AttributeFromFieldId(fieldId int) interface{} - AttributeFromFieldName(fieldName string) interface{} -} - -type tStruct struct { - TFieldContainer - name string -} - -func NewTStructEmpty(name string) TStruct { - return &tStruct{ - name: name, - TFieldContainer: NewTFieldContainer(make([]TField, 0, 0)), - } -} - -func NewTStruct(name string, fields []TField) TStruct { - return &tStruct{ - name: name, - TFieldContainer: NewTFieldContainer(fields), - } -} - -func (p *tStruct) TStructName() string { - return p.name -} - -func (p *tStruct) ThriftName() string { - return p.name -} - -func (p *tStruct) TStructFields() TFieldContainer { - return p.TFieldContainer -} - -func (p *tStruct) String() string { - return p.name -} - -func (p *tStruct) Equals(other interface{}) bool { - cmp, ok := p.CompareTo(other) - return ok && cmp == 0 -} - -func (p *tStruct) CompareTo(other interface{}) (int, bool) { - return TType(STRUCT).Compare(p, other) -} - -func (p *tStruct) AttributeFromFieldId(fieldId int) interface{} { - return nil -} - -func (p *tStruct) AttributeFromFieldName(fieldName string) interface{} { - return p.AttributeFromFieldId(p.FieldIdFromFieldName(fieldName)) -} - - -var ANONYMOUS_STRUCT TStruct - -func init() { - ANONYMOUS_STRUCT = NewTStructEmpty("") -} diff --git a/lib/go/thrift/ttransport.go b/lib/go/thrift/ttransport.go deleted file mode 100644 index f29b0b40..00000000 --- a/lib/go/thrift/ttransport.go +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 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 thrift - -import ( - "os" - "log" - "strconv" -) - -type Flusher interface { - Flush() (err os.Error) -} - -/** - * Generic class that encapsulates the I/O layer. This is basically a thin - * wrapper around the combined functionality of Java input/output streams. - * - */ -type TTransport interface { - /** - * Queries whether the transport is open. - * - * @return True if the transport is open. - */ - IsOpen() bool - - /** - * Opens the transport for reading/writing. - * - * @returns TTransportException if the transport could not be opened - */ - Open() (err os.Error) - - /** - * Closes the transport. - */ - Close() (err os.Error) - - /** - * Reads up to len bytes into buffer buf, starting att offset off. - * - * @param buf Array to read into - * @param off Index to start reading at - * @param len Maximum number of bytes to read - * @return The number of bytes actually read - * @return TTransportException if there was an error reading data - */ - Read(buf []byte) (n int, err os.Error) - - /** - * Guarantees that all of len bytes are actually read off the transport. - * - * @param buf Array to read into - * @param off Index to start reading at - * @param len Maximum number of bytes to read - * @return The number of bytes actually read, which must be equal to len - * @return TTransportException if there was an error reading data - */ - ReadAll(buf []byte) (n int, err os.Error) - - /** - * Writes the buffer to the output - * - * @param buf The output data buffer - * @return Number of bytes written - * @return TTransportException if an error occurs writing data - */ - Write(buf []byte) (n int, err os.Error) - - /** - * Flush any pending data out of a transport buffer. - * - * @return TTransportException if there was an error writing out data. - */ - Flush() (err os.Error) - - /** - * Is there more data to be read? - * - * @return True if the remote side is still alive and feeding us - */ - Peek() bool -} -/* -type TTransportBase struct { -} - -func (p* TTransportBase) IsOpen() bool { - return false; -}; - -func (p* TTransportBase) Peek() bool { - return p.IsOpen(); -} - -func (p* TTransportBase) Open() os.Error { - return NewTTransportException(UNKNOWN, "Subclasses must implement TTransportBase.Open()"); -} - -func (p* TTransportBase) Close() os.Error { - return NewTTransportException(UNKNOWN, "Subclasses must implement TTransportBase.Close()"); -} - -func (p* TTransportBase) Read(buf []byte) (int, os.Error) { - return 0, NewTTransportExceptionDefaultString("Subclasses must implement TTransportBase.Read()"); -} - -func (p* TTransportBase) ReadAll(buf []byte) (n int, err os.Error){ - ret := 0; - size := len(buf); - for (n < size) { - ret, err = p.Read(buf[n:]); - if ret <= 0 { - if err != nil { - err = NewTTransportExceptionDefaultString("Cannot read. Remote side has closed. Tried to read " + string(size) + " bytes, but only got " + string(n) + " bytes."); - } - return ret, err; - } - n += ret; - } - return n, err; -} - -func (p* TTransportBase) Write(buf []byte) (int, os.Error) { - return 0, NewTTransportExceptionDefaultString("Subclasses must implement TTransportBase.Write()"); -} - -func (p* TTransportBase) Flush() os.Error { - return nil; -} -*/ -/** - * Guarantees that all of len bytes are actually read off the transport. - * - * @param buf Array to read into - * @param off Index to start reading at - * @param len Maximum number of bytes to read - * @return The number of bytes actually read, which must be equal to len - * @return TTransportException if there was an error reading data - */ -func ReadAllTransport(p TTransport, buf []byte) (n int, err os.Error) { - ret := 0 - size := len(buf) - for n < size { - ret, err = p.Read(buf[n:]) - if ret <= 0 { - if err != nil { - err = NewTTransportExceptionDefaultString("Cannot read. Remote side has closed. Tried to read " + strconv.Itoa(size) + " bytes, but only got " + strconv.Itoa(n) + " bytes.") - } - return ret, err - } - n += ret - } - return n, err -} - - -var ( - LOGGER *log.Logger -) - -func init() { - LOGGER = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) -} diff --git a/lib/go/thrift/ttransport_exception.go b/lib/go/thrift/ttransport_exception.go deleted file mode 100644 index b9fae17b..00000000 --- a/lib/go/thrift/ttransport_exception.go +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 thrift - -import ( - "os" -) - -/** - * Transport exceptions. - * - */ -type TTransportException interface { - TException - TypeId() int -} - -const ( - UNKNOWN_TRANSPORT_EXCEPTION = 0 - NOT_OPEN = 1 - ALREADY_OPEN = 2 - TIMED_OUT = 3 - END_OF_FILE = 4 -) - -type tTransportException struct { - typeId int - message string -} - -func (p *tTransportException) TypeId() int { - return p.typeId -} - -func (p *tTransportException) String() string { - return p.message -} - -func NewTTransportExceptionDefault() TTransportException { - return NewTTransportExceptionDefaultType(UNKNOWN_TRANSPORT_EXCEPTION) -} - -func NewTTransportExceptionDefaultType(t int) TTransportException { - return NewTTransportException(t, "") -} - -func NewTTransportExceptionDefaultString(m string) TTransportException { - return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, m) -} - -func NewTTransportException(t int, m string) TTransportException { - return &tTransportException{typeId: t, message: m} -} - -func NewTTransportExceptionFromOsError(e os.Error) TTransportException { - if e == nil { - return nil - } - t, ok := e.(TTransportException) - if ok { - return t - } - if e == os.EOF { - return NewTTransportException(END_OF_FILE, e.String()) - } - return NewTTransportExceptionDefaultString(e.String()) -} diff --git a/lib/go/thrift/ttransport_test.go b/lib/go/thrift/ttransport_test.go deleted file mode 100644 index 4158a747..00000000 --- a/lib/go/thrift/ttransport_test.go +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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 thrift_test - -import ( - . "thrift" - "testing" - "net" - "os" - "strconv" -) - -const TRANSPORT_BINARY_DATA_SIZE = 4096 - -var ( - transport_bdata []byte // test data for writing; same as data -) - -func init() { - transport_bdata = make([]byte, TRANSPORT_BINARY_DATA_SIZE) - for i := 0; i < TRANSPORT_BINARY_DATA_SIZE; i++ { - transport_bdata[i] = byte((i + 'a') % 255) - } -} - -func TransportTest(t *testing.T, writeTrans TTransport, readTrans TTransport) { - buf := make([]byte, TRANSPORT_BINARY_DATA_SIZE) - if !writeTrans.IsOpen() { - err := writeTrans.Open() - if err != nil { - t.Fatalf("Transport %T cannot open write transport: %s", writeTrans, err) - } - } - if !readTrans.IsOpen() { - err := readTrans.Open() - if err != nil { - t.Fatalf("Transport %T cannot open read transport: %s", readTrans, err) - } - } - _, err := writeTrans.Write(transport_bdata) - if err != nil { - t.Fatalf("Transport %T cannot write binary data of length %d: %s", writeTrans, len(transport_bdata), err) - } - err = writeTrans.Flush() - if err != nil { - t.Fatalf("Transport %T cannot flush write of binary data: %s", writeTrans, err) - } - n, err := readTrans.ReadAll(buf) - if err != nil { - t.Errorf("Transport %T cannot read binary data of length %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, err) - } - if n != TRANSPORT_BINARY_DATA_SIZE { - t.Errorf("Transport %T read only %d instead of %d bytes of binary data", readTrans, n, TRANSPORT_BINARY_DATA_SIZE) - } - for k, v := range buf { - if v != transport_bdata[k] { - t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k) - } - } - _, err = writeTrans.Write(transport_bdata) - if err != nil { - t.Fatalf("Transport %T cannot write binary data 2 of length %d: %s", writeTrans, len(transport_bdata), err) - } - err = writeTrans.Flush() - if err != nil { - t.Fatalf("Transport %T cannot flush write binary data 2: %s", writeTrans, err) - } - b := readTrans.Peek() - if b != true { - t.Errorf("Transport %T returned %s for Peek()", readTrans, b) - } - buf = make([]byte, TRANSPORT_BINARY_DATA_SIZE) - read := 1 - for n = 0; n < TRANSPORT_BINARY_DATA_SIZE && read != 0; { - read, err = readTrans.Read(buf[n:]) - if err != nil { - t.Errorf("Transport %T cannot read binary data 2 of total length %d from offset %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, n, err) - } - n += read - } - if n != TRANSPORT_BINARY_DATA_SIZE { - t.Errorf("Transport %T read only %d instead of %d bytes of binary data 2", readTrans, n, TRANSPORT_BINARY_DATA_SIZE) - } - for k, v := range buf { - if v != transport_bdata[k] { - t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k) - } - } -} - -func CloseTransports(t *testing.T, readTrans TTransport, writeTrans TTransport) { - err := readTrans.Close() - if err != nil { - t.Errorf("Transport %T cannot close read transport: %s", readTrans, err) - } - if writeTrans != readTrans { - err = writeTrans.Close() - if err != nil { - t.Errorf("Transport %T cannot close write transport: %s", writeTrans, err) - } - } -} - -func FindAvailableTCPServerPort(startPort int) (net.Addr, os.Error) { - for i := startPort; i < 65535; i++ { - s := "127.0.0.1:" + strconv.Itoa(i) - l, err := net.Listen("tcp", s) - if err == nil { - l.Close() - return net.ResolveTCPAddr("tcp", s) - } - } - return nil, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "Could not find available server port") -} diff --git a/lib/go/thrift/ttype.go b/lib/go/thrift/ttype.go deleted file mode 100644 index d024b394..00000000 --- a/lib/go/thrift/ttype.go +++ /dev/null @@ -1,975 +0,0 @@ -/* - * 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 thrift - -import ( - "container/list" - "container/vector" - "strconv" -) - -/** - * Type constants in the Thrift protocol. - */ -type TType byte - -const ( - STOP = 0 - VOID = 1 - BOOL = 2 - BYTE = 3 - I08 = 3 - DOUBLE = 4 - I16 = 6 - I32 = 8 - I64 = 10 - STRING = 11 - UTF7 = 11 - STRUCT = 12 - MAP = 13 - SET = 14 - LIST = 15 - ENUM = 16 - UTF8 = 16 - UTF16 = 17 - GENERIC = 127 -) - -func (p TType) String() string { - switch p { - case STOP: - return "STOP" - case VOID: - return "VOID" - case BOOL: - return "BOOL" - case BYTE: - return "BYTE" - case DOUBLE: - return "DOUBLE" - case I16: - return "I16" - case I32: - return "I32" - case I64: - return "I64" - case STRING: - return "STRING" - case STRUCT: - return "STRUCT" - case MAP: - return "MAP" - case SET: - return "SET" - case LIST: - return "LIST" - case ENUM: - return "ENUM" - case UTF16: - return "UTF16" - case GENERIC: - return "GENERIC" - } - return "Unknown" -} - -func (p TType) IsBaseType() bool { - switch p { - case BOOL, BYTE, DOUBLE, I16, I32, I64, STRING, UTF8, UTF16: - return true - default: - return false - } - return false -} - -func (p TType) IsEmptyType() bool { - switch p { - case STOP, VOID: - return true - default: - return false - } - return false -} - -func (p TType) IsEnum() bool { - switch p { - case ENUM: - return true - default: - return false - } - return false -} - -func (p TType) IsNumericType() bool { - switch p { - case ENUM, BOOL, BYTE, DOUBLE, I16, I32, I64: - return true - default: - return false - } - return false -} - -func (p TType) IsStringType() bool { - switch p { - case STRING, UTF8, UTF16: - return true - default: - return false - } - return false -} - -func (p TType) IsContainer() bool { - switch p { - case MAP, SET, LIST: - return true - default: - return false - } - return false -} - -func (p TType) IsStruct() bool { - switch p { - case STRUCT: - return true - default: - return false - } - return false -} - -func (p TType) IsMap() bool { - switch p { - case MAP: - return true - default: - return false - } - return false -} - -func (p TType) IsList() bool { - switch p { - case LIST: - return true - default: - return false - } - return false -} - -func (p TType) IsSet() bool { - switch p { - case SET: - return true - default: - return false - } - return false -} - -func (p TType) IsInt() bool { - switch p { - case BYTE, I16, I32, I64: - return true - default: - return false - } - return false -} - -func (p TType) Coerce(other interface{}) TType { - if other == nil { - return TType(STOP) - } - switch b := other.(type) { - default: - return TType(STOP) - case nil: - return TType(STOP) - case TType: - return b - case byte: - return TType(b) - case int: - return TType(byte(b)) - case int8: - return TType(byte(b)) - case int32: - return TType(byte(b)) - case int64: - return TType(byte(b)) - case uint: - return TType(byte(b)) - case uint32: - return TType(byte(b)) - case uint64: - return TType(byte(b)) - case float32: - return TType(byte(int(b))) - case float64: - return TType(byte(int(b))) - } - return TType(STOP) -} - -func (p TType) LessType(other interface{}) bool { - return p < p.Coerce(other) -} - -func (p TType) Less(i, j interface{}) bool { - cmp, ok := p.Compare(i, j) - return ok && cmp > 0 -} - - -func (p TType) Compare(i, j interface{}) (int, bool) { - if i == j { - return 0, true - } - if i == nil { - if j == nil { - return 0, true - } - return -1, true - } - if j == nil { - return 1, true - } - ci, iok := p.CoerceData(i) - cj, jok := p.CoerceData(j) - if iok && !jok { - return 1, true - } - if !iok && jok { - return -1, true - } - // hopefully this doesn't happen as Compare() would continuously return 0, false - if !iok && !jok { - return 0, false - } - if ci == cj { - return 0, true - } - if ci == nil { - if cj == nil { - return 0, true - } - return -1, true - } - if cj == nil { - return 1, true - } - switch p { - case STOP, VOID: - // hopefully this doesn't happen as Compare() would continuously return 0, false - return 0, false - case BOOL: - vi := ci.(bool) - vj := cj.(bool) - if vi == vj { - return 0, true - } - if vi == false { - return -1, true - } - return 1, true - case BYTE: - vi := ci.(byte) - vj := cj.(byte) - if vi == vj { - return 0, true - } - if vi < vj { - return -1, true - } - return 1, true - case DOUBLE: - vi := ci.(float64) - vj := cj.(float64) - if vi == vj { - return 0, true - } - if vi < vj { - return -1, true - } - return 1, true - case I16: - vi := ci.(int16) - vj := cj.(int16) - if vi == vj { - return 0, true - } - if vi < vj { - return -1, true - } - return 1, true - case I32: - vi := ci.(int32) - vj := cj.(int32) - if vi == vj { - return 0, true - } - if vi < vj { - return -1, true - } - return 1, true - case I64: - vi := ci.(int64) - vj := cj.(int64) - if vi == vj { - return 0, true - } - if vi < vj { - return -1, true - } - return 1, true - case STRING, UTF8, UTF16: - vi := ci.(string) - vj := cj.(string) - if vi == vj { - return 0, true - } - if vi < vj { - return -1, true - } - return 1, true - case STRUCT: - si := ci.(TStruct) - sj := cj.(TStruct) - if cmp := CompareString(si.ThriftName(), sj.ThriftName()); cmp != 0 { - return cmp, true - } - if cmp, ok := si.TStructFields().CompareTo(sj.TStructFields()); !ok || cmp != 0 { - return cmp, ok - } - for field := range si.TStructFields().Iter() { - a := si.AttributeFromFieldId(field.Id()) - b := sj.AttributeFromFieldId(field.Id()) - if cmp, ok := field.TypeId().Compare(a, b); !ok || cmp != 0 { - return cmp, ok - } - } - return 0, true - case MAP: - mi := ci.(TMap) - mj := cj.(TMap) - ei := mi.KeyType() - if ej := mj.KeyType(); ei != ej { - return CompareInt(int(ei), int(ej)), true - } - if size := mi.Len(); size != mj.Len() { - return CompareInt(size, mj.Len()), true - } - if c, cok := ei.Compare(mi.Keys(), mj.Keys()); c != 0 || !cok { - return c, cok - } - return ei.Compare(mi.Values(), mj.Values()) - case LIST: - li := ci.(TList) - lj := cj.(TList) - ei := li.ElemType() - ej := lj.ElemType() - if ei != ej { - return CompareInt(int(ei), int(ej)), true - } - size := li.Len() - if size != lj.Len() { - return CompareInt(size, lj.Len()), true - } - for k := 0; k < size; k++ { - vi := li.At(k) - vj := lj.At(k) - c, cok := ei.Compare(vi, vj) - if c != 0 || !cok { - return c, cok - } - } - return 0, true - case SET: - li := ci.(TSet) - lj := cj.(TSet) - ei := li.ElemType() - ej := lj.ElemType() - if ei != ej { - return CompareInt(int(ei), int(ej)), true - } - size := li.Len() - if size != lj.Len() { - return CompareInt(size, lj.Len()), true - } - return ei.Compare(li.Values(), lj.Values()) - default: - panic("Invalid thrift type to coerce") - } - return 0, false -} - -func (p TType) CompareValueArrays(li, lj []interface{}) (int, bool) { - size := len(li) - if cmp := CompareInt(size, len(lj)); cmp != 0 { - return cmp, true - } - for i := 0; i < size; i++ { - vi := li[i] - vj := lj[i] - c, cok := p.Compare(vi, vj) - if c != 0 || !cok { - return c, cok - } - } - return 0, true -} - -func (p TType) Equals(other interface{}) bool { - return p == p.Coerce(other) -} - -type Stringer interface { - String() string -} - -type Enumer interface { - String() string - Value() int - IsEnum() bool -} - -func TypeFromValue(data interface{}) TType { - switch i := data.(type) { - default: - return STOP - case nil: - return VOID - case bool: - return BOOL - case float32, float64: - return DOUBLE - case int, int32: - return I32 - case byte: - return BYTE - case int8: - return I08 - case int16: - return I16 - case int64: - return I64 - case string: - return STRING - case TStruct: - return STRUCT - case TMap: - return MAP - case TSet: - return SET - case []interface{}, *list.List, *vector.Vector, TList: - return LIST - } - return STOP -} - -func (p TType) CoerceData(data interface{}) (interface{}, bool) { - if data == nil { - switch p { - case STOP: - return nil, true - case VOID: - return nil, true - case BOOL: - return false, true - case BYTE: - return byte(0), true - case DOUBLE: - return float64(0), true - case I16: - return int16(0), true - case I32: - return int32(0), true - case I64: - return int64(0), true - case STRING, UTF8, UTF16: - return "", true - case STRUCT: - return NewTStructEmpty(""), true - case MAP: - return NewTMapDefault(), true - case LIST: - return NewTListDefault(), true - case SET: - return NewTSetDefault(), true - default: - panic("Invalid thrift type to coerce") - } - } - switch p { - case STOP: - return nil, true - case VOID: - return nil, true - case BOOL: - switch b := data.(type) { - default: - return false, false - case bool: - return b, true - case Numeric: - return bool(b.Int() != 0), true - case int: - return b != 0, true - case byte: - return b != 0, true - case int8: - return b != 0, true - case int16: - return b != 0, true - case int32: - return b != 0, true - case int64: - return b != 0, true - case uint: - return b != 0, true - case uint16: - return b != 0, true - case uint32: - return b != 0, true - case uint64: - return b != 0, true - case float32: - return b != 0, true - case float64: - return b != 0, true - case Stringer: - v := b.String() - if v == "false" || v == "0" || len(v) == 0 { - return false, true - } - return true, true - case string: - if b == "false" || b == "0" || len(b) == 0 { - return false, true - } - return true, true - } - case BYTE: - if b, ok := data.(byte); ok { - return b, true - } - if b, ok := data.(Numeric); ok { - return b.Byte(), true - } - if b, ok := data.(bool); ok { - if b { - return byte(1), true - } - return byte(0), true - } - if b, ok := data.(int); ok { - return byte(b), true - } - if b, ok := data.(int8); ok { - return byte(b), true - } - if b, ok := data.(int16); ok { - return byte(b), true - } - if b, ok := data.(int32); ok { - return byte(b), true - } - if b, ok := data.(int64); ok { - return byte(b), true - } - if b, ok := data.(uint); ok { - return byte(b), true - } - if b, ok := data.(uint8); ok { - return byte(b), true - } - if b, ok := data.(uint16); ok { - return byte(b), true - } - if b, ok := data.(uint32); ok { - return byte(b), true - } - if b, ok := data.(uint64); ok { - return byte(b), true - } - if b, ok := data.(float32); ok { - return byte(int(b)), true - } - if b, ok := data.(float64); ok { - return byte(int(b)), true - } - if b, ok := data.(Stringer); ok { - data = b.String() - } - if b, ok := data.(string); ok { - i1, err := strconv.Atoi(b) - if err != nil { - return byte(int(i1)), true - } - } - return byte(0), false - case DOUBLE: - if b, ok := data.(float32); ok { - return float64(b), true - } - if b, ok := data.(float64); ok { - return b, true - } - if b, ok := data.(Numeric); ok { - return bool(b.Float64() != 0.0), true - } - if b, ok := data.(byte); ok { - return float64(b), true - } - if b, ok := data.(bool); ok { - if b { - return float64(1.0), true - } - return float64(0.0), true - } - if b, ok := data.(int); ok { - return float64(b), true - } - if b, ok := data.(int8); ok { - return float64(b), true - } - if b, ok := data.(int16); ok { - return float64(b), true - } - if b, ok := data.(int32); ok { - return float64(b), true - } - if b, ok := data.(int64); ok { - return float64(b), true - } - if b, ok := data.(uint); ok { - return float64(b), true - } - if b, ok := data.(uint8); ok { - return float64(b), true - } - if b, ok := data.(uint16); ok { - return float64(b), true - } - if b, ok := data.(uint32); ok { - return float64(b), true - } - if b, ok := data.(uint64); ok { - return float64(b), true - } - if b, ok := data.(Stringer); ok { - data = b.String() - } - if b, ok := data.(string); ok { - d1, err := strconv.Atof64(b) - if err != nil { - return d1, true - } - } - return float64(0), false - case I16: - if b, ok := data.(int16); ok { - return b, true - } - if b, ok := data.(int); ok { - return int16(b), true - } - if b, ok := data.(Numeric); ok { - return bool(b.Int16() != 0), true - } - if b, ok := data.(byte); ok { - return int16(b), true - } - if b, ok := data.(bool); ok { - if b { - return int16(1.0), true - } - return int16(0.0), true - } - if b, ok := data.(int8); ok { - return int16(b), true - } - if b, ok := data.(int32); ok { - return int16(b), true - } - if b, ok := data.(int64); ok { - return int16(b), true - } - if b, ok := data.(uint); ok { - return int16(b), true - } - if b, ok := data.(uint8); ok { - return int16(b), true - } - if b, ok := data.(uint16); ok { - return int16(b), true - } - if b, ok := data.(uint32); ok { - return int16(b), true - } - if b, ok := data.(uint64); ok { - return int16(b), true - } - if b, ok := data.(float32); ok { - return int16(int(b)), true - } - if b, ok := data.(float64); ok { - return int16(int(b)), true - } - if b, ok := data.(Stringer); ok { - data = b.String() - } - if b, ok := data.(string); ok { - i1, err := strconv.Atoi(b) - if err != nil { - return int16(i1), true - } - } - return int16(0), false - case I32: - if b, ok := data.(int32); ok { - return b, true - } - if b, ok := data.(int); ok { - return int32(b), true - } - if b, ok := data.(Numeric); ok { - return bool(b.Int32() != 0), true - } - if b, ok := data.(byte); ok { - return int32(b), true - } - if b, ok := data.(bool); ok { - if b { - return int32(1.0), true - } - return int32(0.0), true - } - if b, ok := data.(int8); ok { - return int32(b), true - } - if b, ok := data.(int16); ok { - return int32(b), true - } - if b, ok := data.(int64); ok { - return int32(b), true - } - if b, ok := data.(uint); ok { - return int32(b), true - } - if b, ok := data.(uint8); ok { - return int32(b), true - } - if b, ok := data.(uint16); ok { - return int32(b), true - } - if b, ok := data.(uint32); ok { - return int32(b), true - } - if b, ok := data.(uint64); ok { - return int32(b), true - } - if b, ok := data.(float32); ok { - return int32(int(b)), true - } - if b, ok := data.(float64); ok { - return int32(int(b)), true - } - if b, ok := data.(Stringer); ok { - data = b.String() - } - if b, ok := data.(string); ok { - i1, err := strconv.Atoi(b) - if err != nil { - return int32(i1), true - } - } - return int32(0), false - case I64: - if b, ok := data.(int64); ok { - return b, true - } - if b, ok := data.(int32); ok { - return int64(b), true - } - if b, ok := data.(int); ok { - return int64(b), true - } - if b, ok := data.(Numeric); ok { - return bool(b.Int64() != 0), true - } - if b, ok := data.(byte); ok { - return int64(b), true - } - if b, ok := data.(bool); ok { - if b { - return int64(1.0), true - } - return int64(0.0), true - } - if b, ok := data.(int8); ok { - return int64(b), true - } - if b, ok := data.(int16); ok { - return int64(b), true - } - if b, ok := data.(uint); ok { - return int64(b), true - } - if b, ok := data.(uint8); ok { - return int64(b), true - } - if b, ok := data.(uint16); ok { - return int64(b), true - } - if b, ok := data.(uint32); ok { - return int64(b), true - } - if b, ok := data.(uint64); ok { - return int64(b), true - } - if b, ok := data.(float32); ok { - return int64(b), true - } - if b, ok := data.(float64); ok { - return int64(b), true - } - if b, ok := data.(Stringer); ok { - data = b.String() - } - if b, ok := data.(string); ok { - i1, err := strconv.Atoi64(b) - if err != nil { - return i1, true - } - } - return int64(0), false - case STRING, UTF8, UTF16: - if b, ok := data.(Enumer); ok { - if i1, ok := data.(int); ok { - return i1, true - } - return b.String(), true - } - if b, ok := data.(Stringer); ok { - return b.String(), true - } - if b, ok := data.(string); ok { - return b, true - } - if b, ok := data.(int); ok { - return string(b), true - } - if b, ok := data.(byte); ok { - return string(b), true - } - if b, ok := data.(bool); ok { - if b { - return "true", true - } - return "false", true - } - if b, ok := data.(int8); ok { - return string(b), true - } - if b, ok := data.(int16); ok { - return string(b), true - } - if b, ok := data.(int32); ok { - return string(b), true - } - if b, ok := data.(int64); ok { - return string(b), true - } - if b, ok := data.(uint); ok { - return string(b), true - } - if b, ok := data.(uint8); ok { - return string(b), true - } - if b, ok := data.(uint16); ok { - return string(b), true - } - if b, ok := data.(uint32); ok { - return string(b), true - } - if b, ok := data.(uint64); ok { - return string(b), true - } - if b, ok := data.(float32); ok { - return strconv.Ftoa32(b, 'g', -1), true - } - if b, ok := data.(float64); ok { - return strconv.Ftoa64(b, 'g', -1), true - } - return "", false - case STRUCT: - if b, ok := data.(TStruct); ok { - return b, true - } - return NewTStructEmpty(""), true - case MAP: - if b, ok := data.(TMap); ok { - return b, true - } - return NewTMapDefault(), false - case LIST: - if b, ok := data.(TList); ok { - return b, true - } - return NewTListDefault(), false - case SET: - if b, ok := data.(TSet); ok { - return b, true - } - return NewTSetDefault(), false - default: - panic("Invalid thrift type to coerce") - } - return nil, false -} - -type EqualsOtherInterface interface { - Equals(other interface{}) bool -} - -type EqualsMap interface { - Equals(other TMap) bool -} - -type EqualsSet interface { - Equals(other TSet) bool -} - -type EqualsList interface { - Equals(other TList) bool -} - -type EqualsStruct interface { - Equals(other TStruct) bool -} diff --git a/lib/go/thrift/type.go b/lib/go/thrift/type.go new file mode 100644 index 00000000..7c68c2b9 --- /dev/null +++ b/lib/go/thrift/type.go @@ -0,0 +1,68 @@ +/* + * 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 thrift + +// Type constants in the Thrift protocol +type TType byte + +const ( + STOP = 0 + VOID = 1 + BOOL = 2 + BYTE = 3 + I08 = 3 + DOUBLE = 4 + I16 = 6 + I32 = 8 + I64 = 10 + STRING = 11 + UTF7 = 11 + STRUCT = 12 + MAP = 13 + SET = 14 + LIST = 15 + UTF8 = 16 + UTF16 = 17 + BINARY = 18 +) + +var typeNames = map[int]string{ + STOP: "STOP", + VOID: "VOID", + BOOL: "BOOL", + BYTE: "BYTE", + I16: "I16", + I32: "I32", + I64: "I64", + STRING: "STRING", + STRUCT: "STRUCT", + MAP: "MAP", + SET: "SET", + LIST: "LIST", + UTF8: "UTF8", + UTF16: "UTF16", +} + +func (p TType) String() string { + if s, ok := typeNames[int(p)]; ok { + return s + } + return "Unknown" +} diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am index 6ca82ede..72901a54 100755 --- a/tutorial/Makefile.am +++ b/tutorial/Makefile.am @@ -54,6 +54,10 @@ if WITH_HASKELL #SUBDIRS += hs endif +if WITH_GO +SUBDIRS += go +endif + # # generate html for ThriftTest.thrift # diff --git a/tutorial/go/Make.deps b/tutorial/go/Make.deps deleted file mode 100644 index e4c2b20d..00000000 --- a/tutorial/go/Make.deps +++ /dev/null @@ -1,135 +0,0 @@ -src.install: fmt.install net.install os.install strconv.install thrift.install -archive/tar.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/archive/tar.a -archive/zip.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/archive/zip.a -asn1.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/asn1.a -big.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/big.a -bufio.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/bufio.a -bytes.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/bytes.a -cmath.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/cmath.a -compress/flate.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/flate.a -compress/gzip.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/gzip.a -compress/zlib.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/zlib.a -container/heap.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/heap.a -container/list.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/list.a -container/ring.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/ring.a -container/vector.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/vector.a -crypto.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto.a -crypto/aes.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/aes.a -crypto/block.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/block.a -crypto/blowfish.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/blowfish.a -crypto/cast5.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/cast5.a -crypto/cipher.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/cipher.a -crypto/dsa.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/dsa.a -crypto/elliptic.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/elliptic.a -crypto/hmac.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/hmac.a -crypto/md4.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/md4.a -crypto/md5.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/md5.a -crypto/ocsp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/ocsp.a -crypto/rand.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rand.a -crypto/rc4.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rc4.a -crypto/ripemd160.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/ripemd160.a -crypto/rsa.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rsa.a -crypto/sha1.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha1.a -crypto/sha256.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha256.a -crypto/sha512.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha512.a -crypto/subtle.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/subtle.a -crypto/tls.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/tls.a -crypto/twofish.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/twofish.a -crypto/x509.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/x509.a -crypto/xtea.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/xtea.a -debug/dwarf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/dwarf.a -debug/macho.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/macho.a -debug/elf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/elf.a -debug/gosym.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/gosym.a -debug/pe.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/pe.a -debug/proc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/proc.a -ebnf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/ebnf.a -encoding/ascii85.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/ascii85.a -encoding/base32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/base32.a -encoding/base64.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/base64.a -encoding/binary.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/binary.a -encoding/git85.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/git85.a -encoding/hex.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/hex.a -encoding/line.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/line.a -encoding/pem.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/pem.a -exec.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exec.a -exp/datafmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/datafmt.a -exp/draw.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/draw.a -exp/draw/x11.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/draw/x11.a -exp/eval.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/eval.a -expvar.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/expvar.a -flag.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/flag.a -fmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/fmt.a -go/ast.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/ast.a -go/doc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/doc.a -go/parser.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/parser.a -go/printer.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/printer.a -go/scanner.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/scanner.a -go/token.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/token.a -go/typechecker.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/typechecker.a -gob.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/gob.a -hash.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash.a -hash/adler32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/adler32.a -hash/crc32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/crc32.a -hash/crc64.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/crc64.a -html.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/html.a -http.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http.a -http/pprof.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http/pprof.a -image.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image.a -image/jpeg.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/jpeg.a -image/png.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/png.a -index/suffixarray.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/index/suffixarray.a -io.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/io.a -io/ioutil.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/io/ioutil.a -json.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/json.a -log.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/log.a -math.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/math.a -mime.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/mime.a -mime/multipart.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/mime/multipart.a -net.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net.a -net/dict.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net/dict.a -net/textproto.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net/textproto.a -netchan.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/netchan.a -os.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/os.a -os/signal.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/os/signal.a -patch.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/patch.a -path.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/path.a -rand.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rand.a -reflect.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/reflect.a -regexp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/regexp.a -rpc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rpc.a -rpc/jsonrpc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rpc/jsonrpc.a -runtime.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime.a -runtime/cgo.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/cgo.a -runtime/debug.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/debug.a -runtime/pprof.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/pprof.a -scanner.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/scanner.a -smtp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/smtp.a -sort.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/sort.a -strconv.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/strconv.a -strings.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/strings.a -sync.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/sync.a -syscall.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/syscall.a -syslog.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/syslog.a -tabwriter.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/tabwriter.a -template.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/template.a -testing.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing.a -testing/iotest.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/iotest.a -testing/quick.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/quick.a -testing/script.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/script.a -time.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/time.a -try.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/try.a -unicode.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/unicode.a -utf16.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/utf16.a -utf8.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/utf8.a -websocket.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/websocket.a -xml.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/xml.a -../cmd/cgo.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/cgo.a -../cmd/ebnflint.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/ebnflint.a -../cmd/godoc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/godoc.a -../cmd/gofmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/gofmt.a -../cmd/goinstall.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/goinstall.a -../cmd/govet.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/govet.a -../cmd/goyacc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/goyacc.a -../cmd/hgpatch.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/hgpatch.a -thrift.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/thrift.a diff --git a/tutorial/go/Makefile b/tutorial/go/Makefile deleted file mode 100644 index 50c5dfe6..00000000 --- a/tutorial/go/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -all: Make.deps install - -TARG=thriftlib/tutorialcalculator - -DIRS=\ - src/\ - -GOFILES=\ - - -clean.dirs: $(addsuffix .clean, $(DIRS)) -install.dirs: $(addsuffix .install, $(DIRS)) -test.dirs: $(addsuffix .test, $(DIRS)) - - -%.clean: - +cd $* && $(MAKE) clean - -%.install: - +cd $* && $(MAKE) install - -%.test: - +cd $* && $(MAKE) test - - - -Make.deps: - ./deps.bash - -deps: - ./deps.bash - -clean: clean.dirs - -install: install.dirs - -test: test.dirs - diff --git a/tutorial/go/Makefile.am b/tutorial/go/Makefile.am new file mode 100644 index 00000000..2c2b8bef --- /dev/null +++ b/tutorial/go/Makefile.am @@ -0,0 +1,51 @@ +# +# 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. +# + +THRIFT = $(top_builddir)/compiler/cpp/thrift + +gen-go/tutorial/calculator.go gen-go/shared/shared_service.go: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen go -r $< + +all-local: gen-go/tutorial/calculator.go + + +check: src/git.apache.org/thrift.git/lib/go/thrift + $(THRIFT) -r --gen go $(top_srcdir)/tutorial/tutorial.thrift + cp -r gen-go/* src/ + GOPATH=`pwd` go build ./... + GOPATH=`pwd` go build -o go-tutorial src/*.go + GOPATH=`pwd` go build -o calculator-remote src/tutorial/calculator-remote/calculator-remote.go + +src/git.apache.org/thrift.git/lib/go/thrift: + mkdir -p src/git.apache.org/thrift.git/lib/go + ln -sf $(realpath $(top_srcdir)/lib/go/thrift) src/git.apache.org/thrift.git/lib/go/thrift + +tutorialserver: all + GOPATH=`pwd` go run src/*.go -server=true + +tutorialclient: all + GOPATH=`pwd` go run src/*.go -client=true + +clean-local: + $(RM) -r gen-* + +EXTRA_DIST = \ + client.py \ + handler.py \ + server.py diff --git a/tutorial/go/deps.bash b/tutorial/go/deps.bash deleted file mode 100644 index aec6ec2e..00000000 --- a/tutorial/go/deps.bash +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -OUT="Make.deps" -TMP="Make.deps.tmp" - -if [ -f $OUT ] && ! [ -w $OUT ]; then - echo "$0: $OUT is read-only; aborting." 1>&2 - exit 1 -fi - -# Get list of directories from Makefile -dirs=$(sed '1,/^DIRS=/d; /^$/,$d; s/\\//g' Makefile) -dirs2=$(sed '1,/^DIRS=/d; /^$/,$d; s/\\//g' $GOROOT/src/pkg/Makefile) -dirs3="thrift" -dirpat=$(echo $dirs $dirs2 $dirs3 | sed 's/ /|/g; s/.*/^(&)$/') - -for dir in $dirs; do ( - cd $dir || exit 1 - - sources=$(sed -n 's/\.go\\/.go/p' Makefile) - sources=$(ls $sources 2> /dev/null) # remove .s, .c, etc. - - deps=$( - sed -n '/^import.*"/p; /^import[ \t]*(/,/^)/p' $sources /dev/null | - cut -d '"' -f2 | - egrep "$dirpat" | - grep -v "^$dir\$" | - sed 's/$/.install/' | - sort -u - ) - - echo $dir.install: $deps -) done > $TMP - -for dir in $dirs2; do ( - echo $dir.install: \${GOROOT}/pkg/\${GOOS}_\${GOARCH}/${dir}.a -) done >> $TMP -for dir in $dirs3; do ( - echo $dir.install: \${GOROOT}/pkg/\${GOOS}_\${GOARCH}/${dir}.a -) done >> $TMP - -mv $TMP $OUT diff --git a/tutorial/go/src/CalculatorHandler.go b/tutorial/go/src/CalculatorHandler.go deleted file mode 100644 index 9eb28388..00000000 --- a/tutorial/go/src/CalculatorHandler.go +++ /dev/null @@ -1,101 +0,0 @@ -package main; - -/* - * 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. - */ - -import ( - "fmt" - "os" - "strconv" - "thriftlib/tutorial" - "thriftlib/shared" -) - -type CalculatorHandler struct { - log map[int]*shared.SharedStruct -} - -func NewCalculatorHandler() *CalculatorHandler { - return &CalculatorHandler{log:make(map[int]*shared.SharedStruct)} -} - -func (p *CalculatorHandler) Ping() (err os.Error) { - fmt.Print("ping()\n") - return nil -} - -func (p *CalculatorHandler) Add(num1 int32, num2 int32) (retval17 int32, err os.Error) { - fmt.Print("add(", num1, ",", num2, ")\n") - return num1 + num2, nil -} - -func (p *CalculatorHandler) Calculate(logid int32, w *tutorial.Work) (val int32, ouch *tutorial.InvalidOperation, err os.Error) { - fmt.Print("calculate(", logid, ", {", w.Op, ",", w.Num1, ",", w.Num2, "})\n") - switch(w.Op) { - case tutorial.ADD: - val = w.Num1 + w.Num2 - break - case tutorial.SUBTRACT: - val = w.Num1 - w.Num2 - break - case tutorial.MULTIPLY: - val = w.Num1 * w.Num2 - break - case tutorial.DIVIDE: - if w.Num2 == 0 { - ouch = tutorial.NewInvalidOperation() - ouch.What = int32(w.Op) - ouch.Why = "Cannot divide by 0" - return - } - val = w.Num1 / w.Num2 - break - default: - ouch = tutorial.NewInvalidOperation() - ouch.What = int32(w.Op) - ouch.Why = "Unknown operation" - return - } - entry := shared.NewSharedStruct() - entry.Key = logid - entry.Value = strconv.Itoa(int(val)) - k := int(logid) - /* - oldvalue, exists := p.log[k] - if exists { - fmt.Print("Replacing ", oldvalue, " with ", entry, " for key ", k, "\n") - } else { - fmt.Print("Adding ", entry, " for key ", k, "\n") - } - */ - p.log[k] = entry, true - return val, ouch, err -} - -func (p *CalculatorHandler) GetStruct(key int32) (*shared.SharedStruct, os.Error) { - fmt.Print("getStruct(", key, ")\n") - v, _ := p.log[int(key)] - return v, nil -} - -func (p *CalculatorHandler) Zip() (err os.Error) { - fmt.Print("zip()\n") - return nil -} - diff --git a/tutorial/go/src/GoClient.go b/tutorial/go/src/GoClient.go deleted file mode 100644 index 94405301..00000000 --- a/tutorial/go/src/GoClient.go +++ /dev/null @@ -1,92 +0,0 @@ -package main; - - -/* - * 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. - */ - - -import ( - "fmt" - "net" - "os" - "thrift" - "thriftlib/tutorial" -) - -func Perform(client *tutorial.CalculatorClient) (err os.Error) { - client.Ping() - fmt.Print("ping()\n") - - sum, _ := client.Add(1, 1) - fmt.Print("1+1=", sum, "\n") - - work := tutorial.NewWork() - work.Op = tutorial.DIVIDE - work.Num1 = 1 - work.Num2 = 0 - quotient, ouch, err := client.Calculate(1, work) - if err != nil { - fmt.Print("Error during operation: ", err.String(), "\n") - return err - } else if ouch != nil { - fmt.Print("Invalid operation: ", ouch.String(), "\n") - } else { - fmt.Print("Whoa we can divide by 0 with new value: ", quotient, "\n") - } - - work.Op = tutorial.SUBTRACT - work.Num1 = 15 - work.Num2 = 10 - diff, ouch, err := client.Calculate(1, work) - if err != nil { - fmt.Print("Error during operation: ", err.String(), "\n") - return err - } else if ouch != nil { - fmt.Print("Invalid operation: ", ouch.String(), "\n") - } else { - fmt.Print("15-10=", diff, "\n") - } - - log, err := client.GetStruct(1) - if err != nil { - fmt.Print("Unable to get struct: ", err.String(), "\n") - return err - } else { - fmt.Print("Check log: ", log.Value, "\n") - } - return err -} - - -func RunClient(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory) os.Error { - addr, err := net.ResolveTCPAddr("localhost:9090") - if err != nil { - fmt.Print("Error resolving address: ", err.String(), "\n") - return err - } - transport := thrift.NewTSocketAddr(addr) - if err = transport.Open(); err != nil { - fmt.Print("Error opening connection for protocol ", addr.Network(), " to ", addr.String(), ": ", err.String(), "\n") - return err - } - useTransport := transportFactory.GetTransport(transport) - client := tutorial.NewCalculatorClientFactory(useTransport, protocolFactory) - Perform(client) - return transport.Close() -} diff --git a/tutorial/go/src/GoServer.go b/tutorial/go/src/GoServer.go deleted file mode 100644 index f70a2a95..00000000 --- a/tutorial/go/src/GoServer.go +++ /dev/null @@ -1,85 +0,0 @@ -package main; - - -/* - * 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. - */ - - -import ( - "fmt" - "net" - "thrift" - "thriftlib/tutorial" -) - - -type GoServer struct { - handler tutorial.ICalculator - processor *tutorial.CalculatorProcessor -} - -func NewGoServer() *GoServer { - handler := NewCalculatorHandler() - processor := tutorial.NewCalculatorProcessor(handler) - return &GoServer{handler:handler, processor:processor} -} - -func Simple(processor *tutorial.CalculatorProcessor, transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory, ch chan int) { - addr, err := net.ResolveTCPAddr("localhost:9090") - if err != nil { - fmt.Print("Error resolving address: ", err.String(), "\n") - return - } - serverTransport, err := thrift.NewTServerSocketAddr(addr) - if err != nil { - fmt.Print("Error creating server socket: ", err.String(), "\n") - return - } - server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) - // Use this for a multithreaded server - // TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor)); - - fmt.Print("Starting the simple server... on ", addr, "\n") - for { - err = server.Serve() - if err != nil { - fmt.Print("Error during simple server: ", err.String(), "\n") - return - } - } - fmt.Print("Done with the simple server\n") - ch <- 1 -} - -func Secure(processor *tutorial.CalculatorProcessor) { - addr, _ := net.ResolveTCPAddr("localhost:9091") - serverTransport, _ := thrift.NewTNonblockingServerSocketAddr(addr) - server := thrift.NewTSimpleServer2(processor, serverTransport) - fmt.Print("Starting the secure server... on ", addr, "\n") - server.Serve() - fmt.Print("Done with the secure server\n") -} - -func RunServer(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory) { - server := NewGoServer() - ch := make(chan int) - go Simple(server.processor, transportFactory, protocolFactory, ch) - //go Secure(server.processor) - _ = <- ch -} diff --git a/tutorial/go/src/Makefile b/tutorial/go/src/Makefile deleted file mode 100644 index 87acbcad..00000000 --- a/tutorial/go/src/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -all: install - -TARG=TutorialServerClient - -DIRS=\ - -GOFILES=\ - CalculatorHandler.go\ - GoClient.go\ - GoServer.go\ - main.go - --include ../Make.deps - -include $(GOROOT)/src/Make.cmd - diff --git a/tutorial/go/src/client.go b/tutorial/go/src/client.go new file mode 100644 index 00000000..114de19f --- /dev/null +++ b/tutorial/go/src/client.go @@ -0,0 +1,85 @@ +package main + +/* + * 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. + */ + +import ( + "fmt" + "git.apache.org/thrift.git/lib/go/thrift" + "tutorial" +) + +func handleClient(client *tutorial.CalculatorClient) (err error) { + client.Ping() + fmt.Println("ping()") + + sum, _ := client.Add(1, 1) + fmt.Print("1+1=", sum, "\n") + + work := tutorial.NewWork() + work.Op = tutorial.Operation_DIVIDE + work.Num1 = 1 + work.Num2 = 0 + quotient, ouch, err := client.Calculate(1, work) + if err != nil { + fmt.Println("Error during operation:", err) + return err + } else if ouch != nil { + fmt.Println("Invalid operation:", ouch) + } else { + fmt.Println("Whoa we can divide by 0 with new value:", quotient) + } + + work.Op = tutorial.Operation_SUBTRACT + work.Num1 = 15 + work.Num2 = 10 + diff, ouch, err := client.Calculate(1, work) + if err != nil { + fmt.Println("Error during operation:", err) + return err + } else if ouch != nil { + fmt.Println("Invalid operation:", ouch) + } else { + fmt.Print("15-10=", diff, "\n") + } + + log, err := client.GetStruct(1) + if err != nil { + fmt.Println("Unable to get struct:", err) + return err + } else { + fmt.Println("Check log:", log.Value) + } + return err +} + +func runClient(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory) error { + var transport thrift.TTransport + transport, err := thrift.NewTSocket("localhost:9090") + if err != nil { + fmt.Println("Error opening socket:", err) + return err + } + transport = transportFactory.GetTransport(transport) + defer transport.Close() + if err := transport.Open(); err != nil { + return err + } + return handleClient(tutorial.NewCalculatorClientFactory(transport, protocolFactory)) +} diff --git a/tutorial/go/src/handler.go b/tutorial/go/src/handler.go new file mode 100644 index 00000000..3d4c18ce --- /dev/null +++ b/tutorial/go/src/handler.go @@ -0,0 +1,99 @@ +package main + +/* + * 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. + */ + +import ( + "fmt" + "shared" + "strconv" + "tutorial" +) + +type CalculatorHandler struct { + log map[int]*shared.SharedStruct +} + +func NewCalculatorHandler() *CalculatorHandler { + return &CalculatorHandler{log: make(map[int]*shared.SharedStruct)} +} + +func (p *CalculatorHandler) Ping() (err error) { + fmt.Print("ping()\n") + return nil +} + +func (p *CalculatorHandler) Add(num1 int32, num2 int32) (retval17 int32, err error) { + fmt.Print("add(", num1, ",", num2, ")\n") + return num1 + num2, nil +} + +func (p *CalculatorHandler) Calculate(logid int32, w *tutorial.Work) (val int32, ouch *tutorial.InvalidOperation, err error) { + fmt.Print("calculate(", logid, ", {", w.Op, ",", w.Num1, ",", w.Num2, "})\n") + switch w.Op { + case tutorial.Operation_ADD: + val = w.Num1 + w.Num2 + break + case tutorial.Operation_SUBTRACT: + val = w.Num1 - w.Num2 + break + case tutorial.Operation_MULTIPLY: + val = w.Num1 * w.Num2 + break + case tutorial.Operation_DIVIDE: + if w.Num2 == 0 { + ouch = tutorial.NewInvalidOperation() + ouch.What = int32(w.Op) + ouch.Why = "Cannot divide by 0" + return + } + val = w.Num1 / w.Num2 + break + default: + ouch = tutorial.NewInvalidOperation() + ouch.What = int32(w.Op) + ouch.Why = "Unknown operation" + return + } + entry := shared.NewSharedStruct() + entry.Key = logid + entry.Value = strconv.Itoa(int(val)) + k := int(logid) + /* + oldvalue, exists := p.log[k] + if exists { + fmt.Print("Replacing ", oldvalue, " with ", entry, " for key ", k, "\n") + } else { + fmt.Print("Adding ", entry, " for key ", k, "\n") + } + */ + p.log[k] = entry + return val, ouch, err +} + +func (p *CalculatorHandler) GetStruct(key int32) (*shared.SharedStruct, error) { + fmt.Print("getStruct(", key, ")\n") + v, _ := p.log[int(key)] + return v, nil +} + +func (p *CalculatorHandler) Zip() (err error) { + fmt.Print("zip()\n") + return nil +} diff --git a/tutorial/go/src/main.go b/tutorial/go/src/main.go index 30b5d528..4b9576ee 100644 --- a/tutorial/go/src/main.go +++ b/tutorial/go/src/main.go @@ -1,5 +1,4 @@ -package main; - +package main /* * Licensed to the Apache Software Foundation (ASF) under one @@ -20,67 +19,54 @@ package main; * under the License. */ - import ( - "flag" - "fmt" - "os" - "thrift" + "flag" + "fmt" + "git.apache.org/thrift.git/lib/go/thrift" + "os" ) func Usage() { - fmt.Fprint(os.Stderr, "Usage of ", os.Args[0], " <--server | --client>:\n") - flag.PrintDefaults() - fmt.Fprint(os.Stderr, "\n") - os.Exit(0) + fmt.Fprint(os.Stderr, "Usage of ", os.Args[0], ":\n") + flag.PrintDefaults() + fmt.Fprint(os.Stderr, "\n") } func main() { - flag.Usage = Usage - var client bool - var server bool - var protocol string - var framed bool - var useHttp bool - var help bool - - flag.BoolVar(&client, "client", false, "Run client") - flag.BoolVar(&server, "server", false, "Run server") - flag.StringVar(&protocol, "P", "binary", "Specify the protocol (binary, compact, simplejson)") - flag.BoolVar(&framed, "framed", false, "Use framed transport") - flag.BoolVar(&useHttp, "http", false, "Use http") - flag.BoolVar(&help, "help", false, "See usage string") - flag.Parse() - if help || (client && server) || !(client || server) { - fmt.Print("flag.NArg() == ", flag.NArg(), "\n") - flag.Usage() - } - var protocolFactory thrift.TProtocolFactory - switch protocol { - case "compact": - protocolFactory = thrift.NewTCompactProtocolFactory() - case "simplejson": - protocolFactory = thrift.NewTSimpleJSONProtocolFactory() - case "json": - protocolFactory = thrift.NewTJSONProtocolFactory() - case "binary", "": - protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() - default: - fmt.Fprint(os.Stderr, "Invalid protocol specified", protocol, "\n") - Usage() - os.Exit(1) - } - transportFactory := thrift.NewTTransportFactory() - if framed { - transportFactory = thrift.NewTFramedTransportFactory(transportFactory) - } - - if(client) { - RunClient(transportFactory, protocolFactory) - } else if(server) { - RunServer(transportFactory, protocolFactory) - } else { - flag.Usage() - } - os.Exit(0) + flag.Usage = Usage + server := flag.Bool("server", false, "Run server") + protocol := flag.String("P", "binary", "Specify the protocol (binary, compact, simplejson)") + framed := flag.Bool("framed", false, "Use framed transport") + + flag.Parse() + + var protocolFactory thrift.TProtocolFactory + switch *protocol { + case "compact": + protocolFactory = thrift.NewTCompactProtocolFactory() + case "simplejson": + protocolFactory = thrift.NewTSimpleJSONProtocolFactory() + case "json": + protocolFactory = thrift.NewTJSONProtocolFactory() + case "binary", "": + protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() + default: + fmt.Fprint(os.Stderr, "Invalid protocol specified", protocol, "\n") + Usage() + os.Exit(1) + } + transportFactory := thrift.NewTTransportFactory() + if *framed { + transportFactory = thrift.NewTFramedTransportFactory(transportFactory) + } + + if *server { + if err := runServer(transportFactory, protocolFactory); err != nil { + fmt.Println("error running server:", err) + } + } else { + if err := runClient(transportFactory, protocolFactory); err != nil { + fmt.Println("error running client:", err) + } + } } diff --git a/lib/go/thrift/texception_test.go b/tutorial/go/src/server.go similarity index 59% rename from lib/go/thrift/texception_test.go rename to tutorial/go/src/server.go index 50b3cddb..929e223d 100644 --- a/lib/go/thrift/texception_test.go +++ b/tutorial/go/src/server.go @@ -1,3 +1,5 @@ +package main + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,22 +19,21 @@ * under the License. */ -package thrift_test - import ( - . "thrift" - "os" - "testing" + "fmt" + "git.apache.org/thrift.git/lib/go/thrift" + "tutorial" ) +func runServer(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory) error { + transport, err := thrift.NewTServerSocket("localhost:9090") + if err != nil { + return err + } + handler := NewCalculatorHandler() + processor := tutorial.NewCalculatorProcessor(handler) + server := thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory) -func TestTException(t *testing.T) { - exc := NewTException("") - if exc.String() != "" { - t.Fatalf("Expected empty string for exception but found '%s'", exc.String()) - } - exc = NewTExceptionFromOsError(os.EOF) - if exc.String() != os.EOF.String() { - t.Fatalf("Expected '%s', but found '%s'", os.EOF.String(), exc.String()) - } + fmt.Println("Starting the simple server... on ", transport.Addr()) + return server.Serve() } -- 2.17.1