marshal-structure 1.0

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.
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