erlang-etf 1.1.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +20 -0
  3. data/.gitignore +10 -18
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +15 -4
  7. data/CHANGELOG.md +7 -0
  8. data/Gemfile +10 -6
  9. data/LICENSE.txt +1 -1
  10. data/README.md +13 -13
  11. data/Rakefile +8 -6
  12. data/erlang-etf.gemspec +10 -10
  13. data/lib/erlang-etf.rb +1 -0
  14. data/lib/erlang/etf.rb +363 -30
  15. data/lib/erlang/etf/atom.rb +28 -48
  16. data/lib/erlang/etf/atom_utf8.rb +28 -48
  17. data/lib/erlang/etf/binary.rb +24 -23
  18. data/lib/erlang/etf/bit_binary.rb +35 -27
  19. data/lib/erlang/etf/compressed.rb +61 -35
  20. data/lib/erlang/etf/export.rb +44 -21
  21. data/lib/erlang/etf/float.rb +33 -29
  22. data/lib/erlang/etf/fun.rb +54 -32
  23. data/lib/erlang/etf/integer.rb +24 -12
  24. data/lib/erlang/etf/large_big.rb +31 -37
  25. data/lib/erlang/etf/large_tuple.rb +41 -30
  26. data/lib/erlang/etf/list.rb +55 -25
  27. data/lib/erlang/etf/map.rb +58 -28
  28. data/lib/erlang/etf/new_float.rb +25 -14
  29. data/lib/erlang/etf/new_fun.rb +70 -47
  30. data/lib/erlang/etf/new_reference.rb +51 -24
  31. data/lib/erlang/etf/nil.rb +21 -6
  32. data/lib/erlang/etf/pid.rb +48 -21
  33. data/lib/erlang/etf/port.rb +49 -13
  34. data/lib/erlang/etf/reference.rb +49 -13
  35. data/lib/erlang/etf/small_atom.rb +31 -27
  36. data/lib/erlang/etf/small_atom_utf8.rb +31 -27
  37. data/lib/erlang/etf/small_big.rb +30 -39
  38. data/lib/erlang/etf/small_integer.rb +27 -12
  39. data/lib/erlang/etf/small_tuple.rb +41 -30
  40. data/lib/erlang/etf/string.rb +23 -23
  41. data/lib/erlang/etf/term.rb +109 -70
  42. data/lib/erlang/etf/version.rb +1 -1
  43. metadata +33 -169
  44. data/.rspec +0 -2
  45. data/lib/erlang/etf/bert.rb +0 -74
  46. data/lib/erlang/etf/extensions.rb +0 -144
  47. data/lib/erlang/etf/extensions/array.rb +0 -27
  48. data/lib/erlang/etf/extensions/big_decimal.rb +0 -20
  49. data/lib/erlang/etf/extensions/erlang-export.rb +0 -24
  50. data/lib/erlang/etf/extensions/erlang-list.rb +0 -29
  51. data/lib/erlang/etf/extensions/erlang-map.rb +0 -26
  52. data/lib/erlang/etf/extensions/erlang-nil.rb +0 -20
  53. data/lib/erlang/etf/extensions/erlang-pid.rb +0 -20
  54. data/lib/erlang/etf/extensions/erlang-string.rb +0 -31
  55. data/lib/erlang/etf/extensions/erlang-tuple.rb +0 -29
  56. data/lib/erlang/etf/extensions/false_class.rb +0 -26
  57. data/lib/erlang/etf/extensions/float.rb +0 -18
  58. data/lib/erlang/etf/extensions/hash.rb +0 -30
  59. data/lib/erlang/etf/extensions/integer.rb +0 -46
  60. data/lib/erlang/etf/extensions/nil_class.rb +0 -27
  61. data/lib/erlang/etf/extensions/object.rb +0 -22
  62. data/lib/erlang/etf/extensions/regexp.rb +0 -32
  63. data/lib/erlang/etf/extensions/string.rb +0 -33
  64. data/lib/erlang/etf/extensions/symbol.rb +0 -43
  65. data/lib/erlang/etf/extensions/time.rb +0 -27
  66. data/lib/erlang/etf/extensions/true_class.rb +0 -26
  67. data/lib/erlang/etf/terms.rb +0 -132
  68. data/spec/erlang/etf/atom_spec.rb +0 -90
  69. data/spec/erlang/etf/atom_utf8_spec.rb +0 -90
  70. data/spec/erlang/etf/binary_spec.rb +0 -90
  71. data/spec/erlang/etf/bit_binary_spec.rb +0 -99
  72. data/spec/erlang/etf/compressed_spec.rb +0 -37
  73. data/spec/erlang/etf/export_spec.rb +0 -58
  74. data/spec/erlang/etf/extensions/array_spec.rb +0 -40
  75. data/spec/erlang/etf/extensions/big_decimal_spec.rb +0 -26
  76. data/spec/erlang/etf/extensions/erlang-export_spec.rb +0 -32
  77. data/spec/erlang/etf/extensions/erlang-list_spec.rb +0 -76
  78. data/spec/erlang/etf/extensions/erlang-map_spec.rb +0 -48
  79. data/spec/erlang/etf/extensions/erlang-nil_spec.rb +0 -24
  80. data/spec/erlang/etf/extensions/erlang-pid_spec.rb +0 -33
  81. data/spec/erlang/etf/extensions/erlang-string_spec.rb +0 -41
  82. data/spec/erlang/etf/extensions/erlang-tuple_spec.rb +0 -57
  83. data/spec/erlang/etf/extensions/false_class_spec.rb +0 -29
  84. data/spec/erlang/etf/extensions/float_spec.rb +0 -24
  85. data/spec/erlang/etf/extensions/hash_spec.rb +0 -90
  86. data/spec/erlang/etf/extensions/integer_spec.rb +0 -259
  87. data/spec/erlang/etf/extensions/nil_class_spec.rb +0 -29
  88. data/spec/erlang/etf/extensions/object_spec.rb +0 -30
  89. data/spec/erlang/etf/extensions/regexp_spec.rb +0 -35
  90. data/spec/erlang/etf/extensions/string_spec.rb +0 -43
  91. data/spec/erlang/etf/extensions/symbol_spec.rb +0 -64
  92. data/spec/erlang/etf/extensions/time_spec.rb +0 -32
  93. data/spec/erlang/etf/extensions/true_class_spec.rb +0 -29
  94. data/spec/erlang/etf/float_spec.rb +0 -92
  95. data/spec/erlang/etf/fun_spec.rb +0 -132
  96. data/spec/erlang/etf/integer_spec.rb +0 -57
  97. data/spec/erlang/etf/large_big_spec.rb +0 -67
  98. data/spec/erlang/etf/large_tuple_spec.rb +0 -119
  99. data/spec/erlang/etf/list_spec.rb +0 -159
  100. data/spec/erlang/etf/map_spec.rb +0 -100
  101. data/spec/erlang/etf/new_float_spec.rb +0 -92
  102. data/spec/erlang/etf/new_fun_spec.rb +0 -146
  103. data/spec/erlang/etf/new_reference_spec.rb +0 -60
  104. data/spec/erlang/etf/nil_spec.rb +0 -50
  105. data/spec/erlang/etf/pid_spec.rb +0 -61
  106. data/spec/erlang/etf/port_spec.rb +0 -58
  107. data/spec/erlang/etf/reference_spec.rb +0 -58
  108. data/spec/erlang/etf/small_atom_spec.rb +0 -90
  109. data/spec/erlang/etf/small_atom_utf8_spec.rb +0 -90
  110. data/spec/erlang/etf/small_big_spec.rb +0 -67
  111. data/spec/erlang/etf/small_integer_spec.rb +0 -57
  112. data/spec/erlang/etf/small_tuple_spec.rb +0 -112
  113. data/spec/erlang/etf/string_spec.rb +0 -92
  114. data/spec/erlang/etf/term_spec.rb +0 -27
  115. data/spec/erlang/etf/terms_spec.rb +0 -23
  116. data/spec/erlang/etf_spec.rb +0 -23
  117. data/spec/erlang_spec.rb +0 -95
  118. data/spec/spec_helper.rb +0 -31
