bindata 1.5.1 → 1.6.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 (61) hide show
  1. data/ChangeLog.rdoc +7 -0
  2. data/NEWS.rdoc +11 -0
  3. data/Rakefile +6 -1
  4. data/bindata.gemspec +2 -1
  5. data/doc/manual.md +17 -9
  6. data/examples/gzip.rb +2 -2
  7. data/examples/list.rb +2 -2
  8. data/lib/bindata/alignment.rb +4 -9
  9. data/lib/bindata/array.rb +57 -51
  10. data/lib/bindata/base.rb +13 -110
  11. data/lib/bindata/base_primitive.rb +130 -75
  12. data/lib/bindata/bits.rb +5 -7
  13. data/lib/bindata/choice.rb +24 -32
  14. data/lib/bindata/dsl.rb +1 -6
  15. data/lib/bindata/framework.rb +81 -0
  16. data/lib/bindata/int.rb +5 -7
  17. data/lib/bindata/name.rb +28 -0
  18. data/lib/bindata/offset.rb +42 -53
  19. data/lib/bindata/params.rb +33 -38
  20. data/lib/bindata/struct.rb +2 -6
  21. data/lib/bindata/trace.rb +16 -16
  22. data/lib/bindata/version.rb +1 -1
  23. data/lib/bindata/virtual.rb +3 -3
  24. data/{spec/alignment_spec.rb → test/alignment_test.rb} +17 -16
  25. data/test/array_test.rb +371 -0
  26. data/test/base_primitive_test.rb +312 -0
  27. data/test/base_test.rb +183 -0
  28. data/{spec/bits_spec.rb → test/bits_test.rb} +59 -59
  29. data/test/choice_test.rb +260 -0
  30. data/{spec/spec_common.rb → test/common.rb} +33 -18
  31. data/test/count_bytes_remaining_test.rb +41 -0
  32. data/{spec/deprecated_spec.rb → test/deprecated_test.rb} +5 -7
  33. data/test/float_test.rb +72 -0
  34. data/{spec/int_spec.rb → test/int_test.rb} +34 -43
  35. data/{spec/io_spec.rb → test/io_test.rb} +70 -71
  36. data/{spec/lazy_spec.rb → test/lazy_test.rb} +38 -39
  37. data/test/offset_test.rb +93 -0
  38. data/test/params_test.rb +144 -0
  39. data/{spec/primitive_spec.rb → test/primitive_test.rb} +42 -54
  40. data/{spec/record_spec.rb → test/record_test.rb} +133 -154
  41. data/test/registry_test.rb +104 -0
  42. data/test/rest_test.rb +29 -0
  43. data/test/skip_test.rb +28 -0
  44. data/{spec/string_spec.rb → test/string_test.rb} +96 -97
  45. data/test/stringz_test.rb +127 -0
  46. data/{spec/struct_spec.rb → test/struct_test.rb} +119 -120
  47. data/{spec/system_spec.rb → test/system_test.rb} +66 -106
  48. metadata +39 -38
  49. data/lib/a.rb +0 -24
  50. data/spec/array_spec.rb +0 -331
  51. data/spec/base_primitive_spec.rb +0 -238
  52. data/spec/base_spec.rb +0 -376
  53. data/spec/choice_spec.rb +0 -263
  54. data/spec/count_bytes_remaining_spec.rb +0 -38
  55. data/spec/example.rb +0 -21
  56. data/spec/float_spec.rb +0 -37
  57. data/spec/registry_spec.rb +0 -108
  58. data/spec/rest_spec.rb +0 -26
  59. data/spec/skip_spec.rb +0 -27
  60. data/spec/stringz_spec.rb +0 -118
  61. data/tasks/rspec.rake +0 -17
data/lib/bindata/int.rb CHANGED
@@ -157,10 +157,8 @@ module BinData
157
157
  end
158
158
 
159
159
  # Create classes on demand
160
- class << self
161
- alias_method :const_missing_without_int, :const_missing
162
- def const_missing_with_int(name)
163
- name = name.to_s
160
+ module IntFactory
161
+ def const_missing(name)
164
162
  mappings = {
165
163
  /^Uint(\d+)be$/ => [:big, :unsigned],
166
164
  /^Uint(\d+)le$/ => [:little, :unsigned],
@@ -169,7 +167,7 @@ module BinData
169
167
  }
