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 | 4 | Len | N1
6
- # --- | --- | -------- | ----
7
- # 108 | Len | Elements | Tail
5
+ # | 1 | 4 | | |
6
+ # | --- | ------ | -------- | ---- |
7
+ # | 108 | Length | Elements | Tail |
8
8
  #
9
9
  # `Length` is the number of elements that follows in the `Elements`
10
10
  # section. `Tail` is the final tail of the list; it is [`NIL_EXT`] for a
@@ -17,39 +17,69 @@ module Erlang
17
17
  # [`LIST_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#LIST_EXT
18
18
  #
19
19
  class List
20
- include Term
20
+ include Erlang::ETF::Term
21
21
 
22
- uint8 :tag, always: Terms::LIST_EXT
22
+ UINT32BE = Erlang::ETF::Term::UINT32BE
23
23
 
24
- uint32be :len, always: -> { elements.size }
25
-
26
- term :elements, type: :array, allow_char: true
27
- term :tail
24
+ class << self
25
+ def [](term, elements = nil, tail = nil)
26
+ return term if term.kind_of?(Erlang::ETF::Term)
27
+ term = Erlang.from(term)
28
+ return new(term, elements, tail)
29
+ end
28
30
 
29
- deserialize do |buffer|
30
- len, = buffer.read(BYTES_32).unpack(UINT32BE_PACK)
31
- self.elements = []
32
- len.times do
33
- self.elements << Terms.deserialize(buffer)
31
+ def erlang_load(buffer)
32
+ length, = buffer.read(4).unpack(UINT32BE)
33
+ elements = Array.new(length)
34
+ length.times { |i| elements[i] = Erlang::ETF.read_term(buffer) }
35
+ tail = Erlang::ETF.read_term(buffer)
36
+ return tail if length == 0
37
+ list = Erlang::List.from_enum(elements) + tail
38
+ return new(list, elements, tail)
34
39
  end
35
- deserialize_tail(buffer)
36
- self
37
40
  end
38
41
 
39
- finalize
42
+ def initialize(term, elements = nil, tail = nil)
43
+ raise ArgumentError, "term must be of any type" if not Erlang.is_any(term)
44
+ @term = term
45
+ @elements = elements.freeze
46
+ @tail = tail.freeze
47
+ end
40
48
 
41
- def initialize(elements, tail = Nil.new)
42
- @elements = elements
43
- @tail = tail
49
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
50
+ buffer << LIST_EXT
51
+ elements = nil
52
+ tail = nil
53
+ if not Erlang.is_list(term)
54
+ elements = @elements || []
55
+ tail = @tail || @term
56
+ else
57
+ elements = @elements || (@term.improper? ? @term.to_proper_list : @term)
58
+ tail = @tail || (@term.improper? ? @term.last(true) : Erlang::Nil)
59
+ end
60
+ length = elements.size
61
+ buffer << [length].pack(UINT32BE)
62
+ elements.each { |element| Erlang::ETF.write_term(element, buffer) }
63
+ Erlang::ETF.write_term(tail, buffer)
64
+ return buffer
44
65
  end
45
66
 
46
- def improper?
47
- tail.class != ETF::Nil
67
+ def inspect
68
+ if @elements.nil? and @tail.nil?
69
+ return super
70
+ else
71
+ return "#{self.class}[#{@term.inspect}, #{@elements.inspect}, #{@tail.inspect}]"
72
+ end
48
73
  end
49
74
 
50
- def __ruby_evolve__
51
- ::Erlang::List[*elements.map(&:__ruby_evolve__)].tail(tail.__ruby_evolve__)
75
+ def pretty_print(pp)
76
+ state = [@term]
77
+ state.push(@elements, @tail) if not @elements.nil? or not @tail.nil?
78
+ return pp.group(1, "#{self.class}[", "]") do
79
+ pp.breakable ''
80
+ pp.seplist(state) { |obj| obj.pretty_print(pp) }
81
+ end
52
82
  end
53
83
  end
54
84
  end
55
- end
85
+ end
@@ -2,50 +2,80 @@ module Erlang
2
2
  module ETF
3
3
 
4
4
  #
5
- # 1 | 4 | N | N
6
- # --- | ---- | ---- | ------
7
- # 116 | Size | Keys | Values
5
+ # | 1 | 4 | N |
6
+ # | --- | ----- | ----- |
7
+ # | 116 | Arity | Pairs |
8
8
  #
