marshal-structure 1.1.1 → 2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ef879e59c6e30f4e9a9794f4b712dbff947c508f
4
+ data.tar.gz: 7639105aa9aba80c6c7a8ea2293ed783ca3e22e2
5
+ SHA512:
6
+ metadata.gz: 905840c1775e2787f813ccbc1396b22434b5b41c36eb05136f4d21e3c478f8f3fb676b777c243446712f9fd362b8088c88f115f824e1efcf1b3d0797b656269d
7
+ data.tar.gz: c95e398a52ac662f5de25770e56077c58dbdf1803b9f79f4364f5e13ab73f611f41312362ef6efefea09e77093a9e0dd6fa0fbe97651e450e6179905762d4188
Binary file
data.tar.gz.sig CHANGED
@@ -1 +1,2 @@
1
- 7s5�^MD ��-47ܒ�εɯc��]��T@�nxg���I��cqSWt��� ��`�`B��C� �<�T��^fN$_��"��}�ӟiG��H.�ю�X��� ;�REF(nG��CO
1
+ ��>Ϡِϣ�&�6fi'��O���֦�WM�C[���QO��b<�C3M2�\⌝{��-zvL�Ή��p+����u_�#S��X� �#U�t1�����j��()y(&��;��?Y�s�-�C)c����c[fwv��r1�(����*��Ԩ��h�S��k34��덋��BF��`�B0
2
+ I���A�1`�A��Z@Vh�qR�c�L�o�h�;���l�0�O)+9b��>�͖NGw��b]4�ޒ{7
data/.autotest CHANGED
@@ -1,7 +1,6 @@
1
1
  # -*- ruby -*-
2
2
 
3
3
  require 'autotest/restart'
4
- require 'autotest/isolate'
5
4
 
6
5
  Autotest.add_hook :initialize do |at|
7
6
  at.testlib = 'minitest/autorun'
@@ -1,3 +1,18 @@
1
+ === 2.0 / 2012-05-16
2
+
3
+ * API Change
4
+ * Split #construct into a Tokenizer and Parser. The Structure class is now
5
+ mostly empty.
6
+
7
+ * Enhancements
8
+ * Added a Tokenizer allows examination of a stream without the creation of
9
+ excessive objects.
10
+ * Added a Parser which can be used as a model for further examination of
11
+ Marshal streams.
12
+ * Added an ObjectCounter which counts the number of allocations that will be
13
+ made when loading the stream.
14
+ * Added Marshal::Structure#load which loads the object using Marshal.
15
+
1
16
  === 1.1.1 / 2011-10-06
2
17
 
3
18
  * Bug fix
@@ -5,4 +5,11 @@ README.rdoc
5
5
  Rakefile
6
6
  bin/marshal_structure
7
7
  lib/marshal/structure.rb
8
+ lib/marshal/structure/allocation_counter.rb
9
+ lib/marshal/structure/parser.rb
10
+ lib/marshal/structure/test_case.rb
11
+ lib/marshal/structure/tokenizer.rb
8
12
  test/test_marshal_structure.rb
13
+ test/test_marshal_structure_allocation_counter.rb
14
+ test/test_marshal_structure_parser.rb
15
+ test/test_marshal_structure_tokenizer.rb
@@ -1,18 +1,17 @@
1
1
  = marshal-structure
2
2
 
3
- * https://github.com/drbrain/marshal-structure
3
+ home :: https://github.com/drbrain/marshal-structure
4
+ rdoc :: http://docs.seattlerb.org/marshal-structure
5
+ bugs :: https://github.com/drbrain/marshal-structure/issues
4
6
 
5
- == DESCRIPTION:
7
+ == Description
6
8
 
7
- Dumps a tree based on the Marshal format. Supports the Marshal 4.8 format.
9
+ Tools to inspect and analyze Ruby's Marshal serialization format. Supports
10
+ the Marshal 4.8 format which is emitted by ruby 1.8 through 2.x.
8
11
 
9
- == FEATURES/PROBLEMS:
12
+ == Examples
10
13
 
11
- * Works like Marshal.load
12
-
13
- == SYNOPSIS:
14
-
15
- From the command line:
14
+ To dump the structure of a Marshal stream:
16
15
 
17
16
  ruby -rpp -rmarshal/structure \
18
17
  -e 'pp Marshal::Structure.load Marshal.dump "hello"'
@@ -24,21 +23,17 @@ Fancier usage:
24
23
 
25
24
  ms = Marshal::Structure.new Marshal.dump %w[hello world]
26
25
 
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:
26
+ # print the stream structure
27
+ pp ms.structure
34
28
 
35
- * Ruby 1.8.7+
29
+ # show how many allocations are required to load the stream
30
+ p ms.count_allocations
36
31
 
37
- == INSTALL:
32
+ == Installation
38
33
 
39
34
  gem install marshal-structure
40
35
 
41
- == DEVELOPERS:
36
+ == Developers
42
37
 
43
38
  After checking out the source, run:
44
39
 
@@ -47,11 +42,11 @@ After checking out the source, run:
47
42
  This task will install any missing dependencies, run the tests/specs,
48
43
  and generate the RDoc.
49
44
 
50
- == LICENSE:
45
+ == License
51
46
 
52
47
  (The MIT License)
53
48
 
54
- Copyright (c) 2011 Eric Hodel
49
+ Copyright (c) Eric Hodel
55
50
 
56
51
  Permission is hereby granted, free of charge, to any person obtaining
57
52
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -4,8 +4,8 @@ require 'rubygems'
4
4
  require 'hoe'
5
5
 
6
6
  Hoe.plugin :git
7
- Hoe.plugin :isolate
8
7
  Hoe.plugin :minitest
8
+ Hoe.plugin :travis
9
9
 
10
10
  Hoe.spec 'marshal-structure' do
11
11
  developer 'Eric Hodel', 'drbrain@segment7.net'
@@ -15,12 +15,6 @@ Hoe.spec 'marshal-structure' do
15
15
  self.readme_file = 'README.rdoc'
16
16
  self.extra_rdoc_files << 'README.rdoc' # HACK fix in Hoe
17
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
18
  extra_dev_deps << ['ben_string', '~> 1']
25
19
  end
26
20
 
@@ -1,164 +1,73 @@
1
1
  ##
2
2
  # Marshal::Structure dumps a nested Array describing the structure of a
3
- # Marshal stream.
3
+ # Marshal stream. Marshal format 4.8 (Ruby 1.8 through 2.x) is supported.
4
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.1.1'
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'
5
+ # Examples:
6
+ #
7
+ # To dump the structure of a Marshal stream:
8
+ #
9
+ # ruby -rpp -rmarshal/structure \
10
+ # -e 'pp Marshal::Structure.load Marshal.dump "hello"'
11
+ #
12
+ # Fancier usage:
13
+ #
14
+ # require 'pp'
15
+ # require 'marshal/structure'
16
+ #
17
+ # ms = Marshal::Structure.new Marshal.dump %w[hello world]
18
+ #
19
+ # # print the stream structure
20
+ # pp ms.structure
21
+ #
22
+ # # show how many allocations are required to load the stream
23
+ # p ms.count_allocations
113
24
 
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
25
 
120
- TYPE_MODULE_OLD = 'M'
26
+ class Marshal::Structure
121
27
 
122
28
  ##
123
- # A class (reference, not content)
29
+ # Generic error class for Marshal::Structure
124
30
 
125
- TYPE_CLASS = 'c'
31
+ class Error < RuntimeError
32
+ end
126
33
 
127
34
  ##
128
- # A module (reference, not content)
129
-
130
- TYPE_MODULE = 'm'
35
+ # Raised when the Marshal stream is at the end
131
36
 
132
- ##
133
- # A Symbol
37
+ class EndOfMarshal < Error
134
38
 
135
- TYPE_SYMBOL = ':'
39
+ ##
40
+ # Number of bytes of Marshal stream consumed
136
41
 
137
- ##
138
- # A reference to a previously Symbol
42
+ attr_reader :consumed
139
43
 
140
- TYPE_SYMLINK = ';'
44
+ ##
45
+ # Requested number of bytes that was not fulfillable
141
46
 
142
- ##
143
- # Instance variables for a following object
47
+ attr_reader :requested
144
48
 
145
- TYPE_IVAR = 'I'
49
+ ##
50
+ # Creates a new EndOfMarshal exception. Marshal::Structure previously
51
+ # read +consumed+ bytes and was unable to fulfill the request for
52
+ # +requested+ additional bytes.
146
53
 
147
- ##
148
- # A reference to a previously-stored Object
54
+ def initialize consumed, requested
55
+ @consumed = consumed
56
+ @requested = requested
149
57
 
150
- TYPE_LINK = '@'
58
+ super "consumed #{consumed} bytes, requested #{requested} more"
59
+ end
60
+ end
151
61
 
152
62
  ##
153
- # Objects found in the Marshal stream. Since objects aren't constructed the
154
- # actual object won't be present in this list.
63
+ # Version of Marshal::Structure you are using
155
64
 
156
- attr_reader :objects
65
+ VERSION = '2.0'
157
66
 
158
67
  ##
159
- # Symbols found in the Marshal stream
68
+ # The Marshal stream
160
69
 
161
- attr_reader :symbols
70
+ attr_reader :stream
162
71
 
163
72
  ##
164
73
  # Returns the structure of the Marshaled object +obj+ as nested Arrays.
@@ -178,24 +87,18 @@ class Marshal::Structure
178
87
  data = obj.to_s
179
88
  elsif obj.respond_to? :read then
180
89
  data = obj.read
181
- if data.empty? then
182
- raise EOFError, "end of file reached"
183
- end
90
+ raise EOFError, "end of file reached" if data.empty?
184
91
  elsif obj.respond_to? :getc then # FIXME - don't read all of it upfront
185
92
  data = ''
186
- data << c while (c = obj.getc.chr)
93
+
94
+ while c = obj.getc do
95
+ data << c.chr
96
+ end
187
97
  else
188
98
  raise TypeError, "instance of IO needed"
189
99
  end
190
100
 
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
101
+ new(data).structure
199
102
  end
200
103
 
201
104
  ##
@@ -220,418 +123,47 @@ class Marshal::Structure
220
123
  # Prepares processing of +stream+
221
124
 
222
125
  def initialize stream
223
- @objects = []
224
- @symbols = []
225
-
226
- @stream = stream
227
- @byte_array = stream.bytes.to_a
228
- @consumed = 2
229
- end
230
-
231
- ##
232
- # Adds +obj+ to the objects list
233
-
234
- def add_object obj
235
- return if
236
- [NilClass, TrueClass, FalseClass, Symbol, Fixnum].any? { |c| c === obj }
237
-
238
- index = @objects.size
239
- @objects << obj
240
- index
126
+ @stream = stream
127
+ @tokenizer = Marshal::Structure::Tokenizer.new stream
241
128
  end
242
129
 
243
130
  ##
244
- # Adds +symbol+ to the symbols list
131
+ # Counts allocations required to load the Marshal stream. See
132
+ # Marshal::Structure::AllocationsCounter for a description of how counting
133
+ # is performed.
245
134
 
246
- def add_symlink symbol
247
- index = @symbols.size
248
- @symbols << symbol
249
- index
250
- end
135
+ def count_allocations
136
+ counter = Marshal::Structure::AllocationCounter.new token_stream
251
137
 
252
- ##
253
- # Creates the structure for the remaining stream.
254
-
255
- def construct
256
- type = consume_character
257
-
258
- case type
259
- when TYPE_NIL then
260
- :nil
261
- when TYPE_TRUE then
262
- :true
263
- when TYPE_FALSE then
264
- :false
265
-
266
- when TYPE_ARRAY then
267
- [:array, *construct_array]
268
- when TYPE_BIGNUM then
269
- [:bignum, *construct_bignum]
270
- when TYPE_CLASS then
271
- ref = store_unique_object Object.allocate
272
-
273
- [:class, ref, get_byte_sequence]
274
- when TYPE_DATA then
275
- [:data, *construct_data]
276
- when TYPE_EXTENDED then
277
- [:extended, get_symbol, construct]
278
- when TYPE_FIXNUM then
279
- [:fixnum, construct_integer]
280
- when TYPE_FLOAT then
281
- [:float, *construct_float]
282
- when TYPE_HASH then
283
- [:hash, *construct_hash]
284
- when TYPE_HASH_DEF then
285
- [:hash_default, *construct_hash_def]
286
- when TYPE_IVAR then
287
- [:instance_variables, construct, *construct_instance_variables]
288
- when TYPE_LINK then
289
- [:link, construct_integer]
290
- when TYPE_MODULE, TYPE_MODULE_OLD then
291
- ref = store_unique_object Object.allocate
292
-
293
- [:module, ref, get_byte_sequence]
294
- when TYPE_OBJECT then
295
- [:object, *construct_object]
296
- when TYPE_REGEXP then
297
- [:regexp, *construct_regexp]
298
- when TYPE_STRING then
299
- [:string, *construct_string]
300
- when TYPE_STRUCT then
301
- [:struct, *construct_struct]
302
- when TYPE_SYMBOL then
303
- [:symbol, *construct_symbol]
304
- when TYPE_SYMLINK then
305
- [:symbol_link, construct_integer]
306
- when TYPE_USERDEF then
307
- [:user_defined, *construct_user_defined]
308
- when TYPE_USRMARSHAL then
309
- [:user_marshal, *construct_user_marshal]
310
- when TYPE_UCLASS then
311
- name = get_symbol
312
-
313
- [:user_class, name, construct]
314
- else
315
- raise ArgumentError, "load error, unknown type #{type}"
316
- end
138
+ counter.count
317
139
  end
318
140
 
319
141
  ##
320
- # Creates the body of an +:array+ object
321
-
322
- def construct_array
323
- ref = store_unique_object Object.allocate
324
-
325
- obj = [ref]
326
-
327
- items = construct_integer
328
-
329
- obj << items
330
-
331
- items.times do
332
- obj << construct
333
- end
142
+ # Loads the stream with Marshal.load
334
143
 
335
- obj
144
+ def load
145
+ Marshal.load @stream
336
146
  end
337
147
 
338
148
  ##
339
- # Creates the body of a +:bignum+ object
149
+ # Returns the structure of the Marshal stream.
340
150
 
341
- def construct_bignum
342
- sign = consume_byte == ?- ? -1 : 1
343
- size = construct_integer * 2
151
+ def structure
152
+ parser = Marshal::Structure::Parser.new token_stream
344
153
 
345
- result = 0
346
-
347
- data = consume_bytes size
348
-
349
- data.each_with_index do |data, exp|
350
- result += (data * 2**(exp*8))
351
- end
352
-
353
- ref = store_unique_object Object.allocate
354
-
355
- [ref, sign, size, result]
154
+ parser.parse
356
155
  end
357
156
 
358
157
  ##
359
- # Creates the body of a wrapped C pointer object
360
-
361
- def construct_data
362
- ref = store_unique_object Object.allocate
158
+ # Returns an Enumerator for the tokens in the Marshal stream.
363
159
 
364
- [ref, get_symbol, construct]
365
- end
366
-
367
- ##
368
- # Creates the body of a +:float+ object
369
-
370
- def construct_float
371
- float = get_byte_sequence
372
-
373
- ref = store_unique_object Object.allocate
374
-
375
- [ref, float]
376
- end
377
-
378
- ##
379
- # Creates the body of a +:hash+ object
380
-
381
- def construct_hash
382
- ref = store_unique_object Object.allocate
383
-
384
- obj = [ref]
385
-
386
- pairs = construct_integer
387
- obj << pairs
388
-
389
- pairs.times do
390
- obj << construct
391
- obj << construct
392
- end
393
-
394
- obj
395
- end
396
-
397
- ##
398
- # Creates the body of a +:hash_def+ object
399
-
400
- def construct_hash_def
401
- ref, hash = construct_hash
402
-
403
- [ref, hash, construct]
404
- end
405
-
406
- ##
407
- # Instance variables contain an object followed by a count of instance
408
- # variables and their contents
409
-
410
- def construct_instance_variables
411
- instance_variables = []
412
-
413
- pairs = construct_integer
414
- instance_variables << pairs
415
-
416
- pairs.times do
417
- instance_variables << get_symbol
418
- instance_variables << construct
419
- end
420
-
421
- instance_variables
422
- end
423
-
424
- ##
425
- # Decodes a stored Fixnum
426
-
427
- def construct_integer
428
- c = consume_byte
429
-
430
- # The format appears to be a simple integer compression format
431
- #
432
- # The 0-123 cases are easy, and use one byte
433
- # We've read c as unsigned char in a way, but we need to honor
434
- # the sign bit. We do that by simply comparing with the +128 values
435
- return 0 if c == 0
436
- return c - 5 if 4 < c and c < 128
437
-
438
- # negative, but checked known it's instead in 2's compliment
439
- return c - 251 if 252 > c and c > 127
440
-
441
- # otherwise c (now in the 1 to 4 range) indicates how many
442
- # bytes to read to construct the value.
443
- #
444
- # Because we're operating on a small number of possible values,
445
- # it's cleaner to just unroll the calculate of each
446
-
447
- case c
448
- when 1
449
- consume_byte
450
- when 2
451
- consume_byte | (consume_byte << 8)
452
- when 3
453
- consume_byte | (consume_byte << 8) | (consume_byte << 16)
454
- when 4
455
- consume_byte | (consume_byte << 8) | (consume_byte << 16) |
456
- (consume_byte << 24)
457
-
458
- when 255 # -1
459
- consume_byte - 256
460
- when 254 # -2
461
- (consume_byte | (consume_byte << 8)) - 65536
462
- when 253 # -3
463
- (consume_byte |
464
- (consume_byte << 8) |
465
- (consume_byte << 16)) - 16777216 # 2 ** 24
466
- when 252 # -4
467
- (consume_byte |
468
- (consume_byte << 8) |
469
- (consume_byte << 16) |
470
- (consume_byte << 24)) - 4294967296
471
- else
472
- raise "Invalid integer size: #{c}"
473
- end
474
- end
475
-
476
- ##
477
- # Creates an Object
478
-
479
- def construct_object
480
- ref = store_unique_object Object.allocate
481
-
482
- [ref, get_symbol, construct_instance_variables]
483
- end
484
-
485
- ##
486
- # Creates a Regexp
487
-
488
- def construct_regexp
489
- ref =store_unique_object Object.allocate
490
-
491
- [ref, get_byte_sequence, consume_byte]
492
- end
493
-
494
- ##
495
- # Creates a String
496
-
497
- def construct_string
498
- ref = store_unique_object Object.allocate
499
-
500
- [ref, get_byte_sequence]
501
- end
502
-
503
- ##
504
- # Creates a Struct
505
-
506
- def construct_struct
507
- symbols = []
508
- values = []
509
-
510
- obj_ref = store_unique_object Object.allocate
511
-
512
- obj = [obj_ref, get_symbol]
513
-
514
- members = construct_integer
515
- obj << members
516
-
517
- members.times do
518
- obj << get_symbol
519
- obj << construct
520
- end
521
-
522
- obj
523
- end
524
-
525
- ##
526
- # Creates a Symbol
527
-
528
- def construct_symbol
529
- sym = get_byte_sequence
530
-
531
- ref = store_unique_object sym.to_sym
532
-
533
- [ref, sym]
534
- end
535
-
536
- ##
537
- # Creates an object saved by _dump
538
-
539
- def construct_user_defined
540
- name = get_symbol
541
-
542
- data = get_byte_sequence
543
-
544
- ref = store_unique_object Object.allocate
545
-
546
- [ref, name, data]
547
- end
548
-
549
- ##
550
- # Creates an object saved by marshal_dump
551
-
552
- def construct_user_marshal
553
- name = get_symbol
554
-
555
- obj = Object.allocate
556
-
557
- obj_ref = store_unique_object obj
558
-
559
- [obj_ref, name, construct]
560
- end
561
-
562
- ##
563
- # Consumes +bytes+ from the marshal stream
564
-
565
- def consume bytes
566
- raise ArgumentError, "marshal data too short" if @consumed > @stream.size
567
- data = @stream[@consumed, bytes]
568
- @consumed += bytes
569
- data
570
- end
571
-
572
- ##
573
- # Consumes +count+ bytes from the marshal stream as an Array of bytes
574
-
575
- def consume_bytes count
576
- consume(count).bytes.to_a
577
- end
578
-
579
- ##
580
- # Consumes one byte from the marshal stream
581
-
582
- def consume_byte
583
- raise ArgumentError, "marshal data too short" if
584
- @consumed > @byte_array.size
585
-
586
- data = @byte_array[@consumed]
587
- @consumed += 1
588
-
589
- data
590
- end
591
-
592
- ##
593
- # Consumes one byte from the marshal stream and returns a character
594
-
595
- def consume_character
596
- consume_byte.chr
597
- end
598
-
599
- ##
600
- # Consumes a sequence of bytes from the marshal stream based on the next
601
- # integer
602
-
603
- def get_byte_sequence
604
- size = construct_integer
605
- consume size
606
- end
607
-
608
- ##
609
- # Constructs a Symbol from a TYPE_SYMBOL or TYPE_SYMLINK
610
-
611
- def get_symbol
612
- type = consume_character
613
-
614
- case type
615
- when TYPE_SYMBOL then
616
- [:symbol, *construct_symbol]
617
- when TYPE_SYMLINK then
618
- num = construct_integer
619
- [:symbol_link, num]
620
- else
621
- raise ArgumentError, "expected TYPE_SYMBOL or TYPE_SYMLINK, got #{type.inspect}"
622
- end
623
- end
624
-
625
- ##
626
- # Stores a reference to +obj+
627
-
628
- def store_unique_object obj
629
- if Symbol === obj then
630
- add_symlink obj
631
- else
632
- add_object obj
633
- end
160
+ def token_stream
161
+ @tokenizer.tokens
634
162
  end
635
163
 
636
164
  end
637
165
 
166
+ require 'marshal/structure/allocation_counter'
167
+ require 'marshal/structure/parser'
168
+ require 'marshal/structure/tokenizer'
169
+