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.

Files changed (47) hide show
  1. data/ChangeLog +7 -0
  2. data/README +32 -1167
  3. data/lib/bindata.rb +3 -3
  4. data/lib/bindata/array.rb +5 -6
  5. data/lib/bindata/base.rb +40 -58
  6. data/lib/bindata/base_primitive.rb +7 -11
  7. data/lib/bindata/bits.rb +47 -44
  8. data/lib/bindata/choice.rb +7 -11
  9. data/lib/bindata/deprecated.rb +17 -2
  10. data/lib/bindata/dsl.rb +332 -0
  11. data/lib/bindata/float.rb +48 -50
  12. data/lib/bindata/int.rb +66 -88
  13. data/lib/bindata/params.rb +112 -59
  14. data/lib/bindata/primitive.rb +8 -88
  15. data/lib/bindata/record.rb +11 -99
  16. data/lib/bindata/registry.rb +16 -3
  17. data/lib/bindata/rest.rb +1 -1
  18. data/lib/bindata/sanitize.rb +71 -53
  19. data/lib/bindata/skip.rb +2 -1
  20. data/lib/bindata/string.rb +3 -3
  21. data/lib/bindata/stringz.rb +1 -1
  22. data/lib/bindata/struct.rb +21 -20
  23. data/lib/bindata/trace.rb +8 -0
  24. data/lib/bindata/wrapper.rb +13 -69
  25. data/manual.haml +2 -2
  26. data/spec/array_spec.rb +1 -1
  27. data/spec/base_primitive_spec.rb +4 -4
  28. data/spec/base_spec.rb +19 -6
  29. data/spec/bits_spec.rb +5 -1
  30. data/spec/choice_spec.rb +13 -2
  31. data/spec/deprecated_spec.rb +31 -0
  32. data/spec/example.rb +5 -1
  33. data/spec/io_spec.rb +2 -4
  34. data/spec/lazy_spec.rb +10 -5
  35. data/spec/primitive_spec.rb +13 -5
  36. data/spec/record_spec.rb +149 -45
  37. data/spec/registry_spec.rb +18 -6
  38. data/spec/spec_common.rb +31 -6
  39. data/spec/string_spec.rb +0 -1
  40. data/spec/stringz_spec.rb +4 -4
  41. data/spec/struct_spec.rb +2 -2
  42. data/spec/system_spec.rb +26 -19
  43. data/spec/wrapper_spec.rb +52 -4
  44. data/tasks/manual.rake +1 -1
  45. data/tasks/pkg.rake +13 -0
  46. metadata +121 -46
  47. data/TODO +0 -3
@@ -27,7 +27,7 @@ module BinData
27
27
  # byte.
28
28
  class Stringz < BinData::BasePrimitive
29
29
 
30
- register(self.name, self)
30
+ register_self
31
31
 
32
32
  optional_parameters :max_length
33
33
 
@@ -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
- register(self.name, self)
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 = (::Hash.instance_methods.collect { |meth| meth.to_s } +
54
- %w{alias and begin break case class def defined do else elsif
55
- end ensure false for if in module next nil not or redo
56
- rescue retry return self super then true undef unless until
57
- when while yield} +
58
- %w{array element index value} ).uniq
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(symbol, include_private)
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 = sanitized_field_names(params[:fields])
110
+ field_names = sanitized_field_names(params[:fields])
105
111
  hfield_names = hidden_field_names(params[:hide])
106
112
 
107
- params[:hide] = (hfield_names & field_names)
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 instance_methods.include?(name)
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
- mandatory_parameter :fields
141
- optional_parameters :endian, :hide
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.inject(true) { |all_clear, f| all_clear and (f.nil? or f.clear?) }
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
- super(symbol, include_private) ||
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:
@@ -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.
@@ -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
- class << self
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 "Nothing to wrap" if wrapped.nil?
30
+ raise "no wrapped type was specified in #{self}" if field.nil?
64
31
 
65
- wrapped_type, wrapped_params = wrapped
66
- wrapped_params = wrapped_params.dup
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
- def initialize(params = {}, parent = nil)
100
- super(params, parent)
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
- super || wrapped.respond_to?(symbol, include_private)
59
+ wrapped.respond_to?(symbol, include_private) || super
116
60
  end
117
61
 
118
62
  def method_missing(symbol, *args, &block) #:nodoc:
@@ -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("README")}
310
+ #{File.read("manual.md")}
311
311
 
@@ -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::UnknownTypeError)
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
@@ -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 = BinData::IO.new([42].pack("V"))
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 = BinData::IO.new([56].pack("V"))
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 = BinData::IO.new([56].pack("V"))
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 = BinData::IO.new([34].pack("V"))
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
@@ -184,7 +184,7 @@ describe BinData::Base, "with :check_offset" do
184
184
  end
185
185
 
186
186
  before(:each) do
187
- @io = BinData::IO.create_string_io("12345678901234567890")
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 = BinData::IO.create_string_io("12345678901234567890")
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 = BinData::IO.create_string_io
312
+ io = StringIO.new
298
313
  obj.write(io)
299
- io.rewind
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
 
@@ -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].find_all { |v| (min_value .. max_value).include?(v) }
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
 
@@ -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::UnknownTypeError)
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::UnknownTypeError)
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
 
@@ -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
@@ -1,7 +1,11 @@
1
1
  require 'bindata/base_primitive'
2
2
 
3
3
  class ExampleSingle < BinData::BasePrimitive
4
- register(self.name, self)
4
+ register_self
5
+
6
+ def self.io_with_value(val)
7
+ BinData::IO.new([val].pack("V"))
8
+ end
5
9
 
6
10
  private
7
11
 
@@ -106,8 +106,7 @@ describe BinData::IO do
106
106
  io = BinData::IO.new(stream)
107
107
  io.writebytes("abcd")
108
108
 
109
- stream.rewind
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.rewind
120
- stream.read.should == "abcd"
118
+ stream.value.should == "abcd"
121
119
  end
122
120
 
123
121
  end