packetgen 3.1.3 → 3.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -1
  3. data/bin/pgconsole +1 -0
  4. data/lib/packetgen.rb +33 -4
  5. data/lib/packetgen/capture.rb +51 -28
  6. data/lib/packetgen/config.rb +17 -11
  7. data/lib/packetgen/deprecation.rb +33 -7
  8. data/lib/packetgen/header.rb +2 -9
  9. data/lib/packetgen/header/arp.rb +2 -2
  10. data/lib/packetgen/header/asn1_base.rb +2 -2
  11. data/lib/packetgen/header/base.rb +70 -74
  12. data/lib/packetgen/header/bootp.rb +3 -3
  13. data/lib/packetgen/header/dhcp.rb +2 -2
  14. data/lib/packetgen/header/dhcp/option.rb +2 -2
  15. data/lib/packetgen/header/dhcp/options.rb +2 -2
  16. data/lib/packetgen/header/dhcpv6.rb +12 -12
  17. data/lib/packetgen/header/dhcpv6/duid.rb +11 -5
  18. data/lib/packetgen/header/dhcpv6/option.rb +8 -16
  19. data/lib/packetgen/header/dhcpv6/options.rb +2 -2
  20. data/lib/packetgen/header/dhcpv6/relay.rb +2 -2
  21. data/lib/packetgen/header/dns.rb +9 -9
  22. data/lib/packetgen/header/dns/name.rb +20 -9
  23. data/lib/packetgen/header/dns/opt.rb +2 -2
  24. data/lib/packetgen/header/dns/option.rb +2 -2
  25. data/lib/packetgen/header/dns/qdsection.rb +3 -3
  26. data/lib/packetgen/header/dns/question.rb +37 -35
  27. data/lib/packetgen/header/dns/rr.rb +3 -3
  28. data/lib/packetgen/header/dns/rrsection.rb +2 -2
  29. data/lib/packetgen/header/dot11.rb +30 -51
  30. data/lib/packetgen/header/dot11/control.rb +5 -5
  31. data/lib/packetgen/header/dot11/data.rb +11 -7
  32. data/lib/packetgen/header/dot11/element.rb +16 -16
  33. data/lib/packetgen/header/dot11/management.rb +2 -2
  34. data/lib/packetgen/header/dot11/sub_mngt.rb +2 -12
  35. data/lib/packetgen/header/dot1q.rb +2 -2
  36. data/lib/packetgen/header/dot1x.rb +7 -20
  37. data/lib/packetgen/header/eap.rb +30 -33
  38. data/lib/packetgen/header/eap/fast.rb +2 -2
  39. data/lib/packetgen/header/eap/md5.rb +2 -2
  40. data/lib/packetgen/header/eap/tls.rb +2 -2
  41. data/lib/packetgen/header/eap/ttls.rb +2 -2
  42. data/lib/packetgen/header/eth.rb +13 -11
  43. data/lib/packetgen/header/gre.rb +2 -2
  44. data/lib/packetgen/header/http.rb +2 -0
  45. data/lib/packetgen/header/http/headers.rb +6 -4
  46. data/lib/packetgen/header/http/request.rb +36 -21
  47. data/lib/packetgen/header/http/response.rb +7 -7
  48. data/lib/packetgen/header/http/verbs.rb +3 -3
  49. data/lib/packetgen/header/icmp.rb +2 -2
  50. data/lib/packetgen/header/icmpv6.rb +2 -2
  51. data/lib/packetgen/header/igmp.rb +4 -4
  52. data/lib/packetgen/header/igmpv3.rb +3 -3
  53. data/lib/packetgen/header/igmpv3/group_record.rb +8 -6
  54. data/lib/packetgen/header/igmpv3/mq.rb +2 -2
  55. data/lib/packetgen/header/igmpv3/mr.rb +2 -2
  56. data/lib/packetgen/header/ip.rb +30 -31
  57. data/lib/packetgen/header/ip/addr.rb +10 -3
  58. data/lib/packetgen/header/ip/option.rb +8 -10
  59. data/lib/packetgen/header/ip/options.rb +3 -5
  60. data/lib/packetgen/header/ipv6.rb +2 -2
  61. data/lib/packetgen/header/ipv6/addr.rb +9 -2
  62. data/lib/packetgen/header/ipv6/extension.rb +2 -2
  63. data/lib/packetgen/header/ipv6/hop_by_hop.rb +3 -3
  64. data/lib/packetgen/header/llc.rb +2 -2
  65. data/lib/packetgen/header/mdns.rb +2 -2
  66. data/lib/packetgen/header/mld.rb +2 -2
  67. data/lib/packetgen/header/mldv2.rb +2 -2
  68. data/lib/packetgen/header/mldv2/mcast_address_record.rb +4 -2
  69. data/lib/packetgen/header/mldv2/mlq.rb +2 -2
  70. data/lib/packetgen/header/mldv2/mlr.rb +2 -2
  71. data/lib/packetgen/header/ospfv2.rb +9 -9
  72. data/lib/packetgen/header/ospfv2/db_description.rb +2 -2
  73. data/lib/packetgen/header/ospfv2/hello.rb +2 -2
  74. data/lib/packetgen/header/ospfv2/ls_ack.rb +2 -2
  75. data/lib/packetgen/header/ospfv2/ls_request.rb +4 -2
  76. data/lib/packetgen/header/ospfv2/ls_update.rb +2 -2
  77. data/lib/packetgen/header/ospfv2/lsa.rb +9 -5
  78. data/lib/packetgen/header/ospfv2/lsa_header.rb +8 -7
  79. data/lib/packetgen/header/ospfv3.rb +2 -2
  80. data/lib/packetgen/header/ospfv3/db_description.rb +2 -2
  81. data/lib/packetgen/header/ospfv3/hello.rb +2 -2
  82. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +4 -2
  83. data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -2
  84. data/lib/packetgen/header/ospfv3/ls_request.rb +4 -2
  85. data/lib/packetgen/header/ospfv3/ls_update.rb +2 -2
  86. data/lib/packetgen/header/ospfv3/lsa.rb +5 -5
  87. data/lib/packetgen/header/ospfv3/lsa_header.rb +9 -8
  88. data/lib/packetgen/header/snmp.rb +33 -29
  89. data/lib/packetgen/header/tcp.rb +4 -23
  90. data/lib/packetgen/header/tcp/option.rb +11 -11
  91. data/lib/packetgen/header/tcp/options.rb +2 -2
  92. data/lib/packetgen/header/tftp.rb +6 -6
  93. data/lib/packetgen/header/udp.rb +3 -3
  94. data/lib/packetgen/headerable.rb +5 -4
  95. data/lib/packetgen/inject.rb +23 -0
  96. data/lib/packetgen/inspect.rb +23 -20
  97. data/lib/packetgen/packet.rb +82 -53
  98. data/lib/packetgen/pcap.rb +29 -0
  99. data/lib/packetgen/pcapng.rb +13 -13
  100. data/lib/packetgen/pcapng/block.rb +26 -13
  101. data/lib/packetgen/pcapng/epb.rb +25 -22
  102. data/lib/packetgen/pcapng/file.rb +260 -138
  103. data/lib/packetgen/pcapng/idb.rb +36 -38
  104. data/lib/packetgen/pcapng/shb.rb +51 -53
  105. data/lib/packetgen/pcapng/spb.rb +19 -19
  106. data/lib/packetgen/pcapng/unknown_block.rb +5 -13
  107. data/lib/packetgen/pcaprub_wrapper.rb +81 -0
  108. data/lib/packetgen/proto.rb +2 -2
  109. data/lib/packetgen/types.rb +3 -0
  110. data/lib/packetgen/types/abstract_tlv.rb +27 -7
  111. data/lib/packetgen/types/array.rb +22 -15
  112. data/lib/packetgen/types/cstring.rb +57 -20
  113. data/lib/packetgen/types/enum.rb +7 -2
  114. data/lib/packetgen/types/fieldable.rb +65 -0
  115. data/lib/packetgen/types/fields.rb +182 -117
  116. data/lib/packetgen/types/int.rb +18 -6
  117. data/lib/packetgen/types/int_string.rb +10 -2
  118. data/lib/packetgen/types/length_from.rb +20 -12
  119. data/lib/packetgen/types/oui.rb +4 -2
  120. data/lib/packetgen/types/string.rb +59 -8
  121. data/lib/packetgen/types/tlv.rb +4 -2
  122. data/lib/packetgen/utils.rb +4 -4
  123. data/lib/packetgen/utils/arp_spoofer.rb +2 -2
  124. data/lib/packetgen/version.rb +3 -3
  125. metadata +39 -61
  126. data/.gitignore +0 -13
  127. data/.rubocop.yml +0 -30
  128. data/.travis.yml +0 -19
  129. data/Gemfile +0 -4
  130. data/Rakefile +0 -21
  131. data/packetgen.gemspec +0 -36