@@ -2,9 +2,9 @@ module Erlang
2
2
  module ETF
3
3
 
4
4
  #
5
- # 1 | N1 | N2 | N3
6
- # --- | ------ | -------- | -----
7
- # 113 | Module | Function | Arity
5
+ # | 1 | N1 | N2 | N3 |
6
+ # | --- | ------ | -------- | ----- |
7
+ # | 113 | Module | Function | Arity |
8
8
  #
9
9
  # This term is the encoding for external funs: `fun M:F/A`.
10
10
  #
@@ -22,31 +22,54 @@ module Erlang
22
22
  # [`EXPORT_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#EXPORT_EXT
23
23
  #
24
24
  class Export
25
- include Term
25
+ include Erlang::ETF::Term
26
26
 
27
- uint8 :tag, always: Terms::EXPORT_EXT
27
+ class << self
28
+ def [](term, mod = nil, function = nil, arity = nil)
29
+ return new(term, mod, function, arity)
30
+ end
28
31
 
29
- term :mod # atom, small_atom
30
-
31
- term :function # atom, small_atom
32
+ def erlang_load(buffer)
33
+ mod = Erlang::ETF.read_term(buffer)
34
+ function = Erlang::ETF.read_term(buffer)
35
+ arity = Erlang::ETF.read_term(buffer)
36
+ term = Erlang::Export[Erlang.from(mod), Erlang.from(function), Erlang.from(arity)]
37
+ return new(term, mod, function, arity)
38
+ end
39
+ end
32
40
 
