Module: Cql::Protocol::Decoding

Extended by:
Decoding
Included in:
Decoding, Response, TypeConverter
Defined in:
lib/cql/protocol/decoding.rb

Instance Method Summary collapse

Instance Method Details

#read_byte!(buffer) ⇒ Object



11
12
13
14
15
# File 'lib/cql/protocol/decoding.rb', line 11

def read_byte!(buffer)
  buffer.read_byte
rescue RangeError => e
  raise DecodingError, e.message, e.backtrace
end

#read_bytes!(buffer) ⇒ Object



125
126
127
128
129
130
131
# File 'lib/cql/protocol/decoding.rb', line 125

def read_bytes!(buffer)
  size = read_int!(buffer)
  return nil if size & 0x80000000 == 0x80000000
  buffer.read(size)
rescue RangeError => e
  raise DecodingError, "Not enough bytes available to decode a bytes: #{e.message}", e.backtrace
end

#read_consistency!(buffer) ⇒ Object

Raises:



159
160
161
162
163
# File 'lib/cql/protocol/decoding.rb', line 159

def read_consistency!(buffer)
  index = read_short!(buffer)
  raise DecodingError, "Unknown consistency index #{index}" if index >= CONSISTENCIES.size || CONSISTENCIES[index].nil?
  CONSISTENCIES[index]
end

#read_decimal!(buffer, length = buffer.length) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/cql/protocol/decoding.rb', line 31

def read_decimal!(buffer, length=buffer.length)
  size = read_int!(buffer)
  number_string = read_varint!(buffer, length - 4).to_s
  if number_string.length < size
    if number_string.start_with?(MINUS)
      number_string = number_string[1, number_string.length - 1]
      fraction_string = MINUS + ZERO << DECIMAL_POINT
    else
      fraction_string = ZERO + DECIMAL_POINT
    end
    (size - number_string.length).times { fraction_string << ZERO }
    fraction_string << number_string
  else
    fraction_string = number_string[0, number_string.length - size]
    fraction_string << DECIMAL_POINT
    fraction_string << number_string[number_string.length - size, number_string.length]
  end
  BigDecimal.new(fraction_string)
rescue RangeError => e
  raise DecodingError, e.message, e.backtrace
end

#read_double!(buffer) ⇒ Object



66
67
68
69
70
# File 'lib/cql/protocol/decoding.rb', line 66

def read_double!(buffer)
  buffer.read(8).unpack(Formats::DOUBLE_FORMAT).first
rescue RangeError => e
  raise DecodingError, "Not enough bytes available to decode a double: #{e.message}", e.backtrace
end

#read_float!(buffer) ⇒ Object



72
73
74
75
76
# File 'lib/cql/protocol/decoding.rb', line 72

def read_float!(buffer)
  buffer.read(4).unpack(Formats::FLOAT_FORMAT).first
rescue RangeError => e
  raise DecodingError, "Not enough bytes available to decode a float: #{e.message}", e.backtrace
end

#read_inet!(buffer) ⇒ Object



150
151
152
153
154
155
156
157
# File 'lib/cql/protocol/decoding.rb', line 150

def read_inet!(buffer)
  size = read_byte!(buffer)
  ip_addr = IPAddr.new_ntoh(buffer.read(size))
  port = read_int!(buffer)
  [ip_addr, port]
rescue RangeError => e
  raise DecodingError, "Not enough bytes available to decode an INET: #{e.message}", e.backtrace
end

#read_int!(buffer) ⇒ Object



78
79
80
81
82
83
84
85
86
# File 'lib/cql/protocol/decoding.rb', line 78

def read_int!(buffer)
  val = buffer.read_int
  if (val > 0x7fffffff)
    val = 0 - ((val - 1) ^ 0xffffffff)
  end
  val
rescue RangeError => e
  raise DecodingError, "Not enough bytes available to decode an int: #{e.message}", e.backtrace
end

#read_long!(buffer) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/cql/protocol/decoding.rb', line 53

