bindata 1.1.0 → 1.2.0
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.
- data/ChangeLog +7 -0
- data/README +32 -1167
- data/lib/bindata.rb +3 -3
- data/lib/bindata/array.rb +5 -6
- data/lib/bindata/base.rb +40 -58
- data/lib/bindata/base_primitive.rb +7 -11
- data/lib/bindata/bits.rb +47 -44
- data/lib/bindata/choice.rb +7 -11
- data/lib/bindata/deprecated.rb +17 -2
- data/lib/bindata/dsl.rb +332 -0
- data/lib/bindata/float.rb +48 -50
- data/lib/bindata/int.rb +66 -88
- data/lib/bindata/params.rb +112 -59
- data/lib/bindata/primitive.rb +8 -88
- data/lib/bindata/record.rb +11 -99
- data/lib/bindata/registry.rb +16 -3
- data/lib/bindata/rest.rb +1 -1
- data/lib/bindata/sanitize.rb +71 -53
- data/lib/bindata/skip.rb +2 -1
- data/lib/bindata/string.rb +3 -3
- data/lib/bindata/stringz.rb +1 -1
- data/lib/bindata/struct.rb +21 -20
- data/lib/bindata/trace.rb +8 -0
- data/lib/bindata/wrapper.rb +13 -69
- data/manual.haml +2 -2
- data/spec/array_spec.rb +1 -1
- data/spec/base_primitive_spec.rb +4 -4
- data/spec/base_spec.rb +19 -6
- data/spec/bits_spec.rb +5 -1
- data/spec/choice_spec.rb +13 -2
- data/spec/deprecated_spec.rb +31 -0
- data/spec/example.rb +5 -1
- data/spec/io_spec.rb +2 -4
- data/spec/lazy_spec.rb +10 -5
- data/spec/primitive_spec.rb +13 -5
- data/spec/record_spec.rb +149 -45
- data/spec/registry_spec.rb +18 -6
- data/spec/spec_common.rb +31 -6
- data/spec/string_spec.rb +0 -1
- data/spec/stringz_spec.rb +4 -4
- data/spec/struct_spec.rb +2 -2
- data/spec/system_spec.rb +26 -19
- data/spec/wrapper_spec.rb +52 -4
- data/tasks/manual.rake +1 -1
- data/tasks/pkg.rake +13 -0
- metadata +121 -46
- data/TODO +0 -3
data/lib/bindata/stringz.rb
CHANGED
data/lib/bindata/struct.rb
CHANGED
@@ -47,20 +47,26 @@ module BinData
|
|
47
47
|
# calls to #read, #write, #num_bytes or #snapshot.
|
48
48
|
class Struct < BinData::Base
|
49
49
|
|
50
|
-
|
50
|
+
register_self
|
51
|
+
|
52
|
+
mandatory_parameter :fields
|
53
|
+
optional_parameters :endian, :hide
|
51
54
|
|
52
55
|
# These reserved words may not be used as field names
|
53
|
-
RESERVED =
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
RESERVED = Hash[*
|
57
|
+
(::Hash.instance_methods.collect { |meth| meth.to_s } +
|
58
|
+
%w{alias and begin break case class def defined do else elsif
|
59
|
+
end ensure false for if in module next nil not or redo
|
60
|
+
rescue retry return self super then true undef unless until
|
61
|
+
when while yield} +
|
62
|
+
%w{array element index value} ).
|
63
|
+
uniq.collect { |key| [key, true] }.flatten
|
64
|
+
]
|
59
65
|
|
60
66
|
# A hash that can be accessed via attributes.
|
61
67
|
class Snapshot < Hash #:nodoc:
|
62
68
|
def respond_to?(symbol, include_private = false)
|
63
|
-
has_key?(symbol.to_s) || super
|
69
|
+
has_key?(symbol.to_s) || super
|
64
70
|
end
|
65
71
|
|
66
72
|
def method_missing(symbol, *args)
|
@@ -101,10 +107,10 @@ module BinData
|
|
101
107
|
|
102
108
|
def sanitize_hide(params, sanitizer)
|
103
109
|
if params.needs_sanitizing?(:hide) and params.has_parameter?(:fields)
|
104
|
-
field_names
|
110
|
+
field_names = sanitized_field_names(params[:fields])
|
105
111
|
hfield_names = hidden_field_names(params[:hide])
|
106
112
|
|
107
|
-
params[:hide]
|
113
|
+
params[:hide] = (hfield_names & field_names)
|
108
114
|
end
|
109
115
|
end
|
110
116
|
|
@@ -117,11 +123,10 @@ module BinData
|
|
117
123
|
end
|
118
124
|
|
119
125
|
def ensure_field_names_are_valid(field_names)
|
120
|
-
instance_methods = self.instance_methods.collect { |meth| meth.to_s }
|
121
126
|
reserved_names = RESERVED
|
122
127
|
|
123
128
|
field_names.each do |name|
|
124
|
-
if
|
129
|
+
if self.class.method_defined?(name)
|
125
130
|
raise NameError.new("Rename field '#{name}' in #{self}, " +
|
126
131
|
"as it shadows an existing method.", name)
|
127
132
|
end
|
@@ -137,11 +142,8 @@ module BinData
|
|
137
142
|
end
|
138
143
|
end
|
139
144
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
def initialize(params = {}, parent = nil)
|
144
|
-
super(params, parent)
|
145
|
+
def initialize(parameters = {}, parent = nil)
|
146
|
+
super
|
145
147
|
|
146
148
|
@field_names = get_parameter(:fields).field_names
|
147
149
|
@field_objs = []
|
@@ -152,7 +154,7 @@ module BinData
|
|
152
154
|
end
|
153
155
|
|
154
156
|
def clear? #:nodoc:
|
155
|
-
@field_objs.
|
157
|
+
@field_objs.all? { |f| f.nil? or f.clear? }
|
156
158
|
end
|
157
159
|
|
158
160
|
# Returns a list of the names of all fields accessible through this
|
@@ -168,8 +170,7 @@ module BinData
|
|
168
170
|
end
|
169
171
|
|
170
172
|
def respond_to?(symbol, include_private = false) #:nodoc:
|
171
|
-
|
172
|
-
field_names(true).include?(symbol.to_s.chomp("="))
|
173
|
+
field_names(true).include?(symbol.to_s.chomp("=")) || super
|
173
174
|
end
|
174
175
|
|
175
176
|
def method_missing(symbol, *args, &block) #:nodoc:
|
data/lib/bindata/trace.rb
CHANGED
@@ -10,6 +10,14 @@ module BinData
|
|
10
10
|
def trace(msg)
|
11
11
|
@trace_io.puts(msg)
|
12
12
|
end
|
13
|
+
|
14
|
+
def trace_obj(obj_name, val)
|
15
|
+
if val.length > 30
|
16
|
+
val = val.slice(0 .. 30) + "..."
|
17
|
+
end
|
18
|
+
|
19
|
+
trace "#{obj_name} => #{val}"
|
20
|
+
end
|
13
21
|
end
|
14
22
|
|
15
23
|
# Turn on trace information when reading a BinData object.
|
data/lib/bindata/wrapper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'bindata/base'
|
2
|
+
require 'bindata/dsl'
|
2
3
|
|
3
4
|
module BinData
|
4
5
|
# A Wrapper allows the creation of new BinData types that
|
@@ -19,85 +20,28 @@ module BinData
|
|
19
20
|
# arr.snapshot #=> [3, 3, 3, 3 ,3]
|
20
21
|
#
|
21
22
|
class Wrapper < BinData::Base
|
23
|
+
include DSLMixin
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
def inherited(subclass) #:nodoc:
|
26
|
-
# Register the names of all subclasses of this class.
|
27
|
-
register(subclass.name, subclass)
|
28
|
-
end
|
29
|
-
|
30
|
-
def endian(endian = nil)
|
31
|
-
@endian ||= default_endian
|
32
|
-
if [:little, :big].include?(endian)
|
33
|
-
@endian = endian
|
34
|
-
elsif endian != nil
|
35
|
-
raise ArgumentError,
|
36
|
-
"unknown value for endian '#{endian}' in #{self}", caller(1)
|
37
|
-
end
|
38
|
-
@endian
|
39
|
-
end
|
40
|
-
|
41
|
-
def wrapped(*args)
|
42
|
-
@wrapped ||= default_wrapped
|
43
|
-
if args.length == 2
|
44
|
-
type, params = *args
|
45
|
-
ensure_type_exists(type)
|
46
|
-
|
47
|
-
if wrapped != nil
|
48
|
-
raise SyntaxError, "#{self} can only wrap one type", caller(2)
|
49
|
-
end
|
50
|
-
@wrapped = [type, params]
|
51
|
-
end
|
52
|
-
@wrapped
|
53
|
-
end
|
54
|
-
|
55
|
-
def method_missing(symbol, *args) #:nodoc:
|
56
|
-
type = symbol
|
57
|
-
params = args.length == 0 ? {} : args[0]
|
58
|
-
|
59
|
-
wrapped(type, params)
|
60
|
-
end
|
25
|
+
register_subclasses
|
26
|
+
dsl_parser :only_one_field, :no_fieldnames
|
61
27
|
|
28
|
+
class << self
|
62
29
|
def sanitize_parameters!(params, sanitizer) #:nodoc:
|
63
|
-
raise "
|
30
|
+
raise "no wrapped type was specified in #{self}" if field.nil?
|
64
31
|
|
65
|
-
wrapped_type
|
66
|
-
wrapped_params =
|
32
|
+
wrapped_type = field.type
|
33
|
+
wrapped_params = field.params.dup
|
67
34
|
|
68
35
|
params.move_unknown_parameters_to(wrapped_params)
|
69
36
|
|
70
37
|
params[:wrapped] = sanitizer.create_sanitized_object_prototype(wrapped_type, wrapped_params, endian)
|
71
38
|
end
|
72
|
-
|
73
|
-
#-------------
|
74
|
-
private
|
75
|
-
|
76
|
-
def parent_wrapper
|
77
|
-
ancestors[1..-1].find { |cls|
|
78
|
-
cls.ancestors[1..-1].include?(BinData::Wrapper)
|
79
|
-
}
|
80
|
-
end
|
81
|
-
|
82
|
-
def default_endian
|
83
|
-
wrap = parent_wrapper
|
84
|
-
wrap ? wrap.endian : nil
|
85
|
-
end
|
86
|
-
|
87
|
-
def default_wrapped
|
88
|
-
wrap = parent_wrapper
|
89
|
-
wrap ? wrap.wrapped : nil
|
90
|
-
end
|
91
|
-
|
92
|
-
def ensure_type_exists(type)
|
93
|
-
unless RegisteredClasses.is_registered?(type, endian)
|
94
|
-
raise TypeError, "unknown type '#{type}' for #{self}", caller(3)
|
95
|
-
end
|
96
|
-
end
|
97
39
|
end
|
98
40
|
|
99
|
-
|
100
|
-
|
41
|
+
mandatory_parameter :wrapped
|
42
|
+
|
43
|
+
def initialize(parameters = {}, parent = nil)
|
44
|
+
super
|
101
45
|
|
102
46
|
prototype = get_parameter(:wrapped)
|
103
47
|
@wrapped = prototype.instantiate(self)
|
@@ -112,7 +56,7 @@ module BinData
|
|
112
56
|
end
|
113
57
|
|
114
58
|
def respond_to?(symbol, include_private = false) #:nodoc:
|
115
|
-
|
59
|
+
wrapped.respond_to?(symbol, include_private) || super
|
116
60
|
end
|
117
61
|
|
118
62
|
def method_missing(symbol, *args, &block) #:nodoc:
|
data/manual.haml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
!!!
|
2
|
-
%html{ :xmlns => "http://www.w3.org/1999/xhtml" }
|
2
|
+
%html{ :xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en" }
|
3
3
|
%head
|
4
4
|
%meta{ :content => "text/html; charset=iso-8859-1", "http-equiv" => "Content-Type" }
|
5
5
|
%title
|
@@ -307,5 +307,5 @@
|
|
307
307
|
#main_frame
|
308
308
|
#main_content
|
309
309
|
:maruku
|
310
|
-
#{File.read("
|
310
|
+
#{File.read("manual.md")}
|
311
311
|
|
data/spec/array_spec.rb
CHANGED
@@ -15,7 +15,7 @@ describe BinData::Array, "when instantiating" do
|
|
15
15
|
|
16
16
|
it "should fail if a given type is unknown" do
|
17
17
|
args = {:type => :does_not_exist, :initial_length => 3}
|
18
|
-
lambda { BinData::Array.new(args) }.should raise_error(BinData::
|
18
|
+
lambda { BinData::Array.new(args) }.should raise_error(BinData::UnRegisteredTypeError)
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should not allow both :initial_length and :read_until" do
|
data/spec/base_primitive_spec.rb
CHANGED
@@ -36,7 +36,7 @@ describe BinData::BasePrimitive do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should conform to rule 2 for returning a value" do
|
39
|
-
io =
|
39
|
+
io = ExampleSingle.io_with_value(42)
|
40
40
|
data = ExampleSingle.new(:value => 5)
|
41
41
|
data.expose_methods_for_testing
|
42
42
|
data.do_read(io)
|
@@ -218,14 +218,14 @@ describe BinData::BasePrimitive, "with :value" do
|
|
218
218
|
end
|
219
219
|
|
220
220
|
it "should change during reading" do
|
221
|
-
io =
|
221
|
+
io = ExampleSingle.io_with_value(56)
|
222
222
|
@data.do_read(io)
|
223
223
|
@data.value.should == 56
|
224
224
|
@data.done_read
|
225
225
|
end
|
226
226
|
|
227
227
|
it "should not change after reading" do
|
228
|
-
io =
|
228
|
+
io = ExampleSingle.io_with_value(56)
|
229
229
|
@data.read(io)
|
230
230
|
@data.value.should == 5
|
231
231
|
end
|
@@ -238,7 +238,7 @@ end
|
|
238
238
|
|
239
239
|
describe BinData::BasePrimitive, "with :check_value" do
|
240
240
|
before(:each) do
|
241
|
-
@io =
|
241
|
+
@io = ExampleSingle.io_with_value(34)
|
242
242
|
end
|
243
243
|
|
244
244
|
it "should succeed when check_value is non boolean and correct" do
|
data/spec/base_spec.rb
CHANGED
@@ -184,7 +184,7 @@ describe BinData::Base, "with :check_offset" do
|
|
184
184
|
end
|
185
185
|
|
186
186
|
before(:each) do
|
187
|
-
@io =
|
187
|
+
@io = StringIO.new("12345678901234567890")
|
188
188
|
end
|
189
189
|
|
190
190
|
it "should fail if offset is incorrect" do
|
@@ -222,7 +222,7 @@ describe BinData::Base, "with :adjust_offset" do
|
|
222
222
|
end
|
223
223
|
|
224
224
|
before(:each) do
|
225
|
-
@io =
|
225
|
+
@io = StringIO.new("12345678901234567890")
|
226
226
|
end
|
227
227
|
|
228
228
|
it "should be mutually exclusive with :check_offset" do
|
@@ -288,17 +288,30 @@ describe BinData::Base, "as black box" do
|
|
288
288
|
obj.to_s.should == obj.snapshot.to_s
|
289
289
|
end
|
290
290
|
|
291
|
+
it "should pretty print object as snapshot" do
|
292
|
+
class PPBase < BaseStub
|
293
|
+
def snapshot; [1, 2, 3]; end
|
294
|
+
end
|
295
|
+
obj = SnapshotBase.new
|
296
|
+
actual_io = StringIO.new
|
297
|
+
expected_io = StringIO.new
|
298
|
+
|
299
|
+
require 'pp'
|
300
|
+
PP.pp(obj, actual_io)
|
301
|
+
PP.pp(obj.snapshot, expected_io)
|
302
|
+
|
303
|
+
actual_io.value.should == expected_io.value
|
304
|
+
end
|
305
|
+
|
291
306
|
it "should write the same as to_binary_s" do
|
292
307
|
class WriteToSBase < BaseStub
|
293
308
|
def _do_write(io) io.writebytes("abc"); end
|
294
309
|
end
|
295
310
|
|
296
311
|
obj = WriteToSBase.new
|
297
|
-
io =
|
312
|
+
io = StringIO.new
|
298
313
|
obj.write(io)
|
299
|
-
io.
|
300
|
-
written = io.read
|
301
|
-
obj.to_binary_s.should == written
|
314
|
+
io.value.should == obj.to_binary_s
|
302
315
|
end
|
303
316
|
end
|
304
317
|
|
data/spec/bits_spec.rb
CHANGED
@@ -116,7 +116,11 @@ share_examples_for "All bitfields" do
|
|
116
116
|
mid = (min_value + max_value) / 2
|
117
117
|
hi = max_value - 1
|
118
118
|
|
119
|
-
[lo, mid, hi].
|
119
|
+
[lo, mid, hi].select { |val| value_within_range?(val) }
|
120
|
+
end
|
121
|
+
|
122
|
+
def value_within_range?(val)
|
123
|
+
(min_value .. max_value).include?(val)
|
120
124
|
end
|
121
125
|
end
|
122
126
|
|
data/spec/choice_spec.rb
CHANGED
@@ -20,12 +20,12 @@ describe BinData::Choice, "when instantiating" do
|
|
20
20
|
|
21
21
|
it "should fail if a given type is unknown" do
|
22
22
|
args = {:choices => [:does_not_exist], :selection => 0}
|
23
|
-
lambda { BinData::Choice.new(args) }.should raise_error(BinData::
|
23
|
+
lambda { BinData::Choice.new(args) }.should raise_error(BinData::UnRegisteredTypeError)
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should fail if a given type is unknown" do
|
27
27
|
args = {:choices => {0 => :does_not_exist}, :selection => 0}
|
28
|
-
lambda { BinData::Choice.new(args) }.should raise_error(BinData::
|
28
|
+
lambda { BinData::Choice.new(args) }.should raise_error(BinData::UnRegisteredTypeError)
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should fail if :choices Hash has a symbol as key" do
|
@@ -50,6 +50,17 @@ share_examples_for "Choice initialized with array or hash" do
|
|
50
50
|
@data.selection.should == 3
|
51
51
|
end
|
52
52
|
|
53
|
+
it "should not be able to directly change the current selection" do
|
54
|
+
lambda {
|
55
|
+
@data.selection = 3
|
56
|
+
}.should raise_error(NoMethodError)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should forward #snapshot" do
|
60
|
+
@chooser.choice = 3
|
61
|
+
@data.snapshot.should == 30
|
62
|
+
end
|
63
|
+
|
53
64
|
it "should be able to change the choice" do
|
54
65
|
@chooser.choice = 3
|
55
66
|
|
data/spec/deprecated_spec.rb
CHANGED
@@ -21,3 +21,34 @@ describe BinData::MultiValue, "when defining" do
|
|
21
21
|
}.should raise_error
|
22
22
|
end
|
23
23
|
end
|
24
|
+
|
25
|
+
describe BinData::Base, "when defining" do
|
26
|
+
it "should handle deprecated #register method" do
|
27
|
+
lambda {
|
28
|
+
class DeprecatedRegisterBase < BinData::Base
|
29
|
+
register(self.name, self)
|
30
|
+
end
|
31
|
+
}.should_not raise_error
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should handle deprecated #register method for subclasses" do
|
35
|
+
lambda {
|
36
|
+
class DeprecatedSuperBase < BinData::Base
|
37
|
+
def self.inherited(subclass)
|
38
|
+
register(subclass.name, subclass)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class DeprecatedSubBase < DeprecatedSuperBase
|
43
|
+
end
|
44
|
+
}.should_not raise_error
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should handle deprecated #register method with custom calling" do
|
48
|
+
lambda {
|
49
|
+
class DeprecatedCustomBase < BinData::Base
|
50
|
+
register(name, Object)
|
51
|
+
end
|
52
|
+
}.should_not raise_error
|
53
|
+
end
|
54
|
+
end
|
data/spec/example.rb
CHANGED
data/spec/io_spec.rb
CHANGED
@@ -106,8 +106,7 @@ describe BinData::IO do
|
|
106
106
|
io = BinData::IO.new(stream)
|
107
107
|
io.writebytes("abcd")
|
108
108
|
|
109
|
-
stream.
|
110
|
-
stream.read.should == "abcd"
|
109
|
+
stream.value.should == "abcd"
|
111
110
|
end
|
112
111
|
|
113
112
|
it "should flush" do
|
@@ -116,8 +115,7 @@ describe BinData::IO do
|
|
116
115
|
io.writebytes("abcd")
|
117
116
|
io.flush
|
118
117
|
|
119
|
-
stream.
|
120
|
-
stream.read.should == "abcd"
|
118
|
+
stream.value.should == "abcd"
|
121
119
|
end
|
122
120
|
|
123
121
|
end
|