9
- # The Size specifies the number of keys and values that
10
- # follows the size descriptor.
9
+ # `MAP_EXT` encodes a map. The `Arity` field is an unsigned 4 byte integer
10
+ # in big endian format that determines the number of key-value pairs in the
11
+ # map. Key and value pairs (`Ki => Vi`) are encoded in the `Pairs` section
12
+ # in the following order: `K1, V1, K2, V2,..., Kn, Vn`. Duplicate keys are
13
+ # **not allowed** within the same map.
11
14
  #
12
15
  # (see [`MAP_EXT`])
13
16
  #
14
17
  # [`MAP_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#MAP_EXT
15
18
  #
16
19
  class Map
17
- include Term
20
+ include Erlang::ETF::Term
18
21
 
19
- uint8 :tag, always: Terms::MAP_EXT
22
+ UINT32BE = Erlang::ETF::Term::UINT32BE
20
23
 
21
- uint32be :size, always: -> { keys.size }
22
-
23
- term :keys, type: :array
24
- term :values, type: :array
25
-
26
- deserialize do |buffer|
27
- size, = buffer.read(BYTES_32).unpack(UINT32BE_PACK)
28
- self.keys = []
29
- size.times do
30
- self.keys << Terms.deserialize(buffer)
24
+ class << self
25
+ def [](term, pairs = nil)
26
+ return term if term.kind_of?(Erlang::ETF::Term)
27
+ term = Erlang.from(term)
28
+ return new(term, pairs)
31
29
  end
32
- self.values = []
33
- size.times do
34
- self.values << Terms.deserialize(buffer)
30
+
31
+ def erlang_load(buffer)
32
+ arity, = buffer.read(4).unpack(UINT32BE)
33
+ pairs = Array.new(arity * 2)
34
+ (arity * 2).times { |i| pairs[i] = Erlang::ETF.read_term(buffer) }
35
+ map = Erlang::Map[*pairs]
36
+ return new(map, pairs)
35
37
  end
36
- self
37
38
  end
38
39
 
39
- finalize
40
+ def initialize(term, pairs = nil)
41
+ raise ArgumentError, "term must be of type Map" if not Erlang.is_map(term)
42
+ @term = term
43
+ @pairs = pairs.freeze
44
+ end
40
45
 
41
- def initialize(keys, values)
42
- @keys = keys
43
- @values = values
46
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
47
+ buffer << MAP_EXT
48
+ if @pairs
49
+ arity = @pairs.length.div(2)
50
+ buffer << [arity].pack(UINT32BE)
51
+ (arity * 2).times { |i| Erlang::ETF.write_term(@pairs[i], buffer) }
52
+ else
53
+ arity = @term.size
54
+ buffer << [arity].pack(UINT32BE)
55
+ @term.sort.each { |key, val|
56
+ Erlang::ETF.write_term(key, buffer)
57
+ Erlang::ETF.write_term(val, buffer)
58
+ }
59
+ end
60
+ return buffer
44
61
  end
45
62
 
46
- def __ruby_evolve__
47
- ::Erlang::Map[keys.map(&:__ruby_evolve__).zip(values.map(&:__ruby_evolve__))]
63
+ def inspect
64
+ if @pairs.nil?
65
+ return super
66
+ else
67
+ return "#{self.class}[#{@term.inspect}, #{@pairs.inspect}]"
68
+ end
69
+ end
70
+
71
+ def pretty_print(pp)
72
+ state = [@term]
73
+ state.push(@pairs) if not @pairs.nil?
74
+ return pp.group(1, "#{self.class}[", "]") do
75
+ pp.breakable ''
76
+ pp.seplist(state) { |obj| obj.pretty_print(pp) }
77
+ end
48
78
  end
49
79
  end
50
80
  end
51
- end
81
+ end
@@ -1,12 +1,10 @@
1
- require 'bigdecimal'
2
-
3
1
  module Erlang
4
2
  module ETF
5
3
 
6
4
  #
7
- # 1 | 8
8
- # --- | ----------
9
- # 70 | IEEE Float
5
+ # | 1 | 8 |
6
+ # | --- | ---------- |
7
+ # | 70 | IEEE Float |
10
8
  #
11
9
  # A float is stored as 8 bytes in big-endian IEEE format.
12
10
  #
@@ -17,21 +15,34 @@ module Erlang
17
15
  # [`NEW_FLOAT_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#NEW_FLOAT_EXT
18
16
  #
19
17
  class NewFloat
