marshal-structure 1.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -0,0 +1,9 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+ require 'autotest/isolate'
5
+
6
+ Autotest.add_hook :initialize do |at|
7
+ at.testlib = 'minitest/autorun'
8
+ end
9
+
File without changes
@@ -0,0 +1,5 @@
1
+ === 1.0 / 2011-08-05
2
+
3
+ * Major enhancements
4
+ * Birthday!
5
+
@@ -0,0 +1,7 @@
1
+ .autotest
2
+ History.txt
3
+ Manifest.txt
4
+ README.rdoc
5
+ Rakefile
6
+ lib/marshal/structure.rb
7
+ test/test_marshal_structure.rb
@@ -0,0 +1,73 @@
1
+ = marshal-structure
2
+
3
+ * https://github.com/drbrain/marshal-structure
4
+
5
+ == DESCRIPTION:
6
+
7
+ Dumps a tree based on the Marshal format. Supports the Marshal 4.8 format.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Works like Marshal.load
12
+
13
+ == SYNOPSIS:
14
+
15
+ From the command line:
16
+
17
+ ruby -rpp -rmarshal-structure \
18
+ -e 'pp Marshal::Structure.load Marshal.dump "hello"'
19
+
20
+ Fancier usage:
21
+
22
+ require 'pp'
23
+ require 'marshal-structure'
24
+
25
+ ms = Marshal::Structure.new Marshal.dump %w[hello world]
26
+
27
+ # print the Marshal stream structure
28
+ pp ms.construct
29
+
30
+ # print ruby objects in Marshal stream
31
+ pp ms.objects
32
+
33
+ == REQUIREMENTS:
34
+
35
+ * Ruby 1.8.7+
36
+
37
+ == INSTALL:
38
+
39
+ gem install marshal-structure
40
+
41
+ == DEVELOPERS:
42
+
43
+ After checking out the source, run:
44
+
45
+ $ rake newb
46
+
47
+ This task will install any missing dependencies, run the tests/specs,
48
+ and generate the RDoc.
49
+
50
+ == LICENSE:
51
+
52
+ (The MIT License)
53
+
54
+ Copyright (c) 2011 Eric Hodel
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining
57
+ a copy of this software and associated documentation files (the
58
+ 'Software'), to deal in the Software without restriction, including
59
+ without limitation the rights to use, copy, modify, merge, publish,
60
+ distribute, sublicense, and/or sell copies of the Software, and to
61
+ permit persons to whom the Software is furnished to do so, subject to
62
+ the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be
65
+ included in all copies or substantial portions of the Software.
66
+
67
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
68
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
70
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
71
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
72
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
73
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,27 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.plugin :git
7
+ Hoe.plugin :isolate
8
+ Hoe.plugin :minitest
9
+
10
+ Hoe.spec 'marshal-structure' do
11
+ developer 'Eric Hodel', 'drbrain@segment7.net'
12
+
13
+ rdoc_locations << 'docs.seattlerb.org:/data/www/docs.seattlerb.org/marshal-structure/'
14
+
15
+ self.readme_file = 'README.rdoc'
16
+ self.extra_rdoc_files << 'README.rdoc' # HACK fix in Hoe
17
+
18
+ if respond_to? :isolate_dir= then # HACK Hoe issue #7
19
+ self.isolate_dir = 'tmp/isolate'
20
+ else
21
+ warn 'please: gem install isolate'
22
+ end
23
+
24
+ extra_dev_deps << ['ben_string', '~> 1']
25
+ end
26
+
27
+ # vim: syntax=ruby
@@ -0,0 +1,619 @@
1
+ ##
2
+ # Marshal::Structure dumps a nested Array describing the structure of a
3
+ # Marshal stream.
4
+ #
5
+ # Marshal format 4.8 is supported.
6
+
7
+ class Marshal::Structure
8
+
9
+ ##
10
+ # Version of Marshal::Structure you are using
11
+
12
+ VERSION = '1.0'
13
+
14
+ ##
15
+ # Supported major Marshal version
16
+
17
+ MAJOR_VERSION = 4
18
+
19
+ ##
20
+ # Supported minor Marshal version
21
+
22
+ MINOR_VERSION = 8
23
+
24
+ ##
25
+ # nil type prefix
26
+
27
+ TYPE_NIL = '0'
28
+
29
+ ##
30
+ # true type prefix
31
+
32
+ TYPE_TRUE = 'T'
33
+
34
+ ##
35
+ # false type prefix
36
+
37
+ TYPE_FALSE = 'F'
38
+
39
+ ##
40
+ # Fixnum type prefix
41
+
42
+ TYPE_FIXNUM = 'i'
43
+
44
+ ##
45
+ # An object that has been extended with a module
46
+
47
+ TYPE_EXTENDED = 'e'
48
+
49
+ ##
50
+ # A subclass of a built-in type
51
+
52
+ TYPE_UCLASS = 'C'
53
+
54
+ ##
55
+ # A ruby Object
56
+
57
+ TYPE_OBJECT = 'o'
58
+
59
+ ##
60
+ # A wrapped C pointer
61
+
62
+ TYPE_DATA = 'd'
63
+
64
+ ##
65
+ # An object saved with _dump
66
+
67
+ TYPE_USERDEF = 'u'
68
+
69
+ ##
70
+ # An object saved with marshal_dump
71
+
72
+ TYPE_USRMARSHAL = 'U'
73
+
74
+ ##
75
+ # A Float
76
+
77
+ TYPE_FLOAT = 'f'
78
+
79
+ ##
80
+ # A Bignum
81
+
82
+ TYPE_BIGNUM = 'l'
83
+
84
+ ##
85
+ # A String
86
+
87
+ TYPE_STRING = '"'
88
+
89
+ ##
90
+ # A Regexp
91
+
92
+ TYPE_REGEXP = '/'
93
+
94
+ ##
95
+ # An Array
96
+
97
+ TYPE_ARRAY = '['
98
+
99
+ ##
100
+ # A Hash
101
+
102
+ TYPE_HASH = '{'
103
+
104
+ ##
105
+ # A Hash with a default value (not proc)
106
+
107
+ TYPE_HASH_DEF = '}'
108
+
109
+ ##
110
+ # A Struct
111
+
112
+ TYPE_STRUCT = 'S'
113
+
114
+ ##
115
+ # An old-style Module (reference, not content)
116
+ #
117
+ # I'm not sure what makes this old. The byte stream is identical to
118
+ # TYPE_MODULE
119
+
120
+ TYPE_MODULE_OLD = 'M'
121
+
122
+ ##
123
+ # A class (reference, not content)
124
+
125
+ TYPE_CLASS = 'c'
126
+
127
+ ##
128
+ # A module (reference, not content)
129
+
130
+ TYPE_MODULE = 'm'
131
+
132
+ ##
133
+ # A Symbol
134
+
135
+ TYPE_SYMBOL = ':'
136
+
137
+ ##
138
+ # A reference to a previously Symbol
139
+
140
+ TYPE_SYMLINK = ';'
141
+
142
+ ##
143
+ # Instance variables for a following object
144
+
145
+ TYPE_IVAR = 'I'
146
+
147
+ ##
148
+ # A reference to a previously-stored Object
149
+
150
+ TYPE_LINK = '@'
151
+
152
+ ##
153
+ # Objects found in the Marshal stream. Since objects aren't constructed the
154
+ # actual object won't be present in this list.
155
+
156
+ attr_reader :objects
157
+
158
+ ##
159
+ # Symbols found in the Marshal stream
160
+
161
+ attr_reader :symbols
162
+
163
+ ##
164
+ # Returns the structure of the Marshaled object +obj+ as nested Arrays.
165
+ #
166
+ # For +true+, +false+ and +nil+ the symbol +:true+, +:false+, +:nil+ is
167
+ # returned, respectively.
168
+ #
169
+ # For Fixnum the value is returned.
170
+ #
171
+ # For other objects the first item is the reference for future occurrences
172
+ # of the object and the remaining items describe the object.
173
+ #
174
+ # Symbols have a separate reference table from all other objects.
175
+
176
+ def self.load obj
177
+ if obj.respond_to? :to_str then
178
+ data = obj.to_s
179
+ elsif obj.respond_to? :read then
180
+ data = obj.read
181
+ if data.empty? then
182
+ raise EOFError, "end of file reached"
183
+ end
184
+ elsif obj.respond_to? :getc then # FIXME - don't read all of it upfront
185
+ data = ''
186
+ data << c while (c = obj.getc.chr)
187
+ else
188
+ raise TypeError, "instance of IO needed"
189
+ end
190
+
191
+ major = data[0].ord
192
+ minor = data[1].ord
193
+
194
+ if major != MAJOR_VERSION or minor > MINOR_VERSION then
195
+ raise TypeError, "incompatible marshal file format (can't be read)\n\tformat version #{MAJOR_VERSION}.#{MINOR_VERSION} required; #{major}.#{minor} given"
196
+ end
197
+
198
+ new(data).construct
199
+ end
200
+
201
+ ##
202
+ # Prepares processing of +stream+
203
+
204
+ def initialize stream
205
+ @objects = []
206
+ @symbols = []
207
+
208
+ @stream = stream
209
+ @byte_array = stream.bytes.to_a
210
+ @consumed = 2
211
+ end
212
+
213
+ ##
214
+ # Adds +obj+ to the objects list
215
+
216
+ def add_object obj
217
+ return if
218
+ [NilClass, TrueClass, FalseClass, Symbol, Fixnum].any? { |c| c === obj }
219
+
220
+ index = @objects.size
221
+ @objects << obj
222
+ index
223
+ end
224
+
225
+ ##
226
+ # Adds +symbol+ to the symbols list
227
+
228
+ def add_symlink symbol
229
+ index = @symbols.size
230
+ @symbols << symbol
231
+ index
232
+ end
233
+
234
+ ##
235
+ # Creates the structure for the remaining stream.
236
+
237
+ def construct
238
+ type = consume_character
239
+
240
+ case type
241
+ when TYPE_NIL then
242
+ :nil
243
+ when TYPE_TRUE then
244
+ :true
245
+ when TYPE_FALSE then
246
+ :false
247
+
248
+ when TYPE_ARRAY then
249
+ [:array, *construct_array]
250
+ when TYPE_BIGNUM then
251
+ [:bignum, *construct_bignum]
252
+ when TYPE_CLASS then
253
+ ref = store_unique_object Object.allocate
254
+
255
+ [:class, ref, get_byte_sequence]
256
+ when TYPE_DATA then
257
+ [:data, *construct_data]
258
+ when TYPE_EXTENDED then
259
+ [:extended, get_symbol, construct]
260
+ when TYPE_FIXNUM then
261
+ [:fixnum, construct_integer]
262
+ when TYPE_FLOAT then
263
+ [:float, *construct_float]
264
+ when TYPE_HASH then
265
+ [:hash, *construct_hash]
266
+ when TYPE_HASH_DEF then
267
+ [:hash_default, *construct_hash_def]
268
+ when TYPE_IVAR then
269
+ [:instance_variables, construct, *construct_instance_variables]
270
+ when TYPE_LINK then
271
+ [:link, construct_integer]
272
+ when TYPE_MODULE, TYPE_MODULE_OLD then
273
+ ref = store_unique_object Object.allocate
274
+
275
+ [:module, ref, get_byte_sequence]
276
+ when TYPE_OBJECT then
277
+ [:object, *construct_object]
278
+ when TYPE_REGEXP then
279
+ [:regexp, *construct_regexp]
280
+ when TYPE_STRING then
281
+ [:string, *construct_string]
282
+ when TYPE_STRUCT then
283
+ [:struct, *construct_struct]
284
+ when TYPE_SYMBOL then
285
+ [:symbol, *construct_symbol]
286
+ when TYPE_SYMLINK then
287
+ [:symbol_link, construct_integer]
288
+ when TYPE_USERDEF then
289
+ [:user_defined, *construct_user_defined]
290
+ when TYPE_USRMARSHAL then
291
+ [:user_marshal, *construct_user_marshal]
292
+ when TYPE_UCLASS then
293
+ name = get_symbol
294
+
295
+ [:user_class, name, construct]
296
+ else
297
+ raise ArgumentError, "load error, unknown type #{type}"
298
+ end
299
+ end
300
+
301
+ ##
302
+ # Creates the body of an +:array+ object
303
+
304
+ def construct_array
305
+ ref = store_unique_object Object.allocate
306
+
307
+ obj = [ref]
308
+
309
+ items = construct_integer
310
+
311
+ obj << items
312
+
313
+ items.times do
314
+ obj << construct
315
+ end
316
+
317
+ obj
318
+ end
319
+
320
+ ##
321
+ # Creates the body of a +:bignum+ object
322
+
323
+ def construct_bignum
324
+ sign = consume_byte == ?- ? -1 : 1
325
+ size = construct_integer * 2
326
+
327
+ result = 0
328
+
329
+ data = consume_bytes size
330
+
331
+ data.each_with_index do |data, exp|
332
+ result += (data * 2**(exp*8))
333
+ end
334
+
335
+ ref = store_unique_object Object.allocate
336
+
337
+ [ref, sign, size, result]
338
+ end
339
+
340
+ ##
341
+ # Creates the body of a wrapped C pointer object
342
+
343
+ def construct_data
344
+ ref = store_unique_object Object.allocate
345
+
346
+ [ref, get_symbol, construct]
347
+ end
348
+
349
+ ##
350
+ # Creates the body of a +:float+ object
351
+
352
+ def construct_float
353
+ float = get_byte_sequence
354
+
355
+ ref = store_unique_object Object.allocate
356
+
357
+ [ref, float]
358
+ end
359
+
360
+ ##
361
+ # Creates the body of a +:hash+ object
362
+
363
+ def construct_hash
364
+ ref = store_unique_object Object.allocate
365
+
366
+ obj = [ref]
367
+
368
+ pairs = construct_integer
369
+ obj << pairs
370
+
371
+ pairs.times do
372
+ obj << construct
373
+ obj << construct
374
+ end
375
+
376
+ obj
377
+ end
378
+
379
+ ##
380
+ # Creates the body of a +:hash_def+ object
381
+
382
+ def construct_hash_def
383
+ ref, hash = construct_hash
384
+
385
+ [ref, hash, construct]
386
+ end
387
+
388
+ ##
389
+ # Instance variables contain an object followed by a count of instance
390
+ # variables and their contents
391
+
392
+ def construct_instance_variables
393
+ instance_variables = []
394
+
395
+ pairs = construct_integer
396
+ instance_variables << pairs
397
+
398
+ pairs.times do
399
+ instance_variables << get_symbol
400
+ instance_variables << construct
401
+ end
402
+
403
+ instance_variables
404
+ end
405
+
406
+ ##
407
+ # Decodes a stored Fixnum
408
+
409
+ def construct_integer
410
+ c = consume_byte
411
+
412
+ # The format appears to be a simple integer compression format
413
+ #
414
+ # The 0-123 cases are easy, and use one byte
415
+ # We've read c as unsigned char in a way, but we need to honor
416
+ # the sign bit. We do that by simply comparing with the +128 values
417
+ return 0 if c == 0
418
+ return c - 5 if 4 < c and c < 128
419
+
420
+ # negative, but checked known it's instead in 2's compliment
421
+ return c - 251 if 252 > c and c > 127
422
+
423
+ # otherwise c (now in the 1 to 4 range) indicates how many
424
+ # bytes to read to construct the value.
425
+ #
426
+ # Because we're operating on a small number of possible values,
427
+ # it's cleaner to just unroll the calculate of each
428
+
429
+ case c
430
+ when 1
431
+ consume_byte
432
+ when 2
433
+ consume_byte | (consume_byte << 8)
434
+ when 3
435
+ consume_byte | (consume_byte << 8) | (consume_byte << 16)
436
+ when 4
437
+ consume_byte | (consume_byte << 8) | (consume_byte << 16) |
438
+ (consume_byte << 24)
439
+
440
+ when 255 # -1
441
+ consume_byte - 256
442
+ when 254 # -2
443
+ (consume_byte | (consume_byte << 8)) - 65536
444
+ when 253 # -3
445
+ (consume_byte |
446
+ (consume_byte << 8) |
447
+ (consume_byte << 16)) - 16777216 # 2 ** 24
448
+ when 252 # -4
449
+ (consume_byte |
450
+ (consume_byte << 8) |
451
+ (consume_byte << 16) |
452
+ (consume_byte << 24)) - 4294967296
453
+ else
454
+ raise "Invalid integer size: #{c}"
455
+ end
456
+ end
457
+
458
+ ##
459
+ # Creates an Object
460
+
461
+ def construct_object
462
+ ref = store_unique_object Object.allocate
463
+
464
+ [ref, get_symbol, construct_instance_variables]
465
+ end
466
+
467
+ ##
468
+ # Creates a Regexp
469
+
470
+ def construct_regexp
471
+ ref =store_unique_object Object.allocate
472
+
473
+ [ref, get_byte_sequence, consume_byte]
474
+ end
475
+
476
+ ##
477
+ # Creates a String
478
+
479
+ def construct_string
480
+ ref = store_unique_object Object.allocate
481
+
482
+ [ref, get_byte_sequence]
483
+ end
484
+
485
+ ##
486
+ # Creates a Struct
487
+
488
+ def construct_struct
489
+ symbols = []
490
+ values = []
491
+
492
+ obj_ref = store_unique_object Object.allocate
493
+
494
+ obj = [obj_ref, get_symbol]
495
+
496
+ members = construct_integer
497
+ obj << members
498
+
499
+ members.times do
500
+ obj << get_symbol
501
+ obj << construct
502
+ end
503
+
504
+ obj
505
+ end
506
+
507
+ ##
508
+ # Creates a Symbol
509
+
510
+ def construct_symbol
511
+ sym = get_byte_sequence
512
+
513
+ ref = store_unique_object sym.to_sym
514
+
515
+ [ref, sym]
516
+ end
517
+
518
+ ##
519
+ # Creates an object saved by _dump
520
+
521
+ def construct_user_defined
522
+ name = get_symbol
523
+
524
+ data = get_byte_sequence
525
+
526
+ ref = store_unique_object Object.allocate
527
+
528
+ [ref, name, data]
529
+ end
530
+
531
+ ##
532
+ # Creates an object saved by marshal_dump
533
+
534
+ def construct_user_marshal
535
+ name = get_symbol
536
+
537
+ obj = Object.allocate
538
+
539
+ obj_ref = store_unique_object obj
540
+
541
+ [obj_ref, name, construct]
542
+ end
543
+
544
+ ##
545
+ # Consumes +bytes+ from the marshal stream
546
+
547
+ def consume bytes
548
+ raise ArgumentError, "marshal data too short" if @consumed > @stream.size
549
+ data = @stream[@consumed, bytes]
550
+ @consumed += bytes
551
+ data
552
+ end
553
+
554
+ ##
555
+ # Consumes +count+ bytes from the marshal stream as an Array of bytes
556
+
557
+ def consume_bytes count
558
+ consume(count).bytes.to_a
559
+ end
560
+
561
+ ##
562
+ # Consumes one byte from the marshal stream
563
+
564
+ def consume_byte
565
+ raise ArgumentError, "marshal data too short" if
566
+ @consumed > @byte_array.size
567
+
568
+ data = @byte_array[@consumed]
569
+ @consumed += 1
570
+
571
+ data
572
+ end
573
+
574
+ ##
575
+ # Consumes one byte from the marshal stream and returns a character
576
+
577
+ def consume_character
578
+ consume_byte.chr
579
+ end
580
+
581
+ ##
582
+ # Consumes a sequence of bytes from the marshal stream based on the next
583
+ # integer
584
+
585
+ def get_byte_sequence
586
+ size = construct_integer
587
+ consume size
588
+ end
589
+
590
+ ##
591
+ # Constructs a Symbol from a TYPE_SYMBOL or TYPE_SYMLINK
592
+
593
+ def get_symbol
594
+ type = consume_character
595
+
596
+ case type
597
+ when TYPE_SYMBOL then
598
+ [:symbol, *construct_symbol]
599
+ when TYPE_SYMLINK then
600
+ num = construct_integer
601
+ [:symbol_link, num]
602
+ else
603
+ raise ArgumentError, "expected TYPE_SYMBOL or TYPE_SYMLINK, got #{type.inspect}"
604
+ end
605
+ end
606
+
607
+ ##
608
+ # Stores a reference to +obj+
609
+
610
+ def store_unique_object obj
611
+ if Symbol === obj then
612
+ add_symlink obj
613
+ else
614
+ add_object obj
615
+ end
616
+ end
617
+
618
+ end
619
+
@@ -0,0 +1,171 @@
1
+ require 'minitest/autorun'
2
+ require 'marshal/structure'
3
+ require 'ben_string'
4
+ require 'openssl'
5
+ require 'pp'
6
+
7
+ class OpenSSL::X509::Name
8
+ alias _dump_data to_a
9
+
10
+ def _load_data ary
11
+ ary.each do |entry|
12
+ add_entry(*entry)
13
+ end
14
+ end
15
+ end
16
+
17
+ class B; end
18
+
19
+ module C; end
20
+
21
+ module E; end
22
+
23
+ class M
24
+ def marshal_dump
25
+ 'marshal_dump'
26
+ end
27
+
28
+ def marshal_load o
29
+ end
30
+ end
31
+
32
+ class U
33
+ def self._load str
34
+ new
35
+ end
36
+
37
+ def _dump limit
38
+ s = '_dump'
39
+ s.instance_variable_set :@ivar_on_dump_str, 'value on ivar on dump str'
40
+ s
41
+ end
42
+ end
43
+
44
+ S = Struct.new :f
45
+
46
+ class TestMarshalStructure < MiniTest::Unit::TestCase
47
+
48
+ def mu_pp obj
49
+ s = ''
50
+ s = PP.pp obj, s
51
+ s.chomp
52
+ end
53
+
54
+ def setup
55
+ @MS = Marshal::Structure
56
+ end
57
+
58
+ def test_construct
59
+ str =
60
+ "\004\b{\006:\006a[\031c\006Bm\006C\"\006d/\006e\000i\006" \
61
+ "f\0322.2999999999999998\000ff" \
62
+ "l+\n\000\000\000\000\000\000\000\000\001\0000TF}\000i\000" \
63
+ "S:\006S\006:\006fi\000o:\vObject\000@\017" \
64
+ "U:\006M\"\021marshal_dump" \
65
+ "Iu:\006U\n_dump\006" \
66
+ ":\026@ivar_on_dump_str\"\036value on ivar on dump str" \
67
+ ";\000e:\006Eo;\b\000" \
68
+ "I\"\025string with ivar\006:\v@value\"\017some value" \
69
+ "C:\016BenString\"\000"
70
+
71
+ structure = @MS.load str
72
+
73
+ expected = [
74
+ :hash,
75
+ 0,
76
+ 1,
77
+ [:symbol, 0, "a"],
78
+ [:array,
79
+ 1,
80
+ 20,
81
+ [:class, 2, "B"],
82
+ [:module, 3, "C"],
83
+ [:string, 4, "d"],
84
+ [:regexp, 5, "e", 0],
85
+ [:fixnum, 1],
86
+ [:float, 6, "2.2999999999999998\000ff"],
87
+ [:bignum, 7, 1, 10, 18446744073709551616],
88
+ :nil,
89
+ :true,
90
+ :false,
91
+ [:hash_default, 8, 0, [:fixnum, 0]],
92
+ [:struct, 9, [:symbol, 1, "S"], 1, [:symbol, 2, "f"], [:fixnum, 0]],
93
+ [:object, 10, [:symbol, 3, "Object"], [0]],
94
+ [:link, 10],
95
+ [:user_marshal, 11, [:symbol, 4, "M"], [:string, 12, "marshal_dump"]],
96
+ [:instance_variables,
97
+ [:user_defined, 13, [:symbol, 5, "U"], "_dump"],
98
+ 1,
99
+ [:symbol, 6, "@ivar_on_dump_str"],
100
+ [:string, 14, "value on ivar on dump str"]],
101
+ [:symbol_link, 0],
102
+ [:extended, [:symbol, 7, "E"], [:object, 15, [:symbol_link, 3], [0]]],
103
+ [:instance_variables,
104
+ [:string, 16, "string with ivar"],
105
+ 1,
106
+ [:symbol, 8, "@value"],
107
+ [:string, 17, "some value"]],
108
+ [:user_class, [:symbol, 9, "BenString"], [:string, 18, ""]]]]
109
+
110
+ assert_equal expected, structure
111
+ end
112
+
113
+ def test_construct_data
114
+ name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
115
+ str = Marshal.dump name
116
+
117
+ expected = [
118
+ :data,
119
+ 0,
120
+ [:symbol, 0, "OpenSSL::X509::Name"],
121
+ [:array,
122
+ 1,
123
+ 2,
124
+ [:array, 2, 3,
125
+ [:string, 3, "CN"],
126
+ [:string, 4, "nobody"],
127
+ [:fixnum, 12]],
128
+ [:array, 5, 3,
129
+ [:string, 6, "DC"],
130
+ [:string, 7, "example"],
131
+ [:fixnum, 22]]]]
132
+
133
+ assert_equal expected, @MS.load(str)
134
+ end
135
+
136
+ def test_construct_module_old
137
+ assert_equal [:module, 0, "M"], @MS.load("\x04\x08M\x06M")
138
+ end
139
+
140
+ def test_consume
141
+ ms = @MS.new "\x04\x08\x06M"
142
+
143
+ assert_equal "\x06M", ms.consume(2)
144
+ end
145
+
146
+ def test_consume_bytes
147
+ ms = @MS.new "\x04\x08\x06M"
148
+
149
+ assert_equal [6, 77], ms.consume_bytes(2)
150
+ end
151
+
152
+ def test_consume_byte
153
+ ms = @MS.new "\x04\x08M"
154
+
155
+ assert_equal 77, ms.consume_byte
156
+ end
157
+
158
+ def test_consume_character
159
+ ms = @MS.new "\x04\x08M"
160
+
161
+ assert_equal 'M', ms.consume_character
162
+ end
163
+
164
+ def test_get_byte_sequence
165
+ ms = @MS.new "\x04\x08\x06M"
166
+
167
+ assert_equal "M", ms.get_byte_sequence
168
+ end
169
+
170
+ end
171
+
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: marshal-structure
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ version: "1.0"
10
+ platform: ruby
11
+ authors:
12
+ - Eric Hodel
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain:
16
+ - |
17
+ -----BEGIN CERTIFICATE-----
18
+ MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
19
+ YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu
20
+ ZXQwHhcNMDcxMjIxMDIwNDE0WhcNMDgxMjIwMDIwNDE0WjBBMRAwDgYDVQQDDAdk
21
+ cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ
22
+ FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76
23
+ LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J
24
+ U5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm
25
+ Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY
26
+ mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd
27
+ g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh
28
+ sCANiQ8BAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
29
+ BBS5k4Z75VSpdM0AclG2UvzFA/VW5DANBgkqhkiG9w0BAQUFAAOCAQEAHagT4lfX
30
+ kP/hDaiwGct7XPuVGbrOsKRVD59FF5kETBxEc9UQ1clKWngf8JoVuEoKD774dW19
31
+ bU0GOVWO+J6FMmT/Cp7nuFJ79egMf/gy4gfUfQMuvfcr6DvZUPIs9P/TlK59iMYF
32
+ DIOQ3DxdF3rMzztNUCizN4taVscEsjCcgW6WkUJnGdqlu3OHWpQxZBJkBTjPCoc6
33
+ UW6on70SFPmAy/5Cq0OJNGEWBfgD9q7rrs/X8GGwUWqXb85RXnUVi/P8Up75E0ag
34
+ 14jEc90kN+C7oI/AGCBN0j6JnEtYIEJZibjjDJTSMWlUKKkj30kq7hlUC2CepJ4v
35
+ x52qPcexcYZR7w==
36
+ -----END CERTIFICATE-----
37
+
38
+ date: 2011-08-06 00:00:00 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: minitest
42
+ prerelease: false
43
+ requirement: &id001 !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ hash: 1
49
+ segments:
50
+ - 2
51
+ - 3
52
+ - 1
53
+ version: 2.3.1
54
+ type: :development
55
+ version_requirements: *id001
56
+ - !ruby/object:Gem::Dependency
57
+ name: ben_string
58
+ prerelease: false
59
+ requirement: &id002 !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ~>
63
+ - !ruby/object:Gem::Version
64
+ hash: 1
65
+ segments:
66
+ - 1
67
+ version: "1"
68
+ type: :development
69
+ version_requirements: *id002
70
+ - !ruby/object:Gem::Dependency
71
+ name: hoe
72
+ prerelease: false
73
+ requirement: &id003 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ hash: 17
79
+ segments:
80
+ - 2
81
+ - 9
82
+ version: "2.9"
83
+ type: :development
84
+ version_requirements: *id003
85
+ description: Dumps a tree based on the Marshal format. Supports the Marshal 4.8 format.
86
+ email:
87
+ - drbrain@segment7.net
88
+ executables: []
89
+
90
+ extensions: []
91
+
92
+ extra_rdoc_files:
93
+ - History.txt
94
+ - Manifest.txt
95
+ - README.rdoc
96
+ files:
97
+ - .autotest
98
+ - History.txt
99
+ - Manifest.txt
100
+ - README.rdoc
101
+ - Rakefile
102
+ - lib/marshal/structure.rb
103
+ - test/test_marshal_structure.rb
104
+ - .gemtest
105
+ homepage: https://github.com/drbrain/marshal-structure
106
+ licenses: []
107
+
108
+ metadata: {}
109
+
110
+ post_install_message:
111
+ rdoc_options:
112
+ - --main
113
+ - README.rdoc
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: 3
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ hash: 3
131
+ segments:
132
+ - 0
133
+ version: "0"
134
+ requirements: []
135
+
136
+ rubyforge_project: marshal-structure
137
+ rubygems_version: 1.8.6
138
+ signing_key:
139
+ specification_version: 4
140
+ summary: Dumps a tree based on the Marshal format
141
+ test_files:
142
+ - test/test_marshal_structure.rb
@@ -0,0 +1 @@
1
+ @��\�*<�᳷�WM����F�h��;�� �ȵ0c