Skip to content
Merged
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
55 changes: 29 additions & 26 deletions lib/raven/okjson.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@
# http://golang.org/src/pkg/json/decode.go and
# http://golang.org/src/pkg/utf8/utf8.go
module Raven

module OkJson
Upstream = '42'
Upstream = '43'
extend self


Expand Down Expand Up @@ -62,28 +61,27 @@ def decode(s)
# is not a String.
# Strings contained in x must be valid UTF-8.
def encode(x)
visited = []
case x
when Hash then objenc(x, visited)
when Array then arrenc(x, visited)
when Hash then objenc(x)
when Array then arrenc(x)
else
raise Error, 'root value must be an Array or a Hash'
end
end


def valenc(x, visited)
def valenc(x)
case x
when Hash then objenc(x, visited)
when Array then arrenc(x, visited)
when Hash then objenc(x)
when Array then arrenc(x)
when String then strenc(x)
when Symbol then strenc(x.to_s)
when Numeric then numenc(x)
when true then "true"
when false then "false"
when nil then "null"
else
strenc((x.inspect rescue $!.to_s))
raise Error, "cannot encode #{x.class}: #{x.inspect}"
end
end

Expand Down Expand Up @@ -134,6 +132,10 @@ def objparse(ts)
ts = eat('{', ts)
obj = {}

unless ts[0]
raise Error, "unexpected end of object"
end

if ts[0][0] == '}'
return obj, ts[1..-1]
end
Expand Down Expand Up @@ -177,6 +179,10 @@ def arrparse(ts)
ts = eat('[', ts)
arr = []

unless ts[0]
raise Error, "unexpected end of array"
end

if ts[0][0] == ']'
return arr, ts[1..-1]
end
Expand Down Expand Up @@ -427,18 +433,13 @@ def nibble(c)
end


def objenc(x, visited)
return '"{...}"' if visited.include?(x.__id__)
visited += [x.__id__]
'{' + x.map{|k,v| keyenc(k) + ':' + valenc(v, visited)}.join(',') + '}'
def objenc(x)
'{' + x.map{|k,v| keyenc(k) + ':' + valenc(v)}.join(',') + '}'
end


def arrenc(a, visited)
return '"[...]"' if visited.include?(a.__id__)
visited += [a.__id__]

'[' + a.map{|x| valenc(x, visited)}.join(',') + ']'
def arrenc(a)
'[' + a.map{|x| valenc(x)}.join(',') + ']'
end


Expand All @@ -447,7 +448,7 @@ def keyenc(k)
when String then strenc(k)
when Symbol then strenc(k.to_s)
else
strenc(k.inspect)
raise Error, "Hash key is not a string: #{k.inspect}"
end
end

Expand All @@ -471,11 +472,16 @@ def strenc(s)
# In ruby >= 1.9, s[r] is a codepoint, not a byte.
if rubydoesenc?
begin
c.ord # will raise an error if c is invalid UTF-8
# c.ord will raise an error if c is invalid UTF-8
if c.ord < Spc.ord
c = "\\u%04x" % [c.ord]
end
t.write(c)
rescue
t.write(Ustrerr)
end
elsif c < Spc
t.write("\\u%04x" % c)
elsif Spc <= c && c <= ?~
t.putc(c)
else
Expand All @@ -491,10 +497,8 @@ def strenc(s)


def numenc(x)
if (x.nan? rescue false)
'"NaN"'
elsif (x.infinite? rescue false)
'"Infinite"'
if ((x.nan? || x.infinite?) rescue false)
raise Error, "Numeric cannot be represented: #{x}"
end
"#{x}"
end
Expand Down Expand Up @@ -605,5 +609,4 @@ class Error < ::StandardError
Spc = ' '[0]
Unesc = {?b=>?\b, ?f=>?\f, ?n=>?\n, ?r=>?\r, ?t=>?\t}
end

end
end
5 changes: 5 additions & 0 deletions spec/raven/okjson_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@
expect(Raven::OkJson.decode("[123e090]")).to eq [123000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]
end

it 'it raises the correct error on strings that look like incomplete objects' do
expect{Raven::OkJson.decode("{")}.to raise_error(Raven::OkJson::Error)
expect{Raven::OkJson.decode("[")}.to raise_error(Raven::OkJson::Error)
end

end