170
168
 
171
169
  mappings.each_pair do |regex, args|
172
- if regex =~ name
170
+ if regex =~ name.to_s
173
171
  nbits = $1.to_i
174
172
  if (nbits % 8).zero?
175
173
  return Int.define_class(nbits, *args)
@@ -177,8 +175,8 @@ module BinData
177
175
  end
178
176
  end
179
177
 
180
- const_missing_without_int(name)
178
+ super
181
179
  end
182
- alias_method :const_missing, :const_missing_with_int
183
180
  end
181
+ BinData.extend IntFactory
184
182
  end
@@ -0,0 +1,28 @@
1
+ module BinData
2
+ # == Parameters
3
+ #
4
+ # Parameters may be provided at initialisation to control the behaviour of
5
+ # an object. These parameters are:
6
+ #
7
+ # <tt>:name</tt>:: The name that this object can be referred to may be
8
+ # set explicitly. This is only useful when dynamically
9
+ # generating types.
10
+ # <code><pre>
11
+ # BinData::Struct.new(:name => :my_struct, :fields => ...)
12
+ # array = BinData::Array.new(:type => :my_struct)
13
+ # </pre></code>
14
+ module RegisterNamePlugin
15
+
16
+ def self.included(base) #:nodoc:
17
+ # The registered name may be provided explicitly.
18
+ base.optional_parameter :name
19
+ end
20
+
21
+ def initialize_shared_instance
22
+ if has_parameter?(:name)
23
+ RegisteredClasses.register(get_parameter(:name), self)
24
+ end
25
+ super
26
+ end
27
+ end
28
+ end
@@ -15,77 +15,66 @@ module BinData
15
15
  # position before reading. This is like
16
16
  # <tt>:check_offset</tt>, except that it will
17
17
  # adjust the IO offset instead of raising an error.
18
- module CheckOrAdjustOffsetMixin
18
+ module CheckOrAdjustOffsetPlugin
19
19
 
20
20
  def self.included(base) #:nodoc:
21
21
  base.optional_parameters :check_offset, :adjust_offset
22
22
  base.mutually_exclusive_parameters :check_offset, :adjust_offset
23
23
  end
24
24
 
25
- # Ideally these two methods should be protected,
26
- # but Ruby 1.9.2 requires them to be public.
27
- # see http://redmine.ruby-lang.org/issues/show/2375
28
-
29
- def do_read_with_check_offset(io) #:nodoc:
30
- check_offset(io)
31
- do_read_without_check_offset(io)
25
+ def initialize_shared_instance
26
+ extend CheckOffsetMixin if has_parameter?(:check_offset)
27
+ extend AdjustOffsetMixin if has_parameter?(:adjust_offset)
28
+ super
32
29
  end
33
30
 
34
- def do_read_with_adjust_offset(io) #:nodoc:
35
- adjust_offset(io)
36
- do_read_without_adjust_offset(io)
37
- end
31
+ module CheckOffsetMixin
32
+ def do_read(io) #:nodoc:
33
+ check_offset(io)
34
+ super(io)
35
+ end
38
36
 
39
- #---------------
40
- private
37
+ #---------------
38
+ private
41
39
 
42
- # To be called from BinData::Base#initialize.
43
- #
44
- # Monkey patches #do_read to check or adjust the stream offset
45
- # as appropriate.
46
- def add_methods_for_check_or_adjust_offset
47
- if has_parameter?(:check_offset)
48
- class << self
49
- alias_method :do_read_without_check_offset, :do_read
50
- alias_method :do_read, :do_read_with_check_offset
51
- end
52
- end
53
- if has_parameter?(:adjust_offset)
54
- class << self
55
- alias_method :do_read_without_adjust_offset, :do_read
56
- alias_method :do_read, :do_read_with_adjust_offset
40
+ def check_offset(io)
41
+ actual_offset = io.offset
42
+ expected = eval_parameter(:check_offset, :offset => actual_offset)
43
+
44
+ if not expected
45
+ raise ValidityError, "offset not as expected for #{debug_name}"
46
+ elsif actual_offset != expected and expected != true
47
+ raise ValidityError,
48
+ "offset is '#{actual_offset}' but " +
49
+ "expected '#{expected}' for #{debug_name}"
57
50
  end
58
51
  end
59
52
  end
60
53
 
