binary_struct 2.0.0 → 2.1.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 +7 -0
- data/README.md +26 -5
- data/lib/binary_struct.rb +16 -6
- data/lib/binary_struct/version.rb +1 -1
- data/spec/binary_struct_spec.rb +35 -9
- data/spec/endian_spec.rb +39 -28
- metadata +20 -35
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 390c83f0ae9d53e2c123bfe3190fb1be90573895
|
4
|
+
data.tar.gz: 548e8d4c5b6ba5c17af72412fe8ed8c9e15f48f8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fc67fb8689529bb62ecbec209f2b0a14e04ef60d97a4c8c88520aaca0d754ab33f803537609ac658d57a74671bf25f216b0f1d89f1fc065306f897500fb5320d
|
7
|
+
data.tar.gz: 150aeaf98ef9a9b483d97fbd6f4a8fee590149da79b6b53189f219dd96b314e12870888a26f2206683a223fbf926f394a2cc75f2a4a064586f5ef5056c0267cb
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# BinaryStruct
|
2
2
|
|
3
|
-
[](http://badge.fury.io/rb/binary_struct)
|
4
|
+
[](https://travis-ci.org/ManageIQ/binary_struct)
|
5
|
+
[](https://codeclimate.com/github/ManageIQ/binary_struct)
|
6
|
+
[](https://coveralls.io/r/ManageIQ/binary_struct)
|
7
|
+
[](https://gemnasium.com/ManageIQ/binary_struct)
|
8
8
|
|
9
9
|
BinaryStruct is a class for dealing with binary structured data. It simplifies
|
10
10
|
expressing what the binary structure looks like, with the ability to name the
|
@@ -65,6 +65,27 @@ File.open("test.gif", "wb") { |f| f.write(header) }
|
|
65
65
|
=> "GIF89a\x10\x00\x10\x00\x80\x00\x00"
|
66
66
|
```
|
67
67
|
|
68
|
+
## Note about bit and nibble formats
|
69
|
+
|
70
|
+
BinaryStruct supports bit formats and nibble formats, however note that the
|
71
|
+
underlying Ruby methods, [pack](http://ruby-doc.org/core-2.2.0/Array.html#method-i-pack)
|
72
|
+
and [unpack](http://ruby-doc.org/core-2.2.0/String.html#method-i-unpack), support
|
73
|
+
less than 8 bits by reading an entire byte, even if all of the bits are not used.
|
74
|
+
|
75
|
+
For example,
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
s = "\xFF\x00" # binary: 1111111100000000
|
79
|
+
s.unpack("b8b8") # => ["11111111", "00000000"]
|
80
|
+
s.unpack("b4b4b4b4") # => ["1111", "0000", "", ""]
|
81
|
+
```
|
82
|
+
|
83
|
+
One might expect that the latter would read 4 bits, then the next 4 bits, etc,
|
84
|
+
yielding `["1111", "1111", "0000", "0000"]`, but that is not the case. Instead,
|
85
|
+
the first b4 reads a full byte's worth, then discards the unused 4 bits, and the
|
86
|
+
same happens for the next b4. The third and fourth b4 have nothing left to read,
|
87
|
+
and so just return empty strings.
|
88
|
+
|
68
89
|
## Installation
|
69
90
|
|
70
91
|
Add this line to your application's Gemfile:
|
data/lib/binary_struct.rb
CHANGED
@@ -5,16 +5,16 @@ class BinaryStruct
|
|
5
5
|
SIZES = {
|
6
6
|
'A' => 1, # String with trailing NULs and spaces removed
|
7
7
|
'a' => 1, # String
|
8
|
-
'B' =>
|
9
|
-
'b' =>
|
8
|
+
'B' => 1, # Extract bits from each character (MSB first)
|
9
|
+
'b' => 1, # Extract bits from each character (LSB first)
|
10
10
|
'C' => 1, # Extract a character as an unsigned integer
|
11
11
|
'c' => 1, # Extract a character as a signed integer
|
12
12
|
'E' => nil, # Treat sizeof(double) characters as a double in little-endian byte order
|
13
13
|
'e' => nil, # Treat sizeof(float) characters as a float in little-endian byte order
|
14
14
|
'G' => nil, # Treat sizeof(double) characters as a double in network byte order
|
15
15
|
'g' => nil, # Treat sizeof(float) characters as a float in network byte order
|
16
|
-
'H' =>
|
17
|
-
'h' =>
|
16
|
+
'H' => 1, # Extract hex nibbles from each character (most significant first)
|
17
|
+
'h' => 1, # Extract hex nibbles from each character (least significant first)
|
18
18
|
'I' => 4, # Treat sizeof(int) successive characters as an unsigned native integer
|
19
19
|
'i' => 4, # Treat sizeof(int) successive characters as a signed native integer
|
20
20
|
'L' => 4, # Treat 4 successive characters as an unsigned native long integer
|
@@ -39,7 +39,9 @@ class BinaryStruct
|
|
39
39
|
'Z' => 1, # String with trailing NULs removed
|
40
40
|
}
|
41
41
|
|
42
|
-
STRING_FORMATS = %w(A a M m u)
|
42
|
+
STRING_FORMATS = %w(A a B b H h M m u)
|
43
|
+
BIT_FORMATS = %w(B b)
|
44
|
+
NIBBLE_FORMATS = %w(H h)
|
43
45
|
ENDIAN_FORMATS = %w(I i L l Q q S s)
|
44
46
|
ENDIAN_MODIFIERS = %w(> <)
|
45
47
|
MODIFIERS = ENDIAN_MODIFIERS
|
@@ -56,6 +58,7 @@ class BinaryStruct
|
|
56
58
|
if value.kind_of?(self.class)
|
57
59
|
@definition = value.definition.dup
|
58
60
|
else
|
61
|
+
value = value.to_a.map(&:reverse).flatten if value.kind_of?(Hash)
|
59
62
|
value = Array(value)
|
60
63
|
self.class.validate_definition(value)
|
61
64
|
@definition = value
|
@@ -202,7 +205,14 @@ class BinaryStruct
|
|
202
205
|
modifier, modcount = count[0, 1], count[1..-1]
|
203
206
|
count = modcount if valid_definition_entry_modifier?(modifier)
|
204
207
|
count = count.empty? ? 1 : count.to_i
|
205
|
-
size +=
|
208
|
+
size +=
|
209
|
+
if BIT_FORMATS.include?(type)
|
210
|
+
(count / 8.0).ceil
|
211
|
+
elsif NIBBLE_FORMATS.include?(type)
|
212
|
+
(count / 2.0).ceil
|
213
|
+
else
|
214
|
+
count * SIZES[type]
|
215
|
+
end
|
206
216
|
end
|
207
217
|
size
|
208
218
|
end
|
data/spec/binary_struct_spec.rb
CHANGED
@@ -1,29 +1,50 @@
|
|
1
1
|
describe BinaryStruct do
|
2
2
|
STRUCT_DEF = [
|
3
|
-
'Q',
|
4
|
-
'L',
|
5
|
-
'S',
|
6
|
-
'C',
|
3
|
+
'Q', :quad,
|
4
|
+
'L', 'long',
|
5
|
+
'S', :short,
|
6
|
+
'C', nil,
|
7
|
+
'b5', :binary,
|
7
8
|
'a0', 'none',
|
8
|
-
'a',
|
9
|
+
'a', nil,
|
9
10
|
'a2', 'bc',
|
10
11
|
]
|
11
|
-
STRUCT_DEF_SIZE =
|
12
|
+
STRUCT_DEF_SIZE = 19
|
13
|
+
|
14
|
+
STRUCT_DEF_HASH = {
|
15
|
+
:quad => 'Q',
|
16
|
+
'long' => 'L',
|
17
|
+
:short => 'S',
|
18
|
+
nil => 'C',
|
19
|
+
:binary => 'b5',
|
20
|
+
'none' => 'a0',
|
21
|
+
:unused => 'a',
|
22
|
+
'bc' => 'a2',
|
23
|
+
}
|
12
24
|
|
13
25
|
STRUCT_DEF_ASTERISK = ['a*', :word]
|
14
26
|
STRUCT_DEF_ASTERISK_SIZE = 0 # '*' is ignored
|
15
27
|
|
16
28
|
STRUCT_DEF_UNRECOGNIZED_FORMAT = ['D', nil]
|
17
|
-
STRUCT_DEF_UNSUPPORTED_FORMAT = ['
|
29
|
+
STRUCT_DEF_UNSUPPORTED_FORMAT = ['U', nil]
|
18
30
|
STRUCT_DEF_UNSUPPORTED_COUNT_NEG = ['a-1', nil]
|
19
31
|
STRUCT_DEF_UNSUPPORTED_COUNT_INV = ['aX', nil]
|
20
32
|
|
21
|
-
STRUCT_ENCODED_STR = "\000\111\222\333\444\555\666\777\000\111\222\333\000\111\
|
22
|
-
STRUCT_DECODED_HASH = {
|
33
|
+
STRUCT_ENCODED_STR = "\000\111\222\333\444\555\666\777\000\111\222\333\000\111\000\0320BC".force_encoding("ASCII-8BIT")
|
34
|
+
STRUCT_DECODED_HASH = {
|
35
|
+
:quad => 18_426_034_930_503_010_560,
|
36
|
+
"long" => 3_683_797_248,
|
37
|
+
:short => 18_688,
|
38
|
+
:binary => "01011",
|
39
|
+
"bc" => "BC",
|
40
|
+
"none" => ""
|
41
|
+
}
|
42
|
+
STRUCT_DECODED_HASH2 = STRUCT_DECODED_HASH.merge(:unused => "0")
|
23
43
|
|
24
44
|
it('.new') { expect { BinaryStruct.new }.not_to raise_error }
|
25
45
|
it('.new with definition') { expect { BinaryStruct.new(STRUCT_DEF) }.not_to raise_error }
|
26
46
|
it('.new with definition with *') { expect { BinaryStruct.new(STRUCT_DEF_ASTERISK) }.not_to raise_error }
|
47
|
+
it('.new with Hash defintion') { expect { BinaryStruct.new(STRUCT_DEF_HASH) }.not_to raise_error }
|
27
48
|
it '.new with another BinaryStruct' do
|
28
49
|
s = BinaryStruct.new(STRUCT_DEF)
|
29
50
|
s2 = BinaryStruct.new(s)
|
@@ -38,6 +59,7 @@ describe BinaryStruct do
|
|
38
59
|
|
39
60
|
it('#definition=') { expect { BinaryStruct.new.definition = STRUCT_DEF }.not_to raise_error }
|
40
61
|
it('#definition= with definition with *') { expect { BinaryStruct.new.definition = STRUCT_DEF_ASTERISK }.not_to raise_error }
|
62
|
+
it('#definition= with Hash defintion') { expect { BinaryStruct.new.definition = STRUCT_DEF_HASH }.not_to raise_error }
|
41
63
|
|
42
64
|
it('#definition= with unrecognized format') { expect { BinaryStruct.new.definition = STRUCT_DEF_UNRECOGNIZED_FORMAT }.to raise_error(RuntimeError) }
|
43
65
|
it('#definition= with unsupported format') { expect { BinaryStruct.new.definition = STRUCT_DEF_UNSUPPORTED_FORMAT }.to raise_error(RuntimeError) }
|
@@ -55,6 +77,10 @@ describe BinaryStruct do
|
|
55
77
|
expect(BinaryStruct.new(STRUCT_DEF_ASTERISK).decode("Testing")).to eq(:word => "Testing")
|
56
78
|
end
|
57
79
|
|
80
|
+
it '#decode with Hash defintion' do
|
81
|
+
expect(BinaryStruct.new(STRUCT_DEF_HASH).decode(STRUCT_ENCODED_STR)).to eq(STRUCT_DECODED_HASH2)
|
82
|
+
end
|
83
|
+
|
58
84
|
it '#decode against multiple records' do
|
59
85
|
expect(BinaryStruct.new(STRUCT_DEF).decode(STRUCT_ENCODED_STR * 10, 10)).to eq([STRUCT_DECODED_HASH] * 10)
|
60
86
|
end
|
data/spec/endian_spec.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
describe BinaryStruct do
|
2
2
|
BIG_STRUCT_DEF = [
|
3
|
-
'Q>',
|
4
|
-
'L>',
|
5
|
-
'S>',
|
6
|
-
'C',
|
7
|
-
'
|
8
|
-
'
|
9
|
-
'
|
3
|
+
'Q>', :quad,
|
4
|
+
'L>', 'long',
|
5
|
+
'S>', :short,
|
6
|
+
'C', nil,
|
7
|
+
'b5', :binary,
|
8
|
+
'a0', 'none',
|
9
|
+
'a', nil,
|
10
|
+
'a2', 'bc',
|
10
11
|
]
|
11
|
-
BIG_STRUCT_DEF_SIZE =
|
12
|
+
BIG_STRUCT_DEF_SIZE = 19
|
12
13
|
|
13
14
|
BIG_E_QUAD_STRUCT_DEF = ['Q>2', :quad]
|
14
15
|
BIG_E_QUAD_DEF_SIZE = 16
|
@@ -21,15 +22,16 @@ describe BinaryStruct do
|
|
21
22
|
BIG_STRUCT_DEF_INVALID_ENDIAN_MODIFIER = ['Q_', nil]
|
22
23
|
|
23
24
|
LIL_STRUCT_DEF = [
|
24
|
-
'Q<',
|
25
|
-
'L<',
|
26
|
-
'S<',
|
27
|
-
'C',
|
28
|
-
'
|
29
|
-
'
|
30
|
-
'
|
25
|
+
'Q<', :quad,
|
26
|
+
'L<', 'long',
|
27
|
+
'S<', :short,
|
28
|
+
'C', nil,
|
29
|
+
'b5', :binary,
|
30
|
+
'a0', 'none',
|
31
|
+
'a', nil,
|
32
|
+
'a2', 'bc',
|
31
33
|
]
|
32
|
-
LIL_STRUCT_DEF_SIZE =
|
34
|
+
LIL_STRUCT_DEF_SIZE = 19
|
33
35
|
|
34
36
|
LIL_E_QUAD_STRUCT_DEF = ['Q<2', :quad]
|
35
37
|
LIL_E_QUAD_DEF_SIZE = 16
|
@@ -40,18 +42,27 @@ describe BinaryStruct do
|
|
40
42
|
LIL_STRUCT_DEF_UNRECOG_ENDIAN_FMT = ['Y<', nil]
|
41
43
|
LIL_STRUCT_DEF_UNSUPPORTED_ENDIAN_ATTRIBUTE = ['A<', nil]
|
42
44
|
|
43
|
-
END_STRUCT_ENCODED_STR = "\000\111\222\333\444\555\666\777\000\111\222\333\000\111\
|
44
|
-
|
45
|
-
LIL_ENDIAN_STRUCT_DECODED_HASH =
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
45
|
+
END_STRUCT_ENCODED_STR = "\000\111\222\333\444\555\666\777\000\111\222\333\000\111\000\0320BC"
|
46
|
+
|
47
|
+
LIL_ENDIAN_STRUCT_DECODED_HASH =
|
48
|
+
{
|
49
|
+
:quad => 18_426_034_930_503_010_560,
|
50
|
+
"long" => 3_683_797_248,
|
51
|
+
:short => 18_688,
|
52
|
+
:binary => "01011",
|
53
|
+
"none" => "",
|
54
|
+
"bc" => "BC",
|
55
|
+
}
|
56
|
+
|
57
|
+
BIG_ENDIAN_STRUCT_DECODED_HASH =
|
58
|
+
{
|
59
|
+
:quad => 20_709_143_206_541_055,
|
60
|
+
"long" => 4_821_723,
|
61
|
+
:short => 73,
|
62
|
+
:binary => "01011",
|
63
|
+
"none" => "",
|
64
|
+
"bc" => "BC"
|
65
|
+
}
|
55
66
|
|
56
67
|
it('.new') { expect { BinaryStruct.new }.not_to raise_error }
|
57
68
|
it('.new with big definition') { expect { BinaryStruct.new(BIG_STRUCT_DEF) }.not_to raise_error }
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: binary_struct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
5
|
-
prerelease:
|
4
|
+
version: 2.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Oleg Barenboim
|
@@ -10,83 +9,70 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2015-06-18 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: bundler
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- - ~>
|
18
|
+
- - "~>"
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '1.3'
|
23
21
|
type: :development
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- - ~>
|
25
|
+
- - "~>"
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: '1.3'
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: rake
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- -
|
32
|
+
- - ">="
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: '0'
|
39
35
|
type: :development
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - ">="
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: '0'
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: rspec
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
|
-
- -
|
46
|
+
- - ">="
|
53
47
|
- !ruby/object:Gem::Version
|
54
48
|
version: '3.0'
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
|
-
- -
|
53
|
+
- - ">="
|
61
54
|
- !ruby/object:Gem::Version
|
62
55
|
version: '3.0'
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: coveralls
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
59
|
requirements:
|
68
|
-
- -
|
60
|
+
- - ">="
|
69
61
|
- !ruby/object:Gem::Version
|
70
62
|
version: '0'
|
71
63
|
type: :development
|
72
64
|
prerelease: false
|
73
65
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
66
|
requirements:
|
76
|
-
- -
|
67
|
+
- - ">="
|
77
68
|
- !ruby/object:Gem::Version
|
78
69
|
version: '0'
|
79
|
-
description:
|
70
|
+
description: |2
|
80
71
|
|
81
72
|
BinaryStruct is a class for dealing with binary structured data. It simplifies
|
82
|
-
|
83
73
|
expressing what the binary structure looks like, with the ability to name the
|
84
|
-
|
85
74
|
parts. Given this definition, it is easy to encode/decode the binary structure
|
86
|
-
|
87
75
|
from/to a Hash.
|
88
|
-
|
89
|
-
'
|
90
76
|
email:
|
91
77
|
- chessbyte@gmail.com
|
92
78
|
- fryguy9@gmail.com
|
@@ -94,40 +80,39 @@ executables: []
|
|
94
80
|
extensions: []
|
95
81
|
extra_rdoc_files: []
|
96
82
|
files:
|
83
|
+
- ".rspec"
|
84
|
+
- LICENSE.txt
|
85
|
+
- README.md
|
97
86
|
- lib/binary_struct.rb
|
98
87
|
- lib/binary_struct/version.rb
|
99
|
-
- README.md
|
100
|
-
- LICENSE.txt
|
101
88
|
- spec/binary_struct_spec.rb
|
102
89
|
- spec/data/test.gif
|
103
90
|
- spec/endian_spec.rb
|
104
91
|
- spec/gif_spec.rb
|
105
92
|
- spec/spec_helper.rb
|
106
|
-
- .rspec
|
107
93
|
homepage: http://github.com/ManageIQ/binary_struct
|
108
94
|
licenses:
|
109
95
|
- MIT
|
96
|
+
metadata: {}
|
110
97
|
post_install_message:
|
111
98
|
rdoc_options: []
|
112
99
|
require_paths:
|
113
100
|
- lib
|
114
101
|
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
-
none: false
|
116
102
|
requirements:
|
117
|
-
- -
|
103
|
+
- - ">="
|
118
104
|
- !ruby/object:Gem::Version
|
119
105
|
version: 1.9.3
|
120
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
|
-
- -
|
108
|
+
- - ">="
|
124
109
|
- !ruby/object:Gem::Version
|
125
110
|
version: '0'
|
126
111
|
requirements: []
|
127
112
|
rubyforge_project:
|
128
|
-
rubygems_version:
|
113
|
+
rubygems_version: 2.2.2
|
129
114
|
signing_key:
|
130
|
-
specification_version:
|
115
|
+
specification_version: 4
|
131
116
|
summary: BinaryStruct is a class for dealing with binary structured data.
|
132
117
|
test_files:
|
133
118
|
- spec/binary_struct_spec.rb
|
@@ -135,4 +120,4 @@ test_files:
|
|
135
120
|
- spec/endian_spec.rb
|
136
121
|
- spec/gif_spec.rb
|
137
122
|
- spec/spec_helper.rb
|
138
|
-
- .rspec
|
123
|
+
- ".rspec"
|