lib/thrift/struct.rb in thrift-0.0.751142 vs lib/thrift/struct.rb in thrift-0.0.810255.1

- old
+ new

@@ -1,6 +1,24 @@ -require 'thrift/types' +# +# 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. +# + require 'set' module Thrift module Struct def initialize(d={}) @@ -37,11 +55,11 @@ def fields_with_default_values fields_with_default_values = self.class.instance_variable_get("@fields_with_default_values") unless fields_with_default_values fields_with_default_values = {} struct_fields.each do |fid, field_def| - if field_def[:default] + unless field_def[:default].nil? fields_with_default_values[field_def[:name]] = field_def[:default] end end self.class.instance_variable_set("@fields_with_default_values", fields_with_default_values) end @@ -58,90 +76,95 @@ self.class.instance_variable_set("@names_to_ids", names_to_ids) end names_to_ids[name] end - # Obsoleted by THRIFT-246, which generates this method inline - # TODO: Should be removed at some point. -- Kevin Clark - def struct_fields - self.class.const_get(:FIELDS) - end - def each_field - struct_fields.each do |fid, data| - yield fid, data[:type], data[:name], data[:default], data[:optional] + struct_fields.keys.sort.each do |fid| + data = struct_fields[fid] + yield fid, data end end def inspect(skip_optional_nulls = true) fields = [] - each_field do |fid, type, name, default, optional| + each_field do |fid, field_info| + name = field_info[:name] value = instance_variable_get("@#{name}") - unless skip_optional_nulls && optional && value.nil? + unless skip_optional_nulls && field_info[:optional] && value.nil? fields << "#{name}:#{value.inspect}" end end "<#{self.class} #{fields.join(", ")}>" end def read(iprot) - # TODO(kevinclark): Make sure transport is C readable - if iprot.respond_to?(:decode_binary) - iprot.decode_binary(self, iprot.trans) - else - iprot.read_struct_begin - loop do - fname, ftype, fid = iprot.read_field_begin - break if (ftype == Types::STOP) - handle_message(iprot, fid, ftype) - iprot.read_field_end - end - iprot.read_struct_end + iprot.read_struct_begin + loop do + fname, ftype, fid = iprot.read_field_begin + break if (ftype == Types::STOP) + handle_message(iprot, fid, ftype) + iprot.read_field_end end + iprot.read_struct_end validate 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) - # else - oprot.write_struct_begin(self.class.name) - each_field do |fid, type, name| - unless (value = instance_variable_get("@#{name}")).nil? - if is_container? type - oprot.write_field_begin(name, type, fid) - write_container(oprot, value, struct_fields[fid]) - oprot.write_field_end - else - oprot.write_field(name, type, fid, value) - end + oprot.write_struct_begin(self.class.name) + each_field do |fid, field_info| + name = field_info[:name] + type = field_info[:type] + if (value = instance_variable_get("@#{name}")) + if is_container? type + oprot.write_field_begin(name, type, fid) + write_container(oprot, value, field_info) + oprot.write_field_end + else + oprot.write_field(name, type, fid, value) end end - oprot.write_field_stop - oprot.write_struct_end - # end + end + oprot.write_field_stop + oprot.write_struct_end end def ==(other) - return false unless other.is_a?(self.class) - each_field do |fid, type, name, default| + each_field do |fid, field_info| + name = field_info[:name] return false unless self.instance_variable_get("@#{name}") == other.instance_variable_get("@#{name}") end true end def eql?(other) self.class == other.class && self == other end - # for the time being, we're ok with a naive hash. this could definitely be improved upon. def hash - 0 + field_values = [] + each_field do |fid, field_info| + name = field_info[:name] + field_values << self.instance_variable_get("@#{name}") + end + field_values.hash end + def differences(other) + diffs = [] + unless other.is_a?(self.class) + diffs << "Different class!" + else + each_field do |fid, field_info| + name = field_info[:name] + diffs << "#{name} differs!" unless self.instance_variable_get("@#{name}") == other.instance_variable_get("@#{name}") + end + end + diffs + end + def self.field_accessor(klass, *fields) fields.each do |field| klass.send :attr_reader, field klass.send :define_method, "#{field}=" do |value| Thrift.check_type(value, klass::FIELDS.values.find { |f| f[:name].to_s == field.to_s }, field) if Thrift.type_checking @@ -254,19 +277,22 @@ else raise "Not a container type: #{field[:type]}" end end + CONTAINER_TYPES = [] + CONTAINER_TYPES[Types::LIST] = true + CONTAINER_TYPES[Types::MAP] = true + CONTAINER_TYPES[Types::SET] = true def is_container?(type) - [Types::LIST, Types::MAP, Types::SET].include? type + CONTAINER_TYPES[type] end def field_info(field) { :type => field[:type], :class => field[:class], :key => field[:key], :value => field[:value], :element => field[:element] } end end - deprecate_module! :ThriftStruct => Struct end