20
- include Term
18
+ include Erlang::ETF::Term
21
19
 
22
- uint8 :tag, always: Terms::NEW_FLOAT_EXT
20
+ DOUBLEBE = Erlang::ETF::Term::DOUBLEBE
23
21
 
24
- doublebe :float
22
+ class << self
23
+ def [](term)
24
+ return term if term.kind_of?(Erlang::ETF::Term)
25
+ term = Erlang.from(term)
26
+ return new(term)
27
+ end
25
28
 
26
- finalize
29
+ def erlang_load(buffer)
30
+ float, = buffer.read(8).unpack(DOUBLEBE)
31
+ term = Erlang::Float[float]
32
+ return new(term)
33
+ end
34
+ end
27
35
 
28
- def initialize(float)
29
- @float = float
36
+ def initialize(term)
37
+ raise ArgumentError, "term must be of type Erlang::Float" if not Erlang.is_float(term) or term.old
38
+ @term = term
30
39
  end
31
40
 
32
- def __ruby_evolve__
33
- float
41
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
42
+ buffer << NEW_FLOAT_EXT
43
+ buffer << [@term.data].pack(DOUBLEBE)
44
+ return buffer
34
45
  end
35
46
  end
36
47
  end
37
- end
48
+ end
@@ -2,9 +2,9 @@ module Erlang
2
2
  module ETF
3
3
 
4
4
  #
5
- # 1 | 4 | 1 | 16 | 4 | 4 | N1 | N2 | N3 | N4 | N5
6
- # --- | ---- | ----- | ---- | ----- | ------- | ------ | -------- | ------- | --- | ---------
7
- # 112 | Size | Arity | Uniq | Index | NumFree | Module | Oldindex | OldUniq | Pid | Free Vars
5
+ # | 1 | 4 | 1 | 16 | 4 | 4 | N1 | N2 | N3 | N4 | N5 |
6
+ # | --- | ---- | ----- | ---- | ----- | ------- | ------ | -------- | ------- | --- | --------- |
7
+ # | 112 | Size | Arity | Uniq | Index | NumFree | Module | Oldindex | OldUniq | Pid | Free Vars |
8
8
  #
9
9
  # This is the new encoding of internal funs:
10
10
  #
@@ -60,61 +60,84 @@ module Erlang
60
60
  # [`NEW_FUN_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#NEW_FUN_EXT
61
61
  #
62
62
  class NewFun
63
- include Term
63
+ include Erlang::ETF::Term
64
64
 
65
- uint8 :tag, always: Terms::NEW_FUN_EXT
65
+ UINT8 = Erlang::ETF::Term::UINT8
66
+ UINT32BE = Erlang::ETF::Term::UINT32BE
67
+ UINT128BE = Erlang::ETF::Term::UINT128BE
68
+ HEAD = (UINT32BE + UINT8 + UINT128BE + UINT32BE + UINT32BE).freeze
66
69
 
67
- uint32be :size, default: 0, inclusive: true do
68
- uint8 :arity
69
- string :uniq
70
- uint32be :index
71
- uint32be :num_free, always: -> { free_vars.size }
72
- term :mod
73
- term :old_index
74
- term :old_uniq
75
- term :pid
76
- term :free_vars, type: :array
70
+ class << self
71
+ def [](term, arity = nil, uniq = nil, index = nil, mod = nil, old_index = nil, old_uniq = nil, pid = nil, free_vars = nil)
72
+ return new(term, arity, uniq, index, mod, old_index, old_uniq, pid, free_vars)
73
+ end
74
+
75
+ def erlang_load(buffer)
76
+ _, arity, uniq_hi, uniq_lo, index, num_free = buffer.read(29).unpack(HEAD)
77
+ uniq = (uniq_hi << 64) + uniq_lo
78
+ mod = Erlang::ETF.read_term(buffer)
79
+ old_index = Erlang::ETF.read_term(buffer)
80
+ old_uniq = Erlang::ETF.read_term(buffer)
81
+ pid = Erlang::ETF.read_term(buffer)
82
+ free_vars = Array.new(num_free); num_free.times { |i| free_vars[i] = Erlang::ETF.read_term(buffer) }
83
+ term = Erlang::Function[arity: Erlang.from(arity), uniq: Erlang.from(uniq), index: Erlang.from(index), mod: Erlang.from(mod), old_index: Erlang.from(old_index), old_uniq: Erlang.from(old_uniq), pid: Erlang.from(pid), free_vars: Erlang.from(free_vars)]
84
+ return new(term, arity, uniq, index, mod, old_index, old_uniq, pid, free_vars)
85
+ end
77
86
  end