61
- def check_offset(io)
62
- actual_offset = io.offset
63
- expected = eval_parameter(:check_offset, :offset => actual_offset)
64
-
65
- if not expected
66
- raise ValidityError, "offset not as expected for #{debug_name}"
67
- elsif actual_offset != expected and expected != true
68
- raise ValidityError,
69
- "offset is '#{actual_offset}' but " +
70
- "expected '#{expected}' for #{debug_name}"
54
+ module AdjustOffsetMixin
55
+ def do_read(io) #:nodoc:
56
+ adjust_offset(io)
57
+ super(io)
71
58
  end
72
- end
73
59
 
74
- def adjust_offset(io)
75
- actual_offset = io.offset
76
- expected = eval_parameter(:adjust_offset)
77
- if actual_offset != expected
78
- begin
79
- seek = expected - actual_offset
80
- io.seekbytes(seek)
81
- warn "adjusting stream position by #{seek} bytes" if $VERBOSE
82
- rescue
83
- raise ValidityError,
84
- "offset is '#{actual_offset}' but couldn't seek to " +
85
- "expected '#{expected}' for #{debug_name}"
60
+ #---------------
61
+ private
62
+
63
+ def adjust_offset(io)
64
+ actual_offset = io.offset
65
+ expected = eval_parameter(:adjust_offset)
66
+ if actual_offset != expected
67
+ begin
68
+ seek = expected - actual_offset
69
+ io.seekbytes(seek)
70
+ warn "adjusting stream position by #{seek} bytes" if $VERBOSE
71
+ rescue
72
+ raise ValidityError,
73
+ "offset is '#{actual_offset}' but couldn't seek to " +
74
+ "expected '#{expected}' for #{debug_name}"
75
+ end
86
76
  end
87
77
  end
88
78
  end
89
79
  end
90
80
  end
91
-
@@ -1,53 +1,45 @@
1
1
  require 'bindata/lazy'
2
2
 
3
3
  module BinData
4
- module AcceptedParametersMixin
5
- def self.included(base) #:nodoc:
6
- base.extend ClassMethods
4
+ module AcceptedParametersPlugin
5
+ # Mandatory parameters must be present when instantiating a data object.
6
+ def mandatory_parameters(*args)
7
+ accepted_parameters.mandatory(*args)
7
8
  end
8
9
 
9
- # Class methods to mix in to BinData::Base
10
- module ClassMethods
11
- # Mandatory parameters must be present when instantiating a data object.
12
- def mandatory_parameters(*args)
13
- accepted_parameters.mandatory(*args)
14
- end
15
-
16
- # Optional parameters may be present when instantiating a data object.
17
- def optional_parameters(*args)
18
- accepted_parameters.optional(*args)
19
- end
10
+ # Optional parameters may be present when instantiating a data object.
11
+ def optional_parameters(*args)
12
+ accepted_parameters.optional(*args)
13
+ end
20
14
 
21
- # Default parameters can be overridden when instantiating a data object.
22
- def default_parameters(*args)
23
- accepted_parameters.default(*args)
24
- end
15
+ # Default parameters can be overridden when instantiating a data object.
16
+ def default_parameters(*args)
17
+ accepted_parameters.default(*args)
18
+ end
25
19
 
26
- # Mutually exclusive parameters may not all be present when
27
- # instantiating a data object.
28
- def mutually_exclusive_parameters(*args)
29
- accepted_parameters.mutually_exclusive(*args)
30
- end
20
+ # Mutually exclusive parameters may not all be present when
21
+ # instantiating a data object.
22
+ def mutually_exclusive_parameters(*args)
23
+ accepted_parameters.mutually_exclusive(*args)
24
+ end
31
25
 
32
- alias_method :mandatory_parameter, :mandatory_parameters
33
- alias_method :optional_parameter, :optional_parameters
34
- alias_method :default_parameter, :default_parameters
26
+ alias_method :mandatory_parameter, :mandatory_parameters
27
+ alias_method :optional_parameter, :optional_parameters
28
+ alias_method :default_parameter, :default_parameters
35
29
 
