cql-rb 1.0.0.pre7 → 1.0.0.pre8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/lib/cql/byte_buffer.rb +22 -0
  2. data/lib/cql/client.rb +79 -310
  3. data/lib/cql/client/asynchronous_client.rb +254 -0
  4. data/lib/cql/client/asynchronous_prepared_statement.rb +19 -0
  5. data/lib/cql/client/column_metadata.rb +22 -0
  6. data/lib/cql/client/query_result.rb +34 -0
  7. data/lib/cql/client/result_metadata.rb +31 -0
  8. data/lib/cql/client/synchronous_client.rb +47 -0
  9. data/lib/cql/client/synchronous_prepared_statement.rb +47 -0
  10. data/lib/cql/future.rb +7 -3
  11. data/lib/cql/io.rb +1 -0
  12. data/lib/cql/io/io_reactor.rb +9 -3
  13. data/lib/cql/io/node_connection.rb +2 -2
  14. data/lib/cql/protocol.rb +5 -4
  15. data/lib/cql/protocol/request.rb +23 -0
  16. data/lib/cql/protocol/requests/credentials_request.rb +1 -1
  17. data/lib/cql/protocol/requests/execute_request.rb +13 -84
  18. data/lib/cql/protocol/requests/options_request.rb +1 -1
  19. data/lib/cql/protocol/requests/prepare_request.rb +2 -1
  20. data/lib/cql/protocol/requests/query_request.rb +3 -1
  21. data/lib/cql/protocol/requests/register_request.rb +1 -1
  22. data/lib/cql/protocol/requests/startup_request.rb +1 -2
  23. data/lib/cql/protocol/{response_body.rb → response.rb} +1 -1
  24. data/lib/cql/protocol/responses/authenticate_response.rb +1 -1
  25. data/lib/cql/protocol/responses/error_response.rb +1 -1
  26. data/lib/cql/protocol/responses/ready_response.rb +1 -1
  27. data/lib/cql/protocol/responses/result_response.rb +1 -1
  28. data/lib/cql/protocol/responses/rows_result_response.rb +1 -1
  29. data/lib/cql/protocol/responses/supported_response.rb +1 -1
  30. data/lib/cql/protocol/type_converter.rb +226 -46
  31. data/lib/cql/version.rb +1 -1
  32. data/spec/cql/byte_buffer_spec.rb +38 -0
  33. data/spec/cql/client/asynchronous_client_spec.rb +472 -0
  34. data/spec/cql/client/client_shared.rb +27 -0
  35. data/spec/cql/client/synchronous_client_spec.rb +104 -0
  36. data/spec/cql/client/synchronous_prepared_statement_spec.rb +65 -0
  37. data/spec/cql/future_spec.rb +4 -0
  38. data/spec/cql/io/io_reactor_spec.rb +39 -20
  39. data/spec/cql/protocol/request_spec.rb +17 -0
  40. data/spec/cql/protocol/requests/credentials_request_spec.rb +82 -0
  41. data/spec/cql/protocol/requests/execute_request_spec.rb +174 -0
  42. data/spec/cql/protocol/requests/options_request_spec.rb +24 -0
  43. data/spec/cql/protocol/requests/prepare_request_spec.rb +70 -0
  44. data/spec/cql/protocol/requests/query_request_spec.rb +95 -0
  45. data/spec/cql/protocol/requests/register_request_spec.rb +24 -0
  46. data/spec/cql/protocol/requests/startup_request_spec.rb +29 -0
  47. data/spec/integration/client_spec.rb +26 -19
  48. data/spec/integration/protocol_spec.rb +2 -2
  49. data/spec/integration/regression_spec.rb +1 -1
  50. metadata +35 -9
  51. data/lib/cql/protocol/request_body.rb +0 -15
  52. data/lib/cql/protocol/request_frame.rb +0 -20
  53. data/spec/cql/client_spec.rb +0 -454
  54. data/spec/cql/protocol/request_frame_spec.rb +0 -456
@@ -26,7 +26,11 @@ module Cql
26
26
  # @return [Future<Array>] an array of the values of the constituent futures
