tem_ruby 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,298 @@
1
+ require 'openssl'
2
+ require 'test/unit'
3
+
4
+ require 'tem_ruby'
5
+
6
+ class AbiBuilderTest < Test::Unit::TestCase
7
+ class Wrapped
8
+ attr_accessor :p, :q, :n
9
+ attr_accessor :d # Derived value.
10
+ attr_accessor :c # Constructor value.
11
+
12
+ def initialize(ctor_value = 'ctor default')
13
+ self.c = ctor_value
14
+ end
15
+ end
16
+
17
+ class Multi
18
+ attr_accessor :p, :q, :n
19
+ attr_accessor :a, :b, :c
20
+ attr_accessor :str, :const
21
+ end
22
+
23
+ module Abi
24
+ Tem::Builders::Abi.define_abi self do |abi|
25
+ abi.fixed_length_number :byte, 1, :signed => true
26
+ abi.fixed_length_number :ubyte, 1, :signed => false
27
+
28
+ abi.fixed_length_number :word, 2, :signed => true, :big_endian => false
29
+ abi.fixed_length_number :netword, 2, :signed => true, :big_endian => true
30
+
31
+ abi.fixed_length_number :dword, 4, :signed => true, :big_endian => true
32
+ abi.fixed_length_number :udword, 4, :signed => false, :big_endian => false
33
+
34
+ abi.variable_length_number :vln, :word, :signed => false,
35
+ :big_endian => false
36
+ abi.variable_length_number :net_vln, :netword, :signed => false,
37
+ :big_endian => true
38
+ abi.packed_variable_length_numbers :packed, :word, [:p, :q, :n],
39
+ :signed => false,
40
+ :big_endian => false
41
+ abi.packed_variable_length_numbers :net_packed, :netword,
42
+ [:x, :y, :z, :a],
43
+ :signed => false,
44
+ :big_endian => true
45
+ abi.fixed_length_string :mac_id, 6
46
+ abi.object_wrapper :wrapped_raw, Wrapped, [:packed, nil]
47
+ abi.object_wrapper :wrapped, Wrapped, [:packed, nil],
48
+ :to => lambda { |o| w = Wrapped.new
49
+ w.p, w.q, w.n = o.p, o.q, o.n * 100
50
+ w },
51
+ :read => lambda { |o| w = Wrapped.new(o.c); w.d = o.p * o.q; w },
52
+ :new => lambda { |klass| klass.new('hook-new') }
53
+ abi.object_wrapper :multi, Multi,
54
+ [:packed, nil,:packed, { :p => :a, :q => :b, :n => :c},
55
+ :mac_id, :str, 'constant string', :const]
56
+
57
+ abi.conditional_wrapper :conditional, 2,
58
+ [{:tag => [0x59, 0xAF], :class => String, :type => :mac_id},
59
+ {:tag => [0x59, 0xAC], :class => Integer, :type => :net_vln,
60
+ :predicate => lambda { |n| n % 2 == 1 } },
61
+ {:tag => [0x59, 0xAD], :type => :dword,
62
+ :predicate => lambda { |n| n % 3 == 1 } }]
63
+ end
64
+ end
65
+
66
+ def setup
67
+ @garbage = [0xFD, 0xFC, 0xFD, 0xFC, 0xFD] * 5
68
+ end
69
+
70
+ def test_fixed_and_variable_length_number_encoding
71
+ [
72
+ [:byte, 0, [0]], [:byte, 127, [127]],
73
+ [:byte, -1, [255]], [:byte, -127, [129]], [:byte, -128, [128]],
74
+ [:byte, 128, nil], [:byte, -129, nil],
75
+
76
+ [:word, 0, [0, 0]], [:word, 127, [127, 0]], [:word, 128, [128, 0]],
77
+ [:word, 256, [0, 1]], [:word, 32767, [255, 127]],
78
+ [:word, -1, [255, 255]], [:word, -127, [129, 255]],
79
+ [:word, -128, [128, 255]], [:word, -256, [0, 255]],
80
+ [:word, -32767, [1, 128], [:word, -32768, [0, 128]]],
81
+ [:word, 32768, nil], [:byte, -32769, nil],
82
+
83
+ [:netword, 0, [0, 0]], [:netword, 127, [0, 127]],
84
+ [:netword, 128, [0, 128]],
85
+ [:netword, 256, [1, 0]], [:netword, 32767, [127, 255]],
86
+ [:netword, -1, [255, 255]], [:netword, -127, [255, 129]],
87
+ [:netword, -128, [255, 128]], [:netword, -256, [255, 0]],
88
+ [:netword, -32767, [128, 1], [:netword, -32768, [128, 0]]],
89
+ [:netword, 32768, nil], [:netword, -32769, nil],
90
+
91
+ [:dword, 0x12345678, [0x12, 0x34, 0x56, 0x78]],
92
+ [:udword, 0x12345678, [0x78, 0x56, 0x34, 0x12]],
93
+ [:udword, 0xFFFFFFFF, [255, 255, 255, 255]],
94
+ [:udword, 0xFFFFFFFE, [254, 255, 255, 255]],
95
+
96
+ [:vln, 0, [0x01, 0x00, 0x00]], [:vln, 1, [0x01, 0x00, 0x01]],
97
+ [:vln, 256, [0x02, 0x00, 0x00, 0x01]],
98
+ [:vln, 65537, [0x03, 0x00, 0x01, 0x00, 0x01]],
99
+ [:vln, 0x12345678, [0x04, 0x00, 0x78, 0x56, 0x34, 0x12]],
100
+ [:vln, 0xFFFFFFFF, [0x04, 0x00, 255, 255, 255, 255]],
101
+ [:vln, 0xFFFFFFFE, [0x04, 0x00, 254, 255, 255, 255]],
102
+
103
+ [:net_vln, 0, [0x00, 0x01, 0x00]], [:net_vln, 1, [0x00, 0x01, 0x01]],
104
+ [:net_vln, 256, [0x00, 0x02, 0x01, 0x00]],
105
+ [:net_vln, 65537, [0x00, 0x03, 0x01, 0x00, 0x01]],
106
+ [:net_vln, 0x12345678, [0x00, 0x04, 0x12, 0x34, 0x56, 0x78]],
107
+ [:net_vln, 0xFFFFFFFF, [0x00, 0x04, 255, 255, 255, 255]],
108
+ [:net_vln, 0xFFFFFFFE, [0x00, 0x04, 255, 255, 255, 254]],
109
+ ].each do |test_line|
110
+ type, number, array = *test_line
111
+ if array
112
+ assert_equal array, Abi.send(:"to_#{type}", number),
113
+ "#{type} failed on Ruby number -> array"
114
+ assert_equal array, Abi.send(:"to_#{type}",
115
+ OpenSSL::BN.new(number.to_s)),
116
+ "#{type} failed on OpenSSL number -> array"
117
+ assert_equal number, Abi.send(:"read_#{type}", @garbage + array,
118
+ @garbage.length)
119
+ if Abi.respond_to? :"#{type}_length"
120
+ assert_equal array.length, Abi.send(:"#{type}_length"),
121
+ "#{type} failed on length"
122
+ elsif Abi.respond_to? :"read_#{type}_length"
123
+ assert_equal array.length,
124
+ Abi.send(:"read_#{type}_length", @garbage + array,
125
+ @garbage.length),
126
+ "#{type} failed on read_#{type}_length"
127
+ else
128
+ flunk "#{type} does not provide _length or read_#{type}_length"
129
+ end
130
+ else
131
+ assert_raise RuntimeError do
132
+ assert_equal array, Abi.send(:"to_#{type}", number)
133
+ end
134
+ assert_raise RuntimeError do
135
+ assert_equal array, Abi.send(:"to_#{type}",
136
+ OpenSSL::BN.new(number.to_s))
137
+ end
138
+ end
139
+ end
140
+
141
+ assert_equal [255, 255, 255, 255], Abi.signed_to_udword(-1),
142
+ 'Failed on signed_to_udword'
143
+ end
144
+
145
+ def test_packed_number_encoding
146
+ packed = { :p => 0x123, :q => 0xABCDEF, :n => 5 }
147
+ gold_packed = [0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x23, 0x01, 0xEF, 0xCD,
148
+ 0xAB, 0x05]
149
+ assert_equal gold_packed, Abi.to_packed(packed), 'packed'
150
+ assert_equal packed, Abi.read_packed(@garbage + gold_packed,
151
+ @garbage.length), 'packed'
152
+ assert_equal gold_packed.length,
153
+ Abi.read_packed_length(@garbage + gold_packed,
154
+ @garbage.length),
155
+ 'read_packed_length'
156
+
157
+ net_packed = { :x => 0x271, :y => 0x314159, :z => 0, :a => 0x5AA5 }
158
+ gold_net_packed = [0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02,
159
+ 0x02, 0x71, 0x31, 0x41, 0x59, 0x00, 0x5A, 0xA5 ]
160
+ assert_equal gold_net_packed, Abi.to_net_packed(net_packed), 'net-packed'
161
+ assert_equal net_packed, Abi.read_net_packed(@garbage + gold_net_packed,
162
+ @garbage.length),
163
+ 'net_packed'
164
+ assert_equal gold_net_packed.length,
165
+ Abi.read_net_packed_length(@garbage + gold_net_packed,
166
+ @garbage.length),
167
+ 'read_net_packed_length'
168
+ components = Abi.net_packed_components
169
+ assert_equal [:x, :y, :z, :a], components,
170
+ 'incorrect result from _components'
171
+ assert_raise TypeError, '_components result is mutable' do
172
+ components[0] = :w
173
+ end
174
+ end
175
+
176
+ def test_fixed_length_string_encoding
177
+ [
178
+ [:mac_id, "abcdef", nil, [?a, ?b, ?c, ?d, ?e, ?f]],
179
+ [:mac_id, "abc", "abc\0\0\0", [?a, ?b, ?c, 0, 0, 0]],
180
+ [:mac_id, "", "\0\0\0\0\0\0", [0, 0, 0, 0, 0, 0]],
181
+ [:mac_id, "abcdefg", nil, nil],
182
+ [:mac_id, [?a, ?b, ?c, ?d, ?e, ?f], "abcdef", [?a, ?b, ?c, ?d, ?e, ?f]],
183
+ [:mac_id, [?a, ?b, ?c], "abc\0\0\0", [?a, ?b, ?c, 0, 0, 0]],
184
+ [:mac_id, [], "\0\0\0\0\0\0", [0, 0, 0, 0, 0, 0]],
185
+ [:mac_id, [?a, ?b, ?c, ?d, ?e, ?f, ?g], nil, nil],
186
+ ].each do |line|
187
+ type, source, string, array = *line
188
+ string ||= source
189
+ if array
190
+ assert_equal array, Abi.send(:"to_#{type}", source),
191
+ "#{type} failed on string -> array"
192
+ assert_equal string, Abi.send(:"read_#{type}", @garbage + array,
193
+ @garbage.length)
194
+ else
195
+ assert_raise RuntimeError do
196
+ assert_equal array, Abi.send(:"to_#{type}", source)
197
+ end
198
+ end
199
+ end
200
+ end
201
+
202
+ def test_object_wrapper_directs
203
+ packed = { :p => 2301, :q => 4141, :n => 60 }
204
+ gold_packed = Abi.to_packed packed
205
+ wrapped = Abi.read_wrapped_raw @garbage + gold_packed, @garbage.length
206
+ assert_equal Wrapped, wrapped.class,
207
+ 'Reading wrapped object instantiated wrong class'
208
+ assert_equal [packed[:p], packed[:q], packed[:n], nil, 'ctor default'],
209
+ [wrapped.p, wrapped.q, wrapped.n, wrapped.d, wrapped.c],
210
+ 'Reading wrapped object gave wrong attributes'
211
+ assert_equal gold_packed.length,
212
+ Abi.read_wrapped_raw_length(@garbage + gold_packed,
213
+ @garbage.length),
214
+ 'Reading wrapped object length'
215
+ assert_equal gold_packed, Abi.to_wrapped_raw(wrapped),
216
+ 'Wrapped object -> array'
217
+ end
218
+
219
+ def test_object_wrapper_schema
220
+ packed = { :p => 2301, :q => 4141, :n => 60 }
221
+ xpacked = { :p => 6996, :q => 1331, :n => 22 }
222
+ gold_multi = Abi.to_packed(packed) + Abi.to_packed(xpacked) +
223
+ Abi.to_mac_id("abc")
224
+ multi = Abi.read_multi @garbage + gold_multi, @garbage.length
225
+ assert_equal Multi, multi.class,
226
+ 'Reading wrapped object instantiated wrong class'
227
+ assert_equal [packed[:p], packed[:q], packed[:n],
228
+ xpacked[:p], xpacked[:q], xpacked[:n], "abc\0\0\0",
229
+ "constant string"],
230
+ [multi.p, multi.q, multi.n, multi.a, multi.b, multi.c,
231
+ multi.str, multi.const],
232
+ 'Reading wrapped object gave wrong attributes'
233
+ assert_equal gold_multi, Abi.to_multi(multi),
234
+ 'Wrapped object -> array'
235
+ assert_equal gold_multi.length,
236
+ Abi.read_multi_length(@garbage + gold_multi, @garbage.length),
237
+ 'Reading wrapped object length'
238
+ end
239
+
240
+ def test_object_wrapper_hooks
241
+ packed = { :p => 2301, :q => 4141, :n => 60 }
242
+ gold_packed = Abi.to_packed packed
243
+ wrapped = Abi.read_wrapped @garbage + gold_packed, @garbage.length
244
+ assert_equal Wrapped, wrapped.class,
245
+ 'Reading wrapped object instantiated wrong class'
246
+ assert_equal [nil, nil, nil, packed[:p] * packed[:q], 'hook-new'],
247
+ [wrapped.p, wrapped.q, wrapped.n, wrapped.d, wrapped.c],
248
+ 'Reading wrapped object with hook gave wrong attributes'
249
+
250
+ wrapped = Abi.read_wrapped_raw gold_packed, 0
251
+ packed[:n] *= 100
252
+ gold_packed = Abi.to_packed packed
253
+ assert_equal gold_packed, Abi.to_wrapped(wrapped),
254
+ 'Wrapped object -> array (with hook)'
255
+
256
+ assert_equal gold_packed.length,
257
+ Abi.read_packed_length(@garbage + gold_packed,
258
+ @garbage.length),
259
+ 'Reading wrapped object length'
260
+ end
261
+
262
+ def test_conditional_wrapper
263
+ [
264
+ [:conditional, "abcdef", [0x59, 0xAF, ?a, ?b, ?c, ?d, ?e, ?f]],
265
+ [:conditional, 3, [0x59, 0xAC, 0x00, 0x01, 0x03]],
266
+ [:conditional, 4, [0x59, 0xAD, 0x00, 0x00, 0x00, 0x04]],
267
+ [:conditional, OpenSSL::BN.new('7'), [0x59, 0xAD, 0x00, 0x00, 0x00, 0x07]],
268
+ [:conditional, 6, nil]
269
+ ].each do |test_line|
270
+ type, object, array = *test_line
271
+ if array
272
+ assert_equal array, Abi.send(:"to_#{type}", object),
273
+ "Object #{object.inspect} -> array"
274
+ assert_equal object, Abi.send(:"read_#{type}", @garbage + array,
275
+ @garbage.length)
276
+ assert_equal array.length,
277
+ Abi.send(:"read_#{type}_length", @garbage + array,
278
+ @garbage.length),
279
+ "#{type} failed on read_#{type}_length"
280
+ else
281
+ assert_raise RuntimeError do
282
+ assert_equal array, Abi.send(:"to_#{type}", object)
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ def test_length
289
+ [[:byte, 1], [:ubyte, 1],
290
+ [:word, 2], [:netword, 2],
291
+ [:dword, 4], [:udword, 4],
292
+ [:mac_id, 6]
293
+ ].each do |test_line|
294
+ assert_equal test_line.last, Abi.send(:"#{test_line.first}_length"),
295
+ "length failed for #{test_line.first}"
296
+ end
297
+ end
298
+ end
data/test/test_driver.rb CHANGED
@@ -79,8 +79,8 @@ class DriverTest < TemTestCase
79
79
 