@@ -1,11 +1,11 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
3
+
2
4
  # This file is part of PacketGen
3
5
  # See https://github.com/sdaubert/packetgen for more informations
4
6
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
5
7
  # This program is published under MIT license.
6
8
 
7
- # frozen_string_literal: true
8
-
9
9
  require 'socket'
10
10
 
11
11
  module PacketGen
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of PacketGen
2
4
  # See https://github.com/sdaubert/packetgen for more informations
3
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
@@ -10,6 +12,7 @@ module PacketGen
10
12
  end
11
13
 
12
14
  require_relative 'types/length_from'
15
+ require_relative 'types/fieldable'
13
16
  require_relative 'types/int'
14
17
  require_relative 'types/enum'
15
18
  require_relative 'types/string'
@@ -1,16 +1,16 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
3
+
2
4
  # This file is part of PacketGen
3
5
  # See https://github.com/sdaubert/packetgen for more informations
4
6
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
5
7
  # This program is published under MIT license.
6
8
 
7
- # frozen_string_literal: true
8
-
9
9
  module PacketGen
10
10
  module Types
11
11
  # This class is an abstract class to define type-length-value data.
12
12
  #
13
- # This class supersede {TLV} class, which is not well defined on some corner
13
+ # This class supersedes {TLV} class, which is not well defined on some corner
14
14
  # cases.
