cql-rb 1.0.0.pre7 → 1.0.0.pre8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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