36
- def accepted_parameters #:nodoc:
37
- unless defined? @accepted_parameters
38
- ancestor_params = superclass.respond_to?(:accepted_parameters) ?
39
- superclass.accepted_parameters : nil
40
- @accepted_parameters = AcceptedParameters.new(ancestor_params)
41
- end
42
- @accepted_parameters
30
+ def accepted_parameters #:nodoc:
31
+ unless defined? @accepted_parameters
32
+ ancestor_params = superclass.respond_to?(:accepted_parameters) ?
33
+ superclass.accepted_parameters : nil
34
+ @accepted_parameters = AcceptedParameters.new(ancestor_params)
43
35
  end
36
+ @accepted_parameters
44
37
  end
45
38
 
46
39
  # BinData objects accept parameters when initializing. AcceptedParameters
47
40
  # allow a BinData class to declaratively identify accepted parameters as
48
41
  # mandatory, optional, default or mutually exclusive.
49
42
  class AcceptedParameters
50
-
51
43
  def initialize(ancestor_parameters = nil)
52
44
  if ancestor_parameters
53
45
  @mandatory = ancestor_parameters.mandatory.dup
@@ -89,10 +81,13 @@ module BinData
89
81
  end
90
82
 
91
83
  def mutually_exclusive(*args)
92
- arg1, arg2 = args
93
- if arg1 != nil && arg2 != nil
94
- @mutually_exclusive.push([arg1.to_sym, arg2.to_sym])
95
- @mutually_exclusive.uniq!
84
+ arg1 = args.shift
85
+ while not args.empty?
86
+ args.each do |arg2|
87
+ @mutually_exclusive.push([arg1.to_sym, arg2.to_sym])
88
+ @mutually_exclusive.uniq!
89
+ end
90
+ arg1 = args.shift
96
91
  end
97
92
  @mutually_exclusive
98
93
  end
@@ -113,12 +113,7 @@ module BinData
113
113
  end
114
114
 
115
115
  def hidden_field_names(hidden)
116
- (hidden || []).collect do |h|
117
- unless Symbol === h
118
- warn "Hidden field '#{h}' should be provided as a symbol. Using strings is deprecated"
119
- end
120
- h.to_sym
121
- end
116
+ (hidden || []).collect { |h| h.to_sym }
122
117
  end
123
118
 
124
119
  def ensure_field_names_are_valid(field_names)
@@ -143,6 +138,7 @@ module BinData
143
138
 
144
139
  def initialize_shared_instance
145
140
  @field_names = get_parameter(:fields).field_names.freeze
141
+ super
146
142
  end
147
143
 
148
144
  def initialize_instance
data/lib/bindata/trace.rb CHANGED
@@ -25,14 +25,12 @@ module BinData
25
25
  # This is useful for debugging a BinData declaration.
26
26
  def trace_reading(io = STDERR, &block)
27
27
  @tracer = Tracer.new(io)
28
- BasePrimitive.turn_on_tracing
29
- Choice.turn_on_tracing
28
+ [BasePrimitive, Choice].each { |traced| traced.turn_on_tracing }
30
29
  if block_given?
31
30
  begin
32
31
  block.call
33
32
  ensure
34
- BasePrimitive.turn_off_tracing
35
- Choice.turn_off_tracing
33
+ [BasePrimitive, Choice].each { |traced| traced.turn_off_tracing }
36
34
  @tracer = nil
37
35
  end
38
36
  end
@@ -47,18 +45,19 @@ module BinData
47
45
  class BasePrimitive < BinData::Base
48
46
  class << self
49
47
  def turn_on_tracing
50
- alias_method :hook_after_do_read, :trace_value
48
+ alias_method :do_read_without_hook, :do_read
49
+ alias_method :do_read, :do_read_with_hook
51
50
  end
52
51
 
53
52
  def turn_off_tracing
54
- alias_method :hook_after_do_read, :null_method
53
+ alias_method :do_read, :do_read_without_hook
55
54
  end
56
55
  end
57
56
 
58
- #---------------
59
- private
60
-
61
- def null_method; end
57
+ def do_read_with_hook(io)
58
+ do_read_without_hook(io)
59
+ trace_value
60
+ end
62
61
 
63
62
  def trace_value
64
63
  BinData::trace_message do |tracer|
@@ -71,18 +70,19 @@ module BinData
71
70
  class Choice < BinData::Base
72
71
  class << self
73
72
  def turn_on_tracing
74
- alias_method :hook_before_do_read, :trace_selection
73
+ alias_method :do_read_without_hook, :do_read
74
+ alias_method :do_read, :do_read_with_hook
75
75
  end
