bindata 1.2.2 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bindata might be problematic. Click here for more details.

Files changed (52) hide show
  1. data/ChangeLog +12 -0
  2. data/NEWS +53 -0
  3. data/Rakefile +2 -1
  4. data/examples/NBT.txt +149 -0
  5. data/examples/ip_address.rb +1 -2
  6. data/examples/list.rb +124 -0
  7. data/examples/nbt.rb +195 -0
  8. data/lib/bindata.rb +4 -3
  9. data/lib/bindata/alignment.rb +86 -0
  10. data/lib/bindata/array.rb +21 -29
  11. data/lib/bindata/base.rb +82 -81
  12. data/lib/bindata/base_primitive.rb +66 -48
  13. data/lib/bindata/choice.rb +18 -28
  14. data/lib/bindata/deprecated.rb +17 -0
  15. data/lib/bindata/dsl.rb +25 -15
  16. data/lib/bindata/int.rb +2 -2
  17. data/lib/bindata/io.rb +8 -6
  18. data/lib/bindata/offset.rb +91 -0
  19. data/lib/bindata/primitive.rb +22 -11
  20. data/lib/bindata/record.rb +40 -10
  21. data/lib/bindata/sanitize.rb +15 -30
  22. data/lib/bindata/string.rb +16 -17
  23. data/lib/bindata/stringz.rb +0 -1
  24. data/lib/bindata/struct.rb +17 -6
  25. data/lib/bindata/trace.rb +52 -0
  26. data/lib/bindata/wrapper.rb +28 -6
  27. data/manual.haml +56 -10
  28. data/manual.md +318 -113
  29. data/spec/alignment_spec.rb +61 -0
  30. data/spec/array_spec.rb +139 -178
  31. data/spec/base_primitive_spec.rb +86 -111
  32. data/spec/base_spec.rb +200 -172
  33. data/spec/bits_spec.rb +45 -53
  34. data/spec/choice_spec.rb +91 -87
  35. data/spec/deprecated_spec.rb +36 -14
  36. data/spec/float_spec.rb +16 -68
  37. data/spec/int_spec.rb +26 -27
  38. data/spec/io_spec.rb +105 -105
  39. data/spec/lazy_spec.rb +50 -50
  40. data/spec/primitive_spec.rb +36 -36
  41. data/spec/record_spec.rb +134 -134
  42. data/spec/registry_spec.rb +34 -38
  43. data/spec/rest_spec.rb +8 -11
  44. data/spec/skip_spec.rb +9 -17
  45. data/spec/spec_common.rb +4 -0
  46. data/spec/string_spec.rb +92 -115
  47. data/spec/stringz_spec.rb +41 -74
  48. data/spec/struct_spec.rb +132 -153
  49. data/spec/system_spec.rb +115 -60
  50. data/spec/wrapper_spec.rb +63 -31
  51. data/tasks/pkg.rake +1 -1
  52. metadata +15 -7
data/ChangeLog CHANGED
@@ -1,5 +1,17 @@
1
1
  = BinData Changelog
2
2
 