15
15
  #
16
16
  # ===Usage
@@ -33,7 +33,7 @@ module PacketGen
33
33
  # tlv.value #=> "abcd"
34
34
  #
35
35
  # ===Advanced usage
36
- # Each field's type may be change at generating TLV class:
36
+ # Each field's type may be changed at generating TLV class:
37
37
  # MyTLV = PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16,
38
38
  # length_class: PacketGen::Types::Int16,
39
39
  # value_class: PacketGen::Header::IP::Addr)
@@ -58,9 +58,12 @@ module PacketGen
58
58
  # @since 3.1.0
59
59
  # @since 3.1.1 add +:aliases+ keyword to {#initialize}
60
60
  class AbstractTLV < Types::Fields
61
+ include Fieldable
62
+
61
63
  class <<self
62
64
  # @return [Hash]
63
65
  attr_accessor :aliases
66
+ attr_accessor :header_in_length
64
67
  end
65
68
  self.aliases = {}
66
69
 
@@ -68,12 +71,17 @@ module PacketGen
68
71
  # @param [Class] type_class Class to use for +type+
69
72
  # @param [Class] length_class Class to use for +length+
70
73
  # @param [Class] value_class Class to use for +value+
74
+ # @param [Boolean] header_in_length if +true +, +type+ and +length+ fields are
75
+ # included in length
71
76
  # @return [Class]
72
- def self.create(type_class: Int8Enum, length_class: Int8, value_class: String, aliases: {})
77
+ # @since 3.1.4 Add +header_in_length+ parameter
78
+ def self.create(type_class: Int8Enum, length_class: Int8, value_class: String,
79
+ aliases: {}, header_in_length: false)
73
80
  raise Error, '.create cannot be called on a subclass of PacketGen::Types::AbstractTLV' unless self.equal? AbstractTLV