80
80
  def test_crypto_abi
81
81
  ekey = OpenSSL::PKey::RSA.generate(2048, 65537)
82
- pubk = @tem.new_key_from_ssl ekey, true
83
- privk = @tem.new_key_from_ssl ekey, false
82
+ pubk = Tem::Key.new_from_ssl_key ekey.public_key
83
+ privk = Tem::Key.new_from_ssl_key ekey
84
84
 
85
85
  # array and string encryption/decryption
86
86
  garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
@@ -95,9 +95,9 @@ class DriverTest < TemTestCase
95
95
 
96
96
  # test key serialization/deserialization through encryption/decryption
97
97
  pubk_ys = pubk.to_yaml_str
98
- pubk2 = Tem::CryptoAbi::AsymmetricKey.new_from_yaml_str(pubk_ys)
98
+ pubk2 = Tem::Keys::Asymmetric.new_from_yaml_str(pubk_ys)
99
99
  privk_ys = privk.to_yaml_str
100
- privk2 = Tem::CryptoAbi::AsymmetricKey.new_from_yaml_str(privk_ys)
100
+ privk2 = Tem::Keys::Asymmetric.new_from_yaml_str(privk_ys)
101
101
  encrypted_garbage = pubk.encrypt garbage
102
102
  decrypted_garbage = privk2.decrypt encrypted_garbage