def read_long!(buffer)
  hi, lo = buffer.read(8).unpack(Formats::TWO_INTS_FORMAT)
  if (hi > 0x7fffffff)
    hi ^= 0xffffffff
    lo ^= 0xffffffff
    0 - (hi << 32) - lo - 1
  else
    (hi << 32) + lo
  end
rescue RangeError => e
  raise DecodingError, e.message, e.backtrace
end

#read_long_string!(buffer) ⇒ Object



103
104
105
106
107
108
109
110
# File 'lib/cql/protocol/decoding.rb', line 103

def read_long_string!(buffer)
  length = read_int!(buffer)
  string = buffer.read(length)
  string.force_encoding(::Encoding::UTF_8)
  string
rescue RangeError => e
  raise DecodingError, "Not enough bytes available to decode a long string: #{e.message}", e.backtrace
end

#read_option!(buffer) ⇒ Object



141
142
143
144
145
146
147
148
# File 'lib/cql/protocol/decoding.rb', line 141

def read_option!(buffer)
  id = read_short!(buffer)
  value = nil
  if block_given?
    value = yield id, buffer
  end
  [id, value]
end

#read_short!(buffer) ⇒ Object



88
89
90
91
92
# File 'lib/cql/protocol/decoding.rb', line 88

def read_short!(buffer)
  buffer.read_short
rescue RangeError => e
  raise DecodingError, "Not enough bytes available to decode a short: #{e.message}", e.backtrace
end

#read_short_bytes!(buffer) ⇒ Object



133
134
135
136
137
138
139
# File 'lib/cql/protocol/decoding.rb', line 133

def read_short_bytes!(buffer)
  size = read_short!(buffer)
  return nil if size & 0x8000 == 0x8000
  buffer.read(size)
rescue RangeError => e
  raise DecodingError, "Not enough bytes available to decode a short bytes: #{e.message}", e.backtrace
end

#read_string!(buffer) ⇒ Object



94
95
96
97
98
99
100
101
# File 'lib/cql/protocol/decoding.rb', line 94

def read_string!(buffer)
  length = read_short!(buffer)
  string = buffer.read(length)
  string.force_encoding(::Encoding::UTF_8)
  string
rescue RangeError => e
  raise DecodingError, "Not enough bytes available to decode a string: #{e.message}", e.backtrace
end

#read_string_list!(buffer) ⇒ Object



118
119
120
121
122
123
# File 'lib/cql/protocol/decoding.rb', line 118

def read_string_list!(buffer)
  size = read_short!(buffer)
  size.times.map do
    read_string!(buffer)
  end
end

#read_string_map!(buffer) ⇒ Object



165
166
167
168
169
170
171
172
173
# File 'lib/cql/protocol/decoding.rb', line 165

def read_string_map!(buffer)
  map = {}
  map_size = read_short!(buffer)
  map_size.times do
    key = read_string!(buffer)
    map[key] = read_string!(buffer)
  end
  map
end

#read_string_multimap!(buffer) ⇒ Object



175
176
177
178
179
180
181
182
183
# File 'lib/cql/protocol/decoding.rb', line 175

def read_string_multimap!(buffer)
  map = {}
  map_size = read_short!(buffer)
  map_size.times do
    key = read_string!(buffer)
    map[key] = read_string_list!(buffer)
  end
  map
end

#read_uuid!(buffer, impl = Uuid) ⇒ Object



112
113
114
115
116
# File 'lib/cql/protocol/decoding.rb', line 112

def read_uuid!(buffer, impl=Uuid)
  impl.new(read_varint!(buffer, 16, false))
rescue RangeError => e
  raise DecodingError, "Not enough bytes available to decode a UUID: #{e.message}", e.backtrace
end

#read_varint!(buffer, length = buffer.length, signed = true) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/cql/protocol/decoding.rb', line 17

def read_varint!(buffer, length=buffer.length, signed=true)
  bytes = buffer.read(length)
  n = 0
  bytes.each_byte do |b|
    n = (n << 8) | b
  end
  if signed && bytes.getbyte(0) & 0x80 == 0x80
    n -= 2**(bytes.length * 8)
  end
  n
rescue RangeError => e
  raise DecodingError, e.message, e.backtrace
end