pio 0.25.0 → 0.26.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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +4 -0
  4. data/Rakefile +1 -1
  5. data/bin/terminal-notifier +16 -0
  6. data/features/open_flow10/bad_request.feature +35 -0
  7. data/features/open_flow10/bad_request.raw +0 -0
  8. data/features/open_flow10/barrier_reply.feature +4 -4
  9. data/features/open_flow10/barrier_request.feature +4 -4
  10. data/features/open_flow10/echo_reply.feature +13 -13
  11. data/features/open_flow10/echo_request.feature +6 -6
  12. data/features/open_flow10/enqueue.feature +17 -0
  13. data/features/open_flow10/features_reply.feature +2 -2
  14. data/features/open_flow10/features_request.feature +28 -28
  15. data/features/open_flow10/flow_mod.feature +5 -5
  16. data/features/open_flow10/flow_stats_reply.feature +12 -12
  17. data/features/open_flow10/flow_stats_request.feature +3 -3
  18. data/features/open_flow10/hello.feature +8 -15
  19. data/features/open_flow10/hello_failed.feature +69 -0
  20. data/features/open_flow10/hello_failed.raw +0 -0
  21. data/features/open_flow10/nxast_learn.raw +0 -0
  22. data/features/open_flow10/packet_in.feature +2 -2
  23. data/features/open_flow10/packet_out.feature +13 -13
  24. data/features/open_flow10/port_status.feature +1 -1
  25. data/features/open_flow10/send_out_port.feature +106 -0
  26. data/features/open_flow10/set_ether_destination_address.feature +16 -0
  27. data/features/open_flow10/set_ether_source_address.feature +16 -0
  28. data/features/open_flow10/set_ip_destination_address.feature +16 -0
  29. data/features/open_flow10/set_ip_source_address.feature +16 -0
  30. data/features/open_flow10/set_ip_tos.feature +16 -0
  31. data/features/open_flow10/set_transport_destination_port.feature +16 -0
  32. data/features/open_flow10/set_transport_source_port.feature +16 -0
  33. data/features/open_flow10/set_vlan_priority.feature +16 -0
  34. data/features/open_flow10/set_vlan_vid.feature +16 -0
  35. data/features/open_flow10/strip_vlan_header.feature +15 -0
  36. data/features/open_flow10/vendor_action.feature +14 -0
  37. data/features/open_flow13/bad_request.feature +35 -0
  38. data/features/open_flow13/bad_request.raw +0 -0
  39. data/features/open_flow13/echo_reply.feature +7 -7
  40. data/features/open_flow13/echo_request.feature +7 -7
  41. data/features/open_flow13/features_reply.feature +2 -2
  42. data/features/open_flow13/features_request.feature +28 -28
  43. data/features/open_flow13/flow_mod.feature +24 -24
  44. data/features/open_flow13/hello.feature +5 -5
  45. data/features/open_flow13/hello_failed.feature +69 -0
  46. data/features/open_flow13/hello_failed.raw +0 -0
  47. data/features/open_flow13/packet_in.feature +3 -3
  48. data/features/open_flow13/packet_out.feature +3 -3
  49. data/features/open_flow13/send_out_port.feature +101 -10
  50. data/features/open_flow13/table_stats_reply.raw +0 -0
  51. data/features/open_flow13/table_stats_request.raw +0 -0
  52. data/features/open_flow_read.feature +6 -0
  53. data/features/step_definitions/Gemfile +9 -0
  54. data/features/step_definitions/Gemfile.lock +76 -0
  55. data/features/step_definitions/Guardfile +4 -0
  56. data/features/step_definitions/LICENSE +675 -0
  57. data/features/step_definitions/README.md +7 -0
  58. data/features/step_definitions/Rakefile +10 -0
  59. data/features/step_definitions/dump_flows_steps.rb +13 -0
  60. data/features/step_definitions/packet_data_steps.rb +4 -0
  61. data/features/step_definitions/rest_api_steps.rb +40 -0
  62. data/features/step_definitions/show_stats_steps.rb +83 -0
  63. data/features/step_definitions/trema_steps.rb +33 -0
  64. data/features/step_definitions/virtual_link_steps.rb +8 -0
  65. data/lib/pio/open_flow.rb +5 -5
  66. data/lib/pio/open_flow/echo.rb +1 -1
  67. data/lib/pio/open_flow/error.rb +19 -0
  68. data/lib/pio/open_flow/format.rb +2 -1
  69. data/lib/pio/open_flow/hello_failed_code.rb +21 -0
  70. data/lib/pio/open_flow/open_flow_header.rb +11 -2
  71. data/lib/pio/open_flow/port.rb +69 -0
  72. data/lib/pio/open_flow10.rb +5 -0
  73. data/lib/pio/open_flow10/actions.rb +8 -6
  74. data/lib/pio/open_flow10/enqueue.rb +13 -13
  75. data/lib/pio/open_flow10/error.rb +28 -0
  76. data/lib/pio/open_flow10/error/bad_request.rb +66 -0
  77. data/lib/pio/open_flow10/error/error_type10.rb +26 -0
  78. data/lib/pio/open_flow10/error/hello_failed.rb +41 -0
  79. data/lib/pio/open_flow10/features.rb +6 -10
  80. data/lib/pio/open_flow10/flow_mod.rb +1 -1
  81. data/lib/pio/open_flow10/flow_stats_request.rb +1 -1
  82. data/lib/pio/open_flow10/hello.rb +2 -2
  83. data/lib/pio/open_flow10/match.rb +2 -2
  84. data/lib/pio/{open_flow/phy_port.rb → open_flow10/phy_port16.rb} +4 -4
  85. data/lib/pio/open_flow10/port16.rb +21 -0
  86. data/lib/pio/open_flow10/port_status.rb +1 -1
  87. data/lib/pio/open_flow10/send_out_port.rb +16 -40
  88. data/lib/pio/open_flow10/set_ether_address.rb +9 -8
  89. data/lib/pio/open_flow10/set_ip_address.rb +4 -4
  90. data/lib/pio/open_flow10/set_ip_tos.rb +4 -4
  91. data/lib/pio/open_flow10/set_transport_port.rb +12 -12
  92. data/lib/pio/open_flow10/set_vlan.rb +4 -4
  93. data/lib/pio/open_flow10/set_vlan_vid.rb +0 -12
  94. data/lib/pio/open_flow10/strip_vlan_header.rb +7 -7
  95. data/lib/pio/open_flow10/vendor_action.rb +33 -0
  96. data/lib/pio/open_flow13.rb +3 -0
  97. data/lib/pio/open_flow13/actions.rb +3 -3
  98. data/lib/pio/open_flow13/error.rb +28 -0
  99. data/lib/pio/open_flow13/error/bad_request.rb +66 -0
  100. data/lib/pio/open_flow13/error/error_type13.rb +37 -0
  101. data/lib/pio/open_flow13/error/hello_failed.rb +42 -0
  102. data/lib/pio/open_flow13/features_reply.rb +33 -33
  103. data/lib/pio/open_flow13/features_request.rb +3 -3
  104. data/lib/pio/open_flow13/flow_mod.rb +2 -2
  105. data/lib/pio/open_flow13/goto_table.rb +2 -0
  106. data/lib/pio/open_flow13/packet_out.rb +1 -1
  107. data/lib/pio/open_flow13/port32.rb +21 -0
  108. data/lib/pio/open_flow13/send_out_port.rb +3 -2
  109. data/lib/pio/version.rb +1 -1
  110. data/pio.gemspec +5 -5
  111. data/spec/pio/open_flow10/enqueue_spec.rb +22 -22
  112. data/spec/pio/open_flow10/error/hello_failed_spec.rb +26 -0
  113. data/spec/pio/open_flow10/flow_mod_spec.rb +6 -6
  114. data/spec/pio/open_flow10/flow_stats_request_spec.rb +1 -1
  115. data/spec/pio/open_flow10/hello_spec.rb +3 -3
  116. data/spec/pio/open_flow10/packet_out_spec.rb +33 -33
  117. data/spec/pio/{open_flow/phy_port_spec.rb → open_flow10/phy_port16_spec.rb} +7 -7
  118. data/spec/pio/open_flow10/send_out_port_spec.rb +28 -28
  119. data/spec/pio/open_flow10/set_ether_destination_address_spec.rb +2 -2
  120. data/spec/pio/open_flow10/set_ether_source_address_spec.rb +2 -2
  121. data/spec/pio/open_flow10/set_ip_destination_address_spec.rb +4 -4
  122. data/spec/pio/open_flow10/set_ip_source_address_spec.rb +4 -4
  123. data/spec/pio/open_flow10/set_ip_tos_spec.rb +4 -4
  124. data/spec/pio/open_flow10/set_transport_destination_port_spec.rb +11 -11
  125. data/spec/pio/open_flow10/set_transport_source_port_spec.rb +11 -11
  126. data/spec/pio/open_flow10/set_vlan_priority_spec.rb +4 -4
  127. data/spec/pio/open_flow10/set_vlan_vid_spec.rb +4 -4
  128. data/spec/pio/open_flow10/strip_vlan_header_spec.rb +6 -6
  129. data/spec/pio/open_flow13/error/bad_request_spec.rb +6 -0
  130. data/spec/pio/open_flow13/error/hello_failed_spec.rb +26 -0
  131. data/spec/pio/open_flow13/hello_spec.rb +3 -3
  132. data/spec/support/shared_examples_for_openflow_messages.rb +40 -27
  133. metadata +106 -16
  134. data/lib/pio/open_flow/port_number.rb +0 -39
