Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions lib/redis_client/ruby_connection/buffered_io.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ def gets_chomp
end

def read_chomp(bytes)
raise ArgumentError, "negative byte length: #{bytes}" if bytes < 0

ensure_remaining(bytes + EOL_SIZE)
unless @buffer.byteslice(@offset + bytes, EOL_SIZE) == EOL
raise ArgumentError, "expected CRLF after #{bytes} bytes"
end

str = @buffer.byteslice(@offset, bytes)
@offset += bytes + EOL_SIZE
str
Expand Down Expand Up @@ -72,7 +78,13 @@ def gets_chomp
end

def read_chomp(bytes)
raise ArgumentError, "negative byte length: #{bytes}" if bytes < 0

ensure_remaining(bytes + EOL_SIZE)
unless @buffer.byteslice(@offset + bytes, EOL_SIZE) == EOL
raise ArgumentError, "expected CRLF after #{bytes} bytes"
end

str = @buffer.byteslice(@offset, bytes)
@offset += bytes + EOL_SIZE
str.force_encoding(Encoding::UTF_8)
Expand Down Expand Up @@ -159,24 +171,37 @@ def getbyte
def gets_integer
int = 0
offset = @offset
negative = false
digits = false
while true
chr = @buffer.getbyte(offset)

if chr
if chr == 13 # "\r".ord
unless @buffer.getbyte(offset + 1)
ensure_line
return gets_integer
end
unless @buffer.getbyte(offset + 1) == 10 && digits
raise ArgumentError, "invalid integer line"
end

@offset = offset + 2
break
else
return negative ? -int : int
elsif chr == 45 && offset == @offset # "-".ord
negative = true
elsif chr >= 48 && chr <= 57
digits = true
int = (int * 10) + chr - 48
else
raise ArgumentError, "invalid byte in integer line: #{chr}"
end
offset += 1
else
ensure_line
return gets_integer
end
end

int
end

private
Expand Down
37 changes: 30 additions & 7 deletions lib/redis_client/ruby_connection/resp3.rb
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,19 @@ def parse_boolean(io)
end

def parse_array(io)
parse_sequence(io, io.gets_integer)
parse_sequence(io, parse_length(io))
end

def parse_set(io)
parse_sequence(io, io.gets_integer)
parse_sequence(io, parse_length(io))
end

def parse_map(io)
size = parse_length(io)
raise SyntaxError, "Invalid map length: #{size}" if size < 0

hash = {}
io.gets_integer.times do
size.times do
hash[parse(io).freeze] = parse(io)
end
hash
Expand All @@ -184,7 +187,8 @@ def parse_push(io)
end

def parse_sequence(io, size)
return if size < 0 # RESP2 nil
return if size == -1 # RESP2 nil
raise SyntaxError, "Invalid sequence length: #{size}" if size < -1

array = Array.new(size)
size.times do |index|
Expand All @@ -195,6 +199,8 @@ def parse_sequence(io, size)

def parse_integer(io)
Integer(io.gets_chomp)
rescue ArgumentError => error
raise SyntaxError, error.message
end

def parse_double(io)
Expand All @@ -208,25 +214,42 @@ def parse_double(io)
else
Float(value)
end
rescue ArgumentError => error
raise SyntaxError, error.message
end

def parse_null(io)
io.skip(EOL_SIZE)
io.read_chomp(0)
nil
rescue ArgumentError => error
raise SyntaxError, error.message
end

def parse_blob(io)
bytesize = io.gets_integer
return if bytesize < 0 # RESP2 nil type
bytesize = parse_length(io)
return if bytesize == -1 # RESP2 nil type
raise SyntaxError, "Invalid blob length: #{bytesize}" if bytesize < -1

str = io.read_chomp(bytesize)
str.force_encoding(Encoding::BINARY) unless str.valid_encoding?
str
rescue ArgumentError => error
raise SyntaxError, error.message
end

def parse_verbatim_string(io)
blob = parse_blob(io)
unless blob && blob.bytesize >= 4 && blob.getbyte(3) == 58 # ":".ord
raise SyntaxError, "Invalid verbatim string"
end

blob.byteslice(4..-1)
end

def parse_length(io)
io.gets_integer
rescue ArgumentError => error
raise SyntaxError, error.message
end
end
end
Loading