103
103
  assert_equal garbage, decrypted_garbage, 'pub-encryption+priv-decryption messed up the data'
data/test/test_tem.rb CHANGED
@@ -236,7 +236,8 @@ class TemTest < TemTestCase
236
236
  }
237
237
 
238
238
  result = @tem.execute sec
239
- assert_equal [garbage1, garbage2, garbage2].map { |d| @tem.hash_for_tem d}.flatten,
239
+ assert_equal [garbage1, garbage2, garbage2].map { |d| @tem.tem_hash d}.
240
+ flatten,
240
241
  result, 'cryptographic hashing isn\'t working well'
241
242
  end
242
243
 
@@ -418,8 +419,8 @@ class TemTest < TemTestCase
418
419
 
419
420
  # crypto run with an externally generated key
420
421
  ekey = OpenSSL::PKey::RSA.generate(2048, 65537)
421
- pubk = @tem.new_key_from_ssl ekey, true
422
- privk = @tem.new_key_from_ssl ekey, false
422
+ pubk = Tem::Key.new_from_ssl_key ekey.public_key
423
+ privk = Tem::Key.new_from_ssl_key ekey
423
424
  pubk_id = @tem.tk_post_key pubk, keyd[:authz]
424
425
  privk_id = @tem.tk_post_key privk, keyd[:authz]