@@ -1,7 +1,7 @@
1
1
  require 'bindata'
2
2
  require 'forwardable'
3
3
  require 'pio/monkey_patch/integer'
4
- require 'pio/open_flow/port_number'
4
+ require 'pio/open_flow10/port16'
5
5
 
6
6
  module Pio
7
7
  # An action to enqueue the packet on the specified queue attached to
@@ -11,9 +11,9 @@ module Pio
11
11
  class Format < BinData::Record
12
12
  endian :big
13
13
 
14
- uint16 :type, value: 11
15
- uint16 :message_length, value: 16
16
- port_number :port_number
14
+ uint16 :action_type, value: 11
15
+ uint16 :action_length, value: 16
16
+ port16 :port
17
17
  uint48 :padding
18
18
  hide :padding
19
19
  uint32 :queue_id
@@ -27,28 +27,28 @@ module Pio
27
27
 
28
28
  extend Forwardable
29
29
 
30
- def_delegators :@format, :type
31
- def_delegators :@format, :message_length
32
- def_delegators :@format, :port_number
30
+ def_delegators :@format, :action_type
31
+ def_delegator :@format, :action_length, :length
32
+ def_delegators :@format, :port
33
33
  def_delegators :@format, :queue_id
34
34
  def_delegator :@format, :to_binary_s, :to_binary
