-
Notifications
You must be signed in to change notification settings - Fork 5
/
resp_types.rb
101 lines (91 loc) · 2.45 KB
/
resp_types.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
module BYORedis
RESPError = Struct.new(:message) do
def serialize
"-#{ message }\r\n"
end
end
RESPInteger = Struct.new(:underlying_integer) do
def serialize
":#{ underlying_integer }\r\n"
end
def to_i
underlying_integer.to_i
end
end
RESPSimpleString = Struct.new(:underlying_string) do
def serialize
"+#{ underlying_string }\r\n"
end
end
OKSimpleStringInstance = Object.new.tap do |obj|
OK_SIMPLE_STRING = "+OK\r\n".freeze
def obj.serialize
OK_SIMPLE_STRING
end
end
RESPBulkString = Struct.new(:underlying_string) do
def serialize
"$#{ underlying_string.bytesize }\r\n#{ underlying_string }\r\n"
end
end
NullBulkStringInstance = Object.new.tap do |obj|
NULL_BULK_STRING = "$-1\r\n".freeze
def obj.serialize
NULL_BULK_STRING
end
end
RESPArray = Struct.new(:underlying_array) do
def serialize
serialized_items = underlying_array.map do |item|
case item
when RESPSimpleString, RESPBulkString
item.serialize
when String
RESPBulkString.new(item).serialize
when Integer
RESPInteger.new(item).serialize
when BigDecimal
RESPBulkString.new(Utils.float_to_string(item)).serialize
when Array
RESPArray.new(item).serialize
when nil
NULL_BULK_STRING
else
raise "RESPArray cannot serialize value: #{ item }"
end
end
"*#{ underlying_array.length }\r\n#{ serialized_items.join }"
end
end
EmptyArrayInstance = Object.new.tap do |obj|
EMPTY_ARRAY = "*0\r\n".freeze
def obj.serialize
EMPTY_ARRAY
end
end
NullArrayInstance = Object.new.tap do |obj|
NULL_ARRAY = "*-1\r\n".freeze
def obj.serialize
NULL_ARRAY
end
end
class RESPSerializer
def self.serialize(object)
case object
when Array then RESPArray.new(object)
when RedisSet then RESPArray.new(object.members)
when List then ListSerializer.new(object)
when Integer then RESPInteger.new(object)
when String then RESPBulkString.new(object)
when BigDecimal then RESPBulkString.new(Utils.float_to_string(object))
when Dict
pairs = []
object.each { |k, v| pairs.push(k, v) }
RESPArray.new(pairs)
when nil then NullBulkStringInstance
else
raise "Unknown object for RESP serialization #{ object }"
end
end
end
end