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 | 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