33
- term :arity # small_integer
41
+ def initialize(term, mod = nil, function = nil, arity = nil)
42
+ raise ArgumentError, "term must be of type Erlang::Export" if not term.kind_of?(Erlang::Export)
43
+ @term = term
44
+ @mod = mod
45
+ @function = function
46
+ @arity = arity
47
+ end
34
48
 
35
- finalize
49
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
50
+ buffer << EXPORT_EXT
51
+ Erlang::ETF.write_term(@mod || @term.mod, buffer)
52
+ Erlang::ETF.write_term(@function || @term.function, buffer)
53
+ Erlang::ETF.write_term(@arity || @term.arity, buffer)
54
+ return buffer
55
+ end
36
56
 
37
- def initialize(mod, function, arity)
38
- self.mod = mod
39
- self.function = function
40
- self.arity = arity
57
+ def inspect
58
+ if @mod.nil? and @function.nil? and @arity.nil?
59
+ return super
60
+ else
61
+ return "#{self.class}[#{@term.inspect}, #{@mod.inspect}, #{@function.inspect}, #{@arity.inspect}]"
62
+ end
41
63
  end
42
64
 
43
- def __ruby_evolve__
44
- ::Erlang::Export.new(
45
- mod.__ruby_evolve__,
46
- function.__ruby_evolve__,
47
- arity.__ruby_evolve__
48
- )
65
+ def pretty_print(pp)
66
+ state = [@term]
67
+ state.push(@mod, @function, @arity) if not @mod.nil? or not @function.nil? or not @arity.nil?
68
+ return pp.group(1, "#{self.class}[", "]") do
69
+ pp.breakable ''
70
+ pp.seplist(state) { |obj| obj.pretty_print(pp) }
71
+ end
49
72
  end
50
73
  end
51
74
  end
52
- end
75
+ end
@@ -1,12 +1,10 @@
1
- require 'bigdecimal'
2
-
3
1
  module Erlang
4
2
  module ETF
5
3
 
6
4
  #
7
- # 1 | 31
8
- # --- | ------------
9
- # 99 | Float String
5
+ # | 1 | 31 |
6
+ # | --- | ------------ |
7
+ # | 99 | Float String |
10
8
  #
11
9
  # A float is stored in string format. the format used in sprintf
12
10
  # to format the float is "%.20e" (there are more bytes allocated
@@ -22,41 +20,47 @@ module Erlang
22
20
  # [`FLOAT_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#FLOAT_EXT
23
21
  #
24
22
  class Float