27
27
  #
28
28
  def self.combine(*futures)
29
- CombinedFuture.new(*futures)
29
+ if futures.any?
30
+ CombinedFuture.new(*futures)
31
+ else
32
+ completed([])
33
+ end
30
34
  end
31
35
 
32
36
  # Creates a new future which is completed.
@@ -40,7 +44,7 @@ module Cql
40
44
 
41
45
  # Creates a new future which is failed.
42
46
  #
43
- # @param [Error] the error of the created future
47
+ # @param [Error] error the error of the created future
44
48
  # @return [Future] a failed future
45
49
  #
46
50
  def self.failed(error)
@@ -91,7 +95,7 @@ module Cql
91
95
  #
92
96
  # If the future fails this method will raise the error that failed the future.
93
97
  #
94
- # @returns [Object] the value of this future
98
+ # @return [Object] the value of this future
95
99
  #
96
100
  def value
97
101
  raise @error if @error
@@ -5,6 +5,7 @@ module Cql
5
5
 
6
6
  module Io
7
7
  ConnectionError = Class.new(IoError)
8
+ ConnectionClosedError = Class.new(IoError)
8
9
  ConnectionTimeoutError = Class.new(ConnectionError)
9
10
  NotRunningError = Class.new(CqlError)
10
11
  ConnectionNotFoundError = Class.new(CqlError)
@@ -81,6 +81,12 @@ module Cql
81
81
  connection.on_close do
82
82
  @lock.synchronize do
83
83
  @connections.delete(connection)
84
+ connection_commands, @command_queue = @command_queue.partition do |command|
85
+ command.is_a?(TargetedRequestCommand) && command.connection_id == connection.connection_id
86
+ end
87
+ connection_commands.each do |command|
88
+ command.future.fail!(ConnectionClosedError.new)
89
+ end
84
90
  end
85
91
  end
86
92
  f = connection.open
@@ -93,7 +99,7 @@ module Cql
93
99
 
94
100
  # Sends a request over a random, or specific connection.
95
101
  #
96
- # @param [Cql::Protocol::RequestBody] request the request to send
102
+ # @param [Cql::Protocol::Request] request the request to send
97
103
  # @param [Object] connection_id the ID of the connection which should be
98
104
  # used to send the request
99
105
  # @return [Future<ResultResponse>] a future representing the result of the request
@@ -163,7 +169,7 @@ module Cql
163
169
  if connection && connection.connected? && connection.has_capacity?
164
170
  connection.perform_request(command.request, command.future)
165
171
  elsif connection && connection.connected?
166
- command.future.fail!(ConnectionBusyError.new("Connection ##{command.connection_id} is busy"))
172
+ unexecuted_commands << command
167
173
  else
168
174
  command.future.fail!(ConnectionNotFoundError.new("Connection ##{command.connection_id} does not exist"))
169
175
  end
@@ -176,7 +182,7 @@ module Cql
176
182
  end
177
183
  end
178
184
  end
179
- @command_queue.unshift(*unexecuted_commands) if unexecuted_commands.any?
185
+ @command_queue = unexecuted_commands
180
186
  end
181
187
  end
182
188
  end
@@ -92,7 +92,7 @@ module Cql
92
92
 
93
93
  def perform_request(request, future)
94
94
  stream_id = next_stream_id
95
- Protocol::RequestFrame.new(request, stream_id).write(@write_buffer)
95
+ @write_buffer << request.encode_frame(stream_id)
96
96
  @response_tasks[stream_id] = future
97
97
  rescue => e
98
98
  case e
@@ -111,7 +111,7 @@ module Cql
111
111
  handle_connecting
112
112
  else
113
113
  if !@write_buffer.empty?
114
- bytes_written = @io.write_nonblock(@write_buffer)
114
+ bytes_written = @io.write_nonblock(@write_buffer.cheap_peek)
115
115
  @write_buffer.discard(bytes_written)
116
116
  end
117
117
  end
@@ -26,12 +26,14 @@ module Cql
26
26
 
27
27
  BYTES_FORMAT = 'C*'.freeze