425
426
  i_test_crypto_pki_ops(pubk_id, privk_id, pubk, privk, keyd[:authz])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tem_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Costan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-08 00:00:00 -04:00
12
+ date: 2009-05-26 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,16 +22,6 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: 0.3.0
24
24
  version:
25
- - !ruby/object:Gem::Dependency
26
- name: echoe
27
- type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
35
25
  description: TEM (Trusted Execution Module) driver, written in and for ruby.
36
26
  email: victor@costan.us
37
27
  executables:
@@ -50,21 +40,25 @@ extra_rdoc_files:
50
40
  - bin/tem_stat
51
41
  - CHANGELOG
52
42
  - lib/tem/_cert.rb
53
- - lib/tem/abi.rb
43
+ - lib/tem/apdus/buffers.rb
44
+ - lib/tem/apdus/keys.rb
45
+ - lib/tem/apdus/lifecycle.rb
46
+ - lib/tem/apdus/tag.rb
54
47
  - lib/tem/auto_conf.rb
55
- - lib/tem/buffers.rb
48
+ - lib/tem/builders/abi.rb
49
+ - lib/tem/builders/crypto.rb
56
50
  - lib/tem/ca.rb
57
- - lib/tem/crypto_abi.rb
51
+ - lib/tem/definitions/abi.rb
58
52
  - lib/tem/ecert.rb