25
- include Term
26
-
27
- FLOAT_STRING_FORMAT = "%.20e".freeze
28
-
29
- uint8 :tag, always: Terms::FLOAT_EXT
23
+ include Erlang::ETF::Term
30
24
 
31
- string :float_string
25
+ class << self
26
+ def [](term, float_string = nil)
27
+ return term if term.kind_of?(Erlang::ETF::Term)
28
+ term = Erlang.from(term)
29
+ return new(term, float_string)
30
+ end
32
31
 
33
- undef serialize_float_string
34
- def serialize_float_string(buffer)
35
- if float_string.is_a?(::BigDecimal)
36
- buffer << (FLOAT_STRING_FORMAT % float_string).ljust(31, "\000")
37
- else
38
- buffer << float_string
32
+ def erlang_load(buffer)
33
+ float_string = buffer.read(31)
34
+ term = Erlang::Float[float_string.byteslice(0, float_string.index("\0")), old: true]
35
+ return new(term, float_string)
39
36
  end
40
37
  end
41
38
 
42
- undef deserialize_float_string
43
- def deserialize_float_string(buffer)
44
- self.float_string = buffer.read(31)
39
+ def initialize(term, float_string = nil)
40
+ raise ArgumentError, "term must be of type Erlang::Float" if not Erlang.is_float(term) or not term.old
41
+ @term = term
42
+ @float_string = float_string
45
43
  end
46
44
 
47
- finalize
48
-
49
- def initialize(float_string)
50
- @float_string = float_string
45
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
46
+ buffer << FLOAT_EXT
47
+ buffer << (@float_string || to_float_string)
48
+ return buffer
51
49
  end
52
50
 
53
- def __ruby_evolve__
54
- if float_string.is_a?(::BigDecimal)
55
- float_string
51
+ def inspect
52
+ if @float_string.nil?
53
+ return "#{self.class}[#{@term.inspect}]"
56
54
  else
57
- ::BigDecimal.new(float_string.gsub("\000", ""))
55
+ return "#{self.class}[#{@term.inspect}, #{@float_string.inspect}]"
58
56
  end
59
57
  end
58
+
59
+ private
60
+ def to_float_string
61
+ return @term.to_float_string.ljust(31, "\0")
62
+ end
63
+
60
64
  end
61
65
  end
62
- end
66
+ end
@@ -2,9 +2,9 @@ module Erlang
2
2
  module ETF
3
3
 
4
4
  #
5
- # 1 | 4 | N1 | N2 | N3 | N4 | N5
6
- # --- | ------- | --- | ------ | ----- | ---- | -------------
7
- # 117 | NumFree | Pid | Module | Index | Uniq | Free vars ...
5
+ # | 1 | 4 | N1 | N2 | N3 | N4 | N5 |
6
+ # | --- | ------- | --- | ------ | ----- | ---- | ------------- |
7
+ # | 117 | NumFree | Pid | Module | Index | Uniq | Free vars ... |
8
8
  #
9
9
  # `Pid`
10
10
  # > is a process identifier as in [`PID_EXT`]. It represents the
@@ -38,44 +38,66 @@ module Erlang
38
38
  # [`FUN_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#FUN_EXT
39
39
  #
40
40
  class Fun
41
- include Term
41
+ include Erlang::ETF::Term
42
42
 
43
- uint8 :tag, always: Terms::FUN_EXT
43
+ UINT32BE = Erlang::ETF::Term::UINT32BE
44
44
 
45
- uint16be :num_free, always: -> { free_vars.size }
46
-
47
- term :pid # pid
48
-
49
- term :mod # atom, small_atom
45
+ class << self
46
+ def [](term, pid = nil, mod = nil, index = nil, uniq = nil, free_vars = nil)
47
+ return new(term, pid, mod, index, uniq, free_vars)
48
+ end
50
49
 
