erlectricity 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/Manifest.txt +41 -0
  2. data/README.txt +3 -0
  3. data/Rakefile +68 -0
  4. data/examples/gruff/gruff.erl +62 -0
  5. data/examples/gruff/gruff_provider.rb +38 -0
  6. data/examples/gruff/gruff_run.erl +17 -0
  7. data/examples/gruff/stat_run.erl +18 -0
  8. data/examples/gruff/stat_writer.erl +40 -0
  9. data/examples/tinderl/tinderl.erl +41 -0
  10. data/examples/tinderl/tinderl.rb +23 -0
  11. data/lib/erlectricity/condition.rb +48 -0
  12. data/lib/erlectricity/conditions/hash.rb +15 -0
  13. data/lib/erlectricity/conditions/static.rb +17 -0
  14. data/lib/erlectricity/conditions/type.rb +19 -0
  15. data/lib/erlectricity/constants.rb +37 -0
  16. data/lib/erlectricity/decoder.rb +202 -0
  17. data/lib/erlectricity/encoder.rb +127 -0
  18. data/lib/erlectricity/errors/decode_error.rb +3 -0
  19. data/lib/erlectricity/errors/encode_error.rb +3 -0
  20. data/lib/erlectricity/errors/erlectricity_error.rb +3 -0
  21. data/lib/erlectricity/match_context.rb +20 -0
  22. data/lib/erlectricity/matcher.rb +60 -0
  23. data/lib/erlectricity/port.rb +46 -0
  24. data/lib/erlectricity/receiver.rb +74 -0
  25. data/lib/erlectricity/types/function.rb +3 -0
  26. data/lib/erlectricity/types/new_function.rb +3 -0
  27. data/lib/erlectricity/types/new_reference.rb +3 -0
  28. data/lib/erlectricity/types/pid.rb +3 -0
  29. data/lib/erlectricity/types/reference.rb +3 -0
  30. data/lib/erlectricity/version.rb +9 -0
  31. data/lib/erlectricity.rb +23 -0
  32. data/setup.rb +1585 -0
  33. data/test/condition_spec.rb +78 -0
  34. data/test/decode_spec.rb +133 -0
  35. data/test/encode_spec.rb +125 -0
  36. data/test/matcher_spec.rb +73 -0
  37. data/test/port_spec.rb +35 -0
  38. data/test/receiver_spec.rb +105 -0
  39. data/test/spec_suite.rb +2 -0
  40. data/test/test_erlectricity.rb +2 -0
  41. data/test/test_helper.rb +36 -0
  42. metadata +87 -0
