| Module | ThriftClient::Simple |
| In: |
lib/thrift_client/simple.rb
lib/thrift_client/simple.rb |
This is a simplified form of thrift, useful for clients only, and not making any attempt to have good performance. It‘s intended to be used by small command-line tools that don‘t want to install a dozen ruby files.
| VERSION_1 | = | 0x8001 |
| EXCEPTION | = | (1..3).to_a |
| LIST | = | (0..15).to_a |
| FORMATS | = | { BYTE => "c", DOUBLE => "G", I16 => "n", I32 => "N", } |
| SIZES | = | { BYTE => 1, DOUBLE => 8, I16 => 2, I32 => 4, } |
| ListType | = | make_type(LIST, "ListType", :element_type) |
| MapType | = | make_type(MAP, "MapType", :key_type, :value_type) |
| SetType | = | make_type(SET, "SetType", :element_type) |
| StructType | = | make_type(STRUCT, "StructType", :struct_class) |
| VERSION_1 | = | 0x8001 |
| EXCEPTION | = | (1..3).to_a |
| LIST | = | (0..15).to_a |
| FORMATS | = | { BYTE => "c", DOUBLE => "G", I16 => "n", I32 => "N", } |
| SIZES | = | { BYTE => 1, DOUBLE => 8, I16 => 2, I32 => 4, } |
| ListType | = | make_type(LIST, "ListType", :element_type) |
| MapType | = | make_type(MAP, "MapType", :key_type, :value_type) |
| SetType | = | make_type(SET, "SetType", :element_type) |
| StructType | = | make_type(STRUCT, "StructType", :struct_class) |
# File lib/thrift_client/simple.rb, line 220
220: def self.make_struct(name, *fields)
221: st_name = "ST_#{name}"
222: if Struct.constants.include?(st_name)
223: warn "#{caller[0]}: Struct::#{st_name} is already defined; returning original class."
224: Struct.const_get(st_name)
225: else
226: names = fields.map { |f| f.name.to_sym }
227: klass = Struct.new(st_name, *names)
228: klass.send(:include, ThriftStruct::Include)
229: klass.send(:extend, ThriftStruct::Extend)
230: klass._fields = fields
231: klass
232: end
233: end
# File lib/thrift_client/simple.rb, line 220
220: def self.make_struct(name, *fields)
221: st_name = "ST_#{name}"
222: if Struct.constants.include?(st_name)
223: warn "#{caller[0]}: Struct::#{st_name} is already defined; returning original class."
224: Struct.const_get(st_name)
225: else
226: names = fields.map { |f| f.name.to_sym }
227: klass = Struct.new(st_name, *names)
228: klass.send(:include, ThriftStruct::Include)
229: klass.send(:extend, ThriftStruct::Extend)
230: klass._fields = fields
231: klass
232: end
233: end
# File lib/thrift_client/simple.rb, line 55
55: def self.make_type(type_id, name, *args)
56: klass = Struct.new("STT_#{name}", *args)
57: klass.send(:extend, ComplexType::Extends)
58: klass.send(:include, ComplexType::Includes)
59: klass.type_id = type_id
60: klass
61: end
# File lib/thrift_client/simple.rb, line 55
55: def self.make_type(type_id, name, *args)
56: klass = Struct.new("STT_#{name}", *args)
57: klass.send(:extend, ComplexType::Extends)
58: klass.send(:include, ComplexType::Includes)
59: klass.type_id = type_id
60: klass
61: end
# File lib/thrift_client/simple.rb, line 90
90: def pack_request(method_name, arg_struct, request_id=0)
91: [ VERSION_1, CALL, method_name.to_s.size, method_name.to_s, request_id, arg_struct._pack ].pack("nnNa*Na*")
92: end
# File lib/thrift_client/simple.rb, line 90
90: def pack_request(method_name, arg_struct, request_id=0)
91: [ VERSION_1, CALL, method_name.to_s.size, method_name.to_s, request_id, arg_struct._pack ].pack("nnNa*Na*")
92: end
# File lib/thrift_client/simple.rb, line 69
69: def pack_value(type, value)
70: case type
71: when BOOL
72: [ value ? 1 : 0 ].pack("c")
73: when STRING
74: [ value.size, value ].pack("Na*")
75: when I64
76: [ value >> 32, value & 0xffffffff ].pack("NN")
77: when ListType
78: [ type.element_type.to_i, value.size ].pack("cN") + value.map { |item| pack_value(type.element_type, item) }.join("")
79: when MapType
80: [ type.key_type.to_i, type.value_type.to_i, value.size ].pack("ccN") + value.map { |k, v| pack_value(type.key_type, k) + pack_value(type.value_type, v) }.join("")
81: when SetType
82: [ type.element_type.to_i, value.size ].pack("cN") + value.map { |item| pack_value(type.element_type, item) }.join("")
83: when StructType
84: value._pack
85: else
86: [ value ].pack(FORMATS[type])
87: end
88: end
# File lib/thrift_client/simple.rb, line 69
69: def pack_value(type, value)
70: case type
71: when BOOL
72: [ value ? 1 : 0 ].pack("c")
73: when STRING
74: [ value.size, value ].pack("Na*")
75: when I64
76: [ value >> 32, value & 0xffffffff ].pack("NN")
77: when ListType
78: [ type.element_type.to_i, value.size ].pack("cN") + value.map { |item| pack_value(type.element_type, item) }.join("")
79: when MapType
80: [ type.key_type.to_i, type.value_type.to_i, value.size ].pack("ccN") + value.map { |k, v| pack_value(type.key_type, k) + pack_value(type.value_type, v) }.join("")
81: when SetType
82: [ type.element_type.to_i, value.size ].pack("cN") + value.map { |item| pack_value(type.element_type, item) }.join("")
83: when StructType
84: value._pack
85: else
86: [ value ].pack(FORMATS[type])
87: end
88: end
# File lib/thrift_client/simple.rb, line 130
130: def read_list(s, element_type=nil)
131: etype, len = s.read(5).unpack("cN")
132: expected_type = (element_type and element_type.to_i == etype.to_i) ? element_type : etype
133: rv = []
134: len.times do
135: rv << read_value(s, expected_type)
136: end
137: rv
138: end
# File lib/thrift_client/simple.rb, line 130
130: def read_list(s, element_type=nil)
131: etype, len = s.read(5).unpack("cN")
132: expected_type = (element_type and element_type.to_i == etype.to_i) ? element_type : etype
133: rv = []
134: len.times do
135: rv << read_value(s, expected_type)
136: end
137: rv
138: end
# File lib/thrift_client/simple.rb, line 140
140: def read_map(s, key_type=nil, value_type=nil)
141: ktype, vtype, len = s.read(6).unpack("ccN")
142: rv = {}
143: expected_key_type, expected_value_type = if key_type and value_type and key_type.to_i == ktype and value_type.to_i == vtype
144: [ key_type, value_type ]
145: else
146: [ ktype, vtype ]
147: end
148: len.times do
149: key = read_value(s, expected_key_type)
150: value = read_value(s, expected_value_type)
151: rv[key] = value
152: end
153: rv
154: end
# File lib/thrift_client/simple.rb, line 140
140: def read_map(s, key_type=nil, value_type=nil)
141: ktype, vtype, len = s.read(6).unpack("ccN")
142: rv = {}
143: expected_key_type, expected_value_type = if key_type and value_type and key_type.to_i == ktype and value_type.to_i == vtype
144: [ key_type, value_type ]
145: else
146: [ ktype, vtype ]
147: end
148: len.times do
149: key = read_value(s, expected_key_type)
150: value = read_value(s, expected_value_type)
151: rv[key] = value
152: end
153: rv
154: end
# File lib/thrift_client/simple.rb, line 168
168: def read_response(s, rv_class)
169: version, message_type, method_name_len = s.read(8).unpack("nnN")
170: method_name = s.read(method_name_len)
171: seq_id = s.read(4).unpack("N").first
172: [ method_name, seq_id, read_struct(s, rv_class).rv ]
173: end
# File lib/thrift_client/simple.rb, line 168
168: def read_response(s, rv_class)
169: version, message_type, method_name_len = s.read(8).unpack("nnN")
170: method_name = s.read(method_name_len)
171: seq_id = s.read(4).unpack("N").first
172: [ method_name, seq_id, read_struct(s, rv_class).rv ]
173: end
# File lib/thrift_client/simple.rb, line 156
156: def read_struct(s, struct_class=nil)
157: rv = struct_class.new()
158: while true
159: type = s.read(1).unpack("c").first
160: return rv if type == STOP
161: fid = s.read(2).unpack("n").first
162: field = struct_class ? struct_class._fields.find { |f| (f.fid == fid) and (f.type.to_i == type) } : nil
163: value = read_value(s, field ? field.type : type)
164: rv[field.name] = value if field
165: end
166: end
# File lib/thrift_client/simple.rb, line 156
156: def read_struct(s, struct_class=nil)
157: rv = struct_class.new()
158: while true
159: type = s.read(1).unpack("c").first
160: return rv if type == STOP
161: fid = s.read(2).unpack("n").first
162: field = struct_class ? struct_class._fields.find { |f| (f.fid == fid) and (f.type.to_i == type) } : nil
163: value = read_value(s, field ? field.type : type)
164: rv[field.name] = value if field
165: end
166: end
# File lib/thrift_client/simple.rb, line 94
94: def read_value(s, type)
95: case type
96: when BOOL
97: s.read(1).unpack("c").first != 0
98: when STRING
99: len = s.read(4).unpack("N").first
100: s.read(len)
101: when I64
102: hi, lo = s.read(8).unpack("NN")
103: rv = (hi << 32) | lo
104: (rv >= (1 << 63)) ? (rv - (1 << 64)) : rv
105: when LIST
106: read_list(s)
107: when MAP
108: read_map(s)
109: when STRUCT
110: read_struct(s)
111: when ListType
112: read_list(s, type.element_type)
113: when MapType
114: read_map(s, type.key_type, type.value_type)
115: when StructType
116: read_struct(s, type.struct_class)
117: else
118: rv = s.read(SIZES[type]).unpack(FORMATS[type]).first
119: case type
120: when I16
121: (rv >= (1 << 15)) ? (rv - (1 << 16)) : rv
122: when I32
123: (rv >= (1 << 31)) ? (rv - (1 << 32)) : rv
124: else
125: rv
126: end
127: end
128: end
# File lib/thrift_client/simple.rb, line 94
94: def read_value(s, type)
95: case type
96: when BOOL
97: s.read(1).unpack("c").first != 0
98: when STRING
99: len = s.read(4).unpack("N").first
100: s.read(len)
101: when I64
102: hi, lo = s.read(8).unpack("NN")
103: rv = (hi << 32) | lo
104: (rv >= (1 << 63)) ? (rv - (1 << 64)) : rv
105: when LIST
106: read_list(s)
107: when MAP
108: read_map(s)
109: when STRUCT
110: read_struct(s)
111: when ListType
112: read_list(s, type.element_type)
113: when MapType
114: read_map(s, type.key_type, type.value_type)
115: when StructType
116: read_struct(s, type.struct_class)
117: else
118: rv = s.read(SIZES[type]).unpack(FORMATS[type]).first
119: case type
120: when I16
121: (rv >= (1 << 15)) ? (rv - (1 << 16)) : rv
122: when I32
123: (rv >= (1 << 31)) ? (rv - (1 << 32)) : rv
124: else
125: rv
126: end
127: end
128: end