51
- term :index # small_integer, integer
50
+ def erlang_load(buffer)
51
+ num_free, = buffer.read(4).unpack(UINT32BE)
52
+ pid = Erlang::ETF.read_term(buffer)
53
+ mod = Erlang::ETF.read_term(buffer)
54
+ index = Erlang::ETF.read_term(buffer)
55
+ uniq = Erlang::ETF.read_term(buffer)
56
+ free_vars = Array.new(num_free); num_free.times { |i| free_vars[i] = Erlang::ETF.read_term(buffer) }
57
+ term = Erlang::Function[pid: Erlang.from(pid), mod: Erlang.from(mod), index: Erlang.from(index), uniq: Erlang.from(uniq), free_vars: Erlang.from(free_vars)]
58
+ return new(term, pid, mod, index, uniq, free_vars)
59
+ end
60
+ end
52
61
 
53
- term :uniq # small_integer, integer
62
+ def initialize(term, pid = nil, mod = nil, index = nil, uniq = nil, free_vars = nil)
63
+ raise ArgumentError, "term must be of type Erlang::Function" if not term.kind_of?(Erlang::Function) or term.new_function?
64
+ @term = term
65
+ @pid = pid
66
+ @mod = mod
67
+ @index = index
68
+ @uniq = uniq
69
+ @free_vars = free_vars
70
+ end
54
71
 
55
- term :free_vars, type: :array
72
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
73
+ buffer << FUN_EXT
74
+ free_vars = @free_vars || @term.free_vars
75
+ num_free = free_vars.length
76
+ buffer << [num_free].pack(UINT32BE)
77
+ Erlang::ETF.write_term(@pid || @term.pid, buffer)
78
+ Erlang::ETF.write_term(@mod || @term.mod, buffer)
79
+ Erlang::ETF.write_term(@index || @term.index, buffer)
80
+ Erlang::ETF.write_term(@uniq || @term.uniq, buffer)
81
+ num_free.times { |i| Erlang::ETF.write_term(free_vars[i], buffer) }
82
+ return buffer
83
+ end
56
84
 
57
- deserialize do |buffer|
58
- num_free, = buffer.read(BYTES_16).unpack(UINT16BE_PACK)
59
- deserialize_pid(buffer)
60
- deserialize_mod(buffer)
61
- deserialize_index(buffer)
62
- deserialize_uniq(buffer)
63
- self.free_vars = []
64
- num_free.times do
65
- self.free_vars << Terms.deserialize(buffer)
85
+ def inspect
86
+ if @pid.nil? and @mod.nil? and @index.nil? and @uniq.nil? and @free_vars.nil?
87
+ return super
88
+ else
89
+ return "#{self.class}[#{@term.inspect}, #{@pid.inspect}, #{@mod.inspect}, #{@index.inspect}, #{@uniq.inspect}, #{@free_vars.inspect}]"
66
90
  end
67
- self
68
91
  end
69
92
 
70
- finalize
71
-
72
- def initialize(pid, mod, index, uniq, free_vars = [])
73
- self.pid = pid
74
- self.mod = mod
75
- self.index = index
76
- self.uniq = uniq
77
- self.free_vars = free_vars
93
+ def pretty_print(pp)
94
+ state = [@term]
95
+ state.push(@pid, @mod, @index, @uniq, @free_vars) if not @pid.nil? or not @mod.nil? or not @index.nil? or not @uniq.nil? or not @free_vars.nil?
96
+ return pp.group(1, "#{self.class}[", "]") do
97
+ pp.breakable ''
98
+ pp.seplist(state) { |obj| obj.pretty_print(pp) }
99
+ end
78
100
  end
79
101
  end
80
102
  end
81
- end
103
+ end
@@ -2,9 +2,9 @@ module Erlang
2
2
  module ETF
3
3
 
4
4
  #
5
- # 1 | 4
6
- # --- | ---
7
- # 98 | Int
5
+ # | 1 | 4 |
6
+ # | --- | --- |
7
+ # | 98 | Int |
8
8
  #
9
9
  # Signed 32 bit integer in big-endian format (i.e. MSB first)
10
10
  #
@@ -13,21 +13,33 @@ module Erlang
13
13
  # [`INTEGER_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#INTEGER_EXT
14
14
  #
15
15
  class Integer
16
- include Term
16
+ include Erlang::ETF::Term
17
17
 
