Skip to content

Commit

Permalink
Dump strings as bytes.
Browse files Browse the repository at this point in the history
  • Loading branch information
localhost committed Apr 23, 2015
1 parent 4356175 commit 03eb901
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 4 deletions.
65 changes: 62 additions & 3 deletions lib/tnetstrings.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#!/usr/bin/env ruby -w

# encoding: utf-8

module TNetStrings
def self.dump(data)
case data
when String, Symbol then "#{data.length}:#{data},"
when String then "#{data.bytesize}:#{data.bytes.pack('C*')},"
when Symbol then "#{data.to_s.length}:#{data.to_s},"
when Fixnum then "#{data.to_s.length}:#{data.to_s}#"
when Float then "#{data.to_s.length}:#{data.to_s}^"
when TrueClass then "4:true!"
Expand All @@ -10,11 +15,17 @@ def self.dump(data)
when Array then dump_array(data)
when Hash then dump_hash(data)
else
raise "Can't serialize stuff that's '#{data.class}'."
if data.respond_to?(:to_s)
s = data.to_s
"#{s.length}:#{s},"
else
raise "Can't serialize stuff that's '#{data.class}'."
end
end
end

def self.parse(data)
raise "Invalid data." if data.empty?
payload, payload_type, remain = parse_payload(data)

value = case payload_type
Expand Down Expand Up @@ -42,7 +53,7 @@ def self.parse_payload(data)
if len == 0
payload = ''
else
payload, extra = extra[0..len-1], extra[len..-1]
payload, extra = extra.byteslice(0..len-1), extra.byteslice(len..-1)
end
payload_type, remain = extra[0], extra[1..-1]

Expand Down Expand Up @@ -128,6 +139,22 @@ def test_parse_strings
assert_equal "", r
end

def test_parse_utf8_bytes
n = "3:foo,2:\u00B5,4:\xf0\x9f\x98\x87,"

s, r = TNetStrings::parse(n)
assert_equal "foo", s
assert_equal "2:µ,4:😇,", r

s, r = TNetStrings::parse(r)
assert_equal "µ", s
assert_equal "4:\u{1F607},".force_encoding('UTF-8'), r

s, r = TNetStrings::parse(r)
assert_equal "😇", s
assert_equal "", r
end

def test_parse_fixnum
n = "2:42#"

Expand Down Expand Up @@ -240,6 +267,27 @@ def test_parse_hash
assert_equal "", r
end

def test_parse_exceeding
s = "3:foo,4:true!"

v, r = TNetStrings::parse(s)
assert_equal "foo", v
assert_equal "4:true!", r

v, r = TNetStrings::parse(r)
assert_equal true, v
assert_equal "", r

msg = ""
begin
v, r = TNetStrings::parse(r)
rescue => e
msg = e.message
end
assert_equal "Invalid data.", msg
assert_equal "", r
end

def test_dump_strings
s = TNetStrings::dump("foobar")
assert_equal "6:foobar,", s
Expand All @@ -248,6 +296,17 @@ def test_dump_strings
assert_equal "6:foobar,3:baz,", s
end

def test_dump_byte_strings
s = TNetStrings::dump("ßöö")
assert_equal "6:\xC3\x9F\xC3\xB6\xC3\xB6,".unpack('C*'), s.bytes

s << TNetStrings::dump("µ")
assert_equal "6:ßöö,2:µ,", s.force_encoding("UTF-8")

s << TNetStrings::dump("\u{1F607}").force_encoding('UTF-8')
assert_equal "6:ßöö,2:µ,4:😇,", s.force_encoding("UTF-8")
end

def test_dump_symbol
s = TNetStrings::dump(:foobarbaz)
assert_equal "9:foobarbaz,", s
Expand Down
2 changes: 1 addition & 1 deletion tnetstrings.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = 'tnetstrings'
s.version = '0.1.0'
s.version = '0.1.2'
s.license = 'MIT'
s.author = 'Alex Brem'
s.email = 'alex@fluktuation.net'
Expand Down

0 comments on commit 03eb901

Please sign in to comment.