This commit is contained in:
Tom Preston-Werner 2009-10-24 02:21:04 -07:00
Родитель c55e9c6bdb
Коммит 873c26fba8
4 изменённых файлов: 127 добавлений и 101 удалений

Просмотреть файл

@ -33,3 +33,9 @@ Simple C encoder / Ruby decoder
BERT large 2.270000 0.550000 2.820000 ( 3.029141)
BERT complex 8.680000 0.040000 8.720000 ( 9.097990)
Smarter Ruby decoder
BERT tiny 0.090000 0.000000 0.090000 ( 0.087387)
BERT small 0.790000 0.000000 0.790000 ( 0.850270)
BERT large 4.180000 0.600000 4.780000 ( 4.943164)
BERT complex 18.410000 0.090000 18.500000 ( 19.187804)

Просмотреть файл

@ -150,25 +150,81 @@ module BERT
def read_small_tuple
fail("Invalid Type, not a small tuple") unless read_1 == SMALL_TUPLE
arity = read_1
(0...arity).map { |i| read_any_raw }
read_tuple(read_1)
end
def read_large_tuple
fail("Invalid Type, not a small tuple") unless read_1 == LARGE_TUPLE
arity = read_4
(0...arity).map { |i| read_any_raw }
read_tuple(read_4)
end
def read_tuple(arity)
tuple = Tuple.new(arity)
if arity > 0
tag = read_any_raw
if tag == :bert
read_complex_type(arity)
else
tuple[0] = tag
(arity - 1).times { |i| tuple[i + 1] = read_any_raw }
tuple
end
else
tuple
end
end
def read_complex_type(arity)
case read_any_raw
when :nil
nil
when :true
true
when :false
false
when :time
Time.at(read_any_raw * 1_000_000 + read_any_raw, read_any_raw)
when :regex
source = read_any_raw
opts = read_any_raw
options = 0
options |= Regexp::EXTENDED if opts.include?(:extended)
options |= Regexp::IGNORECASE if opts.include?(:caseless)
options |= Regexp::MULTILINE if opts.include?(:multiline)
Regexp.new(source, options)
when :dict
read_dict
else
nil
end
end
def read_dict
type = read_1
fail("Invalid dict spec, not an erlang list") unless [LIST, NIL].include?(type)
if type == LIST
length = read_4
else
length = 0
end
hash = {}
length.times do |i|
pair = read_any_raw
hash[pair[0]] = pair[1]
end
read_1 if type == LIST
hash
end
def read_nil
fail("Invalid Type, not a nil list") unless read_1 == NIL
List.new([])
[]
end
def read_erl_string
fail("Invalid Type, not an erlang string") unless read_1 == STRING
length = read_2
List.new(read_string(length).unpack('C' * length))
read_string(length).unpack('C' * length)
end
def read_list
@ -176,7 +232,7 @@ module BERT
length = read_4
list = (0...length).map { |i| read_any_raw }
read_1
List.new(list)
list
end
def read_bin

Просмотреть файл

@ -14,46 +14,10 @@ module BERT
#
# Returns the converted Ruby object
def self.convert(item)
case item
when List
item.map { |x| convert(x) }
when Array
if item[0] == :bert
convert_bert(item)
else
Tuple.new(item.map { |x| convert(x) })
end
else
item
end
end
# Convert complex types.
# +item+ is the complex type array
#
# Returns the converted Ruby object
def self.convert_bert(item)
case item[1]
when :nil
nil
when :dict
item[2].inject({}) do |acc, x|
acc[convert(x[0])] = convert(x[1]); acc
end
when :true
true
when :false
false
when :time
Time.at(item[2] * 1_000_000 + item[3], item[4])
when :regex
options = 0
options |= Regexp::EXTENDED if item[3].include?(:extended)
options |= Regexp::IGNORECASE if item[3].include?(:caseless)
options |= Regexp::MULTILINE if item[3].include?(:multiline)
Regexp.new(item[2], options)
else
nil
if item.instance_of?(Array)
item.map { |x| convert(x) }
else
item
end
end
end