18
- uint8 :tag, always: Terms::INTEGER_EXT
18
+ INT32BE = Erlang::ETF::Term::INT32BE
19
19
 
20
- int32be :int
20
+ class << self
21
+ def [](term)
22
+ return term if term.kind_of?(Erlang::ETF::Term)
23
+ term = Erlang.from(term)
24
+ return new(term)
25
+ end
21
26
 
22
- finalize
27
+ def erlang_load(buffer)
28
+ integer, = buffer.read(4).unpack(INT32BE)
29
+ return new(integer)
30
+ end
31
+ end
23
32
 
24
- def initialize(int)
25
- @int = int
33
+ def initialize(term)
34
+ raise ArgumentError, "term must be of type Integer" if not Erlang.is_integer(term)
35
+ @term = term
26
36
  end
27
37
 
28
- def __ruby_evolve__
29
- int
38
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
39
+ buffer << INTEGER_EXT
40
+ buffer << [@term].pack(INT32BE)
41
+ return buffer
30
42
  end
31
43
  end
32
44
  end
33
- end
45
+ end
@@ -2,9 +2,9 @@ module Erlang
2
2
  module ETF
3
3
 
4
4
  #
5
- # 1 | 4 | 1 | n
6
- # --- | --- | ---- | ---------------
7
- # 111 | n | Sign | d(0) ... d(n-1)
5
+ # | 1 | 4 | 1 | n |
6
+ # | --- | --- | ---- | --------------- |
7
+ # | 111 | n | Sign | d(0) ... d(n-1) |
8
8
  #
9
9
  # Same as [`SMALL_BIG_EXT`] with the difference that the length
10
10
  # field is an unsigned 4 byte integer.
@@ -15,44 +15,38 @@ module Erlang
15
15
  # [`LARGE_BIG_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#LARGE_BIG_EXT
16
16
  #
17
17
  class LargeBig
18
- include Term
19
-
20
- uint8 :tag, always: Terms::LARGE_BIG_EXT
21
-
22
- uint32be :n, default: 0 do
23
- uint8 :sign, always: -> { (integer >= 0) ? 0 : 1 }
24
- string :integer
18
+ include Erlang::ETF::Term
19
+
20
+ UINT8 = Erlang::ETF::Term::UINT8
21
+ UINT32BE = Erlang::ETF::Term::UINT32BE
22
+ HEAD = (UINT32BE + UINT8).freeze
23
+
24
+ class << self
25
+ def [](term)
26
+ return term if term.kind_of?(Erlang::ETF::Term)
27
+ term = Erlang.from(term)
28
+ return new(term)
29
+ end
30
+
31
+ def erlang_load(buffer)
32
+ n, sign, = buffer.read(5).unpack(HEAD)
33
+ integer = Erlang::Binary.decode_unsigned(buffer.read(n), :little)
34
+ integer = -integer if sign == 1
35
+ return new(integer)
36
+ end
25
37
  end
26
38
 
27
- undef serialize_integer
28
- def serialize_integer(buffer)
29
- start = buffer.bytesize
30
- buffer << [integer.abs.to_s(2).reverse!].pack(BIN_LSB_PACK)
31
- self.n = buffer.bytesize - start
32
- buffer
33
- end
34
-
35
- undef after_serialize_n
36
- def after_serialize_n(buffer)
37
- buffer[@n_start, BYTES_32] = serialize_n ""
38
- end
39
-
40
- deserialize do |buffer|
41
- deserialize_n(buffer)
42
- sign, = buffer.read(BYTES_8).unpack(UINT8_PACK)
43
- self.integer = buffer.read(n).unpack(BIN_LSB_PACK).at(0).reverse!.to_i(2) * ((sign == 0) ? 1 : -1)
44
- self
45
- end
46
-
47
- finalize
48
-
49
- def initialize(integer)
50
- @integer = integer
39
+ def initialize(term)
40
+ raise ArgumentError, "term must be of type Integer" if not Erlang.is_integer(term)
41
+ @term = term
51
42
  end
52
43
 