28
28
  TWO_INTS_FORMAT = 'NN'.freeze
29
- HEADER_FORMAT = 'c4'.freeze
29
+ HEADER_FORMAT = 'c4N'.freeze
30
30
  end
31
31
 
32
32
  module Constants
33
33
  TRUE_BYTE = "\x01".freeze
34
34
  FALSE_BYTE = "\x00".freeze
35
+ PROTOCOL_VERSION = "\x01".freeze
36
+ COMPRESSION_OFF = "\x00".freeze
35
37
  end
36
38
  end
37
39
  end
@@ -39,7 +41,7 @@ end
39
41
  require 'cql/protocol/encoding'
40
42
  require 'cql/protocol/decoding'
41
43
  require 'cql/protocol/type_converter'
42
- require 'cql/protocol/response_body'
44
+ require 'cql/protocol/response'
43
45
  require 'cql/protocol/responses/error_response'
44
46
  require 'cql/protocol/responses/detailed_error_response'
45
47
  require 'cql/protocol/responses/ready_response'
@@ -55,7 +57,7 @@ require 'cql/protocol/responses/event_response'
55
57
  require 'cql/protocol/responses/schema_change_event_result_response'
56
58
  require 'cql/protocol/responses/status_change_event_result_response'
57
59
  require 'cql/protocol/responses/topology_change_event_result_response'
58
- require 'cql/protocol/request_body'
60
+ require 'cql/protocol/request'
59
61
  require 'cql/protocol/requests/startup_request'
60
62
  require 'cql/protocol/requests/credentials_request'
61
63
  require 'cql/protocol/requests/options_request'
@@ -64,4 +66,3 @@ require 'cql/protocol/requests/query_request'
64
66
  require 'cql/protocol/requests/prepare_request'
65
67
  require 'cql/protocol/requests/execute_request'
66
68
  require 'cql/protocol/response_frame'
67
- require 'cql/protocol/request_frame'
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ module Cql
4
+ module Protocol
5
+ class Request
6
+ include Encoding
7
+
8
+ attr_reader :opcode
9
+
10
+ def initialize(opcode)
11
+ @opcode = opcode
12
+ end
13
+
14
+ def encode_frame(stream_id=0, buffer=ByteBuffer.new)
15
+ raise InvalidStreamIdError, 'The stream ID must be between 0 and 127' unless 0 <= stream_id && stream_id < 128
16
+ buffer << [1, 0, stream_id, opcode, 0].pack(Formats::HEADER_FORMAT)
17
+ write(buffer)
18
+ buffer.update(4, [(buffer.bytesize - 8)].pack(Formats::INT_FORMAT))
19
+ buffer
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class CredentialsRequest < RequestBody
5
+ class CredentialsRequest < Request
6
6
  attr_reader :credentials
7
7
 
8
8
  def initialize(credentials)
@@ -2,25 +2,21 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class ExecuteRequest < RequestBody
5
+ class ExecuteRequest < Request
6
6
  attr_reader :id, :metadata, :values, :consistency
7
7
 
8
8
  def initialize(id, metadata, values, consistency)
9
- super(10)
10
9
  raise ArgumentError, "Metadata for #{metadata.size} columns, but #{values.size} values given" if metadata.size != values.size
10
+ super(10)
11
11
  @id = id
12
12
  @metadata = metadata
13
13
  @values = values
14
14
  @consistency = consistency
15
+ @bytes = encode_body
15
16
  end
16
17
 
17
18
  def write(io)
18
- write_short_bytes(io, @id)
19
- write_short(io, @metadata.size)
20
- @metadata.each_with_index do |(_, _, _, type), index|
21
- write_value(io, @values[index], type)
22
- end
23
- write_consistency(io, @consistency)
19
+ io << @bytes
24
20
  end
25
21
 
26
22
  def to_s
@@ -46,83 +42,16 @@ module Cql
46
42
 
47
43
  private
48
44
 