Просмотреть файл

@ -2,63 +2,63 @@ require 'test_helper'
class DecoderTest < Test::Unit::TestCase
context "BERT Decoder complex type converter" do
should "convert nil" do
before = [:bert, :nil]
after = nil
assert_equal after, BERT::Decoder.convert(before)
end
should "convert nested nil" do
before = [[:bert, :nil], [[:bert, :nil]]]
after = [nil, [nil]]
assert_equal after, BERT::Decoder.convert(before)
end
should "convert hashes" do
before = [:bert, :dict, [[:foo, 'bar']]]
after = {:foo => 'bar'}
assert_equal after, BERT::Decoder.convert(before)
end
should "convert empty hashes" do
before = [:bert, :dict, []]
after = {}
assert_equal after, BERT::Decoder.convert(before)
end
should "convert nested hashes" do
before = [:bert, :dict, [[:foo, [:bert, :dict, [[:baz, 'bar']]]]]]
after = {:foo => {:baz => 'bar'}}
assert_equal after, BERT::Decoder.convert(before)
end
# should "convert nil" do
# before = t[:bert, :nil]
# after = nil
# assert_equal after, BERT::Decoder.convert(before)
# end
#
# should "convert nested nil" do
# before = [t[:bert, :nil], [t[:bert, :nil]]]
# after = [nil, [nil]]
# assert_equal after, BERT::Decoder.convert(before)
# end
#
# should "convert hashes" do
# before = t[:bert, :dict, [[:foo, 'bar']]]
# after = {:foo => 'bar'}
# assert_equal after, BERT::Decoder.convert(before)
# end
#
# should "convert empty hashes" do
# before = t[:bert, :dict, []]
# after = {}
# assert_equal after, BERT::Decoder.convert(before)
# end
#
# should "convert nested hashes" do
# before = t[:bert, :dict, [[:foo, t[:bert, :dict, [[:baz, 'bar']]]]]]
# after = {:foo => {:baz => 'bar'}}
# assert_equal after, BERT::Decoder.convert(before)
# end
should "convert true" do
before = [:bert, :true]
after = true
assert_equal after, BERT::Decoder.convert(before)
# {bert, true}
bert = [131,104,2,100,0,4,98,101,114,116,100,0,4,116,114,117,101].pack('c*')
assert_equal true, BERT::Decoder.decode(bert)
end
should "convert false" do
before = [:bert, :false]
after = false
assert_equal after, BERT::Decoder.convert(before)
end
should "convert times" do
before = [:bert, :time, 1254, 976067, 0]
after = Time.at(1254976067)
assert_equal after, BERT::Decoder.convert(before)
end
should "convert regexen" do
before = [:bert, :regex, '^c(a)t$', [:caseless, :extended]]
after = /^c(a)t$/ix
assert_equal after, BERT::Decoder.convert(before)
end
should "leave other stuff alone" do
before = [1, 2.0, [:foo, 'bar']]
assert_equal before, BERT::Decoder.convert(before)
end
# should "convert false" do
# before = t[:bert, :false]
# after = false
# assert_equal after, BERT::Decoder.convert(before)
# end
#
# should "convert times" do
# before = t[:bert, :time, 1254, 976067, 0]
# after = Time.at(1254976067)
# assert_equal after, BERT::Decoder.convert(before)
# end
#
# should "convert regexen" do
# before = t[:bert, :regex, '^c(a)t$', [:caseless, :extended]]
# after = /^c(a)t$/ix
# assert_equal after, BERT::Decoder.convert(before)
# end
#
# should "leave other stuff alone" do
# before = [1, 2.0, [:foo, 'bar']]
# assert_equal before, BERT::Decoder.convert(before)
# end
end
end