From 159383f789651150ae33748d7d68ef22108d614c Mon Sep 17 00:00:00 2001 From: Kevin Clark Date: Tue, 11 Nov 2008 05:46:04 +0000 Subject: [PATCH] rb: raise if an object is serialized without required fields [THRIFT-143] git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@712945 13f79535-47bb-0310-9956-ffa450edef68 --- compiler/cpp/src/generate/t_rb_generator.cc | 32 +++++++++++++++++++-- lib/rb/benchmark/gen-rb/BenchmarkService.rb | 6 ++++ lib/rb/lib/thrift/struct.rb | 2 ++ lib/rb/spec/gen-rb/NonblockingService.rb | 30 +++++++++++++++++++ lib/rb/spec/gen-rb/ThriftSpec_types.rb | 9 ++++++ 5 files changed, 76 insertions(+), 3 deletions(-) diff --git a/compiler/cpp/src/generate/t_rb_generator.cc b/compiler/cpp/src/generate/t_rb_generator.cc index c6122ce4..f878ad7c 100644 --- a/compiler/cpp/src/generate/t_rb_generator.cc +++ b/compiler/cpp/src/generate/t_rb_generator.cc @@ -62,8 +62,7 @@ class t_rb_generator : public t_oop_generator { */ void generate_rb_struct(std::ofstream& out, t_struct* tstruct, bool is_exception); - void generate_rb_struct_reader(std::ofstream& out, t_struct* tstruct); - void generate_rb_struct_writer(std::ofstream& out, t_struct* tstruct); + void generate_rb_struct_required_validator(std::ofstream& out, t_struct* tstruct); void generate_rb_function_helpers(t_function* tfunction); void generate_rb_simple_constructor(std::ofstream& out, t_struct* tstruct); void generate_rb_simple_exception_constructor(std::ofstream& out, t_struct* tstruct); @@ -463,7 +462,8 @@ void t_rb_generator::generate_rb_struct(std::ofstream& out, t_struct* tstruct, b generate_field_constants(out, tstruct); generate_accessors(out, tstruct); generate_field_defns(out, tstruct); - + generate_rb_struct_required_validator(out, tstruct); + indent_down(); indent(out) << "end" << endl << endl; } @@ -1027,4 +1027,30 @@ void t_rb_generator::generate_rdoc(std::ofstream& out, t_doc* tdoc) { } } +void t_rb_generator::generate_rb_struct_required_validator(std::ofstream& out, + t_struct* tstruct) { + indent(out) << "def validate" << endl; + indent_up(); + + const vector& fields = tstruct->get_members(); + vector::const_iterator f_iter; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + t_field* field = (*f_iter); + if (field->get_req() == t_field::T_REQUIRED) { + indent(out) << "raise Thrift::ProtocolException.new(Thrift::ProtocolException::UNKNOWN, 'Required field " << field->get_name() << " is unset!')"; + if (field->get_type()->is_bool()) { + out << " if @" << field->get_name() << ".nil?"; + } else { + out << " unless @" << field->get_name(); + } + out << endl; + } + } + + indent_down(); + indent(out) << "end" << endl << endl; + +} + THRIFT_REGISTER_GENERATOR(rb, "Ruby", ""); diff --git a/lib/rb/benchmark/gen-rb/BenchmarkService.rb b/lib/rb/benchmark/gen-rb/BenchmarkService.rb index 7d398825..2c3ae4f6 100644 --- a/lib/rb/benchmark/gen-rb/BenchmarkService.rb +++ b/lib/rb/benchmark/gen-rb/BenchmarkService.rb @@ -52,6 +52,9 @@ require File.dirname(__FILE__) + '/Benchmark_types' FIELDS = { N => {:type => Thrift::Types::BYTE, :name => 'n'} } + def validate + end + end class Fibonacci_result @@ -62,6 +65,9 @@ require File.dirname(__FILE__) + '/Benchmark_types' FIELDS = { SUCCESS => {:type => Thrift::Types::I32, :name => 'success'} } + def validate + end + end end diff --git a/lib/rb/lib/thrift/struct.rb b/lib/rb/lib/thrift/struct.rb index c530b33b..a51f2095 100644 --- a/lib/rb/lib/thrift/struct.rb +++ b/lib/rb/lib/thrift/struct.rb @@ -82,6 +82,7 @@ module Thrift end def read(iprot) + validate # TODO(kevinclark): Make sure transport is C readable if iprot.respond_to?(:decode_binary) iprot.decode_binary(self, iprot.trans) @@ -98,6 +99,7 @@ module Thrift end def write(oprot) + validate if oprot.respond_to?(:encode_binary) # TODO(kevinclark): Clean this so I don't have to access the transport. oprot.trans.write oprot.encode_binary(self) diff --git a/lib/rb/spec/gen-rb/NonblockingService.rb b/lib/rb/spec/gen-rb/NonblockingService.rb index ee5fae1c..a8868058 100644 --- a/lib/rb/spec/gen-rb/NonblockingService.rb +++ b/lib/rb/spec/gen-rb/NonblockingService.rb @@ -121,6 +121,9 @@ require File.dirname(__FILE__) + '/ThriftSpec_types' FIELDS = { ENGLISH => {:type => Thrift::Types::BOOL, :name => 'english'} } + def validate + end + end class Greeting_result @@ -131,6 +134,9 @@ require File.dirname(__FILE__) + '/ThriftSpec_types' FIELDS = { SUCCESS => {:type => Thrift::Types::STRUCT, :name => 'success', :class => Hello} } + def validate + end + end class Block_args @@ -139,6 +145,9 @@ require File.dirname(__FILE__) + '/ThriftSpec_types' FIELDS = { } + def validate + end + end class Block_result @@ -149,6 +158,9 @@ require File.dirname(__FILE__) + '/ThriftSpec_types' FIELDS = { SUCCESS => {:type => Thrift::Types::BOOL, :name => 'success'} } + def validate + end + end class Unblock_args @@ -159,6 +171,9 @@ require File.dirname(__FILE__) + '/ThriftSpec_types' FIELDS = { N => {:type => Thrift::Types::I32, :name => 'n'} } + def validate + end + end class Unblock_result @@ -167,6 +182,9 @@ require File.dirname(__FILE__) + '/ThriftSpec_types' FIELDS = { } + def validate + end + end class Shutdown_args @@ -175,6 +193,9 @@ require File.dirname(__FILE__) + '/ThriftSpec_types' FIELDS = { } + def validate + end + end class Shutdown_result @@ -183,6 +204,9 @@ require File.dirname(__FILE__) + '/ThriftSpec_types' FIELDS = { } + def validate + end + end class Sleep_args @@ -193,6 +217,9 @@ require File.dirname(__FILE__) + '/ThriftSpec_types' FIELDS = { SECONDS => {:type => Thrift::Types::DOUBLE, :name => 'seconds'} } + def validate + end + end class Sleep_result @@ -201,6 +228,9 @@ require File.dirname(__FILE__) + '/ThriftSpec_types' FIELDS = { } + def validate + end + end end diff --git a/lib/rb/spec/gen-rb/ThriftSpec_types.rb b/lib/rb/spec/gen-rb/ThriftSpec_types.rb index 0251524a..6e5fed42 100644 --- a/lib/rb/spec/gen-rb/ThriftSpec_types.rb +++ b/lib/rb/spec/gen-rb/ThriftSpec_types.rb @@ -15,6 +15,9 @@ module SpecNamespace FIELDS = { GREETING => {:type => Thrift::Types::STRING, :name => 'greeting', :default => 'hello world'} } + def validate + end + end class Foo @@ -47,6 +50,9 @@ module SpecNamespace ]), :element => {:type => Thrift::Types::I16}}, OPT_STRING => {:type => Thrift::Types::STRING, :name => 'opt_string', :optional => true} } + def validate + end + end class BoolStruct @@ -57,6 +63,9 @@ module SpecNamespace FIELDS = { YESNO => {:type => Thrift::Types::BOOL, :name => 'yesno', :default => true} } + def validate + end + end class SimpleList -- 2.17.1