35
35
 
36
36
  def initialize(user_options)
37
- validate_port_number user_options
37
+ validate_port user_options
38
38
  validate_queue_id user_options
39
39
  @format = Format.new(user_options)
40
40
  end
41
41
 
42
42
  private
43
43
 
44
- def validate_port_number(user_options)
45
- port_number = user_options.fetch(:port_number)
46
- if port_number.is_a?(Symbol) && port_number != :in_port
44
+ def validate_port(user_options)
45
+ port = user_options.fetch(:port)
46
+ if port.is_a?(Symbol) && port != :in_port
47
47
  fail(ArgumentError,
48
- ':port_number must be a valid physical port or :in_port')
48
+ ':port must be a valid physical port or :in_port')
49
49
  end
50
50
  rescue KeyError
51
- raise ArgumentError, ':port_number is a mandatory option'
51
+ raise ArgumentError, ':port is a mandatory option'
52
52
  end
53
53
 
54
54
  def validate_queue_id(user_options)
@@ -0,0 +1,28 @@
1
+ require 'pio/open_flow10/error/error_type10'
2
+
3
+ module Pio
4
+ module OpenFlow10
5
+ # Error message parser
6
+ module Error
7
+ # Error message body parser.
8
+ class BodyParser < BinData::Record
9
+ endian :big
10
+ error_type10 :error_type
11
+ uint16 :error_code
12
+ end
13
+
14
+ def self.read(binary)
15
+ body = OpenFlowHeaderParser.read(binary).body
16
+ klass = case BodyParser.read(body).snapshot.error_type
17
+ when :hello_failed
18
+ HelloFailed
19
+ when :bad_request
20
+ BadRequest
21
+ else
22
+ fail 'Unknown error message.'
23
+ end
24
+ klass.read binary
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,66 @@
1
+ require 'bindata'
2
+ require 'pio/open_flow/format'
3
+ require 'pio/open_flow/message'
4
+ require 'pio/open_flow10/error/error_type10'
5
+
6
+ module Pio
7
+ module OpenFlow10
8
+ module Error
9
+ # Bad request error.
10
+ class BadRequest < OpenFlow::Message
11
+ # Bad request error format.
12
+ class Format < BinData::Record
13
+ # Bad request error body.
14
+ class Body < BinData::Record
15
+ # enum ofp_bad_request_code
16
+ class BadRequestCode < BinData::Primitive
17
+ ERROR_CODES = {
18
+ bad_version: 0,
19
+ bad_type: 1,
20
+ bad_stats: 2,
21
+ bad_vendor: 3,
22
+ bad_subtype: 4,
23
+ permissions_error: 5,
24
+ bad_length: 6,
25
+ buffer_empty: 7,
26
+ buffer_unknown: 8
27
+ }
28
+
29
+ endian :big
30
+ uint16 :error_code
31
+
32
+ def get
33
+ ERROR_CODES.invert.fetch(error_code)
34
+ end
35
+
36
+ def set(value)
37
+ self.error_code = ERROR_CODES.fetch(value)
38
+ end
39
+ end
40
+
41
+ endian :big
42
+
43
+ error_type10 :error_type, value: -> { :bad_request }
44
+ bad_request_code :error_code
45
+ rest :raw_data
46
+
47
+ def length
48
+ 4 + raw_data.length
49
+ end
50
+ end
51
+
52
+ extend OpenFlow::Format
53
+
54
+ header version: 1, message_type: 1
55
+ body :body
56
+
57
+ def length
58
+ 8 + body.length
59
+ end
60
+ end
61
+
62
+ body_option :raw_data
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,26 @@
1
+ module Pio
2
+ module OpenFlow10
3
+ # enum ofp_error_type
4
+ class ErrorType10 < BinData::Primitive
5
+ ERROR_TYPES = {
6
+ hello_failed: 0,
7
+ bad_request: 1,
8
+ bad_action: 2,
9
+ flow_mod_failed: 3,
10
+ port_mod_failed: 4,
11
+ queue_operation_failed: 5
12
+ }
13
+
14
+ endian :big
15
+ uint16 :error_type
16
+
17
+ def get
18
+ ERROR_TYPES.invert.fetch(error_type)
19
+ end
20
+
21
+ def set(value)
22
+ self.error_type = ERROR_TYPES.fetch(value)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,41 @@
1
+ require 'pio/open_flow/format'
2
+ require 'pio/open_flow/hello_failed_code'
3
+ require 'pio/open_flow/message'
4
+ require 'pio/open_flow10/error/error_type10'
5
+
6
+ module Pio
7
+ module OpenFlow10
8
+ module Error
9
+ # Hello failed error.
10
+ class HelloFailed < OpenFlow::Message
11
+ # Hello Failed error format.
12
+ class Format < BinData::Record
13
+ # Hello Failed error body.
14
+ class Body < BinData::Record
15
+ endian :big
16
+
17
+ error_type10 :error_type
18
+ hello_failed_code :error_code
19
+ rest :description
20
+
21
+ def length
22
+ 4 + description.length
23
+ end
24
+ end
25
+
26
+ extend OpenFlow::Format
27
+
28
+ header version: 1, message_type: 1
29
+ body :body
30
+
31
+ def length
32
+ 8 + body.length
33
+ end
34
+ end
35
+
36
+ body_option :error_code
37
+ body_option :description
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,12 +1,13 @@
1
1
  require 'pio/open_flow'
