diff options
Diffstat (limited to 'vendor/thrift/protocol/binary_protocol.rb')
| -rw-r--r-- | vendor/thrift/protocol/binary_protocol.rb | 229 | 
1 files changed, 229 insertions, 0 deletions
| diff --git a/vendor/thrift/protocol/binary_protocol.rb b/vendor/thrift/protocol/binary_protocol.rb new file mode 100644 index 0000000..f9adb20 --- /dev/null +++ b/vendor/thrift/protocol/binary_protocol.rb @@ -0,0 +1,229 @@ +#  +# 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. +#  + +module Thrift +  class BinaryProtocol < BaseProtocol +    VERSION_MASK = 0xffff0000 +    VERSION_1 = 0x80010000 +    TYPE_MASK = 0x000000ff +     +    attr_reader :strict_read, :strict_write + +    def initialize(trans, strict_read=true, strict_write=true) +      super(trans) +      @strict_read = strict_read +      @strict_write = strict_write + +      # Pre-allocated read buffer for fixed-size read methods. Needs to be at least 8 bytes long for +      # read_i64() and read_double(). +      @rbuf = "\0" * 8 +      @rbuf.force_encoding("BINARY") if @rbuf.respond_to?(:force_encoding) +    end + +    def write_message_begin(name, type, seqid) +      # this is necessary because we added (needed) bounds checking to  +      # write_i32, and 0x80010000 is too big for that. +      if strict_write +        write_i16(VERSION_1 >> 16) +        write_i16(type) +        write_string(name) +        write_i32(seqid) +      else +        write_string(name) +        write_byte(type) +        write_i32(seqid) +      end +    end + +    def write_struct_begin(name); nil; end + +    def write_field_begin(name, type, id) +      write_byte(type) +      write_i16(id) +    end + +    def write_field_stop +      write_byte(Thrift::Types::STOP) +    end + +    def write_map_begin(ktype, vtype, size) +      write_byte(ktype) +      write_byte(vtype) +      write_i32(size) +    end + +    def write_list_begin(etype, size) +      write_byte(etype) +      write_i32(size) +    end + +    def write_set_begin(etype, size) +      write_byte(etype) +      write_i32(size) +    end + +    def write_bool(bool) +      write_byte(bool ? 1 : 0) +    end + +    def write_byte(byte) +      raise RangeError if byte < -2**31 || byte >= 2**32 +      trans.write([byte].pack('c')) +    end + +    def write_i16(i16) +      trans.write([i16].pack('n')) +    end + +    def write_i32(i32) +      raise RangeError if i32 < -2**31 || i32 >= 2**31 +      trans.write([i32].pack('N')) +    end + +    def write_i64(i64) +      raise RangeError if i64 < -2**63 || i64 >= 2**64 +      hi = i64 >> 32 +      lo = i64 & 0xffffffff +      trans.write([hi, lo].pack('N2')) +    end + +    def write_double(dub) +      trans.write([dub].pack('G')) +    end + +    def write_string(str) +      write_i32(str.length) +      trans.write(str) +    end + +    def read_message_begin +      version = read_i32 +      if version < 0 +        if (version & VERSION_MASK != VERSION_1) +          raise ProtocolException.new(ProtocolException::BAD_VERSION, 'Missing version identifier') +        end +        type = version & TYPE_MASK +        name = read_string +        seqid = read_i32 +        [name, type, seqid] +      else +        if strict_read +          raise ProtocolException.new(ProtocolException::BAD_VERSION, 'No version identifier, old protocol client?') +        end +        name = trans.read_all(version) +        type = read_byte +        seqid = read_i32 +        [name, type, seqid] +      end +    end + +    def read_struct_begin; nil; end + +    def read_field_begin +      type = read_byte +      if (type == Types::STOP) +        [nil, type, 0] +      else +        id = read_i16 +        [nil, type, id] +      end +    end + +    def read_map_begin +      ktype = read_byte +      vtype = read_byte +      size = read_i32 +      [ktype, vtype, size] +    end + +    def read_list_begin +      etype = read_byte +      size = read_i32 +      [etype, size] +    end + +    def read_set_begin +      etype = read_byte +      size = read_i32 +      [etype, size] +    end + +    def read_bool +      byte = read_byte +      byte != 0 +    end + +    def read_byte +      val = trans.read_byte +      if (val > 0x7f) +        val = 0 - ((val - 1) ^ 0xff) +      end +      val +    end + +    def read_i16 +      trans.read_into_buffer(@rbuf, 2) +      val, = @rbuf.unpack('n') +      if (val > 0x7fff) +        val = 0 - ((val - 1) ^ 0xffff) +      end +      val +    end + +    def read_i32 +      trans.read_into_buffer(@rbuf, 4) +      val, = @rbuf.unpack('N') +      if (val > 0x7fffffff) +        val = 0 - ((val - 1) ^ 0xffffffff) +      end +      val +    end + +    def read_i64 +      trans.read_into_buffer(@rbuf, 8) +      hi, lo = @rbuf.unpack('N2') +      if (hi > 0x7fffffff) +        hi ^= 0xffffffff +        lo ^= 0xffffffff +        0 - (hi << 32) - lo - 1 +      else +        (hi << 32) + lo +      end +    end + +    def read_double +      trans.read_into_buffer(@rbuf, 8) +      val = @rbuf.unpack('G').first +      val +    end + +    def read_string +      sz = read_i32 +      dat = trans.read_all(sz) +      dat +    end + +  end + +  class BinaryProtocolFactory < BaseProtocolFactory +    def get_protocol(trans) +      return Thrift::BinaryProtocol.new(trans) +    end +  end +end | 
