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# this require is to make generated struct definitions happy 21require 'set' 22 23module Thrift 24 class ProtocolException < Exception 25 26 UNKNOWN = 0 27 INVALID_DATA = 1 28 NEGATIVE_SIZE = 2 29 SIZE_LIMIT = 3 30 BAD_VERSION = 4 31 NOT_IMPLEMENTED = 5 32 DEPTH_LIMIT = 6 33 34 attr_reader :type 35 36 def initialize(type=UNKNOWN, message=nil) 37 super(message) 38 @type = type 39 end 40 end 41 42 class BaseProtocol 43 44 attr_reader :trans 45 46 def initialize(trans) 47 @trans = trans 48 end 49 50 def native? 51 puts "wrong method is being called!" 52 false 53 end 54 55 def write_message_begin(name, type, seqid) 56 raise NotImplementedError 57 end 58 59 def write_message_end; nil; end 60 61 def write_struct_begin(name) 62 raise NotImplementedError 63 end 64 65 def write_struct_end; nil; end 66 67 def write_field_begin(name, type, id) 68 raise NotImplementedError 69 end 70 71 def write_field_end; nil; end 72 73 def write_field_stop 74 raise NotImplementedError 75 end 76 77 def write_map_begin(ktype, vtype, size) 78 raise NotImplementedError 79 end 80 81 def write_map_end; nil; end 82 83 def write_list_begin(etype, size) 84 raise NotImplementedError 85 end 86 87 def write_list_end; nil; end 88 89 def write_set_begin(etype, size) 90 raise NotImplementedError 91 end 92 93 def write_set_end; nil; end 94 95 def write_bool(bool) 96 raise NotImplementedError 97 end 98 99 def write_byte(byte) 100 raise NotImplementedError 101 end 102 103 def write_i16(i16) 104 raise NotImplementedError 105 end 106 107 def write_i32(i32) 108 raise NotImplementedError 109 end 110 111 def write_i64(i64) 112 raise NotImplementedError 113 end 114 115 def write_double(dub) 116 raise NotImplementedError 117 end 118 119 # Writes a Thrift String. In Ruby 1.9+, the String passed will be transcoded to UTF-8. 120 # 121 # str - The String to write. 122 # 123 # Raises EncodingError if the transcoding to UTF-8 fails. 124 # 125 # Returns nothing. 126 def write_string(str) 127 raise NotImplementedError 128 end 129 130 # Writes a Thrift Binary (Thrift String with no encoding). In Ruby 1.9+, the String passed 131 # will forced into BINARY encoding. 132 # 133 # buf - The String to write. 134 # 135 # Returns nothing. 136 def write_binary(buf) 137 raise NotImplementedError 138 end 139 140 def read_message_begin 141 raise NotImplementedError 142 end 143 144 def read_message_end; nil; end 145 146 def read_struct_begin 147 raise NotImplementedError 148 end 149 150 def read_struct_end; nil; end 151 152 def read_field_begin 153 raise NotImplementedError 154 end 155 156 def read_field_end; nil; end 157 158 def read_map_begin 159 raise NotImplementedError 160 end 161 162 def read_map_end; nil; end 163 164 def read_list_begin 165 raise NotImplementedError 166 end 167 168 def read_list_end; nil; end 169 170 def read_set_begin 171 raise NotImplementedError 172 end 173 174 def read_set_end; nil; end 175 176 def read_bool 177 raise NotImplementedError 178 end 179 180 def read_byte 181 raise NotImplementedError 182 end 183 184 def read_i16 185 raise NotImplementedError 186 end 187 188 def read_i32 189 raise NotImplementedError 190 end 191 192 def read_i64 193 raise NotImplementedError 194 end 195 196 def read_double 197 raise NotImplementedError 198 end 199 200 # Reads a Thrift String. In Ruby 1.9+, all Strings will be returned with an Encoding of UTF-8. 201 # 202 # Returns a String. 203 def read_string 204 raise NotImplementedError 205 end 206 207 # Reads a Thrift Binary (Thrift String without encoding). In Ruby 1.9+, all Strings will be returned 208 # with an Encoding of BINARY. 209 # 210 # Returns a String. 211 def read_binary 212 raise NotImplementedError 213 end 214 215 # Writes a field based on the field information, field ID and value. 216 # 217 # field_info - A Hash containing the definition of the field: 218 # :name - The name of the field. 219 # :type - The type of the field, which must be a Thrift::Types constant. 220 # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding). 221 # fid - The ID of the field. 222 # value - The field's value to write; object type varies based on :type. 223 # 224 # Returns nothing. 225 def write_field(*args) 226 if args.size == 3 227 # handles the documented method signature - write_field(field_info, fid, value) 228 field_info = args[0] 229 fid = args[1] 230 value = args[2] 231 elsif args.size == 4 232 # handles the deprecated method signature - write_field(name, type, fid, value) 233 field_info = {:name => args[0], :type => args[1]} 234 fid = args[2] 235 value = args[3] 236 else 237 raise ArgumentError, "wrong number of arguments (#{args.size} for 3)" 238 end 239 240 write_field_begin(field_info[:name], field_info[:type], fid) 241 write_type(field_info, value) 242 write_field_end 243 end 244 245 # Writes a field value based on the field information. 246 # 247 # field_info - A Hash containing the definition of the field: 248 # :type - The Thrift::Types constant that determines how the value is written. 249 # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding). 250 # value - The field's value to write; object type varies based on field_info[:type]. 251 # 252 # Returns nothing. 253 def write_type(field_info, value) 254 # if field_info is a Fixnum, assume it is a Thrift::Types constant 255 # convert it into a field_info Hash for backwards compatibility 256 if field_info.is_a? Fixnum 257 field_info = {:type => field_info} 258 end 259 260 case field_info[:type] 261 when Types::BOOL 262 write_bool(value) 263 when Types::BYTE 264 write_byte(value) 265 when Types::DOUBLE 266 write_double(value) 267 when Types::I16 268 write_i16(value) 269 when Types::I32 270 write_i32(value) 271 when Types::I64 272 write_i64(value) 273 when Types::STRING 274 if field_info[:binary] 275 write_binary(value) 276 else 277 write_string(value) 278 end 279 when Types::STRUCT 280 value.write(self) 281 else 282 raise NotImplementedError 283 end 284 end 285 286 # Reads a field value based on the field information. 287 # 288 # field_info - A Hash containing the pertinent data to write: 289 # :type - The Thrift::Types constant that determines how the value is written. 290 # :binary - A flag that indicates if Thrift::Types::STRING is a binary string (string without encoding). 291 # 292 # Returns the value read; object type varies based on field_info[:type]. 293 def read_type(field_info) 294 # if field_info is a Fixnum, assume it is a Thrift::Types constant 295 # convert it into a field_info Hash for backwards compatibility 296 if field_info.is_a? Fixnum 297 field_info = {:type => field_info} 298 end 299 300 case field_info[:type] 301 when Types::BOOL 302 read_bool 303 when Types::BYTE 304 read_byte 305 when Types::DOUBLE 306 read_double 307 when Types::I16 308 read_i16 309 when Types::I32 310 read_i32 311 when Types::I64 312 read_i64 313 when Types::STRING 314 if field_info[:binary] 315 read_binary 316 else 317 read_string 318 end 319 else 320 raise NotImplementedError 321 end 322 end 323 324 def skip(type) 325 case type 326 when Types::BOOL 327 read_bool 328 when Types::BYTE 329 read_byte 330 when Types::I16 331 read_i16 332 when Types::I32 333 read_i32 334 when Types::I64 335 read_i64 336 when Types::DOUBLE 337 read_double 338 when Types::STRING 339 read_string 340 when Types::STRUCT 341 read_struct_begin 342 while true 343 name, type, id = read_field_begin 344 break if type == Types::STOP 345 skip(type) 346 read_field_end 347 end 348 read_struct_end 349 when Types::MAP 350 ktype, vtype, size = read_map_begin 351 size.times do 352 skip(ktype) 353 skip(vtype) 354 end 355 read_map_end 356 when Types::SET 357 etype, size = read_set_begin 358 size.times do 359 skip(etype) 360 end 361 read_set_end 362 when Types::LIST 363 etype, size = read_list_begin 364 size.times do 365 skip(etype) 366 end 367 read_list_end 368 else 369 raise ProtocolException.new(ProtocolException::INVALID_DATA, 'Invalid data') 370 end 371 end 372 373 def to_s 374 "#{trans.to_s}" 375 end 376 end 377 378 class BaseProtocolFactory 379 def get_protocol(trans) 380 raise NotImplementedError 381 end 382 383 def to_s 384 "base" 385 end 386 end 387end 388