53
- def __ruby_evolve__
54
- integer
44
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
45
+ buffer << LARGE_BIG_EXT
46
+ buffer << [Erlang::ETF.intlog2div8(@term), (@term < 0) ? 1 : 0].pack(HEAD)
47
+ buffer << Erlang::Binary.encode_unsigned(@term.abs, :little)
48
+ return buffer
55
49
  end
56
50
  end
57
51
  end
58
- end
52
+ end
@@ -2,9 +2,9 @@ module Erlang
2
2
  module ETF
3
3
 
4
4
  #
5
- # 1 | 4 | N
6
- # --- | ----- | --------
7
- # 105 | Arity | Elements
5
+ # | 1 | 4 | N |
6
+ # | --- | ----- | -------- |
7
+ # | 105 | Arity | Elements |
8
8
  #
9
9
  # Same as [`SMALL_TUPLE_EXT`] with the exception that `Arity` is an
10
10
  # unsigned 4 byte integer in big endian format.
@@ -15,46 +15,57 @@ module Erlang
15
15
  # [`LARGE_TUPLE_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#LARGE_TUPLE_EXT
16
16
  #
17
17
  class LargeTuple
18
- include Term
18
+ include Erlang::ETF::Term
19
19
 
20
- uint8 :tag, always: Terms::LARGE_TUPLE_EXT
20
+ UINT32BE = Erlang::ETF::Term::UINT32BE
21
21
 
22
- uint32be :arity, always: -> { elements.size }
23
-
24
- term :elements, type: :array
22
+ class << self
23
+ def [](term, elements = nil)
24
+ return term if term.kind_of?(Erlang::ETF::Term)
25
+ term = Erlang.from(term)
26
+ return new(term, elements)
27
+ end
25
28
 
26
- deserialize do |buffer|
27
- arity, = buffer.read(BYTES_32).unpack(UINT32BE_PACK)
28
- self.elements = []
29
- arity.times do
30
- self.elements << Terms.deserialize(buffer)
29
+ def erlang_load(buffer)
30
+ arity, = buffer.read(4).unpack(UINT32BE)
31
+ elements = Array.new(arity)
32
+ arity.times { |i| elements[i] = Erlang::ETF.read_term(buffer) }
33
+ tuple = Erlang::Tuple[*elements]
34
+ return new(tuple, elements)
31
35
  end
32
- self
33
36
  end
34
37
 
35
- finalize
36
-
37
- def initialize(elements)
38
- @elements = elements
38
+ def initialize(term, elements = nil)
39
+ raise ArgumentError, "term must be of type Tuple" if not Erlang.is_tuple(term)
40
+ @term = term
41
+ @elements = elements.freeze
39
42
  end
40
43
 
41
- def serialize_header(buffer)
42
- serialize_tag(buffer)
43
- serialize_arity(buffer)
44
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
45
+ buffer << LARGE_TUPLE_EXT
46
+ elements = @elements || @term
47
+ arity = elements.size
48
+ buffer << [arity].pack(UINT32BE)
49
+ elements.each { |element| Erlang::ETF.write_term(element, buffer) }
50
+ return buffer
44
51
  end
45
52
 
46
- def bert?
47
- elements[0].respond_to?(:atom_name) &&
48
- elements[0].atom_name == BERT_PREFIX
53
+ def inspect
54
+ if @elements.nil?
55
+ return super
56
+ else
57
+ return "#{self.class}[#{@term.inspect}, #{@elements.inspect}]"
58
+ end
49
59
  end
50
60
 
51
- def __ruby_evolve__
52
- if bert?
53
- ::Erlang::ETF::BERT.evolve(self)
54
- else
55
- ::Erlang::Tuple[*elements.map(&:__ruby_evolve__)]
61
+ def pretty_print(pp)
62
+ state = [@term]
63
+ state.push(@elements) if not @elements.nil?
64
+ return pp.group(1, "#{self.class}[", "]") do
65
+ pp.breakable ''
66
+ pp.seplist(state) { |obj| obj.pretty_print(pp) }
56
67
  end
57
68
  end
58
69
  end
59
70
  end
60
- end
71
+ end