78
87
 
79
- undef deserialize_uniq
80
- def deserialize_uniq(buffer)
81
- self.uniq = buffer.read(16).unpack(UINT8_PACK + '*')
88
+ def initialize(term, arity = nil, uniq = nil, index = nil, mod = nil, old_index = nil, old_uniq = nil, pid = nil, free_vars = nil)
89
+ raise ArgumentError, "term must be of type Erlang::Function" if not term.kind_of?(Erlang::Function) or not term.new_function?
90
+ @term = term
91
+ @arity = arity
92
+ @uniq = uniq
93
+ @index = index
94
+ @mod = mod
95
+ @old_index = old_index
96
+ @old_uniq = old_uniq
97
+ @pid = pid
98
+ @free_vars = free_vars
82
99
  end
83
100
 
84
- undef serialize_uniq
85
- def serialize_uniq(buffer)
86
- buffer << uniq.pack(UINT8_PACK + '*')
101
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
102
+ buffer << NEW_FUN_EXT
103
+ size = 0
104
+ arity = @arity || @term.arity
105
+ uniq = @uniq || @term.uniq
106
+ index = @index || @term.index
107
+ free_vars = @free_vars || @term.free_vars
108
+ num_free = free_vars.length
109
+ sizestart = buffer.bytesize
110
+ buffer << [size, arity, uniq >> 64, uniq, index, num_free].pack(HEAD)
111
+ Erlang::ETF.write_term(@mod || @term.mod, buffer)
112
+ Erlang::ETF.write_term(@old_index || @term.old_index, buffer)
113
+ Erlang::ETF.write_term(@old_uniq || @term.old_uniq, buffer)
114
+ Erlang::ETF.write_term(@pid || @term.pid, buffer)
115
+ num_free.times { |i| Erlang::ETF.write_term(free_vars[i], buffer) }
116
+ sizeend = buffer.bytesize
117
+ size = sizeend - sizestart
118
+ buffer.setbyte(sizestart + 0, size >> 24)
119
+ buffer.setbyte(sizestart + 1, size >> 16)
120
+ buffer.setbyte(sizestart + 2, size >> 8)
121
+ buffer.setbyte(sizestart + 3, size)
122
+ return buffer
87
123
  end
88
124
 
89
- deserialize do |buffer|
90
- deserialize_size(buffer)
91
- deserialize_arity(buffer)
92
- deserialize_uniq(buffer)
93
- deserialize_index(buffer)
94
- num_free, = buffer.read(BYTES_32).unpack(UINT32BE_PACK)
95
- deserialize_mod(buffer)
96
- deserialize_old_index(buffer)
97
- deserialize_old_uniq(buffer)
98
- deserialize_pid(buffer)
99
- self.free_vars = []
100
- num_free.times do
101
- self.free_vars << Terms.deserialize(buffer)
125
+ def inspect
126
+ if @arity.nil? and @uniq.nil? and @index.nil? and @mod.nil? and @old_index.nil? and @old_uniq.nil? and @pid.nil? and @free_vars.nil?
127
+ return super
128
+ else
129
+ return "#{self.class}[#{@term.inspect}, #{@arity.inspect}, #{@uniq.inspect}, #{@index.inspect}, #{@mod.inspect}, #{@old_index.inspect}, #{@old_uniq.inspect}, #{@pid.inspect}, #{@free_vars.inspect}]"
102
130
  end
103
- self
104
131
  end
105
132
 
106
- finalize
107
-
108
- def initialize(arity, uniq, index, mod, old_index, old_uniq, pid, free_vars = [])
109
- self.arity = arity
110
- self.uniq = uniq
111
- self.index = index
112
- self.mod = mod
113
- self.old_index = old_index
114
- self.old_uniq = old_uniq
115
- self.pid = pid
116
- self.free_vars = free_vars
133
+ def pretty_print(pp)
134
+ state = [@term]
135
+ state.push(@arity, @uniq, @index, @mod, @old_index, @old_uniq, @pid, @free_vars) if not @arity.nil? or not @uniq.nil? or not @index.nil? or not @mod.nil? or not @old_index.nil? or not @old_uniq.nil? or not @pid.nil? or not @free_vars.nil?
136
+ return pp.group(1, "#{self.class}[", "]") do
137
+ pp.breakable ''
138
+ pp.seplist(state) { |obj| obj.pretty_print(pp) }
139
+ end
117
140
  end