2
+ require 'pio/open_flow10/phy_port16'
2
3
 
3
4
  module Pio
4
5
  module OpenFlow10
5
- # OpenFlow 1.0 Features Request and Reply message.
6
+ # Features Request and Reply message.
6
7
  class Features
7
- # OpenFlow 1.0 Features Request message.
8
+ # Features Request message.
8
9
  class Request < OpenFlow::Message
9
- # OpenFlow 1.0 Features Request message
10
+ # Features Request message format.
10
11
  class Format < BinData::Record
11
12
  extend OpenFlow::Format
12
13
 
@@ -17,11 +18,6 @@ module Pio
17
18
  body
18
19
  end
19
20
  end
20
-
21
- def initialize(user_options = {})
22
- validate_user_options user_options
23
- @format = Format.new(header: parse_header_options(user_options))
24
- end
25
21
  end
26
22
 
27
23
  # OpenFlow 1.0 Features Reply message.
@@ -65,7 +61,7 @@ module Pio
65
61
  hide :padding
66
62
  capabilities :capabilities
67
63
  actions_flag :actions
68
- array :ports, type: :phy_port, read_until: :eof
64
+ array :ports, type: :phy_port16, read_until: :eof
69
65
 
70
66
  def dpid
71
67
  datapath_id
@@ -96,7 +92,7 @@ module Pio
96
92
 
