]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/thrift/lib/rb/lib/thrift/union.rb
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / lib / rb / lib / thrift / union.rb
1 #
2 # Licensed to the Apache Software Foundation (ASF) under one
3 # or more contributor license agreements. See the NOTICE file
4 # distributed with this work for additional information
5 # regarding copyright ownership. The ASF licenses this file
6 # to you under the Apache License, Version 2.0 (the
7 # "License"); you may not use this file except in compliance
8 # with the License. You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing,
13 # software distributed under the License is distributed on an
14 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 # KIND, either express or implied. See the License for the
16 # specific language governing permissions and limitations
17 # under the License.
18 #
19
20 module Thrift
21 class Union
22 def initialize(name=nil, value=nil)
23 if name
24 if name.is_a? Hash
25 if name.size > 1
26 raise "#{self.class} cannot be instantiated with more than one field!"
27 end
28
29 name, value = name.keys.first, name.values.first
30 end
31
32 if Thrift.type_checking
33 raise Exception, "#{self.class} does not contain a field named #{name}!" unless name_to_id(name.to_s)
34 end
35
36 if value.nil?
37 raise Exception, "Union #{self.class} cannot be instantiated with setfield and nil value!"
38 end
39
40 Thrift.check_type(value, struct_fields[name_to_id(name.to_s)], name) if Thrift.type_checking
41 elsif !value.nil?
42 raise Exception, "Value provided, but no name!"
43 end
44 @setfield = name
45 @value = value
46 end
47
48 def inspect
49 if get_set_field
50 "<#{self.class} #{@setfield}: #{inspect_field(@value, struct_fields[name_to_id(@setfield.to_s)])}>"
51 else
52 "<#{self.class} >"
53 end
54 end
55
56 def read(iprot)
57 iprot.read_struct_begin
58 fname, ftype, fid = iprot.read_field_begin
59 handle_message(iprot, fid, ftype)
60 iprot.read_field_end
61
62 fname, ftype, fid = iprot.read_field_begin
63 raise "Too many fields for union" unless (ftype == Types::STOP)
64
65 iprot.read_struct_end
66 validate
67 end
68
69 def write(oprot)
70 validate
71 oprot.write_struct_begin(self.class.name)
72
73 fid = self.name_to_id(@setfield.to_s)
74
75 field_info = struct_fields[fid]
76 type = field_info[:type]
77 if is_container? type
78 oprot.write_field_begin(@setfield, type, fid)
79 write_container(oprot, @value, field_info)
80 oprot.write_field_end
81 else
82 oprot.write_field(@setfield, type, fid, @value)
83 end
84
85 oprot.write_field_stop
86 oprot.write_struct_end
87 end
88
89 def ==(other)
90 other.equal?(self) || other.instance_of?(self.class) && @setfield == other.get_set_field && @value == other.get_value
91 end
92 alias_method :eql?, :==
93
94 def hash
95 [self.class.name, @setfield, @value].hash
96 end
97
98 def self.field_accessor(klass, field_info)
99 klass.send :define_method, field_info[:name] do
100 if field_info[:name].to_sym == @setfield
101 @value
102 else
103 raise RuntimeError, "#{field_info[:name]} is not union's set field."
104 end
105 end
106
107 klass.send :define_method, "#{field_info[:name]}=" do |value|
108 Thrift.check_type(value, field_info, field_info[:name]) if Thrift.type_checking
109 @setfield = field_info[:name].to_sym
110 @value = value
111 end
112 end
113
114 def self.qmark_isset_method(klass, field_info)
115 klass.send :define_method, "#{field_info[:name]}?" do
116 get_set_field == field_info[:name].to_sym && !get_value.nil?
117 end
118 end
119
120 def self.generate_accessors(klass)
121 klass::FIELDS.values.each do |field_info|
122 field_accessor(klass, field_info)
123 qmark_isset_method(klass, field_info)
124 end
125 end
126
127 # get the symbol that indicates what the currently set field type is.
128 def get_set_field
129 @setfield
130 end
131
132 # get the current value of this union, regardless of what the set field is.
133 # generally, you should only use this method when you don't know in advance
134 # what field to expect.
135 def get_value
136 @value
137 end
138
139 def <=>(other)
140 if self.class == other.class
141 if get_set_field == other.get_set_field
142 if get_set_field.nil?
143 0
144 else
145 get_value <=> other.get_value
146 end
147 else
148 if get_set_field && other.get_set_field.nil?
149 -1
150 elsif get_set_field.nil? && other.get_set_field
151 1
152 elsif get_set_field.nil? && other.get_set_field.nil?
153 0
154 else
155 name_to_id(get_set_field.to_s) <=> name_to_id(other.get_set_field.to_s)
156 end
157 end
158 else
159 self.class <=> other.class
160 end
161 end
162
163 protected
164
165 def handle_message(iprot, fid, ftype)
166 field = struct_fields[fid]
167 if field and field[:type] == ftype
168 @value = read_field(iprot, field)
169 name = field[:name].to_sym
170 @setfield = name
171 else
172 iprot.skip(ftype)
173 end
174 end
175 end
176 end