118
141
  end
119
142
  end
120
- end
143
+ end
@@ -2,9 +2,9 @@ module Erlang
2
2
  module ETF
3
3
 
4
4
  #
5
- # 1 | 2 | N | 1 | N'
6
- # --- | --- | ---- | -------- | ------
7
- # 114 | Len | Node | Creation | ID ...
5
+ # | 1 | 2 | N | 1 | N' |
6
+ # | --- | --- | ---- | -------- | ------ |
7
+ # | 114 | Len | Node | Creation | ID ... |
8
8
  #
9
9
  # `Node` and `Creation` are as in [`REFERENCE_EXT`].
10
10
  #
@@ -29,36 +29,63 @@ module Erlang
29
29
  # [`NEW_REFERENCE_EXT`]: http://erlang.org/doc/apps/erts/erl_ext_dist.html#NEW_REFERENCE_EXT
30
30
  #
31
31
  class NewReference
32
- include Term
32
+ include Erlang::ETF::Term
33
33
 
34
- uint8 :tag, always: Terms::NEW_REFERENCE_EXT
34
+ UINT8 = Erlang::ETF::Term::UINT8
35
+ UINT16BE = Erlang::ETF::Term::UINT16BE
36
+ UINT32BE = Erlang::ETF::Term::UINT32BE
35
37
 
36
- uint16be :len, always: -> { ids.size }
37
-
38
- term :node
39
-
40
- int8 :creation, maximum: (1 << 2) - 1
41
-
42
- uint32be :ids, type: :array, default: []
38
+ class << self
39
+ def [](term, node = nil, creation = nil, ids = nil)
40
+ return new(term, node, creation, ids)
41
+ end
43
42
 
44
- deserialize do |buffer|
45
- len, = buffer.read(BYTES_16).unpack(UINT16BE_PACK)
46
- deserialize_node(buffer)
47
- deserialize_creation(buffer)
48
- self.ids = []
49
- len.times do
50
- self.ids << buffer.read(BYTES_32).unpack(UINT32BE_PACK).at(0)
43
+ def erlang_load(buffer)
44
+ length, = buffer.read(2).unpack(UINT16BE)
45
+ node = Erlang::ETF.read_term(buffer)
46
+ creation, *ids = buffer.read(1 + (4 * length)).unpack("#{UINT8}#{UINT32BE}#{length}")
47
+ term = Erlang::Reference[Erlang.from(node), Erlang.from(creation), Erlang.from(ids)]
48
+ return new(term, node, creation, ids)
51
49
  end
52
- self
53
50
  end
54
51
 
55
- finalize
56
-
57
- def initialize(node, creation, ids = [])
52
+ def initialize(term, node = nil, creation = nil, ids = nil)
53
+ raise ArgumentError, "term must be of type Erlang::Reference" if not term.kind_of?(Erlang::Reference) or not term.new_reference?
54
+ @term = term
58
55
  @node = node
59
56
  @creation = creation
60
57
  @ids = ids
61
58
  end
59
+
60
+ def erlang_dump(buffer = ::String.new.force_encoding(BINARY_ENCODING))
61
+ buffer << NEW_REFERENCE_EXT
62
+ ids = @ids || @term.ids
63
+ length = ids.size
64
+ buffer << [length].pack(UINT16BE)
65
+ Erlang::ETF.write_term(@node || @term.node, buffer)
66
+ buffer << [
67
+ @creation || @term.creation,
68
+ *ids
69
+ ].pack("#{UINT8}#{UINT32BE}#{length}")
70
+ return buffer
71
+ end
72
+
73
+ def inspect
74
+ if @node.nil? and @creation.nil? and @ids.nil?
75
+ return super
76
+ else
77
+ return "#{self.class}[#{@term.inspect}, #{@node.inspect}, #{@creation.inspect}, #{@ids.inspect}]"
78
+ end
79
+ end
80
+
81
+ def pretty_print(pp)
82
+ state = [@term]
83
+ state.push(@node, @creation, @ids) if not @node.nil? or not @creation.nil? or not @ids.nil?
84
+ return pp.group(1, "#{self.class}[", "]") do
85
+ pp.breakable ''
86
+ pp.seplist(state) { |obj| obj.pretty_print(pp) }
87
+ end
88
+ end
62
89
  end
63
90
  end
64
- end
91
+ end