Skip to content

Commit 03eb901

Browse files
committed
Dump strings as bytes.
1 parent 4356175 commit 03eb901

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

lib/tnetstrings.rb

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
#!/usr/bin/env ruby -w
2+
3+
# encoding: utf-8
4+
15
module TNetStrings
26
def self.dump(data)
37
case data
4-
when String, Symbol then "#{data.length}:#{data},"
8+
when String then "#{data.bytesize}:#{data.bytes.pack('C*')},"
9+
when Symbol then "#{data.to_s.length}:#{data.to_s},"
510
when Fixnum then "#{data.to_s.length}:#{data.to_s}#"
611
when Float then "#{data.to_s.length}:#{data.to_s}^"
712
when TrueClass then "4:true!"
@@ -10,11 +15,17 @@ def self.dump(data)
1015
when Array then dump_array(data)
1116
when Hash then dump_hash(data)
1217
else
13-
raise "Can't serialize stuff that's '#{data.class}'."
18+
if data.respond_to?(:to_s)
19+
s = data.to_s
20+
"#{s.length}:#{s},"
21+
else
22+
raise "Can't serialize stuff that's '#{data.class}'."
23+
end
1424
end
1525
end
1626

1727
def self.parse(data)
28+
raise "Invalid data." if data.empty?
1829
payload, payload_type, remain = parse_payload(data)
1930

2031
value = case payload_type
@@ -42,7 +53,7 @@ def self.parse_payload(data)
4253
if len == 0
4354
payload = ''
4455
else
45-
payload, extra = extra[0..len-1], extra[len..-1]
56+
payload, extra = extra.byteslice(0..len-1), extra.byteslice(len..-1)
4657
end
4758
payload_type, remain = extra[0], extra[1..-1]
4859

@@ -128,6 +139,22 @@ def test_parse_strings
128139
assert_equal "", r
129140
end
130141

142+
def test_parse_utf8_bytes
143+
n = "3:foo,2:\u00B5,4:\xf0\x9f\x98\x87,"
144+
145+
s, r = TNetStrings::parse(n)
146+
assert_equal "foo", s
147+
assert_equal "2:µ,4:😇,", r
148+
149+
s, r = TNetStrings::parse(r)
150+
assert_equal "µ", s
151+
assert_equal "4:\u{1F607},".force_encoding('UTF-8'), r
152+
153+
s, r = TNetStrings::parse(r)
154+
assert_equal "😇", s
155+
assert_equal "", r
156+
end
157+
131158
def test_parse_fixnum
132159
n = "2:42#"
133160

@@ -240,6 +267,27 @@ def test_parse_hash
240267
assert_equal "", r
241268
end
242269

270+
def test_parse_exceeding
271+
s = "3:foo,4:true!"
272+
273+
v, r = TNetStrings::parse(s)
274+
assert_equal "foo", v
275+
assert_equal "4:true!", r
276+
277+
v, r = TNetStrings::parse(r)
278+
assert_equal true, v
279+
assert_equal "", r
280+
281+
msg = ""
282+
begin
283+
v, r = TNetStrings::parse(r)
284+
rescue => e
285+
msg = e.message
286+
end
287+
assert_equal "Invalid data.", msg
288+
assert_equal "", r
289+
end
290+
243291
def test_dump_strings
244292
s = TNetStrings::dump("foobar")
245293
assert_equal "6:foobar,", s
@@ -248,6 +296,17 @@ def test_dump_strings
248296
assert_equal "6:foobar,3:baz,", s
249297
end
250298

299+
def test_dump_byte_strings
300+
s = TNetStrings::dump("ßöö")
301+
assert_equal "6:\xC3\x9F\xC3\xB6\xC3\xB6,".unpack('C*'), s.bytes
302+
303+
s << TNetStrings::dump("µ")
304+
assert_equal "6:ßöö,2:µ,", s.force_encoding("UTF-8")
305+
306+
s << TNetStrings::dump("\u{1F607}").force_encoding('UTF-8')
307+
assert_equal "6:ßöö,2:µ,4:😇,", s.force_encoding("UTF-8")
308+
end
309+
251310
def test_dump_symbol
252311
s = TNetStrings::dump(:foobarbaz)
253312
assert_equal "9:foobarbaz,", s

tnetstrings.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Gem::Specification.new do |s|
22
s.name = 'tnetstrings'
3-
s.version = '0.1.0'
3+
s.version = '0.1.2'
44
s.license = 'MIT'
55
s.author = 'Alex Brem'
66
s.email = '[email protected]'

0 commit comments

Comments
 (0)