97
93
  def physical_ports
98
94
  ports.select do |each|
99
- each.port_no <= PortNumber::MAX
95
+ each.port_no <= Port16::MAX
100
96
  end
101
97
  end
102
98
  end
@@ -49,7 +49,7 @@ module Pio
49
49
  uint32 :buffer_id
50
50
  uint16 :out_port
51
51
  flags :flags
52
- actions :actions, length: -> { header.message_length - 72 }
52
+ actions :actions, length: -> { header.length - 72 }
53
53
 
54
54
  def empty?
55
55
  false
@@ -19,7 +19,7 @@ module Pio
19
19
  uint8 :table_id, initial_value: 0xff
20
20
  string :padding, length: 1
21
21
  hide :padding
22
- port_number :out_port, initial_value: -> { :none }
22
+ port16 :out_port, initial_value: -> { :none }
23
23
  end
24
24
 
25
25
  # Message body of Flow Stats Request.
@@ -5,9 +5,9 @@ require 'pio/open_flow/message'
5
5
  module Pio
6
6
  # OpenFlow 1.0 messages
7
7
  module OpenFlow10
8
- # OpenFlow 1.0 Hello message
8
+ # Hello message
9
9
  class Hello < OpenFlow::Message
10
- # OpenFlow 1.0 Hello message format
10
+ # Hello message format
11
11
  class Format < BinData::Record
12
12
  extend OpenFlow::Format
13
13
 
@@ -48,7 +48,7 @@ module Pio
48
48
  BITS.each_with_object(Hash.new(0)) do |(key, bit), memo|
49
49
  next if flags & bit == 0
50
50
  if /(ip_source_address|ip_destination_address)(\d)/=~ key
51
- memo[$LAST_MATCH_INFO[1].intern] |= 1 << $LAST_MATCH_INFO[2].to_i
51
+ memo[$LAST_MATCH_INFO[1].to_sym] |= 1 << $LAST_MATCH_INFO[2].to_i
52
52
  else
53
53
  memo[key] = true
54
54
  end
@@ -141,7 +141,7 @@ module Pio
141
141
  if user_options.key?(each)
142
142
  memo[each] = 32 - IPv4Address.new(user_options[each]).prefixlen
143
143
  else
144
- memo["#{each}_all".intern] = true
144
+ memo["#{each}_all".to_sym] = true
145
145
  end
146
146
  end
147
147
  @format = MatchFormat.new({ wildcards: flags }.merge user_options)
@@ -2,10 +2,10 @@ require 'bindata'
2
2
  require 'pio/type/mac_address'
3
3
 
4
4
  module Pio
5
- module OpenFlow
5
+ module OpenFlow10
6
6
  # Description of a physical port
7
- class PhyPort < BinData::Record
8
- extend Flags
7
+ class PhyPort16 < BinData::Record
8
+ extend OpenFlow::Flags
9
9
 
10
10
  # enum ofp_port_config
11
11
  flags_32bit :port_config,
@@ -80,7 +80,7 @@ module Pio
80
80
  end
81
81
 
82
82
  def ss.local?
83
- port_no == PortNumber::NUMBERS[:local]
83
+ port_no == OpenFlow10::Port16.reserved_port_number(:local)
84
84
  end
85
85
  end
86
86
  end
