bindata 2.3.3 → 2.3.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bindata might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ChangeLog.rdoc +4 -0
- data/Rakefile +2 -2
- data/examples/gzip.rb +24 -24
- data/examples/ip_address.rb +3 -4
- data/examples/list.rb +20 -20
- data/examples/nbt.rb +14 -14
- data/examples/tcp_ip.rb +12 -14
- data/lib/bindata/alignment.rb +2 -2
- data/lib/bindata/array.rb +22 -23
- data/lib/bindata/base.rb +13 -12
- data/lib/bindata/base_primitive.rb +20 -17
- data/lib/bindata/bits.rb +4 -4
- data/lib/bindata/buffer.rb +5 -5
- data/lib/bindata/choice.rb +11 -13
- data/lib/bindata/count_bytes_remaining.rb +1 -2
- data/lib/bindata/delayed_io.rb +11 -11
- data/lib/bindata/dsl.rb +57 -64
- data/lib/bindata/float.rb +16 -13
- data/lib/bindata/int.rb +6 -6
- data/lib/bindata/io.rb +16 -16
- data/lib/bindata/lazy.rb +3 -3
- data/lib/bindata/name.rb +2 -2
- data/lib/bindata/offset.rb +3 -3
- data/lib/bindata/params.rb +13 -15
- data/lib/bindata/primitive.rb +3 -3
- data/lib/bindata/registry.rb +12 -12
- data/lib/bindata/rest.rb +1 -2
- data/lib/bindata/sanitize.rb +17 -18
- data/lib/bindata/skip.rb +7 -8
- data/lib/bindata/string.rb +6 -6
- data/lib/bindata/stringz.rb +3 -3
- data/lib/bindata/struct.rb +16 -16
- data/lib/bindata/trace.rb +9 -8
- data/lib/bindata/version.rb +1 -1
- data/lib/bindata/virtual.rb +3 -3
- data/lib/bindata/warnings.rb +6 -2
- data/test/alignment_test.rb +4 -4
- data/test/array_test.rb +29 -29
- data/test/base_primitive_test.rb +17 -17
- data/test/base_test.rb +6 -6
- data/test/bits_test.rb +1 -1
- data/test/buffer_test.rb +19 -19
- data/test/choice_test.rb +20 -20
- data/test/count_bytes_remaining_test.rb +1 -1
- data/test/delayed_io_test.rb +26 -26
- data/test/lazy_test.rb +16 -16
- data/test/offset_test.rb +8 -8
- data/test/params_test.rb +11 -11
- data/test/primitive_test.rb +11 -11
- data/test/record_test.rb +50 -50
- data/test/registry_test.rb +26 -26
- data/test/rest_test.rb +1 -1
- data/test/skip_test.rb +27 -27
- data/test/string_test.rb +24 -24
- data/test/stringz_test.rb +1 -1
- data/test/struct_test.rb +76 -75
- data/test/system_test.rb +51 -51
- data/test/virtual_test.rb +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a8a6f316e5cf5c69644ea1e3f841ad322c0e02f
|
4
|
+
data.tar.gz: bf847f59e5d21294aa23a8e55b30316259917995
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce1e8ebef76eca71f03e78fd5d0443b489965433848f4d05137cb02b8e6b90db535fa97cd9e1987d93eddeba11cf8c96fd1cbc4cd2f8f83145a88728d1e65a7f
|
7
|
+
data.tar.gz: 49df943ca5a0347649bfd35f2307f17cd4cb0308472c6d8f4341bd65926b9a805b7e0ad75bab3db71d83f4e6803be32a03fe7e996ddb8455d9b3b5952ab79c02
|
data/ChangeLog.rdoc
CHANGED
data/Rakefile
CHANGED
data/examples/gzip.rb
CHANGED
@@ -22,33 +22,33 @@ class Gzip < BinData::Record
|
|
22
22
|
|
23
23
|
endian :little
|
24
24
|
|
25
|
-
uint16 :ident, :
|
26
|
-
uint8 :compression_method, :
|
27
|
-
|
28
|
-
bit3 :freserved, :
|
29
|
-
bit1 :fcomment, :
|
30
|
-
bit1 :ffile_name, :
|
31
|
-
bit1 :fextra, :
|
32
|
-
bit1 :fcrc16, :
|
25
|
+
uint16 :ident, asserted_value: 0x8b1f
|
26
|
+
uint8 :compression_method, initial_value: DEFLATE
|
27
|
+
|
28
|
+
bit3 :freserved, asserted_value: 0
|
29
|
+
bit1 :fcomment, value: -> { comment.length > 0 ? 1 : 0 }
|
30
|
+
bit1 :ffile_name, value: -> { file_name.length > 0 ? 1 : 0 }
|
31
|
+
bit1 :fextra, value: -> { extra.len > 0 ? 1 : 0 }
|
32
|
+
bit1 :fcrc16, value: 0 # see note at end of file
|
33
33
|
bit1 :ftext
|
34
34
|
|
35
35
|
mtime :mtime
|
36
36
|
uint8 :extra_flags
|
37
|
-
uint8 :os, :
|
37
|
+
uint8 :os, initial_value: 255 # unknown OS
|
38
38
|
|
39
39
|
# The following fields are optional depending on the bits in flags
|
40
40
|
|
41
|
-
struct :extra, :
|
42
|
-
uint16 :len, :
|
43
|
-
string :data, :
|
41
|
+
struct :extra, onlyif: -> { fextra.nonzero? } do
|
42
|
+
uint16 :len, length: -> { data.length }
|
43
|
+
string :data, read_length: :len
|
44
44
|
end
|
45
|
-
stringz :file_name, :
|
46
|
-
stringz :comment, :
|
47
|
-
uint16 :crc16, :
|
45
|
+
stringz :file_name, onlyif: -> { ffile_name.nonzero? }
|
46
|
+
stringz :comment, onlyif: -> { fcomment.nonzero? }
|
47
|
+
uint16 :crc16, onlyif: -> { fcrc16.nonzero? }
|
48
48
|
|
49
49
|
# The length of compressed data must be calculated from the current file offset
|
50
50
|
count_bytes_remaining :bytes_remaining
|
51
|
-
string :compressed_data, :
|
51
|
+
string :compressed_data, read_length: -> { bytes_remaining - footer.num_bytes }
|
52
52
|
|
53
53
|
struct :footer do
|
54
54
|
uint32 :crc32
|
@@ -97,14 +97,14 @@ if __FILE__ == $0
|
|
97
97
|
# Output using the same format as gzip -l -v
|
98
98
|
puts "method crc date time compressed " +
|
99
99
|
"uncompressed ratio uncompressed_name"
|
100
|
-
puts "%5s %08x %6s %5s %19s %19s %5.1f%% %s"
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
100
|
+
puts "%5s %08x %6s %5s %19s %19s %5.1f%% %s" % [comp_meth,
|
101
|
+
g.footer.crc32,
|
102
|
+
g.mtime.strftime('%b %d'),
|
103
|
+
g.mtime.strftime('%H:%M'),
|
104
|
+
g.num_bytes,
|
105
|
+
g.footer.uncompressed_size,
|
106
|
+
ratio,
|
107
|
+
g.file_name]
|
108
108
|
puts "Comment: #{g.comment}" if g.comment?
|
109
109
|
puts
|
110
110
|
|
data/examples/ip_address.rb
CHANGED
@@ -4,15 +4,14 @@ require 'bindata'
|
|
4
4
|
# The underlying binary representation is a sequence of four octets.
|
5
5
|
# The human accessible representation is a dotted quad.
|
6
6
|
class IPAddr < BinData::Primitive
|
7
|
-
array :octets, :
|
7
|
+
array :octets, type: :uint8, initial_length: 4
|
8
8
|
|
9
9
|
def set(val)
|
10
|
-
|
11
|
-
self.octets = ints
|
10
|
+
self.octets = val.split(/\./).map(&:to_i)
|
12
11
|
end
|
13
12
|
|
14
13
|
def get
|
15
|
-
self.octets.
|
14
|
+
self.octets.map(&:to_s).join(".")
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
data/examples/list.rb
CHANGED
@@ -20,15 +20,15 @@ require 'bindata'
|
|
20
20
|
# A first attempt at a declaration would be:
|
21
21
|
#
|
22
22
|
# class Atom < BinData::Record
|
23
|
-
# string :tag, :
|
23
|
+
# string :tag, length: 1, assert: 'a'
|
24
24
|
# int32be :val
|
25
25
|
# end
|
26
26
|
#
|
27
27
|
# class List < BinData::Record
|
28
|
-
# string :tag, :
|
29
|
-
# int32be :num, :
|
30
|
-
# array :vals, :
|
31
|
-
# choice :
|
28
|
+
# string :tag, length: 1, assert: 'l'
|
29
|
+
# int32be :num, value: -> { vals.length }
|
30
|
+
# array :vals, initial_length: :num do
|
31
|
+
# choice selection: ??? do
|
32
32
|
# atom
|
33
33
|
# list
|
34
34
|
# end
|
@@ -50,18 +50,18 @@ require 'bindata'
|
|
50
50
|
# The declaration then becomes:
|
51
51
|
#
|
52
52
|
# class Term < BinData::Record; end # forward declaration
|
53
|
-
#
|
53
|
+
#
|
54
54
|
# class Atom < BinData::Int32be
|
55
55
|
# end
|
56
|
-
#
|
56
|
+
#
|
57
57
|
# class List < BinData::Record
|
58
|
-
# int32be :num, :
|
59
|
-
# array :vals, :
|
58
|
+
# int32be :num, value: -> { vals.length }
|
59
|
+
# array :vals, type: :term, initial_length: :num
|
60
60
|
# end
|
61
|
-
#
|
61
|
+
#
|
62
62
|
# class Term < BinData::Record
|
63
|
-
# string :tag, :
|
64
|
-
# choice :term, :
|
63
|
+
# string :tag, length: 1
|
64
|
+
# choice :term, selection: :tag do
|
65
65
|
# atom 'a'
|
66
66
|
# list 'l'
|
67
67
|
# end
|
@@ -81,21 +81,21 @@ class Atom < BinData::Int32be
|
|
81
81
|
end
|
82
82
|
|
83
83
|
class List < BinData::Record
|
84
|
-
int32be :num, :
|
85
|
-
array :vals, :
|
84
|
+
int32be :num, value: -> { vals.length }
|
85
|
+
array :vals, initial_length: :num, type: :term
|
86
86
|
|
87
87
|
def decode
|
88
|
-
vals.collect
|
88
|
+
vals.collect(&:decode)
|
89
89
|
end
|
90
90
|
|
91
91
|
def self.encode(val)
|
92
|
-
List.new(:
|
92
|
+
List.new(vals: val.collect { |v| Term.encode(v) })
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
96
|
class Term < BinData::Record
|
97
|
-
string :tag, :
|
98
|
-
choice :term, :
|
97
|
+
string :tag, length: 1
|
98
|
+
choice :term, selection: :tag do
|
99
99
|
atom 'a'
|
100
100
|
list 'l'
|
101
101
|
end
|
@@ -106,9 +106,9 @@ class Term < BinData::Record
|
|
106
106
|
|
107
107
|
def self.encode(val)
|
108
108
|
if Fixnum === val
|
109
|
-
Term.new(:
|
109
|
+
Term.new(tag: 'a', term: Atom.encode(val))
|
110
110
|
else
|
111
|
-
Term.new(:
|
111
|
+
Term.new(tag: 'l', term: List.encode(val))
|
112
112
|
end
|
113
113
|
end
|
114
114
|
end
|
data/examples/nbt.rb
CHANGED
@@ -61,8 +61,8 @@ module Nbt
|
|
61
61
|
|
62
62
|
# NBT.txt line 49
|
63
63
|
class TagByteArray < BinData::Record
|
64
|
-
int32be :len,
|
65
|
-
string :data, :
|
64
|
+
int32be :len, value: -> { data.length }
|
65
|
+
string :data, read_length: :len
|
66
66
|
|
67
67
|
def to_formatted_s(indent = 0)
|
68
68
|
"[#{len} bytes]"
|
@@ -71,8 +71,8 @@ module Nbt
|
|
71
71
|
|
72
72
|
# NBT.txt line 53
|
73
73
|
class TagString < BinData::Primitive
|
74
|
-
int16be :len,
|
75
|
-
string :data, :
|
74
|
+
int16be :len, value: -> { data.length }
|
75
|
+
string :data, read_length: :len
|
76
76
|
|
77
77
|
def get
|
78
78
|
self.data
|
@@ -87,7 +87,7 @@ module Nbt
|
|
87
87
|
|
88
88
|
## Payload is the most important class to understand.
|
89
89
|
## This abstraction allows recursive formats.
|
90
|
-
## eg. lists can contain lists can contain lists.
|
90
|
+
## eg. lists can contain lists can contain lists.
|
91
91
|
|
92
92
|
# Forward references used by Payload
|
93
93
|
class TagCompound < BinData::Record; end
|
@@ -111,8 +111,8 @@ module Nbt
|
|
111
111
|
# NBT.txt line 6, 27
|
112
112
|
class NamedTag < BinData::Record
|
113
113
|
int8 :tag_id
|
114
|
-
tag_string :name, :
|
115
|
-
payload :payload, :
|
114
|
+
tag_string :name, onlyif: :not_end_tag?
|
115
|
+
payload :payload, onlyif: :not_end_tag?, selection: :tag_id
|
116
116
|
|
117
117
|
def not_end_tag?
|
118
118
|
tag_id != 0
|
@@ -127,10 +127,10 @@ module Nbt
|
|
127
127
|
|
128
128
|
# NBT.txt line 57
|
129
129
|
class TagList < BinData::Record
|
130
|
-
int8
|
131
|
-
int32be :len,
|
132
|
-
array
|
133
|
-
payload :
|
130
|
+
int8 :tag_id
|
131
|
+
int32be :len, value: -> { data.length }
|
132
|
+
array :data, initial_length: :len do
|
133
|
+
payload selection: :tag_id
|
134
134
|
end
|
135
135
|
|
136
136
|
def to_formatted_s(indent = 0)
|
@@ -138,7 +138,7 @@ module Nbt
|
|
138
138
|
tag_type = "TAG_#{TAG_NAMES[tag_id]}"
|
139
139
|
|
140
140
|
"#{len} entries of type #{tag_type}\n" +
|
141
|
-
pre + "{\n" +
|
141
|
+
pre + "{\n" +
|
142
142
|
data.collect { |el| " #{pre}#{tag_type}: #{el.to_formatted_s(indent + 1)}\n" }.join("") +
|
143
143
|
pre + "}"
|
144
144
|
end
|
@@ -146,14 +146,14 @@ module Nbt
|
|
146
146
|
|
147
147
|
# NBT.txt line 63
|
148
148
|
class TagCompound < BinData::Record
|
149
|
-
array :data, :
|
149
|
+
array :data, read_until: -> { element.tag_id == 0 } do
|
150
150
|
named_tag
|
151
151
|
end
|
152
152
|
|
153
153
|
def to_formatted_s(indent = 0)
|
154
154
|
pre = " " * indent
|
155
155
|
"#{data.length - 1} entries\n" +
|
156
|
-
pre + "{\n" +
|
156
|
+
pre + "{\n" +
|
157
157
|
data[0..-2].collect { |el| el.to_formatted_s(indent + 1) }.join("") +
|
158
158
|
pre + "}"
|
159
159
|
end
|
data/examples/tcp_ip.rb
CHANGED
@@ -11,11 +11,10 @@ require 'bindata'
|
|
11
11
|
|
12
12
|
# Present MAC addresses in a human readable way
|
13
13
|
class MacAddr < BinData::Primitive
|
14
|
-
array :octets, :
|
14
|
+
array :octets, type: :uint8, initial_length: 6
|
15
15
|
|
16
16
|
def set(val)
|
17
|
-
|
18
|
-
self.octets = ints
|
17
|
+
self.octets = val.split(/\./).collect(&:to_i)
|
19
18
|
end
|
20
19
|
|
21
20
|
def get
|
@@ -25,11 +24,10 @@ end
|
|
25
24
|
|
26
25
|
# Present IP addresses in a human readable way
|
27
26
|
class IPAddr < BinData::Primitive
|
28
|
-
array :octets, :
|
27
|
+
array :octets, type: :uint8, initial_length: 4
|
29
28
|
|
30
29
|
def set(val)
|
31
|
-
|
32
|
-
self.octets = ints
|
30
|
+
self.octets = val.split(/\./).collect(&:to_i)
|
33
31
|
end
|
34
32
|
|
35
33
|
def get
|
@@ -57,7 +55,7 @@ class TCP_PDU < BinData::Record
|
|
57
55
|
uint16 :window
|
58
56
|
uint16 :checksum
|
59
57
|
uint16 :urg_ptr
|
60
|
-
string :options, :
|
58
|
+
string :options, read_length: :options_length_in_bytes
|
61
59
|
rest :payload
|
62
60
|
|
63
61
|
def options_length_in_bytes
|
@@ -80,7 +78,7 @@ end
|
|
80
78
|
class IP_PDU < BinData::Record
|
81
79
|
endian :big
|
82
80
|
|
83
|
-
bit4 :version, :
|
81
|
+
bit4 :version, asserted_value: 4
|
84
82
|
bit4 :header_length
|
85
83
|
uint8 :tos
|
86
84
|
uint16 :total_length
|
@@ -92,9 +90,9 @@ class IP_PDU < BinData::Record
|
|
92
90
|
uint16 :checksum
|
93
91
|
ip_addr :src_addr
|
94
92
|
ip_addr :dest_addr
|
95
|
-
string :options, :
|
96
|
-
buffer :payload, :
|
97
|
-
choice :payload, :
|
93
|
+
string :options, read_length: :options_length_in_bytes
|
94
|
+
buffer :payload, length: :payload_length_in_bytes do
|
95
|
+
choice :payload, selection: :protocol do
|
98
96
|
tcp_pdu 6
|
99
97
|
udp_pdu 17
|
100
98
|
rest :default
|
@@ -122,7 +120,7 @@ class Ether < BinData::Record
|
|
122
120
|
mac_addr :dst
|
123
121
|
mac_addr :src
|
124
122
|
uint16 :ether_type
|
125
|
-
choice :payload, :
|
123
|
+
choice :payload, selection: :ether_type do
|
126
124
|
ip_pdu IPV4
|
127
125
|
rest :default
|
128
126
|
end
|
@@ -155,12 +153,12 @@ class Pcap
|
|
155
153
|
uint32 :linktype
|
156
154
|
end
|
157
155
|
|
158
|
-
array :records, :
|
156
|
+
array :records, read_until: :eof do
|
159
157
|
uint32 :ts_sec
|
160
158
|
uint32 :ts_usec
|
161
159
|
uint32 :incl_len
|
162
160
|
uint32 :orig_len
|
163
|
-
string :data, :
|
161
|
+
string :data, length: :incl_len
|
164
162
|
end
|
165
163
|
end
|
166
164
|
end
|
data/lib/bindata/alignment.rb
CHANGED
@@ -37,7 +37,7 @@ module BinData
|
|
37
37
|
#
|
38
38
|
# class MyRecord < BinData::Record
|
39
39
|
# bit4 :preamble
|
40
|
-
# bit_string :str, :
|
40
|
+
# bit_string :str, length: 2
|
41
41
|
# end
|
42
42
|
#
|
43
43
|
module BitAligned
|
@@ -46,7 +46,7 @@ module BinData
|
|
46
46
|
@io = io
|
47
47
|
end
|
48
48
|
def readbytes(n)
|
49
|
-
n.times.inject("") do |bytes,
|
49
|
+
n.times.inject("") do |bytes, _|
|
50
50
|
bytes << @io.readbits(8, :big).chr
|
51
51
|
end
|
52
52
|
end
|
data/lib/bindata/array.rb
CHANGED
@@ -8,22 +8,22 @@ module BinData
|
|
8
8
|
#
|
9
9
|
# data = "\x03\x04\x05\x06\x07\x08\x09"
|
10
10
|
#
|
11
|
-
# obj = BinData::Array.new(:
|
11
|
+
# obj = BinData::Array.new(type: :int8, initial_length: 6)
|
12
12
|
# obj.read(data) #=> [3, 4, 5, 6, 7, 8]
|
13
13
|
#
|
14
|
-
# obj = BinData::Array.new(:
|
15
|
-
# :
|
14
|
+
# obj = BinData::Array.new(type: :int8,
|
15
|
+
# read_until: -> { index == 1 })
|
16
16
|
# obj.read(data) #=> [3, 4]
|
17
17
|
#
|
18
|
-
# obj = BinData::Array.new(:
|
19
|
-
# :
|
18
|
+
# obj = BinData::Array.new(type: :int8,
|
19
|
+
# read_until: -> { element >= 6 })
|
20
20
|
# obj.read(data) #=> [3, 4, 5, 6]
|
21
21
|
#
|
22
|
-
# obj = BinData::Array.new(:
|
23
|
-
# :
|
22
|
+
# obj = BinData::Array.new(type: :int8,
|
23
|
+
# read_until: -> { array[index] + array[index - 1] == 13 })
|
24
24
|
# obj.read(data) #=> [3, 4, 5, 6, 7]
|
25
25
|
#
|
26
|
-
# obj = BinData::Array.new(:
|
26
|
+
# obj = BinData::Array.new(type: :int8, read_until: :eof)
|
27
27
|
# obj.read(data) #=> [3, 4, 5, 6, 7, 8, 9]
|
28
28
|
#
|
29
29
|
# == Parameters
|
@@ -76,7 +76,7 @@ module BinData
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def clear?
|
79
|
-
@element_list.nil?
|
79
|
+
@element_list.nil? || elements.all?(&:clear?)
|
80
80
|
end
|
81
81
|
|
82
82
|
def assign(array)
|
@@ -86,13 +86,13 @@ module BinData
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def snapshot
|
89
|
-
elements.collect
|
89
|
+
elements.collect(&:snapshot)
|
90
90
|
end
|
91
91
|
|
92
92
|
def find_index(obj)
|
93
93
|
elements.index(obj)
|
94
94
|
end
|
95
|
-
|
95
|
+
alias index find_index
|
96
96
|
|
97
97
|
# Returns the first index of +obj+ in self.
|
98
98
|
#
|
@@ -105,7 +105,7 @@ module BinData
|
|
105
105
|
insert(-1, *args)
|
106
106
|
self
|
107
107
|
end
|
108
|
-
|
108
|
+
alias << push
|
109
109
|
|
110
110
|
def unshift(*args)
|
111
111
|
insert(0, *args)
|
@@ -125,18 +125,18 @@ module BinData
|
|
125
125
|
|
126
126
|
# Returns the element at +index+.
|
127
127
|
def [](arg1, arg2 = nil)
|
128
|
-
if arg1.respond_to?(:to_int)
|
128
|
+
if arg1.respond_to?(:to_int) && arg2.nil?
|
129
129
|
slice_index(arg1.to_int)
|
130
|
-
elsif arg1.respond_to?(:to_int)
|
130
|
+
elsif arg1.respond_to?(:to_int) && arg2.respond_to?(:to_int)
|
131
131
|
slice_start_length(arg1.to_int, arg2.to_int)
|
132
|
-
elsif arg1.is_a?(Range)
|
132
|
+
elsif arg1.is_a?(Range) && arg2.nil?
|
133
133
|
slice_range(arg1)
|
134
134
|
else
|
135
135
|
raise TypeError, "can't convert #{arg1} into Integer" unless arg1.respond_to?(:to_int)
|
136
136
|
raise TypeError, "can't convert #{arg2} into Integer" unless arg2.respond_to?(:to_int)
|
137
137
|
end
|
138
138
|
end
|
139
|
-
|
139
|
+
alias slice []
|
140
140
|
|
141
141
|
def slice_index(index)
|
142
142
|
extend_array(index)
|
@@ -168,7 +168,7 @@ module BinData
|
|
168
168
|
# If the array is empty, the first form returns nil, and the second
|
169
169
|
# form returns an empty array.
|
170
170
|
def first(n = nil)
|
171
|
-
if n.nil?
|
171
|
+
if n.nil? && empty?
|
172
172
|
# explicitly return nil as arrays grow automatically
|
173
173
|
nil
|
174
174
|
elsif n.nil?
|
@@ -193,7 +193,7 @@ module BinData
|
|
193
193
|
def length
|
194
194
|
elements.length
|
195
195
|
end
|
196
|
-
|
196
|
+
alias size length
|
197
197
|
|
198
198
|
def empty?
|
199
199
|
length.zero?
|
@@ -275,7 +275,7 @@ module BinData
|
|
275
275
|
|
276
276
|
class ArrayArgProcessor < BaseArgProcessor
|
277
277
|
def sanitize_parameters!(obj_class, params) #:nodoc:
|
278
|
-
unless params.has_parameter?(:initial_length)
|
278
|
+
unless params.has_parameter?(:initial_length) ||
|
279
279
|
params.has_parameter?(:read_until)
|
280
280
|
# ensure one of :initial_length and :read_until exists
|
281
281
|
params[:initial_length] = 0
|
@@ -300,15 +300,14 @@ module BinData
|
|
300
300
|
loop do
|
301
301
|
element = append_new_element
|
302
302
|
element.do_read(io)
|
303
|
-
variables = { :
|
304
|
-
:
|
303
|
+
variables = { index: self.length - 1, element: self.last,
|
304
|
+
array: self }
|
305
305
|
break if eval_parameter(:read_until, variables)
|
306
306
|
end
|
307
307
|
end
|
308
|
-
|
309
308
|
end
|
310
309
|
|
311
|
-
# Logic for the :
|
310
|
+
# Logic for the read_until: :eof parameter
|
312
311
|
module ReadUntilEOFPlugin
|
313
312
|
def do_read(io)
|
314
313
|
loop do
|