bin_struct 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5412a49a789a410de1120e6cbcbf55a7bd07783846a4e2f4cf9bc14eac76bfd
4
- data.tar.gz: 9ae9eabeb7c3fe672e8ba229bc116c9a72bf26c7b1fd9eace52bb0f8036f0fea
3
+ metadata.gz: 5a90f75409d497521af8957e89577a4e8b7c14211e5343aa9126a71ef413d759
4
+ data.tar.gz: b07e2bf73d2cb1f4b7be4340944cd52df4382fc94f171607357adf10ddc7a914
5
5
  SHA512:
6
- metadata.gz: 8fa11b03a84dca208c63d23358187b575982f5331d5c1da7fdd7c2343505ed932bc884a440b23589943d4eb5d9f78f942d77e8b271bef919277536a0ab9ab3b7
7
- data.tar.gz: ecd4e847f6dc8392b759b8ef7a23df05191c697bb471a1ef8c685e12009be544b2dac4f8d77a944190a607b26216d90bd034742c95f9b2034b2701c4ec726602
6
+ metadata.gz: 6acd7aeb0516bf6692ae5971aecb10c8ae685936f24302d909ff16f055118a68588876409819d0ba966e4f3a7b524b194e58713bfb0ccaef95eb542fca221bb3
7
+ data.tar.gz: 790bf0b81cef084c030e0412731e3b0b852815fa1f66f5d28564278579e12b7e3fd3ef3674c6f36dd32bc792e1c248f7f20b3f65f505d3193f370b2d8c6f1d88
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
- ## [Unreleased]
1
+ # Changelog
2
2
 
3
- ## [0.1.0] - 2024-07-13
3
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
+
6
+ ## 0.2.0 - 2024-07-21
7
+
8
+ ### Changed
9
+
10
+ - `BinStruct::Fields` renamed into `BinStruct::Struct`, and `*field*` methods are renamed into `*attr*` or `*attributes*`.
11
+ - `BinStruct::Struct#inspect`: add a title line.
12
+
13
+ ### Fixed
14
+
15
+ - Fix `BinStruct::ArrayOfInt#read_from_array` by using `value:` option.
16
+ - Fix `BinStruct::IntString#calc_length` by using `#from_human` instead of `#read`.
17
+ - `BinStruct::String#to_s`: force binary encoding.
18
+ - `BinStruct::String#<<`: force binary encoding on argument before catenating.
19
+
20
+ ## 0.1.0 - 2024-07-13
4
21
 
5
22
  - Initial release
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # BinStruct
2
2
 