@@ -0,0 +1,21 @@
1
+ require 'pio/open_flow/port'
2
+
3
+ module Pio
4
+ module OpenFlow10
5
+ # Port numbering (16bit).
6
+ class Port16 < OpenFlow::Port
7
+ port_size_in_bytes 16
8
+
9
+ max_port_number 0xff00
10
+
11
+ reserved_ports(in_port: 0xfff8,
12
+ table: 0xfff9,
13
+ normal: 0xfffa,
14
+ flood: 0xfffb,
15
+ all: 0xfffc,
16
+ controller: 0xfffd,
17
+ local: 0xfffe,
18
+ none: 0xffff)
19
+ end
20
+ end
21
+ end
@@ -28,7 +28,7 @@ module Pio
28
28
  reason :reason
29
29
  uint56 :padding
30
30
  hide :padding
31
- phy_port :desc
31
+ phy_port16 :desc
32
32
  end
33
33
 
34
34
  # OpenFlow 1.0 Flow Mod message format.
@@ -1,7 +1,7 @@
1
1
  require 'bindata'
2
2
  require 'forwardable'
3
3
  require 'pio/monkey_patch/integer'
4
- require 'pio/open_flow/port_number'
4
+ require 'pio/open_flow10/port16'
5
5
 
6
6
  module Pio
7
7
  module OpenFlow10
@@ -11,10 +11,10 @@ module Pio
11
11
  class Format < BinData::Record
12
12
  endian :big
13
13
 
14
- uint16 :type, value: 0
15
- uint16 :message_length, value: 8
16
- port_number :port_number
17
- uint16 :max_len, initial_value: 2**16 - 1
14
+ uint16 :action_type, value: 0
15
+ uint16 :action_length, value: 8
16
+ port16 :port
17
+ uint16 :max_length, initial_value: 2**16 - 1
18
18
  end
19
19
 
20
20
  def self.read(raw_data)
@@ -25,49 +25,25 @@ module Pio
25
25
 
26
26
  extend Forwardable
27
27
 
28
- def_delegators :@format, :message_length
29
- def_delegators :@format, :port_number
30
- def_delegators :@format, :max_len
28
+ def_delegators :@format, :action_type
29
+ def_delegator :@format, :action_length, :length
30
+ def_delegators :@format, :port
31
+ def_delegators :@format, :max_length
31
32
  def_delegator :@format, :to_binary_s, :to_binary
32
33
 
33
- # Creates an action to output a packet to a port.
34
- #
35
- # @example
36
- # SendOutPort.new(1)
37
- # SendOutPort.new(port_number: 1)
38
- # SendOutPort.new(port_number: :controller, max_len: 256)
39
- #
40
- # @param [Integer|Hash] user_options
41
- # the port number or the options hash to create this action
42
- # class instance with.
43
- #
44
- # @option user_options [Number] :port_number
45
- # port number an index into switch's physical port list. There
46
- # are also fake output ports. For example a port number set to
47
- # +:flood+ would output packets to all physical ports except
48
- # input port and ports disabled by STP.
49
- # @option user_options [Number] :max_len
50
- # the maximum number of bytes from a packet to send to
51
- # controller when port is set to +:controller+. A zero length
52
- # means no bytes of the packet should be sent. It defaults to
53
- # 64K.
54
- #
55
- # @raise [ArgumentError] if +:port_number+ is not an unsigned
56
- # 16-bit integer.
57
- # @raise [ArgumentError] if +:max_len+ is not an unsigned 16-bit integer.
58
- #
59
34
  # rubocop:disable MethodLength
60
35
  def initialize(user_options)
61
36
  options = if user_options.respond_to?(:to_i)
62
- { port_number: user_options.to_i }
63
- elsif PortNumber::NUMBERS.key?(user_options)
64
- { port_number: user_options }
37
+ { port: user_options.to_i }
38
+ elsif Port16.reserved_port_name?(user_options)
39
+ { port: user_options }
65
40
  else
66
41
  user_options
67
42
  end
68
- max_len = options[:max_len]
69
- if max_len && !max_len.unsigned_16bit?
70
- fail ArgumentError, 'The max_len should be an unsigned 16bit integer.'
43
+ max_length = options[:max_length]
44
+ if max_length && !max_length.unsigned_16bit?
45
+ fail(ArgumentError,
46
+ 'The max_length should be an unsigned 16bit integer.')
71
47
  end
72
48
  @format = Format.new(options)
73
49
  end