74
81
 
75
82
  klass = Class.new(self)
76
83
  klass.aliases = aliases
84
+ klass.header_in_length = header_in_length
77
85
 
78
86
  if type_class < Enum
79
87
  klass.define_field :type, type_class, enum: {}
@@ -117,6 +125,7 @@ module PacketGen
117
125
  # @option options [Integer] :length
118
126
  # @option options [Object] :value
119
127
  def initialize(options={})
128
+ @header_in_length = self.class.header_in_length
120
129
  self.class.aliases.each do |al, orig|
121
130
  options[orig] = options[al] if options.key?(al)
122
131
  end
@@ -136,7 +145,7 @@ module PacketGen
136
145
  idx += self[:type].sz
137
146
  self[:length].read str[idx, self[:length].sz]
138
147
  idx += self[:length].sz
139
- self[:value].read str[idx, self.length]
148
+ self[:value].read str[idx, real_length]
140
149
  self
141
150
  end
142
151
 
@@ -147,6 +156,7 @@ module PacketGen
147
156
  def value=(val)
148
157
  self[:value].from_human val
149
158
  self.length = self[:value].sz
159
+ self.length += self[:type].sz + self[:length].sz if @header_in_length
150
160
  val
151
161
  end
152
162
 
@@ -161,7 +171,17 @@ module PacketGen
161
171
  # @return [String]
162
172
  def to_human
163
173
  my_value = self[:value].is_a?(String) ? self[:value].inspect : self[:value].to_human
164
- "type:%s,length:%u,value:#{my_value}" % [human_type, length]
174
+ 'type:%s,length:%u,value:%s' % [human_type, length, my_value]
175
+ end
176
+
177
+ private
178
+
179
+ def real_length
180
+ if @header_in_length
181
+ self.length - self[:type].sz - self[:length].sz
182
+ else
183
+ self.length
184
+ end
165
185
  end
166
186
  end
167
187
  end
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of PacketGen
2
4
  # See https://github.com/sdaubert/packetgen for more informations
3
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  require 'forwardable'
9
9
 
10
10
  module PacketGen
@@ -27,6 +27,9 @@ module PacketGen
27
27
  # @author Sylvain Daubert
28
28
  class Array
29
29
  extend Forwardable
30
+ include Enumerable
31
+ include Fieldable
32
+ include LengthFrom
30
33
 
31
34
  # @!method [](index)
32
35
  # Return the element at +index+.
@@ -54,9 +57,6 @@ module PacketGen
54
57
  def_delegators :@array, :[], :clear, :each, :empty?, :first, :last, :size
55
58
  alias length size
56
59
 
57
- include Enumerable
58
- include LengthFrom
59
-
60
60
  # Separator used in {#to_human}.
61
61
  # May be ovverriden by subclasses
62
62
  HUMAN_SEPARATOR = ','
@@ -106,7 +106,7 @@ module PacketGen
106
106
  # @return [void]
107
107
  def clear!
108
108
  @array.clear
109
- @counter.read(0) if @counter
109
+ @counter&.read(0)
110
110
  end
111
111
 
112
112
  # Delete an object from this array. Update associated counter if any
@@ -150,7 +150,7 @@ module PacketGen
150
150
  # @return [Array] self
151
151
  def <<(obj)
152
152
  push obj
153
- @counter.read(@counter.to_i + 1) if @counter
153
+ @counter&.read(@counter.to_i + 1)
154
154
  self
155
155
  end
156
156
 
@@ -160,14 +160,11 @@ module PacketGen
160
160
  def read(str)
161
161
  clear
162
162
  return self if str.nil?
163
- return self if @counter && @counter.to_i.zero?
163
+ return self if @counter&.to_i&.zero?
164
164
 
165
165
  str = read_with_length_from(str)
166
- klass = self.class.set_of_klass
167
166
  until str.empty?
168
- obj = klass.new.read(str)
169
- real_klass = real_type(obj)
170
- obj = real_klass.new.read(str) unless real_klass == klass
167
+ obj = create_object_from_str(str)
171
168
  @array << obj