59
53
  - lib/tem/hive.rb
60
- - lib/tem/keys.rb
61
- - lib/tem/lifecycle.rb
54
+ - lib/tem/keys/asymmetric.rb
55
+ - lib/tem/keys/key.rb
56
+ - lib/tem/keys/symmetric.rb
62
57
  - lib/tem/sec_assembler.rb
63
58
  - lib/tem/sec_exec_error.rb
64
59
  - lib/tem/sec_opcodes.rb
65
60
  - lib/tem/seclosures.rb
66
61
  - lib/tem/secpack.rb
67
- - lib/tem/tag.rb
68
62
  - lib/tem/tem.rb
69
63
  - lib/tem/toolkit.rb
70
64
  - lib/tem/transport/auto_configurator.rb
@@ -89,21 +83,25 @@ files:
89
83
  - dev_ca/ca_key.pem
90
84
  - dev_ca/config.yml
91
85
  - lib/tem/_cert.rb
92
- - lib/tem/abi.rb
86
+ - lib/tem/apdus/buffers.rb
87
+ - lib/tem/apdus/keys.rb
88
+ - lib/tem/apdus/lifecycle.rb
89
+ - lib/tem/apdus/tag.rb
93
90
  - lib/tem/auto_conf.rb
94
- - lib/tem/buffers.rb
91
+ - lib/tem/builders/abi.rb
92
+ - lib/tem/builders/crypto.rb
95
93
  - lib/tem/ca.rb
96
- - lib/tem/crypto_abi.rb
94
+ - lib/tem/definitions/abi.rb
97
95
  - lib/tem/ecert.rb
98
96
  - lib/tem/hive.rb
