Permalink
Browse files

more integer types

  • Loading branch information...
1 parent 8c74966 commit d7c7808eab830ed0e2af26906e749199218800d5 @funny-falcon funny-falcon committed Jul 20, 2012
Showing with 185 additions and 33 deletions.
  1. +1 −0 lib/tarantool/exceptions.rb
  2. +41 −15 lib/tarantool/request.rb
  3. +36 −8 lib/tarantool/response.rb
  4. +13 −1 lib/tarantool/serializers.rb
  5. +94 −9 lib/tarantool/util.rb
@@ -4,6 +4,7 @@ class NoMasterError < ConnectionError; end
class ArgumentError < ::ArgumentError; end
class StringTooLong < ArgumentError; end
+ class IntegerFieldOverflow < ArgumentError; end
class TarantoolError < StandardError; end
class ValueError < TarantoolError; end
View
@@ -7,23 +7,19 @@ module Request
include Util::Packer
include Util::TailGetter
include Serializers
- INT32 = 'V'.freeze
- INT64 = 'Q<'.freeze
SELECT_HEADER = 'VVVVV'.freeze
INSERT_HEADER = 'VV'.freeze
UPDATE_HEADER = 'VV'.freeze
DELETE_HEADER = 'VV'.freeze
CALL_HEADER = 'Vwa*'.freeze
INT32_0 = "\x00\x00\x00\x00".freeze
INT32_1 = "\x01\x00\x00\x00".freeze
- BER4 = "\x04".freeze
- BER8 = "\x08".freeze
ZERO = "\x00".freeze
ONE = "\x01".freeze
EMPTY = "".freeze
PACK_STRING = 'wa*'.freeze
LEST_INT32 = -(2**31)
- GREATEST_INT32 = 2**32
+
TYPES_AUTO = [:auto].freeze
TYPES_FALLBACK = [:string].freeze
TYPES_STR_STR = [:string, :string].freeze
@@ -109,7 +105,8 @@ def pack_field(body, field_kind, value)
case field_kind
when :int, :integer
value = value.to_i
- body << BER4 << [value].pack(INT32)
+ _raise_integer_overflow(value, MIN_INT, MAX_INT32) if value > MAX_INT32 or value < 0
+ append_ber_int32!(body, value)
when :string, :bytes, :str
value = value.to_s
value = ZERO + value if value < ONE
@@ -121,13 +118,38 @@ def pack_field(body, field_kind, value)
body << [value.bytesize, value].pack(PACK_STRING)
when :int64
value = value.to_i
- body << BER8 << [value].pack(INT64)
+ _raise_integer_overflow(value, MIN_INT, MAX_INT64) if value > MAX_INT64 or value < 0
+ append_ber_int64!(body, value)
+ when :int16
+ value = value.to_i
+ _raise_integer_overflow(value, MIN_INT, MAX_INT16) if value > MAX_INT16 or value < 0
+ append_ber_int16!(body, value)
+ when :int8
+ value = value.to_i
+ _raise_integer_overflow(value, MIN_INT, MAX_INT8) if value > MAX_INT8 or value < 0
+ append_ber_int8!(body, value)
+ when :sint
+ value = value.to_i
+ _raise_integer_overflow(value, MIN_SINT32, MAX_SINT32) if value > MAX_SINT32 or value < MIN_SINT32
+ append_ber_sint32!(body, value)
+ when :sint64
+ value = value.to_i
+ _raise_integer_overflow(value, MIN_SINT64, MAX_SINT64) if value > MAX_SINT64 or value < MIN_SINT64
+ append_ber_sint64!(body, value)
+ when :sint16
+ value = value.to_i
+ _raise_integer_overflow(value, MIN_SINT16, MAX_SINT16) if value > MAX_SINT16 or value < MIN_SINT16
+ append_ber_sint16!(body, value)
+ when :sint8
+ value = value.to_i
+ _raise_integer_overflow(value, MIN_SINT8, MAX_SINT8) if value > MAX_SINT8 or value < MIN_SINT8
+ append_ber_sint8!(body, value)
when :varint
value = value.to_i
- if 0 <= value && value < GREATEST_INT32
- body << BER4 << [value].pack(INT32)
+ if 0 <= value && value < MAX_INT32
+ append_ber_int32!(body, value)
else
- body << BER8 << [value].pack(INT64)
+ append_ber_sint64!(body, value)
end
when :error
raise IndexIndexError
@@ -149,6 +171,10 @@ def pack_field(body, field_kind, value)
end
end
+ def _raise_integer_overflow(value, min, max)
+ raise IntegerFieldOverflow, "#{value} not in (#{min}..#{max})"
+ end
+
def _modify_request(type, body, fields, ret_tuple, cb, shard_nums, read_write, translators)
response = Response.new(cb, ret_tuple && (ret_tuple != :all ? :first : :all),
fields, translators)
@@ -176,7 +202,7 @@ def _update(space_no, pk, operations, fields, pk_fields, cb, ret_tuple, shard_nu
body = [space_no, flags].pack(UPDATE_HEADER)
pack_tuple(body, pk, pk_fields, 0)
- body << [operations.size].pack(INT32)
+ append_int32!(body, operations.size)
_pack_operations(body, operations, fields)
@@ -239,17 +265,17 @@ def _pack_operations(body, operations, fields)
unless operation.size == 3 && !operation[2].nil?
raise ArgumentError, "wrong arguments for integer operation #{operation.inspect}"
end
- pack_field(body, :int, operation[2])
+ pack_field(body, :sint, operation[2])
when 5
unless operation.size == 5 && !operation[2].nil? && !operation[3].nil?
raise ArgumentError, "wrong arguments for slice operation #{operation.inspect}"
end
str = operation[4].to_s
body << [ 10 + ber_size(str.bytesize) + str.bytesize ].pack('w')
- pack_field(body, :int, operation[2])
- pack_field(body, :int, operation[3])
- pack_field(body, :string, str)
+ append_ber_sint32!(body, operation[2].to_i)
+ append_ber_sint32!(body, operation[3].to_i)
+ body << [str.bytesize, str.to_s].pack(PACK_STRING)
when 7
old_field_no = field_no +
(inserted ||= []).count{|i| i <= field_no} -
View
@@ -83,21 +83,51 @@ def unpack_tuples(data)
tuple << (field_size == 0 ? nil :
case field
when :int, :integer
- if field_size == 4
- unpack_int32!(tuple_str)
- else
+ if field_size != 4
raise ValueError, "Bad field size #{field_size} for integer field ##{i}"
end
+ unpack_int32!(tuple_str)
when :string, :str
str = tuple_str.slice!(0, field_size)
str[0,1] = EMPTY if str < ONE
str.force_encoding(UTF8)
when :int64
- if field_size == 8
- unpack_int64!(tuple_str)
- else
+ if field_size != 8
+ raise ValueError, "Bad field size #{field_size} for 64bit integer field ##{i}"
+ end
+ unpack_int64!(tuple_str)
+ when :bytes
+ tuple_str.slice!(0, field_size)
+ when :int16
+ if field_size != 2
+ raise ValueError, "Bad field size #{field_size} for 16bit integer field ##{i}"
+ end
+ unpack_int16!(tuple_str)
+ when :int8
+ if field_size != 1
+ raise ValueError, "Bad field size #{field_size} for 8bit integer field ##{i}"
+ end
+ unpack_int8!(tuple_str)
+ when :sint
+ if field_size != 4
raise ValueError, "Bad field size #{field_size} for integer field ##{i}"
end
+ unpack_sint32!(tuple_str)
+ when :sint64
+ if field_size != 8
+ raise ValueError, "Bad field size #{field_size} for 64bit integer field ##{i}"
+ end
+ unpack_sint64!(tuple_str)
+ when :sint16
+ if field_size != 2
+ raise ValueError, "Bad field size #{field_size} for 16bit integer field ##{i}"
+ end
+ unpack_sint16!(tuple_str)
+ when :sint8
+ if field_size != 1
+ raise ValueError, "Bad field size #{field_size} for 8bit integer field ##{i}"
+ end
+ unpack_sint8!(tuple_str)
when :varint
case field_size
when 8
@@ -109,8 +139,6 @@ def unpack_tuples(data)
else
raise ValueError, "Bad field size #{field_size} for integer field ##{i}"
end
- when :bytes
- tuple_str.slice!(0, field_size)
when :auto
str = tuple_str.slice!(0, field_size).force_encoding('utf-8')
case field_size
@@ -8,10 +8,22 @@ def check_type(type)
return :string if String == type
case type
- when :int, :integer
+ when :int, :integer, :int32, :integer32
:int
when :int64, :integer64
:int64
+ when :int16, :integer16
+ :int16
+ when :int8, :integer8
+ :int8
+ when :sint, :sinteger, :sint32, :sinteger32
+ :sint
+ when :sint16, :sinteger16
+ :sint16
+ when :sint64, :sinteger64
+ :sint64
+ when :sint8, :sinteger8
+ :sint8
when :varint
:varint
when :str, :string
View
@@ -1,9 +1,36 @@
module Tarantool
module Util
module Packer
+ INT8 = 'C'.freeze
+ INT16 = 'v'.freeze
+ INT32 = 'V'.freeze
+ INT64 = 'Q<'.freeze
+ SINT8 = 'c'.freeze
+ SINT16 = 's<'.freeze
+ SINT32 = 'l<'.freeze
+ SINT64 = 'q<'.freeze
+ MIN_INT = 0
+ MAX_INT64 = 2**64 - 1
+ MAX_INT32 = 2**32 - 1
+ MAX_INT16 = 2**16 - 1
+ MAX_INT8 = 2**8 - 1
+ MAX_SINT64 = 2**63 - 1
+ MAX_SINT32 = 2**31 - 1
+ MAX_SINT16 = 2**15 - 1
+ MAX_SINT8 = 2**7 - 1
+ MIN_SINT64 = -(2**63)
+ MIN_SINT32 = -(2**31)
+ MIN_SINT16 = -(2**15)
+ MIN_SINT8 = -(2**7)
private
EMPTY = ''.freeze
ONE = "\x01".freeze
+ def unpack_int8!(data)
+ int = data.getbyte(0)
+ data[0, 1] = EMPTY
+ data
+ end
+
def unpack_int16(data)
data.getbyte(0) + data.getbyte(1) * 256
end
@@ -27,20 +54,33 @@ def unpack_int32!(data)
end
def unpack_int64!(data)
- int = (data.getbyte(0) + data.getbyte(1) * 256 +
- data.getbyte(2) * 65536 + data.getbyte(3) * 16777216 +
- data.getbyte(4) << 32 + data.getbyte(5) << 40 +
- data.getbyte(6) << 48 + data.getbyte(7) << 56
- )
+ int = data.unpack(INT64)[0]
data[0, 8] = EMPTY
int
end
def unpack_int64(data)
- data.getbyte(0) + data.getbyte(1) * 256 +
- data.getbyte(2) * 65536 + data.getbyte(3) * 16777216 +
- data.getbyte(4) << 32 + data.getbyte(5) << 40 +
- data.getbyte(6) << 48 + data.getbyte(7) << 56
+ data.unpack(INT64)[0]
+ end
+
+ def unpack_sint8!(data)
+ i = unpack_int8!(data)
+ i - ((i & 128) << 1)
+ end
+
+ def unpack_sint16!(data)
+ i = unpack_int16!(data)
+ i - ((i & 32768) << 1)
+ end
+
+ def unpack_sint32!(data)
+ i = unpack_int32!(data)
+ i - ((i >> 31) << 32)
+ end
+
+ def unpack_sint64!(data)
+ i = unpack_int64!(data)
+ i - ((i >> 63) << 64)
end
def ber_size(int)
@@ -65,6 +105,51 @@ def unpack_ber!(data)
data[0, pos+1] = EMPTY
res
end
+
+ def append_int8!(str, int)
+ str << (int & 255)
+ end
+
+ def append_int16!(str, int)
+ str << (int & 255) << ((int>>8) & 255)
+ end
+
+ def append_int32!(str, int)
+ str << (int & 255) << ((int>>8) & 255) <<
+ ((int>>16) & 255) << ((int>>24) & 255)
+ end
+
+ def append_int64!(str, int)
+ str << [int].pack(INT64)
+ end
+
+ alias append_sint8! append_int8!
+ alias append_sint16! append_int16!
+ alias append_sint32! append_int32!
+ alias append_sint64! append_int64!
+
+ def append_ber_int8!(str, int)
+ str << 1 << (int & 255)
+ end
+
+ def append_ber_int16!(str, int)
+ str << 2 << (int & 255) << ((int>>8) & 255)
+ end
+
+ def append_ber_int32!(str, int)
+ str << 4 <<
+ (int & 255) << ((int>>8) & 255) <<
+ ((int>>16) & 255) << ((int>>24) & 255)
+ end
+
+ def append_ber_int64!(str, int)
+ str << 8 << [int].pack(INT64)
+ end
+
+ alias append_ber_sint8! append_ber_int8!
+ alias append_ber_sint16! append_ber_int16!
+ alias append_ber_sint32! append_ber_int32!
+ alias append_ber_sint64! append_ber_int64!
end
module TailGetter

0 comments on commit d7c7808

Please sign in to comment.