3
- BinStruct provides a simple ways to create and dissect binary data. It is an extraction from [PacketGen](https://github.com/lemontree55/packetgen) fields.
3
+ BinStruct provides a simple way to create and dissect binary data. It is an extraction from [PacketGen](https://github.com/lemontree55/packetgen) 3.x Fields.
4
4
 
5
5
  ## Installation
6
6
 
@@ -2,28 +2,28 @@
2
2
 
3
3
  # This file is part of BinStruct
4
4
  # See https://github.com/lemontree55/bin_struct for more informations
5
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
5
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
6
7
  # This program is published under MIT license.
7
8
 
9
+ # BinStruct module
10
+ # @author LemonTree55
8
11
  module BinStruct
9
- # This class is an abstract class to define type-length-value data.
10
- #
11
- # This class supersedes {TLV} class, which is not well defined on some corner
12
- # cases.
12
+ # @abstract Base class to define type-length-value data.
13
13
  #
14
14
  # ===Usage
15
15
  # To simply define a new TLV class, do:
16
16
  # MyTLV = PacketGen::Types::AbstractTLV.create
17
17
  # MyTLV.define_type_enum 'one' => 1, 'two' => 2
18
- # This will define a new +MyTLV+ class, subclass of {Fields}. This class will
19
- # define 3 fields:
18
+ # This will define a new +MyTLV+ class, subclass of {AbstractTLV}. This class will
19
+ # define 3 attributes:
20
20
  # * +#type+, as a {Int8Enum} by default,
21
21
  # * +#length+, as a {Int8} by default,
22
22
  # * and +#value+, as a {String} by default.
23
23
  # +.define_type_enum+ is, here, necessary to define enum hash to be used
24
24
  # for +#type+ accessor, as this one is defined as an {Enum}.
25
25
  #
26
- # This class may then be used as older {TLV} class:
26
+ # This new defined class may now be easily used:
27
27
  # tlv = MyTLV.new(type: 1, value: 'abcd') # automagically set #length from value
28
28
  # tlv.type #=> 1
29
29
  # tlv.human_type #=> 'one'
@@ -31,7 +31,7 @@ module BinStruct
31
31
  # tlv.value #=> "abcd"
32
32
  #
33
33
  # ===Advanced usage
34
- # Each field's type may be changed at generating TLV class:
34
+ # Each attribute's type may be changed at generating TLV class:
35
35
  # MyTLV = PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16,
36
36
  # length_class: PacketGen::Types::Int16,
37
37
  # value_class: PacketGen::Header::IP::Addr)
@@ -42,7 +42,7 @@ module BinStruct
42
42
  # tlv.to_s #=> "\x00\x01\x00\x04\x01\x02\x03\x04"
43
43
  #
44
44
  # Some aliases may also be defined. For example, to create a TLV type
45
- # whose +type+ field should be named +code+:
45
+ # whose +type+ attribute should be named +code+:
46
46
  # MyTLV = PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16,
47
47
  # length_class: PacketGen::Types::Int16,
48
48
  # aliases: { code: :type })
@@ -52,20 +52,20 @@ module BinStruct
52
52
  # tlv.length #=> 4
53
53
  # tlv.value #=> 'abcd'
54
54
  #
55
- # @author Sylvain Daubert
56
- # @since 3.1.0
57
- # @since 3.1.1 add +:aliases+ keyword to {#initialize}
58
- class AbstractTLV < Fields
59
- include Fieldable
55
+ # @author Sylvain Daubert (2016-2024)
56
+ # @author LemonTree55
57
+ class AbstractTLV < Struct
58
+ include Structable
60
59
 
61
60
  # @private
62
- FIELD_TYPES = { 'T' => :type, 'L' => :length, 'V' => :value }.freeze
61
+ ATTR_TYPES = { 'T' => :type, 'L' => :length, 'V' => :value }.freeze
63
62
 
64
63
  class << self
64
+ # Aliases defined in {.create}
65
65
  # @return [Hash]
66
66
  attr_accessor :aliases
67
67
  # @private
68
- attr_accessor :field_in_length
68
+ attr_accessor :attr_in_length
69
69
 
70
70
  # rubocop:disable Metrics/ParameterLists
71
71
 
@@ -73,14 +73,12 @@ module BinStruct
73
73
  # @param [Class] type_class Class to use for +type+
74
74
  # @param [Class] length_class Class to use for +length+
75
75
  # @param [Class] value_class Class to use for +value+
76
- # @param [String] field_order give field order. Each character in [T,L,V] MUST be present once,
76
+ # @param [::String] attr_order gives attribute order. Each character in [T,L,V] MUST be present once,
77
77
  # in the desired order.
78
- # @param [String] field_in_length give fields to compute length on.
78
+ # @param [::String] attr_in_length give attributes to compute length on.
79
79
  # @return [Class]
80
- # @since 3.1.4 Add +header_in_length+ parameter
81
- # @since 3.3.1 Add +field_order+ and +field_in_length' parameters. Deprecate +header_in_length+ parameter.
82
80
  def create(type_class: Int8Enum, length_class: Int8, value_class: String,
83
- aliases: {}, field_order: 'TLV', field_in_length: 'V')
81
+ aliases: {}, attr_order: 'TLV', attr_in_length: 'V')
84
82
  unless equal?(AbstractTLV)
85
83
  raise Error,
86
84
  '.create cannot be called on a subclass of PacketGen::Types::AbstractTLV'
@@ -88,11 +86,11 @@ module BinStruct
88
86
 
89
87
  klass = Class.new(self)
90
88
  klass.aliases = aliases
91
- klass.field_in_length = field_in_length
89
+ klass.attr_in_length = attr_in_length
92
90
 
93
- check_field_in_length(field_in_length)
94
- check_field_order(field_order)
95
- generate_fields(klass, field_order, type_class, length_class, value_class)
91
+ check_attr_in_length(attr_in_length)
92
+ check_attr_order(attr_order)
93
+ generate_attributes(klass, attr_order, type_class, length_class, value_class)
96
94
 
97
95
  aliases.each do |al, orig|
98
96
  klass.instance_eval do
@@ -106,87 +104,93 @@ module BinStruct
106
104
  # rubocop:enable Metrics/ParameterLists
107
105
 
108
106
  # @!attribute type
109
- # @abstract Type attribute for real TLV class
107
+ # @abstract
108
+ # Type attribute for real TLV class
110
109
  # @return [Integer]
111
110
  # @!attribute length
112
- # @abstract Length attribute for real TLV class
111
+ # @abstract
112
+ # Length attribute for real TLV class
113
113
  # @return [Integer]
114
114
  # @!attribute value
115
- # @abstract Value attribute for real TLV class
115
+ # @abstract
116
+ # Value attribute for real TLV class
116
117
  # @return [Object]
117
118
 
118
119
  # @abstract Should only be called on real TLV classes, created by {.create}.
119
- # Set enum hash for {#type} field.
120
- # @param [Hash{String, Symbol => Integer}] hsh enum hash
120
+ # Set enum hash for {#type} attribute.
121
+ # @param [Hash{::String, Symbol => Integer}] hsh enum hash
121
122
  # @return [void]
122
123
  def define_type_enum(hsh)
123
- field_defs[:type][:options][:enum].clear
124
- field_defs[:type][:options][:enum].merge!(hsh)
124
+ attr_defs[:type][:options][:enum].clear
125
+ attr_defs[:type][:options][:enum].merge!(hsh)
125
126
  end
126
127
 
127
128
  # @abstract Should only be called on real TLV classes, created by {.create}.
128
- # Set default value for {#type} field.
129
- # @param [Integer,String,Symbol,nil] default default value from +hsh+ for type
129
+ # Set default value for {#type} attribute.
130
+ # @param [Integer,::String,Symbol,nil] default default value from +hsh+ for type
130
131
  # @return [void]
131
- # @since 3.4.0
132
132
  def define_type_default(default)
133
- field_defs[:type][:default] = default
133
+ attr_defs[:type][:default] = default
134
134
  end
135
135
 
136
136
  private
137
137
 
138
- def check_field_in_length(field_in_length)
139
- return if /^[TLV]{1,3}$/.match?(field_in_length)
138
+ def check_attr_in_length(attr_in_length)
139
+ return if /^[TLV]{1,3}$/.match?(attr_in_length)
140
140
 
141
- raise 'field_in_length must only contain T, L and/or V characters'
141
+ raise 'attr_in_length must only contain T, L and/or V characters'
142
142
  end
143
143
 
144
- def check_field_order(field_order)
145
- if field_order.match(/^[TLV]{3,3}$/) &&
146
- (field_order[0] != field_order[1]) &&
147
- (field_order[0] != field_order[2]) &&
148
- (field_order[1] != field_order[2])
144
+ def check_attr_order(attr_order)
145
+ if attr_order.match(/^[TLV]{3,3}$/) &&
146
+ (attr_order[0] != attr_order[1]) &&
147
+ (attr_order[0] != attr_order[2]) &&
148
+ (attr_order[1] != attr_order[2])
149
149
  return
150
150
  end
151
151
 
152
- raise 'field_order must contain all three letters TLV, each once'
152
+ raise 'attr_order must contain all three letters TLV, each once'
153
153
  end
154
154
 
155
- def generate_fields(klass, field_order, type_class, length_class, value_class)
156
- field_order.each_char do |field_type|
157
- case field_type
155
+ def generate_attributes(klass, attr_order, type_class, length_class, value_class)
156
+ attr_order.each_char do |attr_type|
157
+ case attr_type
158
158
  when 'T'
159
159
  if type_class < Enum
160
- klass.define_field(:type, type_class, enum: {})
160
+ klass.define_attr(:type, type_class, enum: {})
161
161
  else
162
- klass.define_field(:type, type_class)
162
+ klass.define_attr(:type, type_class)
163
163
  end
164
164
  when 'L'
165
- klass.define_field(:length, length_class)
165
+ klass.define_attr(:length, length_class)
166
166
  when 'V'
167
- klass.define_field(:value, value_class)
167
+ klass.define_attr(:value, value_class)
168
168
  end
169
169
  end
170
170
  end
171
171
  end
172
172
 
173
173
  # @!attribute type
174
- # @abstract Type attribute
174
+ # @abstract
175
+ # Type attribute
175
176
  # @return [Integer]
176
177
  # @!attribute length
177
- # @abstract Length
178
+ # @abstract
179
+ # Length attribute
178
180
  # @return [Integer]
179
181
  # @!attribute value
180
- # @abstract Value attribute
182
+ # @abstract
183
+ # Value attribute
181
184
  # @return [Object]enum
182
185
 
183
186
  # @abstract Should only be called on real TLV classes, created by {.create}.
187
+ # Return a new instance of a real TLV class.
184
188
  # @param [Hash] options
185
189
  # @option options [Integer] :type
186
190
  # @option options [Integer] :length
187
191
  # @option options [Object] :value
188
192
  def initialize(options = {})
189
- @field_in_length = self.class.field_in_length
193
+ @attr_in_length = self.class.attr_in_length
190
194
  self.class.aliases.each do |al, orig|
191
195
  options[orig] = options[al] if options.key?(al)
192
196
  end
@@ -199,17 +203,17 @@ module BinStruct
199
203
 
200
204
  # @abstract Should only be called on real TLV class instances.
201
205
  # Populate object from a binary string
202
- # @param [String,nil] str
203
- # @return [Fields] self
206
+ # @param [::String,nil] str
207
+ # @return [AbstractTLV] self
204
208
  def read(str)
205
209
  return self if str.nil?
206
210
 
207
211
  idx = 0
208
- fields.each do |field_name|
209
- field = self[field_name]
210
- length = field_name == :value ? real_length : field.sz
211
- field.read(str[idx, length])
212
- idx += field.sz
212
+ attributes.each do |attr_name|
213
+ attr = self[attr_name]
214
+ length = attr_name == :value ? real_length : attr.sz
215
+ attr.read(str[idx, length])
216
+ idx += attr.sz
213
217
  end
214
218
 
215
219
  self
@@ -219,7 +223,6 @@ module BinStruct
219
223
  # Set +value+. May set +length+ if value is a {Types::String}.
220
224
  # @param [Object] val
221
225
  # @return [Object]
222
- # @since 3.4.0 Base on field's +#from_human+ method
223
226
  def value=(val)
224
227
  if val.is_a?(self[:value].class)
225
228
  self[:value] = val
@@ -233,27 +236,26 @@ module BinStruct
233
236
 
234
237
  # @abstract Should only be called on real TLV class instances.
235
238
  # Get human-readable type
236
- # @return [String]
239
+ # @return [::String]
237
240
  def human_type
238
241
  self[:type].to_human.to_s
239
242
  end
240
243
 
241
244
  # @abstract Should only be called on real TLV class instances.
242
- # @return [String]
245
+ # @return [::String]
243
246
  def to_human
244
247
  my_value = self[:value].is_a?(String) ? self[:value].inspect : self[:value].to_human
245
248
  'type:%s,length:%u,value:%s' % [human_type, length, my_value]
246
249
  end
247
250
 
248
251
  # Calculate length
249
- # @return [void]
250
- # @since 3.4.0
252
+ # @return [Integer]
251
253
  def calc_length
252
- fil = @field_in_length
254
+ ail = @attr_in_length
253
255
 
254
256
  length = 0
255
- fil.each_char do |field_type|
256
- length += self[FIELD_TYPES[field_type]].sz
257
+ ail.each_char do |attr_type|
258
+ length += self[ATTR_TYPES[attr_type]].sz
257
259
  end
258
260
  self.length = length
259
261
  end
@@ -262,8 +264,8 @@ module BinStruct
262
264
 
263
265
  def real_length
264
266
  length = self.length
265
- length -= self[:type].sz if @field_in_length.include?('T')
266
- length -= self[:length].sz if @field_in_length.include?('L')
267
+ length -= self[:type].sz if @attr_in_length.include?('T')
268
+ length -= self[:length].sz if @attr_in_length.include?('L')
267
269
  length
268
270
  end
269
271
  end
@@ -9,10 +9,15 @@
9
9
  require 'forwardable'
10
10
 
11
11
  module BinStruct
12
- # @abstract Base class to define set of {Fields} subclasses.
12
+ # @abstract Base class to define set of {Struct} subclasses.
13
+ #
14
+ # This class mimics regular Ruby Array, but it is {Structable} and responds to {LengthFrom}.
15
+ #
16
+ # Concrete subclasses may define 2 private methods:
17
+ #
13
18
  # == #record_from_hash
14
- # Subclasses should define private method +#record_from_hash+. This method
15
- # is called by {#push} to add an object to the set.
19
+ # This method
20
+ # is called by {#push} and {#<<} to add an object to the set.
16
21
  #
17
22
  # A default method is defined by {Array}: it calls constructor of class defined
18
23
  # by {.set_of}.
@@ -24,16 +29,17 @@ module BinStruct
24
29
  #
25
30
  # Default behaviour of this method is to return argument's class.
26
31
  #
27
- # @author Sylvain Daubert
32
+ # @author Sylvain Daubert (2016-2024)
33
+ # @author LemonTree55
28
34
  class Array
29
35
  extend Forwardable
30
36
  include Enumerable
31
- include Fieldable
37
+ include Structable
32
38
  include LengthFrom
33
39
 
34
40
  # @!method [](index)
35
41
  # Return the element at +index+.
36
- # @param [integer] index
42
+ # @param [Integer] index
37
43
  # @return [Object]
38
44
  # @!method clear
39
45
  # Clear array.
@@ -41,10 +47,10 @@ module BinStruct
41
47
  # @!method each
42
48
  # Calls the given block once for each element in self, passing that
43
49
  # element as a parameter. Returns the array itself.
44
- # @return [Array]
50
+ # @return [::Array]
45
51
  # @method empty?
46
52
  # Return +true+ if contains no element.
47
- # @return [Booelan]
53
+ # @return [Boolean]
48
54
  # @!method first
49
55
  # Return first element
50
56
  # @return [Object]
@@ -58,14 +64,13 @@ module BinStruct
58
64
  alias length size
59
65
 
60
66
  # Separator used in {#to_human}.
61
- # May be ovverriden by subclasses
67
+ # May be overriden by subclasses
62
68
  HUMAN_SEPARATOR = ','
63
69
 
64
70
  # rubocop:disable Naming/AccessorMethodName
65
71
  class << self
66
72
  # Get class set with {.set_of}.
67
73
  # @return [Class]
68
- # @since 3.0.0
69
74
  def set_of_klass
70
75
  @klass
71
76
  end
@@ -89,10 +94,13 @@ module BinStruct
89
94
 
90
95
  # Initialize array for copy:
91
96
  # * duplicate internal array.
97
+ # @note Associated counter, if any, is not duplicated
92
98
  def initialize_copy(_other)
93
99
  @array = @array.dup
94
100
  end
95
101
 
102
+ # Check equality. Equality is checked on underlying array.
103
+ # @return [Boolean]
96
104
  def ==(other)
97
105
  @array == case other
98
106
  when Array
@@ -118,7 +126,7 @@ module BinStruct
118
126
  deleted
119
127
  end
120
128
 
121
- # Delete element at +index+.
129
+ # Delete element at +index+. Update associated counter if any
122
130
  # @param [Integer] index
123
131
  # @return [Object,nil] deleted object
124
132
  def delete_at(index)
@@ -129,13 +137,14 @@ module BinStruct
129
137
 
130
138
  # @abstract depend on private method +#record_from_hash+ which should be
131
139
  # declared by subclasses.
132
- # Add an object to this array
140
+ # Add an object to this array. Do not update associated counter.
133
141
  # @param [Object] obj type depends on subclass
134
- # @return [Array] self
142
+ # @return [self]
143
+ # @see #<<
135
144
  def push(obj)
136
145
  obj = case obj
137
146
  when Hash
138
- record_from_hash obj
147
+ record_from_hash(obj)
139
148
  else
140
149
  obj
141
150
  end
@@ -147,15 +156,15 @@ module BinStruct
147
156
  # declared by subclasses.
148
157
  # Add an object to this array, and increment associated counter, if any
149
158
  # @param [Object] obj type depends on subclass
150
- # @return [Array] self
159
+ # @return [self]
151
160
  def <<(obj)
152
- push obj
161
+ push(obj)
153
162
  @counter&.from_human(@counter.to_i + 1)
154
163
  self
155
164
  end
156
165
 
157
166
  # Populate object from a string or from an array of hashes
158
- # @param [String, Array<Hash>] data
167
+ # @param [::String, ::Array<Hash>] data
159
168
  # @return [self]
160
169
  def read(data)
161
170
  clear
@@ -174,20 +183,20 @@ module BinStruct
174
183
  to_s.size
175
184
  end
176
185
 
177
- # Return an Array
186
+ # Return underlying Ruby Array
178
187
  # @return [::Array]
179
188
  def to_a
180
189
  @array
181
190
  end
182
191
 
183
192
  # Get binary string
184
- # @return [String]
193
+ # @return [::String]
185
194
  def to_s
186
195
  @array.map(&:to_s).join
187
196
  end
188
197
 
189
198
  # Get a human readable string
190
- # @return [String]
199
+ # @return [::String]
191
200
  def to_human
192
201
  @array.map(&:to_human).join(self.class::HUMAN_SEPARATOR)
193
202
  end
@@ -251,36 +260,36 @@ module BinStruct
251
260
  return self if ary.empty?
252
261
 
253
262
  ary.each do |i|
254
- self << self.class.set_of_klass.new(i)
263
+ self << self.class.set_of_klass.new(value: i)
255
264
  end
256
265
  end
257
266
  end
258
267
 
259
- # Specialized array to handle serie of {Int8}.
268
+ # Specialized {Array} to handle serie of {Int8}.
260
269
  class ArrayOfInt8 < Array
261
270
  include ArrayOfIntMixin
262
271
  set_of Int8
263
272
  end
264
273
 
265
- # Specialized array to handle serie of {Int16}.
274
+ # Specialized {Array} to handle serie of {Int16}.
266
275
  class ArrayOfInt16 < Array
267
276
  include ArrayOfIntMixin
268
277
  set_of Int16
269
278
  end
270
279
 
271
- # Specialized array to handle serie of {Int16le}.
280
+ # Specialized {Array} to handle serie of {Int16le}.
272
281
  class ArrayOfInt16le < Array
273
282
  include ArrayOfIntMixin
274
283
  set_of Int16le
275
284
  end
276
285
 
277
- # Specialized array to handle serie of {Int32}.
286
+ # Specialized {Array} to handle serie of {Int32}.
278
287
  class ArrayOfInt32 < BinStruct::Array
279
288
  include ArrayOfIntMixin
280
289
  set_of Int32
281
290
  end
282
291
 
283
- # Specialized array to handle serie of {Int32le}.
292
+ # Specialized {Array} to handle serie of {Int32le}.
284
293
  class ArrayOfInt32le < BinStruct::Array
285
294
  include ArrayOfIntMixin
286
295
  set_of Int32le
@@ -10,19 +10,68 @@ require 'forwardable'
10
10
 
11
11
  module BinStruct
12
12
  # This class handles null-terminated strings (aka C strings).
13
- # @author Sylvain Daubert
14
- # @since 3.1.6 no more a subclass or regular String
13
+ # @author Sylvain Daubert (2016-2024)
14
+ # @author LemonTree55
15
15
  class CString
16
16
  extend Forwardable
17
- include Fieldable
18
-
17
+ include Structable
18
+
19
+ # @!method [](index)
20
+ # @overload [](index)
21
+ # Return the character at +index+.
22
+ # @param [Integer] index
23
+ # @overload [](start, length)
24
+ # Return the substring starting at +start+ with +length+ length.
25
+ # @param [Integer] start
26
+ # @param [Integer] length
27
+ # @return [::String,nil]
28
+ # @!method length
29
+ # Return string length (without null-terminator)
30
+ # @return [Integer]
31
+ # @method size
32
+ # Return string length (without null-terminator)
33
+ # @return [Integer]
34
+ # @see #length
35
+ # @!method ==
36
+ # Check equality with underlying Ruby String
37
+ # @return [Boolean]
38
+ # @!method unpack
39
+ # Apply unpack on underlying Ruby String
40
+ # @see ::String#unpack
41
+ # @return [::Array]
42
+ # @!method force_encoding
43
+ # @see ::String#force_encoding
44
+ # @!method encoding
45
+ # @see ::String#encoding
46
+ # @return [Encoding]
47
+ # @!method index(substring, offset = 0)
48
+ # Returns the Integer index of the first occurrence of the given substring, or +nil+ if none found.
49
+ # @param [::String] substring
50
+ # @param [Integer] offset
51
+ # @return [Integer,nil]
52
+ # @!method empty?
53
+ # Return +true+ is string is empty.
54
+ # @return [Boolean]
55
+ # @!method encode(encoding, **options)
56
+ # @return [::String]
57
+ # @see ::String#encode
58
+ # @!method slice(*args)
59
+ # Returns the substring of +self+ specified by the arguments.
60
+ # @see ::String#slice
61
+ # @return [String,nil]
62
+ # @!method slice!(*args)
63
+ # Removes the substring of +self+ specified by the arguments; returns the removed substring.
64
+ # @see ::String#slice!
65
+ # @return [String,nil]
19
66
  def_delegators :@string, :[], :length, :size, :inspect, :==,
20
67
  :unpack, :force_encoding, :encoding, :index, :empty?,
21
68
  :encode, :slice, :slice!
22
69
 
70
+ # Underlying Ruby String
23
71
  # @return [::String]
24
72
  attr_reader :string
25
- # @return [Integer]
73
+ # Static length, if any
74
+ # @return [Integer,nil]
26
75
  attr_reader :static_length
27
76
 
28
77
  # @param [Hash] options
@@ -32,8 +81,9 @@ module BinStruct
32
81
  @static_length = options[:static_length]
33
82
  end
34
83
 
84
+ # Populate self from binary string
35
85
  # @param [::String] str
36
- # @return [String] self
86
+ # @return [self]
37
87
  def read(str)
38
88
  s = str.to_s
39
89
  s = s[0, static_length] if static_length?
@@ -42,8 +92,8 @@ module BinStruct
42
92
  self
43
93
  end
44
94
 
45
- # get null-terminated string
46
- # @return [String]
95
+ # Get null-terminated string
96
+ # @return [::String]
47
97
  def to_s
48
98
  if static_length?
49
99
  s = string[0, static_length - 1]
@@ -63,6 +113,7 @@ module BinStruct
63
113
  self
64
114
  end
65
115
 
116
+ # Get C String size in bytes
66
117
  # @return [Integer]
67
118
  def sz
68
119
  if static_length?
@@ -74,19 +125,19 @@ module BinStruct
74
125
 
75
126
  # Say if a static length is defined
76
127
  # @return [Boolean]
77
- # @since 3.1.6
78
128
  def static_length?
79
129
  !static_length.nil?
80
130
  end
81
131
 
82
132
  # Populate CString from a human readable string
83
- # @param [String] str
133
+ # @param [::String] str
84
134
  # @return [self]
85
135
  def from_human(str)
86
136
  read str
87
137
  end
88
138
 
89
- # @return [String]
139
+ # Get human-readable string
140
+ # @return [::String]
90
141
  def to_human
91
142
  string
92
143
  end