Using Ruby StringIO's gets method -
if run following code:
require 'stringio' chunked_data = stringio.new("7\r\nhello, \r\n6\r\nworld!\r\n0\r\n") data = "" until chunked_data.eof? if chunk_head = chunked_data.gets("\r\n") print chunk_head if chunk = chunked_data.read(chunk_head.to_i) print chunk data << chunk end end end
i output:
7 hello, 6 world! 0
according docs, gets
method takes separator , returns next line based on separator. if replace \r\n
in string , separator .
, separator functionality seems no longer work , this:
7.hello, .6.world!.0.
what's going on?
to see what's going on, let's replace print
more explicit output:
require 'stringio' def parse(chunked_data, separator) data = "" until chunked_data.eof? if chunk_head = chunked_data.gets(separator) puts "chunk_head: #{chunk_head.inspect}" if chunk = chunked_data.read(chunk_head.to_i) puts " chunk: #{chunk.inspect}" data << chunk end end end data end result = parse(stringio.new("7\r\nhello, \r\n6\r\nworld!\r\n0\r\n"), "\r\n") puts " result: #{result.inspect}"
output:
chunk_head: "7\r\n" chunk: "hello, " chunk_head: "\r\n" chunk: "" chunk_head: "6\r\n" chunk: "world!" chunk_head: "\r\n" chunk: "" chunk_head: "0\r\n" chunk: ""
now .
:
result = parse(stringio.new("7.hello, .6.world!.0."), ".") puts " result: #{result.inspect}"
output:
chunk_head: "7." chunk: "hello, " chunk_head: "." chunk: "" chunk_head: "6." chunk: "world!" chunk_head: "." chunk: "" chunk_head: "0." chunk: "" result: "hello, world!"
as can see, works either way , result identical.
although result correct, there seems bug in code: don't read separator after chunk
. can fixed adding chunked_data.gets(separator)
or chunked_data.read(separator.bytesize)
after if/end
block:
def parse(chunked_data, separator) data = "" until chunked_data.eof? if chunk_head = chunked_data.gets(separator) puts "chunk_head: #{chunk_head.inspect}" if chunk = chunked_data.read(chunk_head.to_i) puts " chunk: #{chunk.inspect}" data << chunk end chunked_data.read(separator.bytesize) end end data end result = parse(stringio.new("7.hello, .6.world!.0."), ".") puts " result: #{result.inspect}"
output:
chunk_head: "7." chunk: "hello, " chunk_head: "6." chunk: "world!" chunk_head: "0." chunk: "" result: "hello, world!"
that looks better.
Comments
Post a Comment