99
- - lib/tem/keys.rb
100
- - lib/tem/lifecycle.rb
97
+ - lib/tem/keys/asymmetric.rb
98
+ - lib/tem/keys/key.rb
99
+ - lib/tem/keys/symmetric.rb
101
100
  - lib/tem/sec_assembler.rb
102
101
  - lib/tem/sec_exec_error.rb
103
102
  - lib/tem/sec_opcodes.rb
104
103
  - lib/tem/seclosures.rb
105
104
  - lib/tem/secpack.rb
106
- - lib/tem/tag.rb
107
105
  - lib/tem/tem.rb
108
106
  - lib/tem/toolkit.rb
109
107
  - lib/tem/transport/auto_configurator.rb
@@ -119,6 +117,7 @@ files:
119
117
  - Rakefile
120
118
  - README
121
119
  - test/_test_cert.rb
120
+ - test/builders/test_abi_builder.rb
122
121
  - test/tem_test_case.rb
123
122
  - test/test_driver.rb
124
123
  - test/test_exceptions.rb
@@ -137,6 +136,8 @@ files:
137
136
  - tem_ruby.gemspec
138
137
  has_rdoc: true
139
138
  homepage: http://tem.rubyforge.org
139
+ licenses: []
140
+
140
141
  post_install_message:
141
142
  rdoc_options:
142
143
  - --line-numbers
@@ -162,11 +163,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
163
  requirements: []
163
164
 
164
165
  rubyforge_project: tem
165
- rubygems_version: 1.3.1
166
+ rubygems_version: 1.3.3
166
167
  signing_key:
167
- specification_version: 2
168
+ specification_version: 3
168
169
  summary: TEM (Trusted Execution Module) driver, written in and for ruby.
169
170
  test_files:
171
+ - test/builders/test_abi_builder.rb
170
172
  - test/test_driver.rb
171
173
  - test/test_exceptions.rb
172
174
  - test/test_tem.rb
data/lib/tem/abi.rb DELETED
@@ -1,55 +0,0 @@
1
- module Tem::Abi
2
- def self.included(klass)
3
- klass.extend MixedMethods
4
-
5
- klass.tem_value_type :byte, 1, :signed => true, :endian => :big
6
- klass.tem_value_type :ubyte, 1, :signed => false, :endian => :big
7
- klass.tem_value_type :short, 2, :signed => true, :endian => :big
8
- klass.tem_value_type :ushort, 2, :signed => false, :endian => :big
9
- klass.tem_value_type :ps_addr, 20, :signed => false, :endian => :big
10
- klass.tem_value_type :ps_value, 20, :signed => false, :endian => :big
11
- end
12
-
13
- module MixedMethods
14
- def tem_value_type(name, bytes, options = {:signed => true, :endian => :big})
15
- range = 1 << (8 * bytes)
16
- if options[:signed]
17
- min, max = -(range >> 1), (range >> 1) - 1
18
- else
19
- min, max = 0, range - 1
20
- end
21
-
22
- badass_defines = Proc.new do
23
- define_method("read_tem_#{name}".to_sym) do |array, offset|
24
- array = array.reverse unless options[:endian] == :big
25
- n = (0...bytes).inject(0) { |v, i| (v << 8) | array[offset + i] }
26
- rv = (options[:signed] and n > max) ? n - range : n
27
- # pp [:read, name, array, offset, rv]
28
- return rv
29
- end
30
- define_method("to_tem_#{name}".to_sym) do |n|
31
- n = n.to_i
32
- raise "Value #{n} not between #{min} and #{max}" unless (n <= max) and (n >= min)
33
- n += range if(options[:signed] and n < 0)
34
- array = []
35
- bytes.times { array.push(n & 0xFF); n >>= 8 }
36
- array.reverse! if options[:endian] == :big
37
- # pp [:to, name, n, array]
38
- return array
39
- end
40
- define_method("to_tem_#{name}_reladdr".to_sym) do |n|
41
- n = n.to_i
42
- n += range if (n < 0 and (not options[:signed]))
43
- array = []
44
- bytes.times { array.push(n & 0xFF); n >>= 8 }
45
- array.reverse! if options[:endian] == :big
46
- return array
47
- end
48
- define_method("tem_#{name}_length".to_sym) { bytes }
49
- end
50
-
51
- self.class_eval(&badass_defines)
52
- (class << self; self; end).module_eval(&badass_defines)
53
- end
54
- end
55
- end