49
- def write_value(io, value, type)
50
- if Array === type
51
- raise InvalidValueError, 'Value for collection must be enumerable' unless value.is_a?(Enumerable)
52
- case type.first
53
- when :list, :set
54
- _, sub_type = type
55
- raw = ''
56
- write_short(raw, value.size)
57
- value.each do |element|
58
- rr = ''
59
- write_value(rr, element, sub_type)
60
- raw << rr[2, rr.length - 2]
61
- end
62
- write_bytes(io, raw)
63
- when :map
64
- _, key_type, value_type = type
65
- raw = ''
66
- write_short(raw, value.size)
67
- value.each do |key, value|
68
- rr = ''
69
- write_value(rr, key, key_type)
70
- raw << rr[2, rr.length - 2]
71
- rr = ''
72
- write_value(rr, value, value_type)
73
- raw << rr[2, rr.length - 2]
74
- end
75
- write_bytes(io, raw)
76
- else
77
- raise UnsupportedColumnTypeError, %(Unsupported column collection type: #{type.first})
78
- end
79
- else
80
- case type
81
- when :ascii
82
- write_bytes(io, value.encode(::Encoding::ASCII))
83
- when :bigint
84
- write_int(io, 8)
85
- write_long(io, value)
86
- when :blob
87
- write_bytes(io, value.encode(::Encoding::BINARY))
88
- when :boolean
89
- write_int(io, 1)
90
- io << (value ? Constants::TRUE_BYTE : Constants::FALSE_BYTE)
91
- when :decimal
92
- raw = write_decimal('', value)
93
- write_int(io, raw.size)
94
- io << raw
95
- when :double
96
- write_int(io, 8)
97
- write_double(io, value)
98
- when :float
99
- write_int(io, 4)
100
- write_float(io, value)
101
- when :inet
102
- write_int(io, value.ipv6? ? 16 : 4)
103
- io << value.hton
104
- when :int
105
- write_int(io, 4)
106
- write_int(io, value)
107
- when :text, :varchar
108
- write_bytes(io, value.encode(::Encoding::UTF_8))
109
- when :timestamp
110
- ms = (value.to_f * 1000).to_i
111
- write_int(io, 8)
112
- write_long(io, ms)
113
- when :timeuuid, :uuid
114
- write_int(io, 16)
115
- write_uuid(io, value)
116
- when :varint
117
- raw = write_varint('', value)
118
- write_int(io, raw.length)
119
- io << raw
120
- else
121
- raise UnsupportedColumnTypeError, %(Unsupported column type: #{type})
122
- end
45
+ def encode_body
46
+ buffer = ByteBuffer.new
47
+ type_converter = TypeConverter.new
48
+ write_short_bytes(buffer, @id)
49
+ write_short(buffer, @metadata.size)
50
+ @metadata.each_with_index do |(_, _, _, type), index|
51
+ type_converter.to_bytes(buffer, type, @values[index])
123
52
  end
124
- rescue TypeError => e
125
- raise TypeError, %("#{value}" cannot be encoded as #{type.to_s.upcase}: #{e.message}), e.backtrace
53
+ write_consistency(buffer, @consistency)
54
+ buffer.to_s
126
55
  end
127
56
  end
128
57
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class OptionsRequest < RequestBody
5
+ class OptionsRequest < Request
6
6
  def initialize
7
7
  super(5)
8
8
  end
@@ -2,10 +2,11 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class PrepareRequest < RequestBody
5
+ class PrepareRequest < Request
6
6
  attr_reader :cql
7
7
 
8
8
  def initialize(cql)
9
+ raise ArgumentError, 'No CQL given!' unless cql
9
10
  super(9)
10
11
  @cql = cql
11
12
  end
@@ -2,10 +2,12 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class QueryRequest < RequestBody
5
+ class QueryRequest < Request
6
6
  attr_reader :cql, :consistency
7
7
 
8
8
  def initialize(cql, consistency)
9
+ raise ArgumentError, %(No CQL given!) unless cql
10
+ raise ArgumentError, %(No such consistency: #{consistency.inspect}) unless CONSISTENCIES.include?(consistency)
9
11
  super(7)
10
12
  @cql = cql
11
13
  @consistency = consistency
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class RegisterRequest < RequestBody
5
+ class RegisterRequest < Request
6
6
  def initialize(*events)
7
7
  super(11)
8
8
  @events = events
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class StartupRequest < RequestBody
5
+ class StartupRequest < Request
6
6
  def initialize(cql_version='3.0.0', compression=nil)
7
7
  super(1)
8
8
  @arguments = {CQL_VERSION => cql_version}
@@ -11,7 +11,6 @@ module Cql
11
11
 
12
12
  def write(io)
13
13
  write_string_map(io, @arguments)
14
- io
15
14
  end
16
15
 
17
16
  def to_s
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Cql
5
5
  module Protocol
6
- class ResponseBody
6
+ class Response
7
7
  extend Decoding
8
8
 
9
9
  def self.decode!(buffer)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class AuthenticateResponse < ResponseBody
5
+ class AuthenticateResponse < Response
6
6
  attr_reader :authentication_class
7
7
 
8
8
  def self.decode!(buffer)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class ErrorResponse < ResponseBody
5
+ class ErrorResponse < Response
6
6
  attr_reader :code, :message
7
7
 
8
8
  def initialize(*args)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class ReadyResponse < ResponseBody
5
+ class ReadyResponse < Response
6
6
  def self.decode!(buffer)
7
7
  new
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class ResultResponse < ResponseBody
5
+ class ResultResponse < Response
6
6
  def self.decode!(buffer)
7
7
  kind = read_int!(buffer)
8
8
  case kind
@@ -89,7 +89,7 @@ module Cql
89
89
  rows_count.times do |row_index|
90
90
  row = {}
91
91
  column_specs.each do |column_spec|
92
- row[column_spec[2]] = type_converter.convert_type(buffer, column_spec[3])
92
+ row[column_spec[2]] = type_converter.from_bytes(buffer, column_spec[3])
93
93
  end
94
94
  rows << row
95
95
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cql
4
4
  module Protocol
5
- class SupportedResponse < ResponseBody
5
+ class SupportedResponse < Response
6
6
  attr_reader :options
7
7
 
8
8
  def initialize(options)
@@ -8,120 +8,193 @@ module Cql
8
8
  module Protocol
9
9
  class TypeConverter
10
10
  include Decoding
11
+ include Encoding
11
12
 
12
13
  def initialize
13
- @conversions = conversions
14
+ @from_bytes_converters = from_bytes_converters
15
+ @to_bytes_converters = to_bytes_converters
14
16
  end
15
17
 
16
- def convert_type(buffer, type, size_bytes=4)
18
+ def from_bytes(buffer, type, size_bytes=4)
17
19
  return nil if buffer.empty?
18
20
  case type
19
21
  when Array
20
22
  return nil unless read_size(buffer, size_bytes)
21
23
  case type.first
22
24
  when :list
23
- convert_list(buffer, @conversions[type[1]])
25
+ bytes_to_list(buffer, @from_bytes_converters[type[1]])
24
26
  when :map
25
- convert_map(buffer, @conversions[type[1]], @conversions[type[2]])
27
+ bytes_to_map(buffer, @from_bytes_converters[type[1]], @from_bytes_converters[type[2]])
26
28
  when :set
27
- convert_set(buffer, @conversions[type[1]])
29
+ bytes_to_set(buffer, @from_bytes_converters[type[1]])
28
30
  end
29
31
  else
30
- @conversions[type].call(buffer, size_bytes)
32
+ @from_bytes_converters[type].call(buffer, size_bytes)
31
33
  end
32
34
  end
33
35
 
34
- def conversions
36
+ def to_bytes(io, type, value, size_bytes=4)
37
+ case type
38
+ when Array
39
+ unless value.is_a?(Enumerable)
40
+ raise InvalidValueError, 'Value for collection must be enumerable'
41
+ end
42
+ case type.first
43
+ when :list, :set
44
+ _, sub_type = type
45
+ raw = ''
46
+ write_short(raw, value.size)
47
+ value.each do |element|
48
+ to_bytes(raw, sub_type, element, 2)
49
+ end
50
+ write_bytes(io, raw)
51
+ when :map
52
+ _, key_type, value_type = type
53
+ raw = ''
54
+ write_short(raw, value.size)
55
+ value.each do |key, value|
56
+ to_bytes(raw, key_type, key, 2)
57
+ to_bytes(raw, value_type, value, 2)
58
+ end
59
+ write_bytes(io, raw)
60
+ else
61
+ raise UnsupportedColumnTypeError, %(Unsupported column collection type: #{type.first})
62
+ end
63
+ else
64
+ converter = @to_bytes_converters[type]
65
+ unless converter
66
+ raise UnsupportedColumnTypeError, %(Unsupported column type: #{type})
67
+ end
68
+ converter.call(io, value, size_bytes)
69
+ end
70
+ rescue TypeError => e
71
+ raise TypeError, %("#{value}" cannot be encoded as #{type.to_s.upcase}: #{e.message}), e.backtrace
72
+ end
73
+
74
+ private
75
+
76
+ def from_bytes_converters
77
+ {
78
+ :ascii => method(:bytes_to_ascii),
79
+ :bigint => method(:bytes_to_bigint),
80
+ :blob => method(:bytes_to_blob),
81
+ :boolean => method(:bytes_to_boolean),
82
+ :counter => method(:bytes_to_bigint),
83
+ :decimal => method(:bytes_to_decimal),
84
+ :double => method(:bytes_to_double),
85
+ :float => method(:bytes_to_float),
86
+ :int => method(:bytes_to_int),
87
+ :timestamp => method(:bytes_to_timestamp),
88
+ :varchar => method(:bytes_to_varchar),
89
+ :text => method(:bytes_to_varchar),
90
+ :varint => method(:bytes_to_varint),
91
+ :timeuuid => method(:bytes_to_uuid),
92
+ :uuid => method(:bytes_to_uuid),
93
+ :inet => method(:bytes_to_inet),
94
+ }
95
+ end
96
+
97
+ def to_bytes_converters
35
98
  {
36
- :ascii => method(:convert_ascii),
37
- :bigint => method(:convert_bigint),
38
- :blob => method(:convert_blob),
39
- :boolean => method(:convert_boolean),
40
- :counter => method(:convert_bigint),
41
- :decimal => method(:convert_decimal),
42
- :double => method(:convert_double),
43
- :float => method(:convert_float),
44
- :int => method(:convert_int),
45
- :timestamp => method(:convert_timestamp),
46
- :varchar => method(:convert_varchar),
47
- :text => method(:convert_varchar),
48
- :varint => method(:convert_varint),
49
- :timeuuid => method(:convert_uuid),
50
- :uuid => method(:convert_uuid),
51
- :inet => method(:convert_inet),
99
+ :ascii => method(:ascii_to_bytes),
100
+ :bigint => method(:bigint_to_bytes),
101
+ :blob => method(:blob_to_bytes),
102
+ :boolean => method(:boolean_to_bytes),
103
+ :decimal => method(:decimal_to_bytes),
104
+ :double => method(:double_to_bytes),
105
+ :float => method(:float_to_bytes),
106
+ :inet => method(:inet_to_bytes),
107
+ :int => method(:int_to_bytes),
108
+ :text => method(:varchar_to_bytes),
109
+ :varchar => method(:varchar_to_bytes),
110
+ :timestamp => method(:timestamp_to_bytes),
111
+ :timeuuid => method(:uuid_to_bytes),
112
+ :uuid => method(:uuid_to_bytes),
113
+ :varint => method(:varint_to_bytes),
52
114
  }
53
115
  end
54
116
 
55
- def convert_ascii(buffer, size_bytes)
117
+ def read_size(buffer, size_bytes)
118
+ if size_bytes == 2
119
+ size = buffer.read_short
120
+ return nil if size & 0x8000 == 0x8000
121
+ else
122
+ size = buffer.read_int
123
+ return nil if size & 0x80000000 == 0x80000000
124
+ end
125
+ size
126
+ end
127
+
128
+ def bytes_to_ascii(buffer, size_bytes)
56
129
  bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
57
130
  bytes ? bytes.force_encoding(::Encoding::ASCII) : nil
58
131
  end
59
132
 
60
- def convert_bigint(buffer, size_bytes)
133
+ def bytes_to_bigint(buffer, size_bytes)
61
134
  return nil unless read_size(buffer, size_bytes)
62
135
  read_long!(buffer)
63
136
  end
64
137
 
65
- def convert_blob(buffer, size_bytes)
138
+ def bytes_to_blob(buffer, size_bytes)
66
139
  bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
67
140
  bytes ? bytes : nil
68
141
  end
69
142
 
70
- def convert_boolean(buffer, size_bytes)
143
+ def bytes_to_boolean(buffer, size_bytes)
71
144
  return nil unless read_size(buffer, size_bytes)
72
145
  buffer.read(1) == Constants::TRUE_BYTE
73
146
  end
74
147
 
75
- def convert_decimal(buffer, size_bytes)
148
+ def bytes_to_decimal(buffer, size_bytes)
76
149
  size = read_size(buffer, size_bytes)
77
150
  return nil unless size
78
151
  read_decimal!(buffer, size)
79
152
  end
80
153
 
81
- def convert_double(buffer, size_bytes)
154
+ def bytes_to_double(buffer, size_bytes)
82
155
  return nil unless read_size(buffer, size_bytes)
83
156
  read_double!(buffer)
84
157
  end
85
158
 
86
- def convert_float(buffer, size_bytes)
159
+ def bytes_to_float(buffer, size_bytes)
87
160
  return nil unless read_size(buffer, size_bytes)
88
161
  read_float!(buffer)
89
162
  end
90
163
 
91
- def convert_int(buffer, size_bytes)
164
+ def bytes_to_int(buffer, size_bytes)
92
165
  return nil unless read_size(buffer, size_bytes)
93
166
  read_int!(buffer)
94
167
  end
95
168
 
96
- def convert_timestamp(buffer, size_bytes)
169
+ def bytes_to_timestamp(buffer, size_bytes)
97
170
  return nil unless read_size(buffer, size_bytes)
98
171
  timestamp = read_long!(buffer)
99
172
  Time.at(timestamp/1000.0)
100
173
  end
101
174
 
102
- def convert_varchar(buffer, size_bytes)
175
+ def bytes_to_varchar(buffer, size_bytes)
103
176
  bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
104
177
  bytes ? bytes.force_encoding(::Encoding::UTF_8) : nil
105
178
  end
106
179
 
107
- def convert_varint(buffer, size_bytes)
180
+ def bytes_to_varint(buffer, size_bytes)
108
181
  size = read_size(buffer, size_bytes)
109
182
  return nil unless size
110
183
  read_varint!(buffer, size)
111
184
  end
112
185
 
113
- def convert_uuid(buffer, size_bytes)
186
+ def bytes_to_uuid(buffer, size_bytes)
114
187
  return nil unless read_size(buffer, size_bytes)
115
188
  read_uuid!(buffer)
116
189
  end
117
190
 
118
- def convert_inet(buffer, size_bytes)
191
+ def bytes_to_inet(buffer, size_bytes)
119
192
  size = read_size(buffer, size_bytes)
120
193
  return nil unless size
121
194
  IPAddr.new_ntoh(buffer.read(size))
122
195
  end
123
196
 
124
- def convert_list(buffer, value_converter)
197
+ def bytes_to_list(buffer, value_converter)
125
198
  list = []
126
199
  size = buffer.read_short
127
200
  size.times do
@@ -130,7 +203,7 @@ module Cql
130
203
  list
131
204
  end
132
205
 
133
- def convert_map(buffer, key_converter, value_converter)
206
+ def bytes_to_map(buffer, key_converter, value_converter)
134
207
  map = {}
135
208
  size = buffer.read_short
136
209
  size.times do
@@ -141,7 +214,7 @@ module Cql
141
214
  map
142
215
  end
143
216
 
144
- def convert_set(buffer, value_converter)
217
+ def bytes_to_set(buffer, value_converter)
145
218
  set = Set.new
146
219
  size = buffer.read_short
147
220
  size.times do
@@ -150,15 +223,122 @@ module Cql
150
223
  set
151
224
  end
152
225
 
153
- def read_size(buffer, size_bytes)
154
- if size_bytes == 2
155
- size = buffer.read_short
156
- return nil if size & 0x8000 == 0x8000
226
+ def ascii_to_bytes(io, value, size_bytes)
227
+ v = value.encode(::Encoding::ASCII)
228
+ if size_bytes == 4
229
+ write_bytes(io, v)
157
230
  else
158
- size = buffer.read_int
159
- return nil if size & 0x80000000 == 0x80000000
231
+ write_short_bytes(io, v)
232
+ end
233
+ end
234
+
235
+ def bigint_to_bytes(io, value, size_bytes)
236
+ if size_bytes == 4
237
+ write_int(io, 8)
238
+ else
239
+ write_short(io, 8)
240
+ end
241
+ write_long(io, value)
242
+ end
243
+
244
+ def blob_to_bytes(io, value, size_bytes)
245
+ v = value.encode(::Encoding::BINARY)
246
+ if size_bytes == 4
247
+ write_bytes(io, v)
248
+ else
249
+ write_short_bytes(io, v)
250
+ end
251
+ end
252
+
253
+ def boolean_to_bytes(io, value, size_bytes)
254
+ if size_bytes == 4
255
+ write_int(io, 1)
256
+ else
257
+ write_short(io, 1)
258
+ end
259
+ io << (value ? Constants::TRUE_BYTE : Constants::FALSE_BYTE)
260
+ end
261
+
262
+ def decimal_to_bytes(io, value, size_bytes)
263
+ raw = write_decimal('', value)
264
+ if size_bytes == 4
265
+ write_bytes(io, raw)
266
+ else
267
+ write_short_bytes(io, raw)
268
+ end
269
+ end
270
+
271
+ def double_to_bytes(io, value, size_bytes)
272
+ if size_bytes == 4
273
+ write_int(io, 8)
274
+ else
275
+ write_short(io, 8)
276
+ end
277
+ write_double(io, value)
278
+ end
279
+
280
+ def float_to_bytes(io, value, size_bytes)
281
+ if size_bytes == 4
282
+ write_int(io, 4)
283
+ else
284
+ write_short(io, 4)
285
+ end
286
+ write_float(io, value)
287
+ end
288
+
289
+ def inet_to_bytes(io, value, size_bytes)
290
+ if size_bytes == 4
291
+ write_int(io, value.ipv6? ? 16 : 4)
292
+ else
293
+ write_short(io, value.ipv6? ? 16 : 4)
294
+ end
295
+ io << value.hton
296
+ end
297
+
298
+ def int_to_bytes(io, value, size_bytes)
299
+ if size_bytes == 4
300
+ write_int(io, 4)
301
+ else
302
+ write_short(io, 4)
303
+ end
304
+ write_int(io, value)
305
+ end
306
+
307
+ def varchar_to_bytes(io, value, size_bytes)
308
+ v = value.encode(::Encoding::UTF_8)
309
+ if size_bytes == 4
310
+ write_bytes(io, v)
311
+ else
312
+ write_short_bytes(io, v)
313
+ end
314
+ end
315
+
316
+ def timestamp_to_bytes(io, value, size_bytes)
317
+ ms = (value.to_f * 1000).to_i
318
+ if size_bytes == 4
319
+ write_int(io, 8)
320
+ else
321
+ write_short(io, 8)
322
+ end
323
+ write_long(io, ms)
324
+ end
325
+
326
+ def uuid_to_bytes(io, value, size_bytes)
327
+ if size_bytes == 4
328
+ write_int(io, 16)
329
+ else
330
+ write_short(io, 16)
331
+ end
332
+ write_uuid(io, value)
333
+ end
334
+
335
+ def varint_to_bytes(io, value, size_bytes)
336
+ raw = write_varint('', value)
337
+ if size_bytes == 4
338
+ write_bytes(io, raw)
339
+ else
340
+ write_short_bytes(io, raw)
160
341
  end
161
- size
162
342
  end
163
343
  end
164
344
  end