Subversion Repositories SmartDukaan

Rev

Rev 30 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
30 ashish 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 BinaryProtocol < BaseProtocol
22
    VERSION_MASK = 0xffff0000
23
    VERSION_1 = 0x80010000
24
    TYPE_MASK = 0x000000ff
25
 
26
    attr_reader :strict_read, :strict_write
27
 
28
    def initialize(trans, strict_read=true, strict_write=true)
29
      super(trans)
30
      @strict_read = strict_read
31
      @strict_write = strict_write
32
    end
33
 
34
    def write_message_begin(name, type, seqid)
35
      # this is necessary because we added (needed) bounds checking to 
36
      # write_i32, and 0x80010000 is too big for that.
37
      if strict_write
38
        write_i16(VERSION_1 >> 16)
39
        write_i16(type)
40
        write_string(name)
41
        write_i32(seqid)
42
      else
43
        write_string(name)
44
        write_byte(type)
45
        write_i32(seqid)
46
      end
47
    end
48
 
49
    def write_struct_begin(name); nil; end
50
 
51
    def write_field_begin(name, type, id)
52
      write_byte(type)
53
      write_i16(id)
54
    end
55
 
56
    def write_field_stop
57
      write_byte(Thrift::Types::STOP)
58
    end
59
 
60
    def write_map_begin(ktype, vtype, size)
61
      write_byte(ktype)
62
      write_byte(vtype)
63
      write_i32(size)
64
    end
65
 
66
    def write_list_begin(etype, size)
67
      write_byte(etype)
68
      write_i32(size)
69
    end
70
 
71
    def write_set_begin(etype, size)
72
      write_byte(etype)
73
      write_i32(size)
74
    end
75
 
76
    def write_bool(bool)
77
      write_byte(bool ? 1 : 0)
78
    end
79
 
80
    def write_byte(byte)
81
      raise RangeError if byte < -2**31 || byte >= 2**32
82
      trans.write([byte].pack('c'))
83
    end
84
 
85
    def write_i16(i16)
86
      trans.write([i16].pack('n'))
87
    end
88
 
89
    def write_i32(i32)
90
      raise RangeError if i32 < -2**31 || i32 >= 2**31
91
      trans.write([i32].pack('N'))
92
    end
93
 
94
    def write_i64(i64)
95
      raise RangeError if i64 < -2**63 || i64 >= 2**64
96
      hi = i64 >> 32
97
      lo = i64 & 0xffffffff
98
      trans.write([hi, lo].pack('N2'))
99
    end
100
 
101
    def write_double(dub)
102
      trans.write([dub].pack('G'))
103
    end
104
 
105
    def write_string(str)
106
      write_i32(str.length)
107
      trans.write(str)
108
    end
109
 
110
    def read_message_begin
111
      version = read_i32
112
      if version < 0
113
        if (version & VERSION_MASK != VERSION_1)
114
          raise ProtocolException.new(ProtocolException::BAD_VERSION, 'Missing version identifier')
115
        end
116
        type = version & TYPE_MASK
117
        name = read_string
118
        seqid = read_i32
119
        [name, type, seqid]
120
      else
121
        if strict_read
122
          raise ProtocolException.new(ProtocolException::BAD_VERSION, 'No version identifier, old protocol client?')
123
        end
124
        name = trans.read_all(version)
125
        type = read_byte
126
        seqid = read_i32
127
        [name, type, seqid]
128
      end
129
    end
130
 
131
    def read_struct_begin; nil; end
132
 
133
    def read_field_begin
134
      type = read_byte
135
      if (type == Types::STOP)
136
        [nil, type, 0]
137
      else
138
        id = read_i16
139
        [nil, type, id]
140
      end
141
    end
142
 
143
    def read_map_begin
144
      ktype = read_byte
145
      vtype = read_byte
146
      size = read_i32
147
      [ktype, vtype, size]
148
    end
149
 
150
    def read_list_begin
151
      etype = read_byte
152
      size = read_i32
153
      [etype, size]
154
    end
155
 
156
    def read_set_begin
157
      etype = read_byte
158
      size = read_i32
159
      [etype, size]
160
    end
161
 
162
    def read_bool
163
      byte = read_byte
164
      byte != 0
165
    end
166
 
167
    def read_byte
168
      dat = trans.read_all(1)
169
      val = dat[0].ord
170
      if (val > 0x7f)
171
        val = 0 - ((val - 1) ^ 0xff)
172
      end
173
      val
174
    end
175
 
176
    def read_i16
177
      dat = trans.read_all(2)
178
      val, = dat.unpack('n')
179
      if (val > 0x7fff)
180
        val = 0 - ((val - 1) ^ 0xffff)
181
      end
182
      val
183
    end
184
 
185
    def read_i32
186
      dat = trans.read_all(4)
187
      val, = dat.unpack('N')
188
      if (val > 0x7fffffff)
189
        val = 0 - ((val - 1) ^ 0xffffffff)
190
      end
191
      val
192
    end
193
 
194
    def read_i64
195
      dat = trans.read_all(8)
196
      hi, lo = dat.unpack('N2')
197
      if (hi > 0x7fffffff)
198
        hi ^= 0xffffffff
199
        lo ^= 0xffffffff
200
 
201
      else
202
        (hi << 32) + lo
203
      end
204
    end
205
 
206
    def read_double
207
      dat = trans.read_all(8)
208
      val = dat.unpack('G').first
209
      val
210
    end
211
 
212
    def read_string
213
      sz = read_i32
214
      dat = trans.read_all(sz)
215
      dat
216
    end
217
 
218
  end
219
 
220
  class BinaryProtocolFactory < BaseProtocolFactory
221
    def get_protocol(trans)
222
      return Thrift::BinaryProtocol.new(trans)
223
    end
224
  end
225
end