erlang-etf 1.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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