data/Manifest.txt ADDED
@@ -0,0 +1,41 @@
1
+ Manifest.txt
2
+ README.txt
3
+ Rakefile
4
+ examples/gruff/gruff.erl
5
+ examples/gruff/gruff_provider.rb
6
+ examples/gruff/gruff_run.erl
7
+ examples/gruff/stat_run.erl
8
+ examples/gruff/stat_writer.erl
9
+ examples/tinderl/tinderl.erl
10
+ examples/tinderl/tinderl.rb
11
+ lib/erlectricity.rb
12
+ lib/erlectricity/condition.rb
13
+ lib/erlectricity/conditions/hash.rb
14
+ lib/erlectricity/conditions/static.rb
15
+ lib/erlectricity/conditions/type.rb
16
+ lib/erlectricity/constants.rb
17
+ lib/erlectricity/decoder.rb
18
+ lib/erlectricity/encoder.rb
19
+ lib/erlectricity/errors/decode_error.rb
20
+ lib/erlectricity/errors/encode_error.rb
21
+ lib/erlectricity/errors/erlectricity_error.rb
22
+ lib/erlectricity/match_context.rb
23
+ lib/erlectricity/matcher.rb
24
+ lib/erlectricity/port.rb
25
+ lib/erlectricity/receiver.rb
26
+ lib/erlectricity/types/function.rb
27
+ lib/erlectricity/types/new_function.rb
28
+ lib/erlectricity/types/new_reference.rb
29
+ lib/erlectricity/types/pid.rb
30
+ lib/erlectricity/types/reference.rb
31
+ lib/erlectricity/version.rb
32
+ setup.rb
33
+ test/condition_spec.rb
34
+ test/decode_spec.rb
35
+ test/encode_spec.rb
36
+ test/matcher_spec.rb
37
+ test/port_spec.rb
38
+ test/receiver_spec.rb
39
+ test/spec_suite.rb
40
+ test/test_erlectricity.rb
41
+ test/test_helper.rb
data/README.txt ADDED
@@ -0,0 +1,3 @@
1
+ README for erlectricity
2
+ =======================
3
+
data/Rakefile ADDED
@@ -0,0 +1,68 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'fileutils'
10
+ require 'hoe'
11
+ include FileUtils
12
+ require File.join(File.dirname(__FILE__), 'lib', 'erlectricity', 'version')
13
+
14
+ AUTHOR = 'Scott Fleckenstein' # can also be an array of Authors
15
+ EMAIL = "nullstyle@gmail.com"
16
+ DESCRIPTION = "A library to interface erlang and ruby through the erlang port system"
17
+ GEM_NAME = 'erlectricity' # what ppl will type to install your gem
18
+ RUBYFORGE_PROJECT = 'erlectricity' # The unix name for your project
19
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
20
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
21
+
22
+ NAME = "erlectricity"
23
+ REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
24
+ VERS = Erlectricity::VERSION::STRING + (REV ? ".#{REV}" : "")
25
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
26
+ RDOC_OPTS = ['--quiet', '--title', 'erlectricity documentation',
27
+ "--opname", "index.html",
28
+ "--line-numbers",
29
+ "--main", "README",
30
+ "--inline-source"]
31
+
32
+ class Hoe
33
+ def extra_deps
34
+ @extra_deps.reject { |x| Array(x).first == 'hoe' }
35
+ end
36
+ end
37
+
38
+ # Generate all the Rake tasks
39
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
40
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
41
+ p.author = AUTHOR
42
+ p.description = DESCRIPTION
43
+ p.email = EMAIL
44
+ p.summary = DESCRIPTION
45
+ p.url = HOMEPATH
46
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
47
+ p.test_globs = ["test/**/test_*.rb"]
48
+ p.clean_globs = CLEAN #An array of file patterns to delete on clean.
49
+
50
+ # == Optional
51
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
52
+ #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
53
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
54
+ end
55
+
56
+ desc 'Release the website and new gem version'
57
+ task :deploy => [:check_version, :release]
58
+
59
+ task :check_version do
60
+ unless ENV['VERSION']
61
+ puts 'Must pass a VERSION=x.y.z release version'
62
+ exit
63
+ end
64
+ unless ENV['VERSION'] == VERS
65
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
66
+ exit
67
+ end
68
+ end
@@ -0,0 +1,62 @@
1
+ -module(gruff).
2
+ -export([start/0, stop/0, plot/4]).
3
+
4
+ start() ->
5
+ spawn(fun() ->
6
+ register(gruff, self()),
7
+ process_flag(trap_exit, true),
8
+ Cmd = "ruby ./gruff_provider.rb",
9
+ Port = open_port({spawn, Cmd}, [{packet, 4}, use_stdio, exit_status, binary]),
10
+ port_loop(Port)
11
+ end).
12
+
13
+ stop() -> gruff ! stop.
14
+
15
+ plot(Name, Font, Data, Labels) ->
16
+ gruff ! {plot, self(), Name, Font, Data, Labels},
17
+ receive
18
+ {result, Bin} -> Bin
19
+ end.
20
+
21
+ send_data(_Port, []) -> ok;
22
+ send_data(Port, [{Name, Points}|Rest]) ->
23
+ Data = {data, Name, Points},
24
+ Port ! {self(), {command, term_to_binary(Data)}},
25
+ send_data(Port, Rest).
26
+
27
+ send_labels(Port, Labels) ->
28
+ Data = {labels, Labels},
29
+ Port ! {self(), {command, term_to_binary(Data)}}.
30
+
31
+
32
+ port_loop(Port) ->
33
+ receive
34
+ {plot, Caller, Name, Font, Data, Labels} ->
35
+ PlotData = term_to_binary({plot, Name, 'Line', Font}),
36
+ Port ! {self(), {command, PlotData}},
37
+
38
+ send_data(Port, Data),
39
+ send_labels(Port, Labels),
40
+
41
+ EndData = term_to_binary('end'),
42
+ Port ! {self(), {command, EndData}},
43
+ Result = get_result(Port),
44
+ Caller ! {result, Result },
45
+
46
+ port_loop(Port);
47
+
48
+ stop ->
49
+ Port ! {self(), close},
50
+ receive
51
+ {Port, closed} -> exit(normal)
52
+ end
53
+ end.
54
+
55
+ get_result(Port) ->
56
+ receive
57
+ {Port, {data, Data}} ->
58
+ {result, Bin} = binary_to_term(Data),
59
+ Bin;
60
+ {'EXIT', Port, Reason} ->
61
+ exit({port_terminated,Reason})
62
+ end.
@@ -0,0 +1,38 @@
1
+ $:.unshift(File.dirname(__FILE__) + "/../../lib/")
2
+ require 'rubygems'
3
+ require 'erlectricity'
4
+ require 'gruff'
5
+
6
+ receive do
7
+
8
+
9
+
10
+ match(:plot, string(:name), atom(:style), string(:font)) do
11
+ graph = Gruff.const_get(style).new
12
+ graph.title = name
13
+ graph.font = font
14
+ graph.legend_font_size = 10
15
+
16
+
17
+ receive do
18
+ match(:data, atom(:name), list(:points)) do
19
+ graph.data name, points
20
+ receive_loop
21
+ end
22
+
23
+ match(:labels, hash(:label_data)) do
24
+ graph.labels = label_data
25
+ receive_loop
26
+ end
27
+
28
+ match(:end){ :ok }
29
+ end
30
+
31
+
32
+ send! :result, graph.to_blob
33
+ receive_loop
34
+ end
35
+
36
+ end
37
+
38
+
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env escript
2
+ -export([main/1]).
3
+ main(_Any) ->
4
+ Data = [
5
+ {apples, [10, 2, 3, 4, 4, 3]},
6
+ {oranges, [4, 8, 7, 9, 8, 9]},
7
+ {watermelons, [2, 3, 1, 5, 6, 8]},
8
+ {peaches, [9, 9, 10, 8, 7, 9]}
9
+ ],
10
+ gruff:start(),
11
+ Result = gruff:plot(
12
+ <<"My Charts">>,
13
+ <<"/Users/scott/Library/Fonts/Arial">>,
14
+ Data,
15
+ [{0, <<"2003">>}, {2, <<"2004">>}, {4, <<"2005">>}]
16
+ ),
17
+ file:write_file("out.png", Result).
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env escript
2
+ -export([main/1]).
3
+ main(_Any) ->
4
+ gruff:start(),
5
+ MemoryWriter = stat_writer:start(<<"Memory Info">>, fun() -> erlang:memory() end),
6
+ ProcessWriter = stat_writer:start(<<"Process Info">>,
7
+ fun() ->
8
+ {_, QueueLength} = erlang:process_info(erlang:whereis(gruff), message_queue_len),
9
+ [{processes, erlang:system_info(process_count)},
10
+ {gruff_queue_length, QueueLength}]
11
+ end
12
+ ),
13
+ receive
14
+ after 20000 ->
15
+ MemoryWriter ! stop,
16
+ ProcessWriter ! stop,
17
+ elang:halt()
18
+ end.
@@ -0,0 +1,40 @@
1
+ -module(stat_writer).
2
+ -export([start/2, loop/3]).
3
+
4
+ start(Title, Fun) ->
5
+ spawn(?MODULE, loop, [Title, Fun, []]).
6
+
7
+ loop(Title, Fun, []) ->
8
+ Data = accumulate([], Fun()),
9
+ loop(Title, Fun, Data, 0).
10
+
11
+ loop(Title, Fun, Data, Generation) ->
12
+ receive
13
+ {stop} -> ok
14
+ after 3000 ->
15
+ NewGeneration = Generation + 1,
16
+ NewData = accumulate(Data, Fun()),
17
+ NewChart = gruff:plot(
18
+ list_to_binary([Title, << "- Generation" >>, integer_to_list(NewGeneration)]),
19
+ <<"/Users/scott/Library/Fonts/Arial">>,
20
+ NewData,
21
+ []
22
+ ),
23
+ file:write_file(io_lib:format("~s - ~s.png", [Title, integer_to_list(NewGeneration)]),NewChart),
24
+ loop(Title, Fun, NewData, NewGeneration)
25
+ end.
26
+
27
+ process_axis({Name, PreviousReadings}, {Name, Reading}) ->
28
+ {Name, [Reading|PreviousReadings]}.
29
+
30
+ accumulate(Data, []) -> Data;
31
+ accumulate([], [{Name, Reading}|Rest]) ->
32
+ Data = [{Name, [Reading]}],
33
+ accumulate(Data, Rest);
34
+ accumulate(Data, [{Name, Reading}|Rest]) ->
35
+ MergedData = case lists:keysearch(Name, 1, Data) of
36
+ {value, Axis} -> lists:keyreplace(Name, 1, Data, process_axis(Axis, {Name, Reading}));
37
+ false ->
38
+ [{Name, [Reading]}|Data]
39
+ end,
40
+ accumulate(MergedData, Rest).
@@ -0,0 +1,41 @@
1
+ -module(tinderl).
2
+ -export([start/4, stop/0, speak/1, paste/1]).
3
+
4
+ start(Domain, Email, Password, Room) ->
5
+ spawn(fun() ->
6
+ register(tinderl, self()),
7
+ process_flag(trap_exit, true),
8
+ Cmd = lists:flatten(io_lib:format("ruby ./tinderl.rb ~s ~s ~s ~s", [Domain, Email, Password, Room])),
9
+ Port = open_port({spawn, Cmd}, [{packet, 4}, use_stdio, exit_status, binary]),
10
+ port_loop(Port)
11
+ end).
12
+
13
+ stop() -> tinderl ! stop.
14
+
15
+ speak(String) when is_binary(String) -> tinderl ! {speak, self(), String}.
16
+ paste(String) when is_binary(String) -> tinderl ! {paste, self(), String}.
17
+
18
+ port_loop(Port) ->
19
+ receive
20
+ {speak, _Caller, String} ->
21
+ Data = term_to_binary({speak, String}),
22
+ Port ! {self(), {command, Data}},
23
+
24
+ port_loop(Port);
25
+
26
+ {paste, _Caller, String} ->
27
+ Data = term_to_binary({paste, String}),
28
+ Port ! {self(), {command, Data}},
29
+
30
+ port_loop(Port);
31
+
32
+ stop ->
33
+ Port ! {self(), close},
34
+ receive
35
+ {Port, closed} -> exit(normal)
36
+ end;
37
+
38
+ {'EXIT', Port, Reason} ->
39
+ exit({port_terminated,Reason})
40
+ end.
41
+
@@ -0,0 +1,23 @@
1
+ $:.unshift(File.dirname(__FILE__) + "/../../lib/")
2
+ require 'rubygems'
3
+ require 'erlectricity'
4
+ require 'tinder'
5
+
6
+ domain, email, password, room_name = *ARGV
7
+ campfire = Tinder::Campfire.new domain
8
+ campfire.login email, password
9
+ room = campfire.find_room_by_name room_name
10
+
11
+ receive do
12
+ match(:speak, any(:comment)) do
13
+ room.speak comment
14
+ receive_loop
15
+ end
16
+
17
+ match(:paste, any(:comment)) do
18
+ room.paste comment
19
+ receive_loop
20
+ end
21
+ end
22
+
23
+ room.leave if room
@@ -0,0 +1,48 @@
1
+ module Erlectricity
2
+ class Condition
3
+ attr_accessor :binding_name
4
+
5
+ def initialize(binding_name=nil)
6
+ self.binding_name = binding_name
7
+ end
8
+
9
+ def bindings_for(arg)
10
+ {}
11
+ end
12
+
13
+ def satisfies?(arg)
14
+ false
15
+ end
16
+
17
+ end
18
+
19
+ module Conditions
20
+ def atom(name=nil)
21
+ TypeCondition.new(Symbol, name)
22
+ end
23
+
24
+ def any(name=nil)
25
+ TypeCondition.new(Object, name)
26
+ end
27
+
28
+ def number(name=nil)
29
+ TypeCondition.new(Fixnum, name)
30
+ end
31
+
32
+ def pid(name=nil)
33
+ TypeCondition.new(Erlectricity::Pid, name)
34
+ end
35
+
36
+ def string(name=nil)
37
+ TypeCondition.new(String, name)
38
+ end
39
+
40
+ def list(name=nil)
41
+ TypeCondition.new(Array, name)
42
+ end
43
+
44
+ def hash(name=nil)
45
+ HashCondition.new(name)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,15 @@
1
+ module Erlectricity
2
+ class HashCondition < Condition
3
+
4
+ def satisfies?(arg)
5
+ return false unless arg.class == Array
6
+ arg.all?{|x| x.class == Array && x.length == 2}
7
+ end
8
+
9
+ def bindings_for(arg)
10
+ return {} unless self.binding_name
11
+ flattened = arg.inject([]){|memo, kv| memo + kv}
12
+ {self.binding_name => Hash[*flattened]}
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module Erlectricity
2
+ class StaticCondition < Condition
3
+ attr_accessor :value
4
+ def initialize(value, name=nil)
5
+ self.value = value
6
+ super(name)
7
+ end
8
+
9
+ def satisfies?(arg)
10
+ arg.eql? value
11
+ end
12
+
13
+ def bindings_for(arg)
14
+ {}
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ module Erlectricity
2
+ class TypeCondition < Condition
3
+ attr_accessor :type
4
+
5
+ def initialize(type, name=nil)
6
+ self.type = type
7
+ super(name)
8
+ end
9
+
10
+ def satisfies?(arg)
11
+ arg.is_a? self.type
12
+ end
13
+
14
+ def bindings_for(arg)
15
+ return {} unless self.binding_name
16
+ {self.binding_name => arg}
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,37 @@
1
+ module Erlectricity
2
+ module External
3
+ module Types
4
+ SMALL_INT = 97
5
+ INT = 98
6
+
7
+ SMALL_BIGNUM = 110
8
+ LARGE_BIGNUM = 111
9
+
10
+ FLOAT = 99
11
+
12
+ ATOM = 100
13
+ REF = 101 #old style reference
14
+ NEW_REF = 114
15
+ PORT = 102 #not supported accross node boundaries
16
+ PID = 103
17
+
18
+ SMALL_TUPLE = 104
19
+ LARGE_TUPLE = 105
20
+
21
+ NIL = 106
22
+ STRING = 107
23
+ LIST = 108
24
+ BIN = 109
25
+
26
+ FUN = 117
27
+ NEW_FUN = 112
28
+ end
29
+
30
+ VERSION = 131
31
+
32
+ MAX_INT = (1 << 27) -1
33
+ MIN_INT = -(1 << 27)
34
+ MAX_ATOM = 255
35
+ end
36
+
37
+ end
@@ -0,0 +1,202 @@
1
+ module Erlectricity
2
+ class Decoder
3
+ attr_accessor :in
4
+ include Erlectricity::External::Types
5
+
6
+ def self.read_any_from(string)
7
+ new(StringIO.new(string)).read_any
8
+ end
9
+
10
+ def initialize(ins)
11
+ @in = ins
12
+ @peeked = ""
13
+ end
14
+
15
+ def read_any
16
+ fail("Bad Magic") unless read_1 == Erlectricity::External::VERSION
17
+ read_any_raw
18
+ end
19
+
20
+ def read_any_raw
21
+ case peek_1
22
+ when ATOM then read_atom
23
+ when SMALL_INT then read_small_int
24
+ when INT then read_int
25
+ when SMALL_BIGNUM then read_small_bignum
26
+ when LARGE_BIGNUM then read_large_bignum
27
+ when FLOAT then read_float
28
+ when NEW_REF then read_new_reference
29
+ when PID then read_pid
30
+ when SMALL_TUPLE then read_small_tuple
31
+ when LARGE_TUPLE then read_large_tuple
32
+ when NIL then read_nil
33
+ when STRING then read_erl_string
34
+ when LIST then read_list
35
+ when BIN then read_bin
36
+ else
37
+ fail("Unknown term tag: #{peek_1}")
38
+ end
39
+ end
40
+
41
+ def read(length)
42
+ if length < @peeked.length
43
+ result = @peeked[0...length]
44
+ @peeked = @peeked[length..-1]
45
+ length = 0
46
+ else
47
+ result = @peeked
48
+ @peeked = ''
49
+ length -= result.length
50
+ end
51
+
52
+ if length > 0
53
+ result << @in.read(length)
54
+ end
55
+ result
56
+ end
57
+
58
+ def peek(length)
59
+ if length <= @peeked.length
60
+ @peeked[0...length]
61
+ else
62
+ read_bytes = @in.read(length - @peeked.length)
63
+ @peeked << read_bytes if read_bytes
64
+ @peeked
65
+ end
66
+ end
67
+
68
+ def peek_1
69
+ peek(1).unpack("C").first
70
+ end
71
+
72
+ def peek_2
73
+ peek(2).unpack("n").first
74
+ end
75
+
76
+ def read_1
77
+ read(1).unpack("C").first
78
+ end
79
+
80
+ def read_2
81
+ read(2).unpack("n").first
82
+ end
83
+
84
+ def read_4
85
+ read(4).unpack("N").first
86
+ end
87
+
88
+ def read_string(length)
89
+ read(length)
90
+ end
91
+
92
+ def read_atom
93
+ fail("Invalid Type, not an atom") unless read_1 == ATOM
94
+ length = read_2
95
+ read_string(length).to_sym
96
+ end
97
+
98
+ def read_small_int
99
+ fail("Invalid Type, not a small int") unless read_1 == SMALL_INT
100
+ read_1
101
+ end
102
+
103
+ def read_int
104
+ fail("Invalid Type, not an int") unless read_1 == INT
105
+ value = read_4
106
+ negative = (value >> 31)[0] == 1
107
+ value = (value - (1 << 32)) if negative
108
+ value = Fixnum.induced_from(value)
109
+ end
110
+
111
+ def read_small_bignum
112
+ fail("Invalid Type, not a small bignum") unless read_1 == SMALL_BIGNUM
113
+ size = read_1
114
+ sign = read_1
115
+ bytes = read_string(size).unpack("C" * size)
116
+ added = bytes.zip((0..bytes.length).to_a).inject(0) do |result, byte_index|
117
+ byte, index = *byte_index
118
+ value = (byte * (256 ** index))
119
+ sign != 0 ? (result - value) : (result + value)
120
+ end
121
+ Bignum.induced_from(added)
122
+ end
123
+
124
+ def read_large_bignum
125
+ fail("Invalid Type, not a large bignum") unless read_1 == LARGE_BIGNUM
126
+ size = read_4
127
+ sign = read_1
128
+ bytes = read_string(size).unpack("C" * size)
129
+ added = bytes.zip((0..bytes.length).to_a).inject(0) do |result, byte_index|
130
+ byte, index = *byte_index
131
+ value = (byte * (256 ** index))
132
+ sign != 0 ? (result - value) : (result + value)
133
+ end
134
+ Bignum.induced_from(added)
135
+ end
136
+
137
+ def read_float
138
+ fail("Invalid Type, not a float") unless read_1 == FLOAT
139
+ string_value = read_string(31)
140
+ result = string_value.to_f
141
+ end
142
+
143
+ def read_new_reference
144
+ fail("Invalid Type, not a new-style reference") unless read_1 == NEW_REF
145
+ size = read_2
146
+ node = read_atom
147
+ creation = read_1
148
+ id = (0...size).map{|i| read_4 }
149
+ NewReference.new(node, creation, id)
150
+ end
151
+
152
+ def read_pid
153
+ fail("Invalid Type, not a pid") unless read_1 == PID
154
+ node = read_atom
155
+ id = read_4
156
+ serial = read_4
157
+ creation = read_1
158
+ Pid.new(node, id, serial, creation)
159
+ end
160
+
161
+ def read_small_tuple
162
+ fail("Invalid Type, not a small tuple") unless read_1 == SMALL_TUPLE
163
+ arity = read_1
164
+
165
+ (0...arity).map{|i| read_any_raw }
166
+ end
167
+
168
+ def read_large_tuple
169
+ fail("Invalid Type, not a small tuple") unless read_1 == LARGE_TUPLE
170
+ arity = read_4
171
+ (0...arity).map{|i| read_any_raw}
172
+ end
173
+
174
+ def read_nil
175
+ fail("Invalid Type, not a nil list") unless read_1 == NIL
176
+ []
177
+ end
178
+
179
+ def read_erl_string
180
+ fail("Invalid Type, not an erlang string") unless read_1 == STRING
181
+ length = read_2
182
+ read_string(length).unpack('C' * length)
183
+ end
184
+
185
+ def read_list
186
+ fail("Invalid Type, not an erlang list") unless read_1 == LIST
187
+ length = read_4
188
+ (0...length).map{|i| read_any_raw}
189
+ end
190
+
191
+ def read_bin
192
+ fail("Invalid Type, not an erlang binary") unless read_1 == BIN
193
+ length = read_4
194
+ read_string(length)
195
+ end
196
+
197
+ def fail(str)
198
+ raise DecodeError, str
199
+ end
200
+
201
+ end
202
+ end