76
76
 
77
77
  def turn_off_tracing
78
- alias_method :hook_before_do_read, :null_method
78
+ alias_method :do_read, :do_read_without_hook
79
79
  end
80
80
  end
81
81
 
82
- #---------------
83
- private
84
-
85
- def null_method; end
82
+ def do_read_with_hook(io)
83
+ trace_selection
84
+ do_read_without_hook(io)
85
+ end
86
86
 
87
87
  def trace_selection
88
88
  BinData::trace_message do |tracer|
@@ -1,3 +1,3 @@
1
1
  module BinData
2
- VERSION = "1.5.1"
2
+ VERSION = "1.6.0"
3
3
  end
@@ -15,7 +15,7 @@ module BinData
15
15
  #
16
16
  # obj = A.read("abcdeabcde")
17
17
  # obj.a #=> "abcde"
18
- # obj.b.offset #=> 10
18
+ # obj.c.offset #=> 10
19
19
  #
20
20
  class Virtual < BinData::BasePrimitive
21
21
 
@@ -23,8 +23,8 @@ module BinData
23
23
 
24
24
  class << self
25
25
  def sanitize_parameters!(params) #:nodoc:
26
- if params.has_parameter?(:assert_value)
27
- fail ":assert_value can not be used on virtual field"
26
+ if params.has_parameter?(:asserted_value)
27
+ fail ":asserted_value can not be used on virtual field"
28
28
  end
29
29
  end
30
30
  end
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require File.expand_path(File.join(File.dirname(__FILE__), "spec_common"))
4
- require 'bindata'
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "common"))
5
4
 
6
5
  describe BinData::ResumeByteAlignment do
7
6
  class ResumeAlignmentRecord < BinData::Record
@@ -10,29 +9,29 @@ describe BinData::ResumeByteAlignment do
10
9
  bit4 :b
11
10
  end
12
11
 
13
- subject { ResumeAlignmentRecord.new }
12
+ let(:obj) { ResumeAlignmentRecord.new }
14
13
 
15
14
  it "resets read alignment" do
16
- subject.read "\x12\x34"
15
+ obj.read "\x12\x34"
17
16
 
18
- subject.a.should == 1
19
- subject.b.should == 3
17
+ obj.a.must_equal 1
18
+ obj.b.must_equal 3
20
19
  end
21
20
 
22
21
  it "resets write alignment" do
23
- subject.assign(:a => 2, :b => 7)
22
+ obj.assign(:a => 2, :b => 7)
24
23
 
25
- subject.to_binary_s.should == "\x20\x70"
24
+ obj.to_binary_s.must_equal "\x20\x70"
26
25
  end
27
26
  end
28
27
 
29
28
  describe BinData::BitAligned do
30
29
  it "does not apply to BinData::Primitives" do
31
- expect {
30
+ lambda {
32
31
  class BitAlignedPrimitive < BinData::Primitive
33
32
  bit_aligned
34
33
  end
35
- }.to raise_error
34
+ }.must_raise RuntimeError
36
35
  end
37
36
 
38
37
  class BitString < BinData::String
@@ -45,17 +44,19 @@ describe BinData::BitAligned do
45
44
  bit4 :afterward
46
45
  end
47
46
 
48
- subject { BitAlignedRecord.new }
47
+ let(:obj) { BitAlignedRecord.new }
49
48
 
50
- its(:num_bytes) { should == 3 }
49
+ it "#num_bytes as expected" do
50
+ obj.num_bytes.must_equal 3
51
+ end
51
52
 
52
53
  it "reads as expected" do
53
- subject.read("\x56\x36\x42")
54
- subject.should == {"preamble" => 5, "str" => "cd", "afterward" => 2}
54
+ obj.read("\x56\x36\x42")
55
+ obj.snapshot.must_equal({"preamble" => 5, "str" => "cd", "afterward" => 2})
55
56
  end
56
57
 
57
58
  it "writes as expected" do
58
- subject.assign(:preamble => 5, :str => "ab", :afterward => 1)
59
- subject.to_binary_s.should == "\x56\x16\x21"
59
+ obj.assign(:preamble => 5, :str => "ab", :afterward => 1)
60
+ obj.to_binary_s.must_equal "\x56\x16\x21"
60
61
  end
61
62
  end