172
169
  str.slice!(0, obj.sz)
173
170
  break if @counter && self.size == @counter.to_i
@@ -203,9 +200,7 @@ module PacketGen
203
200
 
204
201
  def record_from_hash(hsh)
205
202
  obj_klass = self.class.set_of_klass
206
- unless obj_klass
207
- raise NotImplementedError, 'class should define #record_from_hash or declare type of elements in set with .set_of'
208
- end
203
+ raise NotImplementedError, 'class should define #record_from_hash or declare type of elements in set with .set_of' unless obj_klass
209
204
 
210
205
  obj = obj_klass.new(hsh) if obj_klass
211
206
  klass = real_type(obj)
@@ -215,6 +210,18 @@ module PacketGen
215
210
  def real_type(obj)
216
211
  obj.class
217
212
  end
213
+
214
+ def create_object_from_str(str)
215
+ klass = self.class.set_of_klass
216
+ obj = klass.new.read(str)
217
+ real_klass = real_type(obj)
218
+
219
+ if real_klass == klass
220
+ obj
221
+ else
222
+ real_klass.new.read(str)
223
+ end
224
+ end
218
225
  end
219
226
 
220
227
  # Specialized array to handle serie of {Int8}.
@@ -1,20 +1,35 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
3
+
2
4
  # This file is part of PacketGen
3
5
  # See https://github.com/sdaubert/packetgen for more informations
4
6
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
5
7
  # This program is published under MIT license.
6
8
 
7
- # frozen_string_literal: true
9
+ require 'forwardable'
8
10
 
9
11
  module PacketGen
10
12
  module Types
11
13
  # This class handles null-terminated strings (aka C strings).
12
14
  # @author Sylvain Daubert
13
- class CString < ::String
15
+ # @since 3.1.6 no more a subclass or regular String
16
+ class CString
17
+ extend Forwardable
18
+ include Fieldable
19
+
20
+ def_delegators :@string, :[], :length, :size, :inspect, :==,
21
+ :unpack, :force_encoding, :encoding, :index, :empty?,
22
+ :encode, :slice, :slice!
23
+
24
+ # @return [::String]
25
+ attr_reader :string
26
+ # @return [Integer]
27
+ attr_reader :static_length
28
+
14
29
  # @param [Hash] options
15
30
  # @option options [Integer] :static_length set a static length for this string
16
31
  def initialize(options={})
17
- super()
32
+ register_internal_string(+'')
18
33
  @static_length = options[:static_length]
19
34
  end
20
35
 
@@ -22,38 +37,49 @@ module PacketGen
22
37
  # @return [String] self
23
38
  def read(str)
24
39
  s = str.to_s
25
- s = s[0, @static_length] if @static_length.is_a? Integer
26
- idx = s.index(0.chr)
27
- s = s[0, idx] unless idx.nil?
28
- self.replace s
40
+ s = s[0, static_length] if static_length?
41
+ register_internal_string s
42
+ remove_null_character
29
43
  self
30
44
  end
31
45
 
32
46
  # get null-terminated string
33
47
  # @return [String]
34
48
  def to_s
35
- if defined?(@static_length) && @static_length.is_a?(Integer)
36
- if self.size >= @static_length
37
- s = self[0, @static_length]
38
- s[-1] = "\x00".encode(s.encoding)
39
- PacketGen.force_binary s
40
- else
41
- PacketGen.force_binary(self + "\0" * (@static_length - self.length))
42
- end
49
+ if static_length?
50
+ s = string[0, static_length - 1]
51
+ s << "\x00" * (static_length - s.length)
43
52
  else
44
- PacketGen.force_binary(self + +"\x00".encode(self.encoding))
53
+ s = "#{string}\x00"
45
54
  end
55
+ PacketGen.force_binary(s)
56
+ end
57
+
58
+ # Append the given string to CString
59
+ # @param [#to_s] str
60
+ # @return [self]
61
+ def <<(str)
62
+ @string << str.to_s
63
+ remove_null_character
64
+ self
46
65
  end
