bindata 1.4.5 → 1.5.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 → ChangeLog.rdoc} +11 -1
- data/{NEWS → NEWS.rdoc} +7 -1
- data/README.md +54 -0
- data/lib/bindata.rb +4 -5
- data/lib/bindata/base.rb +33 -1
- data/lib/bindata/deprecated.rb +17 -55
- data/lib/bindata/dsl.rb +0 -4
- data/lib/bindata/io.rb +2 -2
- data/lib/bindata/params.rb +1 -1
- data/lib/bindata/primitive.rb +2 -2
- data/lib/bindata/sanitize.rb +12 -2
- data/lib/bindata/string.rb +5 -20
- data/lib/bindata/stringz.rb +2 -4
- data/lib/bindata/struct.rb +16 -9
- data/manual.haml +5 -0
- data/manual.md +26 -7
- data/spec/array_spec.rb +6 -0
- data/spec/deprecated_spec.rb +0 -89
- data/spec/int_spec.rb +1 -1
- data/spec/spec_common.rb +7 -0
- data/spec/string_spec.rb +1 -1
- data/spec/struct_spec.rb +10 -0
- data/tasks/pkg.rake +3 -3
- metadata +10 -12
- data/README +0 -50
- data/lib/bindata/wrapper.rb +0 -121
- data/spec/wrapper_spec.rb +0 -185
@@ -1,5 +1,15 @@
|
|
1
1
|
= BinData Changelog
|
2
2
|
|
3
|
+
== Version 1.5.0 (2013-05-21)
|
4
|
+
|
5
|
+
* Moved to github.
|
6
|
+
* Updated to Ruby 2.0
|
7
|
+
* Arrays now accept BinData object factories for :type (feature request by
|
8
|
+
Matt Dainty).
|
9
|
+
* Dynamically generated BinData objects can use the :name parameter to
|
10
|
+
register themselves.
|
11
|
+
* Remove functionality that has been deprecated for two years.
|
12
|
+
|
3
13
|
== Version 1.4.5 (2012-07-24)
|
4
14
|
|
5
15
|
* Added the :pad_front option for padding to occur at the front of a String.
|
@@ -22,7 +32,7 @@
|
|
22
32
|
|
23
33
|
== Version 1.4.2 (2011-08-06)
|
24
34
|
|
25
|
-
*
|
35
|
+
* \=~ now works for strings.
|
26
36
|
|
27
37
|
== Version 1.4.1 (2011-06-20)
|
28
38
|
|
data/{NEWS → NEWS.rdoc}
RENAMED
@@ -1,3 +1,9 @@
|
|
1
|
+
= 1.5.0
|
2
|
+
|
3
|
+
Finally moved the source code to github.
|
4
|
+
|
5
|
+
Deprecated functionality has been removed to cleanup the codebase.
|
6
|
+
|
1
7
|
= 1.4.4
|
2
8
|
|
3
9
|
== Deprecations
|
@@ -31,7 +37,7 @@ It should be changed to:
|
|
31
37
|
uint8 :initial_value => :initial_element_value
|
32
38
|
end
|
33
39
|
|
34
|
-
See http://bindata.rubyforge.org
|
40
|
+
See http://bindata.rubyforge.org/manual.html#extending_existing_types for details.
|
35
41
|
|
36
42
|
= 1.3.0
|
37
43
|
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# What is BinData?
|
2
|
+
|
3
|
+
Do you ever find yourself writing code like this?
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
io = File.open(...)
|
7
|
+
len = io.read(2).unpack("v")
|
8
|
+
name = io.read(len)
|
9
|
+
width, height = io.read(8).unpack("VV")
|
10
|
+
puts "Rectangle #{name} is #{width} x #{height}"
|
11
|
+
```
|
12
|
+
|
13
|
+
It’s ugly, violates DRY and feels like you’re writing Perl, not Ruby.
|
14
|
+
|
15
|
+
There is a better way. Here’s how you’d write the above using BinData.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
class Rectangle < BinData::Record
|
19
|
+
endian :little
|
20
|
+
uint16 :len
|
21
|
+
string :name, :read_length => :len
|
22
|
+
uint32 :width
|
23
|
+
uint32 :height
|
24
|
+
end
|
25
|
+
|
26
|
+
io = File.open(...)
|
27
|
+
r = Rectangle.read(io)
|
28
|
+
puts "Rectangle #{r.name} is #{r.width} x #{r.height}"
|
29
|
+
```
|
30
|
+
|
31
|
+
BinData makes it easy to create new data types. It supports all the common
|
32
|
+
primitive datatypes that are found in structured binary data formats. Support
|
33
|
+
for dependent and variable length fields is built in.
|
34
|
+
|
35
|
+
# Installation
|
36
|
+
|
37
|
+
$ sudo gem install bindata
|
38
|
+
|
39
|
+
-or-
|
40
|
+
|
41
|
+
$ sudo ruby setup.rb
|
42
|
+
|
43
|
+
# Documentation
|
44
|
+
|
45
|
+
[http://bindata.rubyforge.org/manual.html](http://bindata.rubyforge.org/manual.html)
|
46
|
+
|
47
|
+
-or-
|
48
|
+
|
49
|
+
$ rake manual
|
50
|
+
|
51
|
+
# Contact
|
52
|
+
|
53
|
+
If you have any queries / bug reports / suggestions, please contact me
|
54
|
+
(Dion Mendel) via email at dion@lostrealm.com
|
data/lib/bindata.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# BinData -- Binary data manipulator.
|
2
|
-
# Copyright (c) 2007 -
|
2
|
+
# Copyright (c) 2007 - 2013 Dion Mendel.
|
3
3
|
|
4
4
|
require 'bindata/array'
|
5
5
|
require 'bindata/bits'
|
@@ -15,7 +15,6 @@ require 'bindata/string'
|
|
15
15
|
require 'bindata/stringz'
|
16
16
|
require 'bindata/struct'
|
17
17
|
require 'bindata/trace'
|
18
|
-
require 'bindata/wrapper'
|
19
18
|
require 'bindata/alignment'
|
20
19
|
require 'bindata/deprecated'
|
21
20
|
|
@@ -24,13 +23,13 @@ require 'bindata/deprecated'
|
|
24
23
|
# A declarative way to read and write structured binary data.
|
25
24
|
#
|
26
25
|
# A full reference manual is available online at
|
27
|
-
# http://bindata.rubyforge.org.
|
26
|
+
# http://bindata.rubyforge.org/manual.html
|
28
27
|
#
|
29
28
|
# == License
|
30
29
|
#
|
31
30
|
# BinData is released under the same license as Ruby.
|
32
31
|
#
|
33
|
-
# Copyright (c) 2007 -
|
32
|
+
# Copyright (c) 2007 - 2013 Dion Mendel.
|
34
33
|
module BinData
|
35
|
-
VERSION = "1.
|
34
|
+
VERSION = "1.5.0"
|
36
35
|
end
|
data/lib/bindata/base.rb
CHANGED
@@ -82,6 +82,9 @@ module BinData
|
|
82
82
|
# Register all subclasses of this class.
|
83
83
|
register_subclasses
|
84
84
|
|
85
|
+
# The registered name may be provided explicitly.
|
86
|
+
optional_parameter :name
|
87
|
+
|
85
88
|
# Creates a new data object.
|
86
89
|
#
|
87
90
|
# Args are optional, but if present, must be in the following order.
|
@@ -93,12 +96,27 @@ module BinData
|
|
93
96
|
#
|
94
97
|
# +parent+ is the parent data object (e.g. struct, array, choice) this
|
95
98
|
# object resides under.
|
99
|
+
#
|
100
|
+
# == Parameters
|
101
|
+
#
|
102
|
+
# Parameters may be provided at initialisation to control the behaviour of
|
103
|
+
# an object. These params are:
|
104
|
+
#
|
105
|
+
# <tt>:name</tt>:: The name that this object can be referred to may be
|
106
|
+
# set explicitly. This is only useful when dynamically
|
107
|
+
# generating types.
|
108
|
+
# <code><pre>
|
109
|
+
# BinData::Struct.new(:name => :my_struct, :fields => ...)
|
110
|
+
# array = BinData::Array.new(:type => :my_struct)
|
111
|
+
# </pre></code>
|
112
|
+
#
|
96
113
|
def initialize(*args)
|
97
114
|
value, parameters, parent = extract_args(args)
|
98
115
|
|
99
116
|
@params = SanitizedParameters.sanitize(parameters, self.class)
|
100
117
|
@parent = parent
|
101
118
|
|
119
|
+
register_prototype
|
102
120
|
add_methods_for_check_or_adjust_offset
|
103
121
|
|
104
122
|
initialize_shared_instance
|
@@ -111,7 +129,7 @@ module BinData
|
|
111
129
|
|
112
130
|
# Creates a new data object based on this instance.
|
113
131
|
#
|
114
|
-
# All parameters will be be duplicated. Use this method
|
132
|
+
# All parameters will be be duplicated. Use this method
|
115
133
|
# when creating multiple objects with the same parameters.
|
116
134
|
def new(value = nil, parent = nil)
|
117
135
|
obj = clone
|
@@ -265,6 +283,12 @@ module BinData
|
|
265
283
|
self.class.arg_extractor.extract(self.class, the_args)
|
266
284
|
end
|
267
285
|
|
286
|
+
def register_prototype
|
287
|
+
if has_parameter?(:name)
|
288
|
+
RegisteredClasses.register(get_parameter(:name), self)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
268
292
|
def furthest_ancestor
|
269
293
|
if parent.nil?
|
270
294
|
self
|
@@ -275,6 +299,14 @@ module BinData
|
|
275
299
|
end
|
276
300
|
end
|
277
301
|
|
302
|
+
def binary_string(str)
|
303
|
+
if str.respond_to?(:force_encoding)
|
304
|
+
str.dup.force_encoding(Encoding::BINARY)
|
305
|
+
else
|
306
|
+
str.dup
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
278
310
|
###########################################################################
|
279
311
|
# To be implemented by subclasses
|
280
312
|
|
data/lib/bindata/deprecated.rb
CHANGED
@@ -18,15 +18,27 @@ end
|
|
18
18
|
module BinData
|
19
19
|
class Base
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
# Don't override initialize. If you are defining a new kind of datatype
|
22
|
+
# (list, array, choice etc) then put your initialization code in
|
23
|
+
# #initialize_instance. This is because BinData objects can be initialized
|
24
|
+
# as prototypes and your initialization code may not be called.
|
25
|
+
#
|
26
|
+
# If you're subclassing BinData::Record, you are definitely doing the wrong
|
27
|
+
# thing. Read the documentation on how to use BinData.
|
28
|
+
# http://bindata.rubyforge.org/manual.html#records
|
29
|
+
alias_method :initialize_without_warning, :initialize
|
30
|
+
def initialize_with_warning(*args)
|
23
31
|
owner = method(:initialize).owner
|
24
32
|
if owner != BinData::Base
|
25
|
-
|
33
|
+
msg = "Don't override #initialize on #{owner}."
|
34
|
+
if %w(BinData::Base BinData::BasePrimitive).include? self.class.superclass.name
|
35
|
+
msg += "\nrename #initialize to #initialize_instance."
|
36
|
+
end
|
37
|
+
fail msg
|
26
38
|
end
|
27
|
-
|
39
|
+
initialize_without_warning(*args)
|
28
40
|
end
|
29
|
-
alias_method :initialize, :
|
41
|
+
alias_method :initialize, :initialize_with_warning
|
30
42
|
|
31
43
|
def initialize_instance(*args)
|
32
44
|
unless args.empty?
|
@@ -34,55 +46,5 @@ module BinData
|
|
34
46
|
end
|
35
47
|
end
|
36
48
|
|
37
|
-
class << self
|
38
|
-
def register_self
|
39
|
-
warn "#{caller[0]} `register_self' is no longer needed as of BinData 1.3.2. You can delete this line"
|
40
|
-
end
|
41
|
-
|
42
|
-
def register(name, class_to_register)
|
43
|
-
warn "#{caller[0]} `register' is no longer needed as of BinData 1.3.2. You can delete this line"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def _do_read(io)
|
48
|
-
warn "#{caller[0]} `_do_read(io)' is deprecated as of BinData 1.3.0. Replace with `do_read(io)'"
|
49
|
-
do_read(io)
|
50
|
-
end
|
51
|
-
|
52
|
-
def _do_write(io)
|
53
|
-
warn "#{caller[0]} `_do_write(io)' is deprecated as of BinData 1.3.0. Replace with `do_write(io)'"
|
54
|
-
do_write(io)
|
55
|
-
end
|
56
|
-
|
57
|
-
def _do_num_bytes
|
58
|
-
warn "#{caller[0]} `_do_num_bytes' is deprecated as of BinData 1.3.0. Replace with `do_num_bytes'"
|
59
|
-
do_num_bytes
|
60
|
-
end
|
61
|
-
|
62
|
-
def _assign(val)
|
63
|
-
warn "#{caller[0]} `_assign(val)' is deprecated as of BinData 1.3.0. Replace with `assign(val)'"
|
64
|
-
assign(val)
|
65
|
-
end
|
66
|
-
|
67
|
-
def _snapshot
|
68
|
-
warn "#{caller[0]} `_snapshot' is deprecated as of BinData 1.3.0. Replace with `snapshot'"
|
69
|
-
snapshot
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
class SingleValue
|
74
|
-
class << self
|
75
|
-
def inherited(subclass) #:nodoc:
|
76
|
-
fail "BinData::SingleValue is deprecated. Downgrade to BinData 0.11.1.\nYou will need to make changes to your code before you can use BinData >= 1.0.0"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
class MultiValue
|
82
|
-
class << self
|
83
|
-
def inherited(subclass) #:nodoc:
|
84
|
-
fail "BinData::MultiValue is deprecated. Downgrade to BinData 0.11.1.\nYou will need to make changes to your code before you can use BinData >= 1.0.0"
|
85
|
-
end
|
86
|
-
end
|
87
49
|
end
|
88
50
|
end
|
data/lib/bindata/dsl.rb
CHANGED
@@ -90,8 +90,6 @@ module BinData
|
|
90
90
|
to_choice_params
|
91
91
|
when :primitive
|
92
92
|
to_struct_params
|
93
|
-
when :wrapper
|
94
|
-
raise "Wrapper is deprecated"
|
95
93
|
else
|
96
94
|
raise "unknown parser type #{@parser_type}"
|
97
95
|
end
|
@@ -122,8 +120,6 @@ module BinData
|
|
122
120
|
[:multiple_fields, :all_or_none_fieldnames, :sanitize_fields, :fieldnames_are_values]
|
123
121
|
when :primitive
|
124
122
|
[:multiple_fields, :optional_fieldnames, :sanitize_fields]
|
125
|
-
when :wrapper
|
126
|
-
[:only_one_field, :no_fieldnames]
|
127
123
|
else
|
128
124
|
raise "unknown parser type #{parser_type}"
|
129
125
|
end
|
data/lib/bindata/io.rb
CHANGED
@@ -7,7 +7,7 @@ module BinData
|
|
7
7
|
|
8
8
|
# Creates a StringIO around +str+.
|
9
9
|
def self.create_string_io(str = "")
|
10
|
-
if
|
10
|
+
if str.respond_to?(:force_encoding)
|
11
11
|
str = str.dup.force_encoding(Encoding::BINARY)
|
12
12
|
end
|
13
13
|
StringIO.new(str)
|
@@ -19,7 +19,7 @@ module BinData
|
|
19
19
|
# +io+ is a string it will be automatically wrapped in an StringIO object.
|
20
20
|
#
|
21
21
|
# The IO can handle bitstreams in either big or little endian format.
|
22
|
-
#
|
22
|
+
#
|
23
23
|
# M byte1 L M byte2 L
|
24
24
|
# S 76543210 S S fedcba98 S
|
25
25
|
# B B B B
|
data/lib/bindata/params.rb
CHANGED
@@ -123,7 +123,7 @@ module BinData
|
|
123
123
|
def self.invalid_parameter_names
|
124
124
|
unless defined? @invalid_names
|
125
125
|
all_names = LazyEvaluator.instance_methods(true) + Kernel.methods
|
126
|
-
allowed_names = ["type", :type] # ruby 1.8 vs 1.9
|
126
|
+
allowed_names = ["name", "type", :name, :type] # ruby 1.8 vs 1.9
|
127
127
|
invalid_names = (all_names - allowed_names).uniq
|
128
128
|
@invalid_names = Hash[*invalid_names.collect { |key| [key.to_sym, true] }.flatten]
|
129
129
|
end
|
data/lib/bindata/primitive.rb
CHANGED
@@ -16,11 +16,11 @@ module BinData
|
|
16
16
|
# class PascalString < BinData::Primitive
|
17
17
|
# uint8 :len, :value => lambda { data.length }
|
18
18
|
# string :data, :read_length => :len
|
19
|
-
#
|
19
|
+
#
|
20
20
|
# def get
|
21
21
|
# self.data
|
22
22
|
# end
|
23
|
-
#
|
23
|
+
#
|
24
24
|
# def set(v)
|
25
25
|
# self.data = v
|
26
26
|
# end
|
data/lib/bindata/sanitize.rb
CHANGED
@@ -10,8 +10,18 @@ module BinData
|
|
10
10
|
endian = endian.endian if endian.respond_to? :endian
|
11
11
|
obj_params ||= {}
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
if BinData::Base === obj_type
|
14
|
+
obj_class = obj_type
|
15
|
+
else
|
16
|
+
obj_class = RegisteredClasses.lookup(obj_type, endian)
|
17
|
+
end
|
18
|
+
|
19
|
+
if BinData::Base === obj_class
|
20
|
+
@factory = obj_class
|
21
|
+
else
|
22
|
+
@obj_class = obj_class
|
23
|
+
@obj_params = SanitizedParameters.new(obj_params, @obj_class, endian)
|
24
|
+
end
|
15
25
|
end
|
16
26
|
|
17
27
|
def instantiate(value = nil, parent = nil)
|
data/lib/bindata/string.rb
CHANGED
@@ -76,24 +76,17 @@ module BinData
|
|
76
76
|
private
|
77
77
|
|
78
78
|
def sanitized_pad_byte(byte)
|
79
|
-
result = byte.is_a?(Integer) ? byte.chr :
|
80
|
-
|
79
|
+
result = byte.is_a?(Integer) ? byte.chr : byte.to_s
|
80
|
+
len = result.respond_to?(:bytesize) ? result.bytesize : result.length
|
81
|
+
if len > 1
|
81
82
|
raise ArgumentError, ":pad_byte must not contain more than 1 byte"
|
82
83
|
end
|
83
84
|
result
|
84
85
|
end
|
85
|
-
|
86
|
-
def byte_string(str)
|
87
|
-
if RUBY_VERSION >= "1.9"
|
88
|
-
str.force_encoding(Encoding::BINARY)
|
89
|
-
else
|
90
|
-
str
|
91
|
-
end
|
92
|
-
end
|
93
86
|
end
|
94
87
|
|
95
88
|
def assign(val)
|
96
|
-
super(
|
89
|
+
super(binary_string(val))
|
97
90
|
end
|
98
91
|
|
99
92
|
def snapshot
|
@@ -110,16 +103,8 @@ module BinData
|
|
110
103
|
#---------------
|
111
104
|
private
|
112
105
|
|
113
|
-
def byte_string(str)
|
114
|
-
if RUBY_VERSION >= "1.9"
|
115
|
-
str.force_encoding(Encoding::BINARY)
|
116
|
-
else
|
117
|
-
str
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
106
|
def clamp_to_length(str)
|
122
|
-
str =
|
107
|
+
str = binary_string(str)
|
123
108
|
|
124
109
|
len = eval_parameter(:length) || str.length
|
125
110
|
if str.length == len
|
data/lib/bindata/stringz.rb
CHANGED
@@ -29,8 +29,7 @@ module BinData
|
|
29
29
|
optional_parameters :max_length
|
30
30
|
|
31
31
|
def assign(val)
|
32
|
-
val
|
33
|
-
super(val)
|
32
|
+
super(binary_string(val))
|
34
33
|
end
|
35
34
|
|
36
35
|
def snapshot
|
@@ -67,8 +66,7 @@ module BinData
|
|
67
66
|
end
|
68
67
|
|
69
68
|
def trim_and_zero_terminate(str)
|
70
|
-
str
|
71
|
-
|
69
|
+
str = binary_string(str)
|
72
70
|
str = truncate_after_first_zero_byte(str)
|
73
71
|
str = trim_to(str, eval_parameter(:max_length))
|
74
72
|
append_zero_byte_if_needed(str)
|
data/lib/bindata/struct.rb
CHANGED
@@ -163,7 +163,7 @@ module BinData
|
|
163
163
|
end
|
164
164
|
|
165
165
|
def snapshot
|
166
|
-
snapshot = Snapshot.new
|
166
|
+
snapshot = Snapshot.new
|
167
167
|
field_names.each do |name|
|
168
168
|
obj = find_obj_for_name(name)
|
169
169
|
snapshot[name] = obj.snapshot if include_obj(obj)
|
@@ -303,7 +303,7 @@ module BinData
|
|
303
303
|
elsif val.nil?
|
304
304
|
{}
|
305
305
|
else
|
306
|
-
hash = Snapshot.new
|
306
|
+
hash = Snapshot.new
|
307
307
|
val.each_pair { |k,v| hash[k] = v }
|
308
308
|
hash
|
309
309
|
end
|
@@ -330,18 +330,20 @@ module BinData
|
|
330
330
|
not obj.has_parameter?(:onlyif) or obj.eval_parameter(:onlyif)
|
331
331
|
end
|
332
332
|
|
333
|
-
|
334
|
-
|
335
|
-
def initialize(order = [])
|
336
|
-
@order = order.compact
|
337
|
-
end
|
338
|
-
|
339
|
-
if RUBY_VERSION <= "1.9"
|
333
|
+
if RUBY_VERSION <= "1.9"
|
334
|
+
module OrderedHash #:nodoc:
|
340
335
|
def keys
|
336
|
+
@order ||= []
|
341
337
|
k = super
|
342
338
|
@order & k
|
343
339
|
end
|
344
340
|
|
341
|
+
def []=(key, value)
|
342
|
+
@order ||= []
|
343
|
+
@order << key
|
344
|
+
super(key, value)
|
345
|
+
end
|
346
|
+
|
345
347
|
def each
|
346
348
|
keys.each do |k|
|
347
349
|
yield [k, self[k]]
|
@@ -354,6 +356,11 @@ module BinData
|
|
354
356
|
end
|
355
357
|
end
|
356
358
|
end
|
359
|
+
end
|
360
|
+
|
361
|
+
# A hash that can be accessed via attributes.
|
362
|
+
class Snapshot < ::Hash #:nodoc:
|
363
|
+
include OrderedHash if RUBY_VERSION <= "1.9"
|
357
364
|
|
358
365
|
def has_key?(key)
|
359
366
|
super(key.to_s)
|
data/manual.haml
CHANGED
@@ -354,6 +354,11 @@
|
|
354
354
|
Extending existing Types
|
355
355
|
.acc-section
|
356
356
|
.acc-content
|
357
|
+
%li
|
358
|
+
%a{ :href => "#dynamically_creating_types" }
|
359
|
+
Dynamically creating Types
|
360
|
+
.acc-section
|
361
|
+
.acc-content
|
357
362
|
%li
|
358
363
|
%a{ :href => "#skipping_over_unused_data" }
|
359
364
|
Skipping over unused data
|
data/manual.md
CHANGED
@@ -40,13 +40,17 @@ manipulating.
|
|
40
40
|
It supports all the common datatypes that are found in structured binary
|
41
41
|
data. Support for dependent and variable length fields is built in.
|
42
42
|
|
43
|
-
Last updated:
|
43
|
+
Last updated: 2013-05-21
|
44
|
+
|
45
|
+
## Source code
|
46
|
+
|
47
|
+
[BinData](http://github.com/dmendel/bindata) is hosted on Github.
|
44
48
|
|
45
49
|
## License
|
46
50
|
|
47
51
|
BinData is released under the same license as Ruby.
|
48
52
|
|
49
|
-
Copyright © 2007 -
|
53
|
+
Copyright © 2007 - 2013 [Dion Mendel](mailto:dion@lostrealm.com)
|
50
54
|
|
51
55
|
## Donate
|
52
56
|
|
@@ -57,13 +61,14 @@ Want to donate? My favourite local charity is
|
|
57
61
|
|
58
62
|
# Installation
|
59
63
|
|
60
|
-
You can install BinData via rubygems.
|
64
|
+
You can install BinData via rubygems (recommended).
|
61
65
|
|
62
66
|
gem install bindata
|
63
67
|
|
64
|
-
|
65
|
-
|
66
|
-
|
68
|
+
or as source package.
|
69
|
+
|
70
|
+
git clone http://github.com/dmendel/bindata.git
|
71
|
+
cd bindata && ruby setup.rb
|
67
72
|
|
68
73
|
---------------------------------------------------------------------------
|
69
74
|
|
@@ -1357,6 +1362,20 @@ We can also use the block form syntax:
|
|
1357
1362
|
end
|
1358
1363
|
{:ruby}
|
1359
1364
|
|
1365
|
+
## Dynamically creating Types
|
1366
|
+
|
1367
|
+
Sometimes the format of a record is not known until runtime. You can use the
|
1368
|
+
`BinData::Struct` class to dynamically create a new type. To be able to reuse
|
1369
|
+
this type, you can give it a name.
|
1370
|
+
|
1371
|
+
# Dynamically create my_new_type
|
1372
|
+
BinData::Struct.new(:name => :my_new_type,
|
1373
|
+
:fields => [ [:int8, :a], [:int8, :b] ])
|
1374
|
+
|
1375
|
+
# Create an array of these types
|
1376
|
+
array = BinData::Array.new(:type => :my_new_type)
|
1377
|
+
{:ruby}
|
1378
|
+
|
1360
1379
|
## Skipping over unused data
|
1361
1380
|
|
1362
1381
|
Some structures contain binary data that is irrelevant to your purposes.
|
@@ -1559,7 +1578,7 @@ decided by the `protocol` field.
|
|
1559
1578
|
Modelling this structure can be difficult when the nesting is recursive, e.g.
|
1560
1579
|
IP tunneling. Here is an example of the simplest possible recursive TLV structure,
|
1561
1580
|
a [list that can contains atoms or other
|
1562
|
-
lists](http://
|
1581
|
+
lists](http://github.com/dmendel/bindata/blob/master/examples/list.rb).
|
1563
1582
|
|
1564
1583
|
---------------------------------------------------------------------------
|
1565
1584
|
|
data/spec/array_spec.rb
CHANGED
@@ -30,6 +30,12 @@ describe BinData::Array, "when instantiating" do
|
|
30
30
|
args = {:initial_length => 3, :read_until => lambda { false } }
|
31
31
|
expect { BinData::Array.new(args) }.to raise_error(ArgumentError)
|
32
32
|
end
|
33
|
+
|
34
|
+
it "accepts BinData::Base as :type" do
|
35
|
+
obj = BinData::Int8.new(:initial_value => 5)
|
36
|
+
array = BinData::Array.new(:type => obj, :initial_length => 1)
|
37
|
+
array.should == [5]
|
38
|
+
end
|
33
39
|
end
|
34
40
|
|
35
41
|
describe BinData::Array, "with no elements" do
|
data/spec/deprecated_spec.rb
CHANGED
@@ -4,24 +4,6 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec_common"))
|
|
4
4
|
require File.expand_path(File.join(File.dirname(__FILE__), "example"))
|
5
5
|
require 'bindata'
|
6
6
|
|
7
|
-
describe BinData::SingleValue, "when defining" do
|
8
|
-
it "fails when inheriting from deprecated SingleValue" do
|
9
|
-
expect {
|
10
|
-
class SubclassSingleValue < BinData::SingleValue
|
11
|
-
end
|
12
|
-
}.to raise_error
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe BinData::MultiValue, "when defining" do
|
17
|
-
it "fails inheriting from deprecated MultiValue" do
|
18
|
-
expect {
|
19
|
-
class SubclassMultiValue < BinData::MultiValue
|
20
|
-
end
|
21
|
-
}.to raise_error
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
7
|
describe BinData::Base, "when defining" do
|
26
8
|
it "fails if #initialize is overridden" do
|
27
9
|
class BaseWithInitialize < BinData::Base
|
@@ -46,75 +28,4 @@ describe BinData::Base, "when defining" do
|
|
46
28
|
BaseWithInitializeInstance.new
|
47
29
|
}.not_to raise_error
|
48
30
|
end
|
49
|
-
|
50
|
-
it "handles deprecated #register_self method" do
|
51
|
-
expect {
|
52
|
-
class DeprecatedRegisterSelfBase < BinData::Base
|
53
|
-
register_self
|
54
|
-
end
|
55
|
-
}.not_to raise_error
|
56
|
-
end
|
57
|
-
|
58
|
-
it "handles deprecated #register method" do
|
59
|
-
expect {
|
60
|
-
class DeprecatedRegisterBase < BinData::Base
|
61
|
-
register(self.name, self)
|
62
|
-
end
|
63
|
-
}.not_to raise_error
|
64
|
-
end
|
65
|
-
|
66
|
-
it "handles deprecated #register method for subclasses" do
|
67
|
-
expect {
|
68
|
-
class DeprecatedSuperBase < BinData::Base
|
69
|
-
def self.inherited(subclass)
|
70
|
-
register(subclass.name, subclass)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
class DeprecatedSubBase < DeprecatedSuperBase
|
75
|
-
end
|
76
|
-
}.not_to raise_error
|
77
|
-
end
|
78
|
-
|
79
|
-
it "handles deprecated #register method with custom calling" do
|
80
|
-
expect {
|
81
|
-
class DeprecatedCustomBase < BinData::Base
|
82
|
-
register(name, Object)
|
83
|
-
end
|
84
|
-
}.not_to raise_error
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe BinData::Base do
|
89
|
-
class DeprecatedBase < BinData::Base
|
90
|
-
end
|
91
|
-
|
92
|
-
subject { DeprecatedBase.new }
|
93
|
-
let(:io) { "abcde" }
|
94
|
-
|
95
|
-
it "forwards _do_read to do_read" do
|
96
|
-
subject.should_receive(:do_read).with(io)
|
97
|
-
subject._do_read(io)
|
98
|
-
end
|
99
|
-
|
100
|
-
it "forwards _do_write to do_write" do
|
101
|
-
subject.should_receive(:do_write).with(io)
|
102
|
-
subject._do_write(io)
|
103
|
-
end
|
104
|
-
|
105
|
-
it "forwards _do_num_bytes to do_num_bytes" do
|
106
|
-
subject.should_receive(:do_num_bytes)
|
107
|
-
subject._do_num_bytes
|
108
|
-
end
|
109
|
-
|
110
|
-
it "forwards _assign to assign" do
|
111
|
-
val = 3
|
112
|
-
subject.should_receive(:assign).with(val)
|
113
|
-
subject._assign(val)
|
114
|
-
end
|
115
|
-
|
116
|
-
it "forwards _snapshot to snapshot" do
|
117
|
-
subject.should_receive(:snapshot)
|
118
|
-
subject._snapshot
|
119
|
-
end
|
120
31
|
end
|
data/spec/int_spec.rb
CHANGED
data/spec/spec_common.rb
CHANGED
data/spec/string_spec.rb
CHANGED
@@ -269,7 +269,7 @@ describe BinData::String, "with Ruby 1.9 encodings" do
|
|
269
269
|
end
|
270
270
|
|
271
271
|
subject { UTF8String.new }
|
272
|
-
let(:binary_str) { "\xC3\x85\xC3\x84\xC3\x96" }
|
272
|
+
let(:binary_str) { binary("\xC3\x85\xC3\x84\xC3\x96") }
|
273
273
|
let(:utf8_str) { binary_str.dup.force_encoding('UTF-8') }
|
274
274
|
|
275
275
|
it "stores assigned values as binary" do
|
data/spec/struct_spec.rb
CHANGED
@@ -338,3 +338,13 @@ describe BinData::Struct, "with nested endian" do
|
|
338
338
|
subject.d.should == 4
|
339
339
|
end
|
340
340
|
end
|
341
|
+
|
342
|
+
describe BinData::Struct, "with dynamically named types" do
|
343
|
+
it "instantiates" do
|
344
|
+
dyn = BinData::Struct.new(:name => :my_struct, :fields => [[:int8, :a, {:initial_value => 3}]])
|
345
|
+
|
346
|
+
obj = BinData::Struct.new(:fields => [[:my_struct, :v]])
|
347
|
+
|
348
|
+
obj.v.a.should == 3
|
349
|
+
end
|
350
|
+
end
|
data/tasks/pkg.rake
CHANGED
@@ -9,12 +9,12 @@ begin
|
|
9
9
|
s.summary = 'A declarative way to read and write binary file formats'
|
10
10
|
s.author = 'Dion Mendel'
|
11
11
|
s.email = 'dion@lostrealm.com'
|
12
|
-
s.homepage = 'http://bindata
|
12
|
+
s.homepage = 'http://github.com/dmendel/bindata'
|
13
13
|
s.rubyforge_project = 'bindata'
|
14
14
|
s.require_path = 'lib'
|
15
15
|
s.has_rdoc = true
|
16
|
-
s.extra_rdoc_files = ['NEWS']
|
17
|
-
s.rdoc_options << '--main' << 'NEWS'
|
16
|
+
s.extra_rdoc_files = ['NEWS.rdoc']
|
17
|
+
s.rdoc_options << '--main' << 'NEWS.rdoc'
|
18
18
|
s.files = PKG_FILES
|
19
19
|
s.add_development_dependency('rspec', [">= 2.10.0"])
|
20
20
|
s.add_development_dependency('haml')
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bindata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
- 4
|
9
8
|
- 5
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 1.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dion Mendel
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2013-05-21 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rspec
|
@@ -89,14 +89,14 @@ executables: []
|
|
89
89
|
extensions: []
|
90
90
|
|
91
91
|
extra_rdoc_files:
|
92
|
-
- NEWS
|
92
|
+
- NEWS.rdoc
|
93
93
|
files:
|
94
|
-
-
|
95
|
-
- NEWS
|
94
|
+
- NEWS.rdoc
|
96
95
|
- COPYING
|
96
|
+
- README.md
|
97
97
|
- BSDL
|
98
|
-
- README
|
99
98
|
- Rakefile
|
99
|
+
- ChangeLog.rdoc
|
100
100
|
- INSTALL
|
101
101
|
- examples/ip_address.rb
|
102
102
|
- examples/list.rb
|
@@ -124,7 +124,6 @@ files:
|
|
124
124
|
- spec/string_spec.rb
|
125
125
|
- spec/base_spec.rb
|
126
126
|
- spec/registry_spec.rb
|
127
|
-
- spec/wrapper_spec.rb
|
128
127
|
- spec/skip_spec.rb
|
129
128
|
- spec/float_spec.rb
|
130
129
|
- lib/bindata/count_bytes_remaining.rb
|
@@ -144,7 +143,6 @@ files:
|
|
144
143
|
- lib/bindata/base_primitive.rb
|
145
144
|
- lib/bindata/struct.rb
|
146
145
|
- lib/bindata/bits.rb
|
147
|
-
- lib/bindata/wrapper.rb
|
148
146
|
- lib/bindata/offset.rb
|
149
147
|
- lib/bindata/record.rb
|
150
148
|
- lib/bindata/dsl.rb
|
@@ -161,13 +159,13 @@ files:
|
|
161
159
|
- setup.rb
|
162
160
|
- manual.haml
|
163
161
|
- manual.md
|
164
|
-
homepage: http://bindata
|
162
|
+
homepage: http://github.com/dmendel/bindata
|
165
163
|
licenses: []
|
166
164
|
|
167
165
|
post_install_message:
|
168
166
|
rdoc_options:
|
169
167
|
- --main
|
170
|
-
- NEWS
|
168
|
+
- NEWS.rdoc
|
171
169
|
require_paths:
|
172
170
|
- lib
|
173
171
|
required_ruby_version: !ruby/object:Gem::Requirement
|
data/README
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
= What is BinData?
|
2
|
-
|
3
|
-
Do you ever find yourself writing code like this?
|
4
|
-
|
5
|
-
io = File.open(...)
|
6
|
-
len = io.read(2).unpack("v")
|
7
|
-
name = io.read(len)
|
8
|
-
width, height = io.read(8).unpack("VV")
|
9
|
-
puts "Rectangle #{name} is #{width} x #{height}"
|
10
|
-
|
11
|
-
It’s ugly, violates DRY and feels like you’re writing Perl, not Ruby.
|
12
|
-
|
13
|
-
There is a better way. Here’s how you’d write the above using BinData.
|
14
|
-
|
15
|
-
class Rectangle < BinData::Record
|
16
|
-
endian :little
|
17
|
-
uint16 :len
|
18
|
-
string :name, :read_length => :len
|
19
|
-
uint32 :width
|
20
|
-
uint32 :height
|
21
|
-
end
|
22
|
-
|
23
|
-
io = File.open(...)
|
24
|
-
r = Rectangle.read(io)
|
25
|
-
puts "Rectangle #{r.name} is #{r.width} x #{r.height}"
|
26
|
-
|
27
|
-
BinData makes it easy to create new data types. It supports all the common
|
28
|
-
primitive datatypes that are found in structured binary data formats. Support
|
29
|
-
for dependent and variable length fields is built in.
|
30
|
-
|
31
|
-
= Installation
|
32
|
-
|
33
|
-
$ sudo gem install bindata
|
34
|
-
|
35
|
-
-or-
|
36
|
-
|
37
|
-
$ sudo ruby setup.rb
|
38
|
-
|
39
|
-
= Documentation
|
40
|
-
|
41
|
-
http://bindata.rubyforge.org/
|
42
|
-
|
43
|
-
-or-
|
44
|
-
|
45
|
-
$ rake manual
|
46
|
-
|
47
|
-
= Contact
|
48
|
-
|
49
|
-
If you have any queries / bug reports / suggestions, please contact me
|
50
|
-
(Dion Mendel) via email at dion@lostrealm.com
|
data/lib/bindata/wrapper.rb
DELETED
@@ -1,121 +0,0 @@
|
|
1
|
-
require 'bindata/base'
|
2
|
-
require 'bindata/dsl'
|
3
|
-
|
4
|
-
module BinData
|
5
|
-
class SanitizedParameters < Hash
|
6
|
-
def move_unknown_parameters_to(dest)
|
7
|
-
unused_keys = keys - @the_class.accepted_parameters.all
|
8
|
-
unused_keys.each do |key|
|
9
|
-
dest[key] = delete(key)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# A Wrapper allows the creation of new BinData types that
|
15
|
-
# provide default parameters.
|
16
|
-
#
|
17
|
-
# require 'bindata'
|
18
|
-
#
|
19
|
-
# class Uint8Array < BinData::Wrapper
|
20
|
-
# default_parameter :initial_element_value => 0
|
21
|
-
#
|
22
|
-
# array :initial_length => 2 do
|
23
|
-
# uint8 :initial_value => :initial_element_value
|
24
|
-
# end
|
25
|
-
# end
|
26
|
-
#
|
27
|
-
# arr = Uint8Array.new
|
28
|
-
# arr.snapshot #=> [0, 0]
|
29
|
-
#
|
30
|
-
# arr = Uint8Array.new(:initial_length => 5, :initial_element_value => 3)
|
31
|
-
# arr.snapshot #=> [3, 3, 3, 3 ,3]
|
32
|
-
#
|
33
|
-
class Wrapper < BinData::Base
|
34
|
-
include DSLMixin
|
35
|
-
|
36
|
-
unregister_self
|
37
|
-
dsl_parser :wrapper
|
38
|
-
|
39
|
-
class << self
|
40
|
-
def sanitize_parameters!(params) #:nodoc:
|
41
|
-
raise "no wrapped type was specified in #{self}" if fields[0].nil?
|
42
|
-
|
43
|
-
wrapped_type = fields[0].type
|
44
|
-
wrapped_params = fields[0].params.dup
|
45
|
-
|
46
|
-
params.move_unknown_parameters_to(wrapped_params)
|
47
|
-
|
48
|
-
params.endian = endian unless endian.nil?
|
49
|
-
params[:wrapped] = params.create_sanitized_object_prototype(wrapped_type, wrapped_params)
|
50
|
-
|
51
|
-
wrapped_class = params[:wrapped].instance_variable_get(:@obj_class)
|
52
|
-
warn "BinData::Wrapper is deprecated as of BinData 1.3.2. #{self} should derive from #{wrapped_class}\n See http://bindata.rubyforge.org/#extending_existing_types"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
mandatory_parameter :wrapped
|
57
|
-
|
58
|
-
def initialize_instance
|
59
|
-
prototype = get_parameter(:wrapped)
|
60
|
-
@wrapped = prototype.instantiate(nil, self)
|
61
|
-
end
|
62
|
-
|
63
|
-
def clear #:nodoc:
|
64
|
-
@wrapped.clear
|
65
|
-
end
|
66
|
-
|
67
|
-
def clear? #:nodoc:
|
68
|
-
@wrapped.clear?
|
69
|
-
end
|
70
|
-
|
71
|
-
def assign(val)
|
72
|
-
@wrapped.assign(val)
|
73
|
-
end
|
74
|
-
|
75
|
-
def snapshot
|
76
|
-
@wrapped.snapshot
|
77
|
-
end
|
78
|
-
|
79
|
-
def respond_to?(symbol, include_private = false) #:nodoc:
|
80
|
-
@wrapped.respond_to?(symbol, include_private) || super
|
81
|
-
end
|
82
|
-
|
83
|
-
def method_missing(symbol, *args, &block) #:nodoc:
|
84
|
-
@wrapped.__send__(symbol, *args, &block)
|
85
|
-
end
|
86
|
-
|
87
|
-
def do_read(io) #:nodoc:
|
88
|
-
@wrapped.do_read(io)
|
89
|
-
end
|
90
|
-
|
91
|
-
def do_write(io) #:nodoc
|
92
|
-
@wrapped.do_write(io)
|
93
|
-
end
|
94
|
-
|
95
|
-
def do_num_bytes #:nodoc:
|
96
|
-
@wrapped.do_num_bytes
|
97
|
-
end
|
98
|
-
|
99
|
-
#---------------
|
100
|
-
private
|
101
|
-
|
102
|
-
def extract_args(args)
|
103
|
-
klass = wrapped_class
|
104
|
-
if klass
|
105
|
-
klass.arg_extractor.extract(klass, args)
|
106
|
-
else
|
107
|
-
super
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def wrapped_class
|
112
|
-
return nil if self.class.fields[0].nil?
|
113
|
-
|
114
|
-
begin
|
115
|
-
RegisteredClasses.lookup(self.class.fields[0].type, self.class.endian)
|
116
|
-
rescue BinData::UnRegisteredTypeError
|
117
|
-
nil
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
data/spec/wrapper_spec.rb
DELETED
@@ -1,185 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "spec_common"))
|
4
|
-
require 'bindata'
|
5
|
-
|
6
|
-
describe BinData::Wrapper do
|
7
|
-
it "is not registered" do
|
8
|
-
expect {
|
9
|
-
BinData::RegisteredClasses.lookup("Wrapper")
|
10
|
-
}.to raise_error(BinData::UnRegisteredTypeError)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe BinData::Wrapper, "with errors" do
|
15
|
-
it "does not wrap more than one type" do
|
16
|
-
lambda {
|
17
|
-
class WrappedMultipleTypes < BinData::Wrapper
|
18
|
-
uint8
|
19
|
-
uint8
|
20
|
-
end
|
21
|
-
}.should raise_error_on_line(SyntaxError, 3) { |err|
|
22
|
-
err.message.should == "attempting to wrap more than one type in #{WrappedMultipleTypes}"
|
23
|
-
}
|
24
|
-
end
|
25
|
-
|
26
|
-
it "fails if wrapped type has a name" do
|
27
|
-
lambda {
|
28
|
-
class WrappedWithName < BinData::Wrapper
|
29
|
-
uint8 :a
|
30
|
-
end
|
31
|
-
}.should raise_error_on_line(SyntaxError, 2) { |err|
|
32
|
-
err.message.should == "field must not have a name in #{WrappedWithName}"
|
33
|
-
}
|
34
|
-
end
|
35
|
-
|
36
|
-
it "fails if no types to wrap" do
|
37
|
-
class WrappedNoTypes < BinData::Wrapper
|
38
|
-
end
|
39
|
-
|
40
|
-
lambda {
|
41
|
-
WrappedNoTypes.new
|
42
|
-
}.should raise_error(RuntimeError) { |err|
|
43
|
-
err.message.should == "no wrapped type was specified in #{WrappedNoTypes}"
|
44
|
-
}
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe BinData::Wrapper, "around a Primitive" do
|
49
|
-
class WrappedPrimitive < BinData::Wrapper
|
50
|
-
default_parameter :a => 3
|
51
|
-
|
52
|
-
uint8 :initial_value => :a
|
53
|
-
end
|
54
|
-
|
55
|
-
it "accesses custom parameter" do
|
56
|
-
subject = WrappedPrimitive.new
|
57
|
-
subject.assign(3)
|
58
|
-
subject.should == 3
|
59
|
-
end
|
60
|
-
|
61
|
-
it "overrides custom default parameter" do
|
62
|
-
subject = WrappedPrimitive.new(:a => 5)
|
63
|
-
subject.should == 5
|
64
|
-
end
|
65
|
-
|
66
|
-
it "overrides parameter" do
|
67
|
-
subject = WrappedPrimitive.new(:initial_value => 7)
|
68
|
-
subject.should == 7
|
69
|
-
end
|
70
|
-
|
71
|
-
it "clears" do
|
72
|
-
subject = WrappedPrimitive.new
|
73
|
-
subject.assign(3)
|
74
|
-
subject.should_not be_clear
|
75
|
-
|
76
|
-
subject.clear
|
77
|
-
subject.should be_clear
|
78
|
-
end
|
79
|
-
|
80
|
-
it "reads" do
|
81
|
-
subject = WrappedPrimitive.new
|
82
|
-
subject.assign(3)
|
83
|
-
str = subject.to_binary_s
|
84
|
-
|
85
|
-
WrappedPrimitive.read(str).should == 3
|
86
|
-
end
|
87
|
-
|
88
|
-
it "respond_to and forward messages to the wrapped object" do
|
89
|
-
subject = WrappedPrimitive.new
|
90
|
-
subject.assign(5)
|
91
|
-
|
92
|
-
subject.should respond_to(:to_int)
|
93
|
-
subject.to_int.should == 5
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
describe BinData::Wrapper, "around an Array" do
|
98
|
-
class WrappedIntArray < BinData::Wrapper
|
99
|
-
endian :big
|
100
|
-
default_parameter :initial_element_value => 0
|
101
|
-
array do
|
102
|
-
uint16 :initial_value => :initial_element_value
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
it "forwards parameters" do
|
107
|
-
subject = WrappedIntArray.new(:initial_length => 7)
|
108
|
-
subject.length.should == 7
|
109
|
-
end
|
110
|
-
|
111
|
-
it "overrides default parameters" do
|
112
|
-
subject = WrappedIntArray.new(:initial_length => 3, :initial_element_value => 5)
|
113
|
-
subject.to_binary_s.should == "\x00\x05\x00\x05\x00\x05"
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
describe BinData::Wrapper, "around a Choice" do
|
118
|
-
class WrappedChoice < BinData::Wrapper
|
119
|
-
endian :big
|
120
|
-
choice :choices => { 'a' => :uint8, 'b' => :uint16 }
|
121
|
-
end
|
122
|
-
|
123
|
-
it "forwards parameters" do
|
124
|
-
subject = WrappedChoice.new(:selection => 'b')
|
125
|
-
subject.num_bytes.should == 2
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe BinData::Wrapper, "inside a Record" do
|
130
|
-
class WrappedUint32le < BinData::Wrapper
|
131
|
-
uint32le
|
132
|
-
end
|
133
|
-
|
134
|
-
class RecordWithWrapped < BinData::Record
|
135
|
-
wrapped_uint32le :a, :onlyif => false, :value => 1
|
136
|
-
wrapped_uint32le :b, :onlyif => true, :value => 2
|
137
|
-
end
|
138
|
-
|
139
|
-
it "handles onlyif" do
|
140
|
-
subject = RecordWithWrapped.new
|
141
|
-
subject.should == {'b' => 2}
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
describe BinData::Wrapper, "around a Record" do
|
146
|
-
class RecordToBeWrapped < BinData::Record
|
147
|
-
default_parameter :arg => 3
|
148
|
-
uint8 :a, :initial_value => :arg
|
149
|
-
uint8 :b
|
150
|
-
end
|
151
|
-
|
152
|
-
class WrappedRecord < BinData::Wrapper
|
153
|
-
record_to_be_wrapped
|
154
|
-
end
|
155
|
-
|
156
|
-
it "forwards parameters" do
|
157
|
-
subject = WrappedRecord.new(:arg => 5)
|
158
|
-
subject.a.should == 5
|
159
|
-
end
|
160
|
-
|
161
|
-
it "assigns value" do
|
162
|
-
subject = WrappedRecord.new(:b => 5)
|
163
|
-
subject.b.should == 5
|
164
|
-
end
|
165
|
-
|
166
|
-
it "assigns value and forward parameters" do
|
167
|
-
subject = WrappedRecord.new({:b => 5}, :arg => 7)
|
168
|
-
subject.a.should == 7
|
169
|
-
subject.b.should == 5
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
describe BinData::Wrapper, "derived classes" do
|
174
|
-
class ParentDerivedWrapper < BinData::Wrapper
|
175
|
-
uint32le
|
176
|
-
end
|
177
|
-
|
178
|
-
class ChildDerivedWrapper < ParentDerivedWrapper
|
179
|
-
end
|
180
|
-
|
181
|
-
it "wraps" do
|
182
|
-
a = ChildDerivedWrapper.new
|
183
|
-
a.num_bytes.should == 4
|
184
|
-
end
|
185
|
-
end
|