struct_packing 0.0.1 → 0.0.2
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.
- data/.document +5 -0
- data/C-like_structure_declaration.rdoc +117 -0
- data/Gemfile +13 -0
- data/History.txt +4 -4
- data/LICENSE.txt +20 -0
- data/Manifest.txt +13 -14
- data/PostInstall.txt +7 -7
- data/README.rdoc +63 -59
- data/Rakefile +47 -20
- data/VERSION +1 -0
- data/lib/struct_packing/base.rb +91 -0
- data/lib/struct_packing/packable.rb +49 -0
- data/lib/struct_packing/unpackable.rb +79 -0
- data/lib/struct_packing/util.rb +119 -0
- data/lib/struct_packing.rb +20 -12
- data/script/console +9 -9
- data/script/destroy +14 -14
- data/script/generate +14 -14
- data/struct_packing.gemspec +76 -0
- data/test/struct_packing/test_base.rb +48 -0
- data/test/struct_packing/test_packable.rb +89 -0
- data/test/struct_packing/test_unpackable.rb +87 -0
- data/test/struct_packing/test_util.rb +17 -0
- data/test/test_helper.rb +3 -3
- data/test/test_struct_packing.rb +1 -37
- metadata +52 -25
- data/.gemtest +0 -0
data/.document
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
= C-language like structure declaration
|
2
|
+
|
3
|
+
== Overview:
|
4
|
+
|
5
|
+
StructPacking uses "C like structure declaration" to define
|
6
|
+
object packing byte array format.
|
7
|
+
It is mostly compatible with struct definition in C language, and
|
8
|
+
some extended notation to support byte packing function in Ruby language.
|
9
|
+
|
10
|
+
This is mainly use to genarate Ruby pack template string from C language's struct
|
11
|
+
declaration.
|
12
|
+
|
13
|
+
== Syntax:
|
14
|
+
Syntax is same as C-language variable declaration.
|
15
|
+
[sign-modifier] <type> <variable-name> [ [array-length] ];
|
16
|
+
|
17
|
+
|
18
|
+
== Type:
|
19
|
+
* Traditional C language's types.
|
20
|
+
* char
|
21
|
+
* short
|
22
|
+
* int
|
23
|
+
* long
|
24
|
+
* long long
|
25
|
+
* float
|
26
|
+
* double
|
27
|
+
|
28
|
+
|
29
|
+
* C99 types.
|
30
|
+
* int8_t
|
31
|
+
* int16_t
|
32
|
+
* int32_t
|
33
|
+
* int64_t
|
34
|
+
* uint8_t
|
35
|
+
* uint16_t
|
36
|
+
* uint32_t
|
37
|
+
* uint64_t
|
38
|
+
|
39
|
+
* Extend keyword for Ruby pack string support.
|
40
|
+
* ascii
|
41
|
+
* utf8
|
42
|
+
* big
|
43
|
+
* big16
|
44
|
+
* big32
|
45
|
+
* little
|
46
|
+
* little16
|
47
|
+
* little32
|
48
|
+
* big float
|
49
|
+
* little float
|
50
|
+
* big double
|
51
|
+
* little double
|
52
|
+
|
53
|
+
== Variable-name:
|
54
|
+
Variable-name is identifier of this variable.
|
55
|
+
This is must unique in this struct.
|
56
|
+
|
57
|
+
In StructPacking package, variable-name is used to make relation object
|
58
|
+
with struct definition.
|
59
|
+
Packing function is get value from object's attr-getter which is same name as
|
60
|
+
variable-name, and pack the value toC-like_structure_declaration.rdoc
|
61
|
+
|
62
|
+
== Array-length
|
63
|
+
If "[]" is placed after variable-name, this variable define as array.
|
64
|
+
|
65
|
+
== Sign-modifier:
|
66
|
+
* signed
|
67
|
+
* unsigned
|
68
|
+
are sign-modifier.
|
69
|
+
|
70
|
+
== Bit-field
|
71
|
+
* TODO
|
72
|
+
|
73
|
+
|
74
|
+
== Ruby pack template mapping:
|
75
|
+
|
76
|
+
* Signed (or not assinged)
|
77
|
+
|
78
|
+
*char*:: "c"
|
79
|
+
*int8_t*:: "c"
|
80
|
+
*short*:: "s"
|
81
|
+
*int16_t*:: "s"
|
82
|
+
*int*:: "i"
|
83
|
+
*int32_t*:: "l"
|
84
|
+
*long*:: "l"
|
85
|
+
*long* *long*:: "q"
|
86
|
+
*int64_t*:: "q"
|
87
|
+
*float*:: "f"
|
88
|
+
*double*:: "d"
|
89
|
+
|
90
|
+
* Unsigned
|
91
|
+
|
92
|
+
*unsigned* *char*:: "C"
|
93
|
+
*uint8_t*:: "C"
|
94
|
+
*unsigned* *short*:: "S"
|
95
|
+
*uint16_t*:: "S"
|
96
|
+
*unsigned* *int*:: "I"
|
97
|
+
*unsigned* *long*:: "L"
|
98
|
+
*uint32_t*:: "L"
|
99
|
+
*unsigned* *long* *long*:: "Q"
|
100
|
+
*uint64_t*:: "Q"
|
101
|
+
|
102
|
+
* Extend types
|
103
|
+
|
104
|
+
*ascii*:: "a"
|
105
|
+
*utf8*:: "U"
|
106
|
+
*big*:: "N"
|
107
|
+
*big16*:: "n"
|
108
|
+
*big32*:: "N"
|
109
|
+
*little*:: "V"
|
110
|
+
*little16*:: "v"
|
111
|
+
*little32*:: "V"
|
112
|
+
*big* *float*:: "g"
|
113
|
+
*little* *float*:: "e"
|
114
|
+
*big* *double*:: "G"
|
115
|
+
*little* *double*:: "E"
|
116
|
+
|
117
|
+
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "shoulda", ">= 0"
|
10
|
+
gem "rdoc", "~> 3.12"
|
11
|
+
gem "bundler", "~> 1.2.0"
|
12
|
+
gem "jeweler", "~> 1.8.4"
|
13
|
+
end
|
data/History.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
=== 0.0.1 2013-02-11
|
2
|
-
|
3
|
-
* 1 major enhancement:
|
4
|
-
* Initial release
|
1
|
+
=== 0.0.1 2013-02-11
|
2
|
+
|
3
|
+
* 1 major enhancement:
|
4
|
+
* Initial release
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 TOKITA Hiroshi
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
-
History.txt
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
script/console
|
8
|
-
script/
|
9
|
-
script/destroy
|
10
|
-
script/
|
11
|
-
script/generate
|
12
|
-
|
13
|
-
test/
|
14
|
-
test/test_struct_packing.rb
|
1
|
+
History.txt
|
2
|
+
C-like_structure_declaration.rdoc
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
lib/struct_packing.rb
|
6
|
+
script/console
|
7
|
+
script/console.cmd
|
8
|
+
script/destroy
|
9
|
+
script/destroy.cmd
|
10
|
+
script/generate
|
11
|
+
script/generate.cmd
|
12
|
+
test/test_helper.rb
|
13
|
+
test/test_struct_packing.rb
|
data/PostInstall.txt
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
For more information on struct_packing, see http://struct_packing.rubyforge.org
|
3
|
-
|
4
|
-
NOTE: Change this information in PostInstall.txt
|
5
|
-
You can also delete it if you don't want it.
|
6
|
-
|
7
|
-
|
1
|
+
|
2
|
+
For more information on struct_packing, see http://struct_packing.rubyforge.org
|
3
|
+
|
4
|
+
NOTE: Change this information in PostInstall.txt
|
5
|
+
You can also delete it if you don't want it.
|
6
|
+
|
7
|
+
|
data/README.rdoc
CHANGED
@@ -1,59 +1,63 @@
|
|
1
|
-
= struct_packing
|
2
|
-
|
3
|
-
* http://github.com/TOKITAHiroshi/struct_packing
|
4
|
-
|
5
|
-
== DESCRIPTION:
|
6
|
-
|
7
|
-
* Read/Write ruby object to byte array with C-like struct declarations.
|
8
|
-
|
9
|
-
==
|
10
|
-
|
11
|
-
*
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
obj =
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
the
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
1
|
+
= struct_packing
|
2
|
+
|
3
|
+
* http://github.com/TOKITAHiroshi/struct_packing
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
* Read/Write ruby object to byte array with C-like struct declarations.
|
8
|
+
|
9
|
+
== INSTALL:
|
10
|
+
|
11
|
+
* sudo gem install struct_packing
|
12
|
+
|
13
|
+
|
14
|
+
== SYNOPSIS:
|
15
|
+
=== Packing object to byte array.
|
16
|
+
class PackableOStruct < OpenStruct
|
17
|
+
include StructPacking::Packable
|
18
|
+
self.byte_format = "int foo; char bar; byte[1] baz;"
|
19
|
+
end
|
20
|
+
|
21
|
+
obj = PackableOStruct.new
|
22
|
+
obj.foo = 1
|
23
|
+
obj.bar = 2
|
24
|
+
obj.baz = [8]
|
25
|
+
packed_bytes = obj.pack # => "\x01\x00\x00\x00\x02\b"
|
26
|
+
|
27
|
+
|
28
|
+
=== Read object attributes from byte array.
|
29
|
+
class UnpackableOStruct < OpenStruct
|
30
|
+
include StructPacking::Unpackable
|
31
|
+
self.byte_format = "char foo; byte[1] bar; int baz;"
|
32
|
+
end
|
33
|
+
|
34
|
+
obj = UnpackableOStruct.from_data [1, 2, 3, 0, 0, 0].pack("C*")
|
35
|
+
obj.foo # => 1
|
36
|
+
obj.bar # => [2]
|
37
|
+
obj.baz # => 3
|
38
|
+
|
39
|
+
|
40
|
+
== LICENSE:
|
41
|
+
|
42
|
+
(The MIT License)
|
43
|
+
|
44
|
+
Copyright (c) 2013 TOKITA Hiroshi
|
45
|
+
|
46
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
47
|
+
a copy of this software and associated documentation files (the
|
48
|
+
'Software'), to deal in the Software without restriction, including
|
49
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
50
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
51
|
+
permit persons to whom the Software is furnished to do so, subject to
|
52
|
+
the following conditions:
|
53
|
+
|
54
|
+
The above copyright notice and this permission notice shall be
|
55
|
+
included in all copies or substantial portions of the Software.
|
56
|
+
|
57
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
58
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
59
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
60
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
61
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
62
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
63
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,26 +1,53 @@
|
|
1
|
-
|
2
|
-
gem 'hoe', '>= 2.1.0'
|
3
|
-
require 'hoe'
|
4
|
-
require 'fileutils'
|
5
|
-
require './lib/struct_packing'
|
1
|
+
# encoding: utf-8
|
6
2
|
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "struct_packing"
|
18
|
+
gem.homepage = "http://github.com/TOKITAHiroshi/struct_packing"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{* Read/Write ruby object to byte array with C-like struct declarations.}
|
21
|
+
gem.description = %Q{* Read/Write ruby object to byte array with C-like struct declarations.}
|
22
|
+
gem.email = ["tokita.hiroshi@gmail.com"]
|
23
|
+
gem.authors = ["TOKITA Hiroshi"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
18
27
|
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
=begin
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |test|
|
37
|
+
test.libs << 'test'
|
38
|
+
test.pattern = 'test/**/test_*.rb'
|
39
|
+
test.verbose = true
|
40
|
+
test.rcov_opts << '--exclude "gems/*"'
|
19
41
|
end
|
42
|
+
=end
|
43
|
+
task :default => :test
|
20
44
|
|
21
|
-
require '
|
22
|
-
|
45
|
+
require 'rdoc/task'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
23
48
|
|
24
|
-
|
25
|
-
|
26
|
-
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "struct_packing #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.2
|
@@ -0,0 +1,91 @@
|
|
1
|
+
|
2
|
+
module StructPacking
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
# Common defines for Packable and Unpackable
|
7
|
+
module Base
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def self.included(base)
|
12
|
+
base.extend ClassMethods
|
13
|
+
end
|
14
|
+
|
15
|
+
public
|
16
|
+
|
17
|
+
# Get structure format string used in packing this object.
|
18
|
+
#
|
19
|
+
# This method work as just wrapper to same name class-method.
|
20
|
+
def internal_format
|
21
|
+
self.class.internal_format
|
22
|
+
end
|
23
|
+
|
24
|
+
# Get field name list of this class.
|
25
|
+
def field_names
|
26
|
+
self.class.field_names
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get field type list of this class.
|
30
|
+
def field_types
|
31
|
+
self.class.field_types
|
32
|
+
end
|
33
|
+
|
34
|
+
# Get Ruby's pack tenplate string for this class.
|
35
|
+
def pack_template
|
36
|
+
self.class.pack_template
|
37
|
+
end
|
38
|
+
|
39
|
+
# Common extending methods for Packable and Unpackable.
|
40
|
+
#
|
41
|
+
# Automatically extend on including StructPacking::Base module.
|
42
|
+
module ClassMethods
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# TODO temporary initializer for @@struct_internal_format
|
47
|
+
def check_vardef
|
48
|
+
if not self.class_variable_defined?(:@@struct_internal_format)
|
49
|
+
class_eval("@@struct_internal_format = ''")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
public
|
54
|
+
|
55
|
+
# Get internal structure format used to pack a object of this class.
|
56
|
+
def internal_format
|
57
|
+
check_vardef # TODO Find more good way!
|
58
|
+
|
59
|
+
Util.internal_format_from( self.class_variable_get(:@@struct_internal_format) )
|
60
|
+
end
|
61
|
+
|
62
|
+
# Set structure format for this class by string.
|
63
|
+
def byte_format=(text)
|
64
|
+
check_vardef # TODO Find more good way!
|
65
|
+
|
66
|
+
self.class_variable_set(:@@struct_internal_format, text)
|
67
|
+
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
# Get field name list of this class.
|
72
|
+
def field_names
|
73
|
+
internal_format.keys
|
74
|
+
end
|
75
|
+
|
76
|
+
# Get field type list of this class.
|
77
|
+
def field_types
|
78
|
+
internal_format.values
|
79
|
+
end
|
80
|
+
|
81
|
+
# Get Ruby's pack tenplate string for this class.
|
82
|
+
def pack_template
|
83
|
+
check_vardef # TODO Find more good way!
|
84
|
+
|
85
|
+
Util.pack_template_from( self.class_variable_get(:@@struct_internal_format) )
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module StructPacking
|
3
|
+
|
4
|
+
# Packable module provides object-packing function.
|
5
|
+
#
|
6
|
+
# A class include this module, and call struct defining method,
|
7
|
+
# pack method returns defined byte-array-form of that class's instance.
|
8
|
+
#
|
9
|
+
# == SYNOPSIS:
|
10
|
+
# class PackableOStruct < OpenStruct
|
11
|
+
# include StructPacking::Packable
|
12
|
+
# self.byte_format = "int foo; char bar; byte[1] baz;"
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# obj = PackableOStruct.new
|
16
|
+
# obj.foo = 1
|
17
|
+
# obj.bar = 2
|
18
|
+
# obj.baz = [8]
|
19
|
+
# packed_bytes = obj.pack # => "\x01\x00\x00\x00\x02\b"
|
20
|
+
module Packable
|
21
|
+
private
|
22
|
+
|
23
|
+
include Base
|
24
|
+
|
25
|
+
def self.included(base)
|
26
|
+
base.send("include", Base)
|
27
|
+
end
|
28
|
+
|
29
|
+
public
|
30
|
+
|
31
|
+
# Pack this object to byte array.
|
32
|
+
#
|
33
|
+
# If attribute defined in byte_format,
|
34
|
+
# but object has no attr_getter, treat as the attribute is zero.
|
35
|
+
def pack()
|
36
|
+
values = field_names.collect do |n|
|
37
|
+
begin
|
38
|
+
instance_eval { send(n) }
|
39
|
+
rescue NoMethodError
|
40
|
+
0
|
41
|
+
end
|
42
|
+
end
|
43
|
+
values.flatten!
|
44
|
+
|
45
|
+
values.pack( pack_template )
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module StructPacking
|
2
|
+
|
3
|
+
# Unpackable module provides value assign function from packed byte array.
|
4
|
+
#
|
5
|
+
# A class include this module, and call struct defininesg method,
|
6
|
+
# A instance's unpack method assign variables from packed object.
|
7
|
+
# This module also provide read_struct_data class method
|
8
|
+
# which construct object and assign values from packed object.
|
9
|
+
module Unpackable
|
10
|
+
include StructPacking::Base
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def self.included(base)
|
15
|
+
base.send("include", Base)
|
16
|
+
base.extend ClassMethods
|
17
|
+
end
|
18
|
+
|
19
|
+
# Extending methods for Unpackable class.
|
20
|
+
#
|
21
|
+
# Automatically extend on including StructPacking::Unpackable module.
|
22
|
+
module ClassMethods
|
23
|
+
|
24
|
+
# Construct object byte array.
|
25
|
+
#
|
26
|
+
# This method is simply do object construct and values assignment.
|
27
|
+
# If attribute defined in byte_format,
|
28
|
+
# but object has no attr_setter, do nothing.
|
29
|
+
#
|
30
|
+
# TODO: Including class must have default constructor.
|
31
|
+
#
|
32
|
+
# * _bytes_ packed structure. (see Packable.pack)
|
33
|
+
def unpack(bytes)
|
34
|
+
obj = self.new
|
35
|
+
set_values_from_byte_to_object(bytes, obj)
|
36
|
+
end
|
37
|
+
|
38
|
+
alias :from_data :unpack
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def set_values_from_byte_to_object(bytes, obj)
|
43
|
+
|
44
|
+
values = bytes.unpack( pack_template )
|
45
|
+
|
46
|
+
field_names.zip(gather_array_field(values) ).each do |name,value|
|
47
|
+
begin
|
48
|
+
obj.instance_eval {
|
49
|
+
send("#{name}=", value)
|
50
|
+
}
|
51
|
+
rescue NoMethodError
|
52
|
+
end
|
53
|
+
end
|
54
|
+
obj
|
55
|
+
end
|
56
|
+
|
57
|
+
def gather_array_field(values)
|
58
|
+
field_types.collect do |name|
|
59
|
+
if name =~ /.*\[\w*(\d+)\w*\]\w*/
|
60
|
+
[0..$1.to_i].to_a.collect { values.shift }
|
61
|
+
else
|
62
|
+
values.shift
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
public
|
69
|
+
|
70
|
+
# Set attributes from packed struct byte array.
|
71
|
+
#
|
72
|
+
# If attribute defined in byte_format,
|
73
|
+
# but object has no attr_setter, do nothing.
|
74
|
+
def read_struct_data(bytes)
|
75
|
+
self.class.set_values_from_byte_to_object(bytes, self)
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|