47
66
 
48
67
  # @return [Integer]
49
68
  def sz
50
- if @static_length.is_a? Integer
51
- @static_length
69
+ if static_length?
70
+ static_length
52
71
  else
53
72
  to_s.size
54
73
  end
55
74
  end
56
75
 
76
+ # Say if a static length is defined
77
+ # @return [Boolean]
78
+ # @since 3.1.6
79
+ def static_length?
80
+ !static_length.nil?
81
+ end
82
+
57
83
  # Populate CString from a human readable string
58
84
  # @param [String] str
59
85
  # @return [self]
@@ -63,8 +89,19 @@ module PacketGen
63
89
 
64
90
  # @return [String]
65
91
  def to_human
66
- idx = self.index(+"\x00".encode(self.encoding)) || self.sz
67
- self[0, idx]
92
+ string
93
+ end
94
+
95
+ private
96
+
97
+ def register_internal_string(str)
98
+ @string = str
99
+ PacketGen.force_binary(@string)
100
+ end
101
+
102
+ def remove_null_character
103
+ idx = string.index(0.chr)
104
+ register_internal_string(string[0, idx]) unless idx.nil?
68
105
  end
69
106
  end
70
107
  end
@@ -1,11 +1,11 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
3
+
2
4
  # This file is part of PacketGen
3
5
  # See https://github.com/sdaubert/packetgen for more informations
4
6
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
5
7
  # This program is published under MIT license.
6
8
 
7
- # frozen_string_literal: true
8
-
9
9
  module PacketGen
10
10
  module Types
11
11
  # @abstract Base enum class to handle binary integers with limited
@@ -55,6 +55,7 @@ module PacketGen
55
55
  nil
56
56
  when ::String
57
57
  raise ArgumentError, "#{value.inspect} not in enumeration" unless @enum.key? value
58
+
58
59
  @enum[value]
59
60
  else
60
61
  value.to_i
@@ -70,6 +71,10 @@ module PacketGen
70
71
  def to_human
71
72
  @enum.key(to_i) || "<unknown:#{@value}>"
72
73
  end
74
+
75
+ def format_inspect
76
+ format_str % [to_human, to_i]
77
+ end
73
78
  end
74
79
 
75
80
  # Enumeration on one byte. See {Enum}.
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of PacketGen
4
+ # See https://github.com/sdaubert/packetgen for more informations
5
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # This program is published under MIT license.
7
+
8
+ module PacketGen
9
+ module Types
10
+ # Mixin to define minimal API for a class to be embbeded as a field in
11
+ # {Fields} type.
12
+ #
13
+ # == Optional methods
14
+ # These methods may, optionally, be defined by fieldable types:
15
+ # * +from_human+ to load data from a human-readable string.
16
+ # @author Sylvain Daubert
17
+ # @since 3.1.6
18
+ module Fieldable
19
+ # Get type name
20
+ # @return [String]
21
+ def type_name
22
+ self.class.to_s.split('::').last
23
+ end
24
+
25
+ # rubocop:disable Lint/UselessMethodDefinition
26
+ # These methods are defined for documentation.
27
+
28
+ # Populate object from a binary string
29
+ # @param [String] str
30
+ # @return [Fields] self
31
+ # @abstract subclass should overload it.
32
+ def read(str)
33
+ super
34
+ end
35
+
36
+ # Return object as a binary string
37
+ # @return [String]
38
+ # @abstract subclass should overload it.
39
+ def to_s
40
+ super
41
+ end
42
+
43
+ # Size of object as binary string
44
+ # @return [Integer]
45
+ def sz
46
+ to_s.size
47
+ end
48
+
49
+ # Return a human-readbale string
50
+ # @return [String]
51
+ # @abstract subclass should overload it.
52
+ def to_human
53
+ super
54
+ end
55
+
56
+ # rubocop:enable Lint/UselessMethodDefinition
57
+
58
+ # Format object when inspecting a {Field} object
59
+ # @return [String]
60
+ def format_inspect
61
+ to_human
62
+ end
63
+ end
64
+ end
65
+ end