3
+ == Version 1.3.0 (2011-01-25)
4
+
5
+ * BinData objects can now assign values when instantiating.
6
+ * Improved support for bit-based alignment.
7
+ * Updated reference manual.
8
+ * Added examples for declaring recursive structures.
9
+ * Objects deriving from BinData::Base should no longer override #initialize.
10
+ * Added BinData::Base(#new, #initialize_instance) to speed up
11
+ instantiation of multiple objects.
12
+ * Updated specs to rspec-1.3.0
13
+ * BinData::Struct.hide now expects symbols instead of strings.
14
+
3
15
  == Version 1.2.2 (2010-12-14)
4
16
 
5
17
  * Added Base.bindata_name method.
data/NEWS CHANGED
@@ -1,3 +1,56 @@
1
+ = 1.3.0
2
+
3
+ == New features
4
+
5
+ You can now assign values to BinData objects when instantiating them.
6
+
7
+ Previously:
8
+ obj = BinData::Stringz.new(:max_length => 10)
9
+ obj.assign("abc")
10
+
11
+ Now:
12
+ obj = BinData::Stringz.new("abc", :max_length => 10)
13
+
14
+ == Backwards incompatible changes
15
+
16
+ This version makes some backwards incompatible changes for more advanced
17
+ users of BinData.
18
+
19
+ This only affects you if you have created your own custom types by
20
+ subclassing BinData::Base or BinData::BasePrimitive.
21
+
22
+ All instance variables must now be initialized in #initialize_instance.
23
+ Implementing #initialize is no longer allowed.
24
+
25
+ Run your existing code in $VERBOSE mode ("ruby -w"), and BinData will
26
+ inform you of any changes you need to make to your code.
27
+
28
+ If your code previously looked like:
29
+
30
+ class MyType < BinData::Base
31
+ register_self
32
+
33
+ def initialize(parameters = {}, parent = nil)
34
+ super
35
+
36
+ @var1 = ...
37
+ @var2 = ...
38
+ end
39
+ ...
40
+ end
41
+
42
+ You must change it to look like:
43
+
44
+ class MyType < BinData::Base
45
+ register_self
46
+
47
+ def initialize_instance
48
+ @var1 = ...
49
+ @var2 = ...
50
+ end
51
+ ...
52
+ end
53
+
1
54
  = 1.0.0
2
55
 
3
56
  Version 1.0.0 removes all deprecated features. If you are upgrading from a
data/Rakefile CHANGED
@@ -7,7 +7,8 @@ CURRENT_VERSION = BinData::VERSION
7
7
 
8
8
  PKG_FILES = FileList[
9
9
  "[A-Z]*",
10
- "{examples,spec,lib}/**/*.rb",
10
+ "examples/**/*",
11
+ "{spec,lib}/**/*.rb",
11
12
  "tasks/**/*.rake",
12
13
  "setup.rb",
13
14
  "manual.haml",
@@ -0,0 +1,149 @@
1
+ Named Binary Tag specification
2
+
3
+ NBT (Named Binary Tag) is a tag based binary format designed to carry large amounts of binary data with smaller amounts of additional data.
4
+ An NBT file consists of a single GZIPped Named Tag of type TAG_Compound.
5
+
6
+ A Named Tag has the following format:
7
+
8
+ byte tagType
9
+ TAG_String name
10
+ [payload]
11
+
12
+ The tagType is a single byte defining the contents of the payload of the tag.
13
+
14
+ The name is a descriptive name, and can be anything (eg "cat", "banana", "Hello World!"). It has nothing to do with the tagType.
15
+ The purpose for this name is to name tags so parsing is easier and can be made to only look for certain recognized tag names.
16
+ Exception: If tagType is TAG_End, the name is skipped and assumed to be "".
17
+
18
+ The [payload] varies by tagType.
19
+
20
+ Note that ONLY Named Tags carry the name and tagType data. Explicitly identified Tags (such as TAG_String above) only contains the payload.
21
+
22
+
23
+ The tag types and respective payloads are:
24
+
25
+ TYPE: 0 NAME: TAG_End
26
+ Payload: None.
27
+ Note: This tag is used to mark the end of a list.
28
+ Cannot be named! If type 0 appears where a Named Tag is expected, the name is assumed to be "".
29
+ (In other words, this Tag is always just a single 0 byte when named, and nothing in all other cases)
30
+
31
+ TYPE: 1 NAME: TAG_Byte
32
+ Payload: A single signed byte (8 bits)
33
+
34
+ TYPE: 2 NAME: TAG_Short
35
+ Payload: A signed short (16 bits, big endian)
36
+
37
+ TYPE: 3 NAME: TAG_Int
38
+ Payload: A signed short (32 bits, big endian)
39
+
40
+ TYPE: 4 NAME: TAG_Long
41
+ Payload: A signed long (64 bits, big endian)
42
+
43
+ TYPE: 5 NAME: TAG_Float
44
+ Payload: A floating point value (32 bits, big endian, IEEE 754-2008, binary32)
45
+
46
+ TYPE: 6 NAME: TAG_Double
47
+ Payload: A floating point value (64 bits, big endian, IEEE 754-2008, binary64)
48
+
49
+ TYPE: 7 NAME: TAG_Byte_Array
50
+ Payload: TAG_Int length
51
+ An array of bytes of unspecified format. The length of this array is <length> bytes
52
+
53
+ TYPE: 8 NAME: TAG_String
54
+ Payload: TAG_Short length
55
+ An array of bytes defining a string in UTF-8 format. The length of this array is <length> bytes
56
+
57
+ TYPE: 9 NAME: TAG_List
58
+ Payload: TAG_Byte tagId
59
+ TAG_Int length
60
+ A sequential list of Tags (not Named Tags), of type <typeId>. The length of this array is <length> Tags
61
+ Notes: All tags share the same type.
62
+
63
+ TYPE: 10 NAME: TAG_Compound
64
+ Payload: A sequential list of Named Tags. This array keeps going until a TAG_End is found.
65
+ TAG_End end
66
+ Notes: If there's a nested TAG_Compound within this tag, that one will also have a TAG_End, so simply reading until the next TAG_End will not work.
67
+ The names of the named tags have to be unique within each TAG_Compound
68
+ The order of the tags is not guaranteed.
69
+
70
+
71
+
72
+
73
+
74
+ Decoding example:
75
+ (Use http://www.minecraft.net/docs/test.nbt to test your implementation)
76
+
77
+
78
+ First we start by reading a Named Tag.
79
+ After unzipping the stream, the first byte is a 10. That means the tag is a TAG_Compound (as expected by the specification).
80
+
81
+ The next two bytes are 0 and 11, meaning the name string consists of 11 UTF-8 characters. In this case, they happen to be "hello world".
82
+ That means our root tag is named "hello world". We can now move on to the payload.
83
+
84
+ From the specification, we see that TAG_Compound consists of a series of Named Tags, so we read another byte to find the tagType.
85
+ It happens to be an 8. The name is 4 letters long, and happens to be "name". Type 8 is TAG_String, meaning we read another two bytes to get the length,
86
+ then read that many bytes to get the contents. In this case, it's "Bananrama".
87
+
88
+ So now we know the TAG_Compound contains a TAG_String named "name" with the content "Bananrama"
89
+
90
+ We move on to reading the next Named Tag, and get a 0. This is TAG_End, which always has an implied name of "". That means that the list of entries
91
+ in the TAG_Compound is over, and indeed all of the NBT file.
92
+
93
+ So we ended up with this:
94
+
95
+ TAG_Compound("hello world"): 1 entries
96
+ {
97
+ TAG_String("name"): Bananrama
98
+ }
99
+
100
+
101
+
102
+ For a slightly longer test, download http://www.minecraft.net/docs/bigtest.nbt
103
+ You should end up with this:
104
+
105
+ TAG_Compound("Level"): 11 entries
106
+ {
107
+ TAG_Short("shortTest"): 32767
108
+ TAG_Long("longTest"): 9223372036854775807
109
+ TAG_Float("floatTest"): 0.49823147
110
+ TAG_String("stringTest"): HELLO WORLD THIS IS A TEST STRING ���!
111
+ TAG_Int("intTest"): 2147483647
112
+ TAG_Compound("nested compound test"): 2 entries
113
+ {
114
+ TAG_Compound("ham"): 2 entries
115
+ {
116
+ TAG_String("name"): Hampus
117
+ TAG_Float("value"): 0.75
118
+ }
119
+ TAG_Compound("egg"): 2 entries
120
+ {
121
+ TAG_String("name"): Eggbert
122
+ TAG_Float("value"): 0.5
123
+ }
124
+ }
125
+ TAG_List("listTest (long)"): 5 entries of type TAG_Long
126
+ {
127
+ TAG_Long: 11
128
+ TAG_Long: 12
129
+ TAG_Long: 13
130
+ TAG_Long: 14
131
+ TAG_Long: 15
132
+ }
133
+ TAG_Byte("byteTest"): 127
134
+ TAG_List("listTest (compound)"): 2 entries of type TAG_Compound
135
+ {
136
+ TAG_Compound: 2 entries
137
+ {
138
+ TAG_String("name"): Compound tag #0
139
+ TAG_Long("created-on"): 1264099775885
140
+ }
141
+ TAG_Compound: 2 entries
142
+ {
143
+ TAG_String("name"): Compound tag #1
144
+ TAG_Long("created-on"): 1264099775885
145
+ }
146
+ }
147
+ TAG_Byte_Array("byteArrayTest (the first 1000 values of (n*n*255+n*7)%100, starting with n=0 (0, 62, 34, 16, 8, ...))"): [1000 bytes]
148
+ TAG_Double("doubleTest"): 0.4931287132182315
149
+ }
@@ -16,8 +16,7 @@ class IPAddr < BinData::Primitive
16
16
  end
17
17
  end
18
18
 
19
- ip = IPAddr.new
20
- ip.value = "127.0.0.1"
19
+ ip = IPAddr.new("127.0.0.1")
21
20
 
22
21
  puts "human readable value: #{ip}" #=> 127.0.0.1
23
22
  puts "binary representation: #{ip.to_binary_s.inspect}" #=> "\177\000\000\001"
@@ -0,0 +1,124 @@
1
+ require 'bindata'
2
+
3
+ # An example of a recursively defined data format.
4
+ #
5
+ # This format is used to describe atoms and lists.
6
+ # It is recursive because lists can contain other lists.
7
+ #
8
+ # Atoms - contain a single integer
9
+ # Lists - contain a mixture of atoms and lists
10
+ #
11
+ # The binary representation is:
12
+ #
13
+ # Atoms - A single byte 'a' followed by an int32 containing the value.
14
+ # Lists - A single byte 'l' followed by an int32 denoting the number of
15
+ # items in the list. This is followed by all the items in the list.
16
+ #
17
+ # All integers are big endian.
18
+ #
19
+ #
20
+ # A first attempt at a declaration would be:
21
+ #
22
+ # class Atom < BinData::Record
23
+ # string :tag, :length => 1, :check_value => 'a'
24
+ # int32be :val
25
+ # end
26
+ #
27
+ # class List < BinData::Record
28
+ # string :tag, :length => 1, :check_value => 'l'
29
+ # int32be :num, :value => lambda { vals.length }
30
+ # array :vals, :initial_length => :num do
31
+ # choice :selection => ??? do
32
+ # atom
33
+ # list
34
+ # end
35
+ # end
36
+ # end
37
+ #
38
+ # Notice how we get stuck on attemping to write a declaration for
39
+ # the contents of the list. We can't determine if the list item is
40
+ # an atom or list because we haven't read it yet. It appears that
41
+ # we can't proceed.
42
+ #
43
+ # The cause of the problem is that the tag identifying the type is
44
+ # coupled with that type.
45
+ #
46
+ # The solution is to decouple the tag from the type. We introduce a
47
+ # new type 'Term' that is a thin container around the tag plus the
48
+ # type (atom or list).
49
+ #
50
+ # The declaration then becomes:
51
+ #
52
+ # class Term < BinData::Record; end # forward declaration
53
+ #
54
+ # class Atom < BinData::Wrapper
55
+ # int32be
56
+ # end
57
+ #
58
+ # class List < BinData::Record
59
+ # int32be :num, :value => lambda { vals.length }
60
+ # array :vals, :type => :term, :initial_length => :num
61
+ # end
62
+ #
63
+ # class Term < BinData::Record
64
+ # string :tag, :length => 1
65
+ # choice :term, :selection => :tag do
66
+ # atom 'a'
67
+ # list 'l'
68
+ # end
69
+ # end
70
+
71
+
72
+ class Term < BinData::Record; end # Forward declaration
73
+
74
+ class Atom < BinData::Wrapper
75
+ int32be
76
+
77
+ def decode
78
+ snapshot
79
+ end
80
+
81
+ def self.encode(val)
82
+ Atom.new(val)
83
+ end
84
+ end
85
+
86
+ class List < BinData::Record
87
+ int32be :num, :value => lambda { vals.length }
88
+ array :vals, :initial_length => :num, :type => :term
89
+
90
+ def decode
91
+ vals.collect { |v| v.decode }
92
+ end
93
+
94
+ def self.encode(val)
95
+ List.new(:vals => val.collect { |v| Term.encode(v) })
96
+ end
97
+ end
98
+
99
+ class Term < BinData::Record
100
+ string :tag, :length => 1
101
+ choice :term, :selection => :tag do
102
+ atom 'a'
103
+ list 'l'
104
+ end
105
+
106
+ def decode
107
+ term.decode
108
+ end
109
+
110
+ def self.encode(val)
111
+ if Fixnum === val
112
+ Term.new(:tag => 'a', :term => Atom.encode(val))
113
+ else
114
+ Term.new(:tag => 'l', :term => List.encode(val))
115
+ end
116
+ end
117
+ end
118
+
119
+
120
+ p Term.encode(4)
121
+ p Term.encode(4).decode
122
+ puts
123
+ p Term.encode([1, [2, 3], 4])
124
+ p Term.encode([1, [2, 3], 4]).decode
@@ -0,0 +1,195 @@
1
+ require 'bindata'
2
+
3
+ # An example reader for Minecraft's NBT format.
4
+ # http://www.minecraft.net/docs/NBT.txt
5
+ #
6
+ # This is an example of how to write a BinData
7
+ # declaration for a recursively defined file format.
8
+ module Nbt
9
+
10
+ TAG_NAMES = {
11
+ 0 => "End",
12
+ 1 => "Byte",
13
+ 2 => "Short",
14
+ 3 => "Int",
15
+ 4 => "Long",
16
+ 5 => "Float",
17
+ 6 => "Double",
18
+ 7 => "Byte_Array",
19
+ 8 => "String",
20
+ 9 => "List",
21
+ 10 => "Compound"
22
+ }
23
+
24
+ # NBT.txt line 25
25
+ class TagEnd < BinData::Primitive
26
+ def get; ""; end
27
+ def set(v); end
28
+
29
+ def to_formatted_s(indent = 0); to_s; end
30
+ end
31
+
32
+ # NBT.txt line 31
33
+ class TagByte < BinData::Wrapper
34
+ int8
35
+
36
+ def to_formatted_s(indent = 0); to_s; end
37
+ end
38
+
39
+ # NBT.txt line 34
40
+ class TagShort < BinData::Wrapper
41
+ int16be
42
+
43
+ def to_formatted_s(indent = 0); to_s; end
44
+ end
45
+
46
+ # NBT.txt line 37
47
+ class TagInt < BinData::Wrapper
48
+ int32be
49
+
50
+ def to_formatted_s(indent = 0); to_s; end
51
+ end
52
+
53
+ # NBT.txt line 40
54
+ class TagLong < BinData::Wrapper
55
+ int64be
56
+
57
+ def to_formatted_s(indent = 0); to_s; end
58
+ end
59
+
60
+ # NBT.txt line 43
61
+ class TagFloat < BinData::Wrapper
62
+ float_be
63
+
64
+ def to_formatted_s(indent = 0); to_s; end
65
+ end
66
+
67
+ # NBT.txt line 46
68
+ class TagDouble < BinData::Wrapper
69
+ double_be
70
+
71
+ def to_formatted_s(indent = 0); to_s; end
72
+ end
73
+
74
+ # NBT.txt line 49
75
+ class TagByteArray < BinData::Record
76
+ int32be :len, :value => lambda { data.length }
77
+ string :data, :read_length => :len
78
+
79
+ def to_formatted_s(indent = 0)
80
+ "[#{len} bytes]"
81
+ end
82
+ end
83
+
84
+ # NBT.txt line 53
85
+ class TagString < BinData::Primitive
86
+ int16be :len, :value => lambda { data.length }
87
+ string :data, :read_length => :len
88
+
89
+ def get
90
+ self.data
91
+ end
92
+
93
+ def set(v)
94
+ self.data = v
95
+ end
96
+
97
+ def to_formatted_s(indent = 0); to_s; end
98
+ end
99
+
100
+ ## Payload is the most important class to understand.
101
+ ## This abstraction allows recursive formats.
102
+ ## eg. lists can contain lists can contain lists.
103
+
104
+ # Forward references used by Payload
105
+ class TagCompound < BinData::Record; end
106
+ class TagList < BinData::Record; end
107
+
108
+ # NBT.txt line 10
109
+ class Payload < BinData::Wrapper
110
+ mandatory_parameter :tag_selector
111
+ choice :selection => :tag_selector do
112
+ tag_end 0
113
+ tag_byte 1
114
+ tag_short 2
115
+ tag_int 3
116
+ tag_long 4
117
+ tag_float 5
118
+ tag_double 6
119
+ tag_byte_array 7
120
+ tag_string 8
121
+ tag_list 9
122
+ tag_compound 10
123
+ end
124
+ end
125
+
126
+ # NBT.txt line 6, 27
127
+ class NamedTag < BinData::Record
128
+ int8 :tag_id
129
+ tag_string :name, :onlyif => :not_end_tag?
130
+ payload :payload, :onlyif => :not_end_tag?, :tag_selector => :tag_id
131
+
132
+ def not_end_tag?
133
+ tag_id != 0
134
+ end
135
+
136
+ def to_formatted_s(indent = 0)
137
+ " " * indent +
138
+ "TAG_#{TAG_NAMES[tag_id]}(\"#{name}\"): " +
139
+ payload.to_formatted_s(indent) + "\n"
140
+ end
141
+ end
142
+
143
+ # NBT.txt line 57
144
+ class TagList < BinData::Record
145
+ int8 :tag_id
146
+ int32be :len, :value => lambda { data.length }
147
+ array :data, :initial_length => :len do
148
+ payload :tag_selector => :tag_id
149
+ end
150
+
151
+ def to_formatted_s(indent = 0)
152
+ pre = " " * indent
153
+ tag_type = "TAG_#{TAG_NAMES[tag_id]}"
154
+
155
+ "#{len} entries of type #{tag_type}\n" +
156
+ pre + "{\n" +
157
+ data.collect { |el| " #{pre}#{tag_type}: #{el.to_formatted_s(indent + 1)}\n" }.join("") +
158
+ pre + "}"
159
+ end
160
+ end
161
+
162
+ # NBT.txt line 63
163
+ class TagCompound < BinData::Record
164
+ array :data, :read_until => lambda { element.tag_id == 0 } do
165
+ named_tag
166
+ end
167
+
168
+ def to_formatted_s(indent = 0)
169
+ pre = " " * indent
170
+ "#{data.length - 1} entries\n" +
171
+ pre + "{\n" +
172
+ data[0..-2].collect { |el| el.to_formatted_s(indent + 1) }.join("") +
173
+ pre + "}"
174
+ end
175
+ end
176
+
177
+ # NBT.txt line 3
178
+ class Nbt < BinData::Wrapper
179
+ named_tag
180
+
181
+ def self.read(io)
182
+ require 'zlib'
183
+ super(Zlib::GzipReader.new(io))
184
+ end
185
+ end
186
+ end
187
+
188
+ if $0 == __FILE__
189
+ require 'stringio'
190
+
191
+ bigtest_nbt = StringIO.new "\037\213\b\000\000\000\000\000\000\003\355T\317O\032A\024~\302\002\313\226\202\261\304\020c\314\253\265\204\245\333\315B\021\211\261\210\026,\232\r\032\330\2501\206\270+\303\202.\273fw\260\361\324K{lz\353?\323#\177C\317\275\366\277\240\303/{i\317\275\3602\311\367\346\275o\346{o&y\002\004TrO,\016x\313\261M\215x\364\343pb>\b{\035\307\245\223\030\017\202G\335\356\204\002b\265\242\252\307xv\\W\313\250U\017\e\310\326\036j\225\206\206\r\255~X{\217\203\317\203O\203o\317\003\020n[\216>\276\2458Ld\375\020\352\332t\246\#@\334f.i\341\265\323\273s\372v\v)\333\v\340\357\350=\0368[\357\021\bV\365\336]\337\v@\340^\267\372d\267\004\000\214ALs\306\bUL\323 .}\244\300\310\302\020\263\272\336X\vS\243\356D\216E\0030\261'S\214L\361\351\024\243S\214\205\341\331\237\343\263\362D\201\245|3\335\330\273\307\252u\023_(\034\b\327.\321Y?\257\035\e`!Y\337\372\361\005\376\301\316\374\235\275\000\274\361@\311\370\205B@F\376\236\353\352\017\223:h\207`\273\35327\243(\n\216\273\365\320ic\312N\333\351\354\346\346+;\275%\276dI\t=\252\273\224\375\030~\350\322\016\332o\025L\261h>+\341\233\234\204\231\274\204\005\teY\026E\000\377/(\256/\362\302\262\244.\035 wZ;\271\214\312\347)\337QA\311\026\265\305m\241*\255,\3051\177\272z\222\216^\235_\370\022\005#\e\321\366\267w\252\315\225r\274\236\337X]K\227\256\222\027\271D\320\200\310\372>\277\263\334T\313\aun\243\266vY\222\223\251\334QP\231k\3145\346\032\377W#\bB\313\351\e\326x\302\354\376\374z\373}x\323\204\337\324\362\244\373\b\006\000\000"
192
+
193
+ nbt = Nbt::Nbt.read(bigtest_nbt)
194
+ puts nbt.to_formatted_s
195
+ end