python-pickle 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +17 -0
  3. data/README.md +4 -1
  4. data/lib/python/pickle/deserializer.rb +142 -80
  5. data/lib/python/pickle/instructions/bin_persid.rb +31 -0
  6. data/lib/python/pickle/instructions/global.rb +11 -41
  7. data/lib/python/pickle/instructions/has_namespace_and_name.rb +61 -0
  8. data/lib/python/pickle/instructions/inst.rb +34 -0
  9. data/lib/python/pickle/instructions/next_buffer.rb +5 -1
  10. data/lib/python/pickle/instructions/obj.rb +30 -0
  11. data/lib/python/pickle/instructions/persid.rb +31 -0
  12. data/lib/python/pickle/instructions/readonly_buffer.rb +4 -0
  13. data/lib/python/pickle/instructions.rb +64 -0
  14. data/lib/python/pickle/protocol0.rb +313 -68
  15. data/lib/python/pickle/protocol1.rb +225 -93
  16. data/lib/python/pickle/protocol2.rb +205 -124
  17. data/lib/python/pickle/protocol3.rb +92 -123
  18. data/lib/python/pickle/protocol4.rb +188 -165
  19. data/lib/python/pickle/protocol5.rb +98 -166
  20. data/lib/python/pickle/version.rb +1 -1
  21. data/lib/python/pickle.rb +71 -39
  22. data/spec/deserializer_spec.rb +359 -0
  23. data/spec/fixtures/set_v0.pkl +11 -0
  24. data/spec/fixtures/set_v1.pkl +0 -0
  25. data/spec/fixtures/set_v2.pkl +0 -0
  26. data/spec/fixtures/set_v3.pkl +0 -0
  27. data/spec/fixtures/set_v4.pkl +0 -0
  28. data/spec/fixtures/set_v5.pkl +0 -0
  29. data/spec/generate_pickles2.py +1 -0
  30. data/spec/generate_pickles3.py +1 -0
  31. data/spec/integration/load/protocol0_spec.rb +10 -0
  32. data/spec/integration/load/protocol1_spec.rb +10 -0
  33. data/spec/integration/load/protocol2_spec.rb +10 -0
  34. data/spec/integration/load/protocol3_spec.rb +10 -0
  35. data/spec/integration/load/protocol4_spec.rb +10 -0
  36. data/spec/integration/load/protocol5_spec.rb +10 -0
  37. data/spec/pickle_spec.rb +61 -0
  38. data/spec/protocol0_read_instruction_examples.rb +44 -0
  39. metadata +14 -2
@@ -5,13 +5,19 @@ require 'python/pickle/instructions/short_bin_bytes'
5
5
  module Python
6
6
  module Pickle
7
7
  class Protocol3 < Protocol2
8
- # Opcodes for Pickle protocol version 2.
8
+ # The `BINBYTES` opcode.
9
9
  #
10
- # @see http://formats.kaitai.io/python_pickle/ruby.html
11
- OPCODES = Protocol2::OPCODES + Set[
12
- 66, # BINBYTES
13
- 67 # SHORT_BINBYTES
14
- ]
10
+ # @since 0.2.0
11
+ #
12
+ # @see https://github.com/python/cpython/blob/v3.10.9/Lib/pickle.py#L175
13
+ BINBYTES = 66
14
+
15
+ # The `SHORT_BINBYTES` opcode.
16
+ #
17
+ # @since 0.2.0
18
+ #
19
+ # @see https://github.com/python/cpython/blob/v3.10.9/Lib/pickle.py#L176
20
+ SHORT_BINBYTES = 67
15
21
 
16
22
  #
17
23
  # Reads an instruction from the pickle stream.
@@ -27,137 +33,100 @@ module Python
27
33
  #
28
34
  # Protocol 0 instructions
29
35
  #
30
- when 40 # MARK
31
- Instructions::MARK
32
- when 46 # STOP
33
- Instructions::STOP
34
- when 48 # POP
35
- Instructions::POP
36
- when 49 # POP_MARK
37
- Instructions::POP_MARK
38
- when 50 # DUP
39
- Instructions::DUP
40
- when 70 # FLOAT
41
- Instructions::Float.new(read_float)
42
- when 73 # INT
43
- Instructions::Int.new(read_int)
44
- when 76 # LONG
45
- Instructions::Long.new(read_long)
46
- when 78 # NONE
47
- Instructions::NONE
48
- when 82 # REDUCE
49
- Instructions::REDUCE
50
- when 83 # STRING
51
- Instructions::String.new(read_string)
52
- when 86 # UNICODE
53
- Instructions::String.new(read_unicode_string)
54
- when 97 # APPEND
55
- Instructions::APPEND
56
- when 98 # BUILD
57
- Instructions::BUILD
58
- when 99 # GLOBAL
59
- Instructions::Global.new(read_nl_string,read_nl_string)
60
- when 100 # DICT
61
- Instructions::DICT
62
- when 103 # GET
63
- Instructions::Get.new(read_int)
64
- when 108 # LIST
65
- Instructions::LIST
66
- when 112 # PUT
67
- Instructions::Put.new(read_int)
68
- when 115 # SETITEM
69
- Instructions::SETITEM
70
- when 116 # TUPLE
71
- Instructions::TUPLE
36
+ when MARK then Instructions::MARK
37
+ when STOP then Instructions::STOP
38
+ when POP then Instructions::POP
39
+ when POP_MARK then Instructions::POP_MARK
40
+ when DUP then Instructions::DUP
41
+ when FLOAT then read_float_instruction
42
+ when INT then read_int_instruction
43
+ when LONG then read_long_instruction
44
+ when NONE then Instructions::NONE
45
+ when REDUCE then Instructions::REDUCE
46
+ when STRING then read_string_instruction
47
+ when UNICODE then read_unicode_instruction
48
+ when APPEND then Instructions::APPEND
49
+ when BUILD then Instructions::BUILD
50
+ when GLOBAL then read_global_instruction
51
+ when DICT then Instructions::DICT
52
+ when GET then read_get_instruction
53
+ when LIST then Instructions::LIST
54
+ when PUT then read_put_instruction
55
+ when SETITEM then Instructions::SETITEM
56
+ when TUPLE then Instructions::TUPLE
57
+ when INST then read_inst_instruction
58
+ when OBJ then Instructions::OBJ
59
+ when PERSID then read_persid_instruction
60
+ when BINPERSID then Instructions::BINPERSID
72
61
  #
73
62
  # Protocol 1 instructions
74
63
  #
75
- when 41 # EMPTY_TUPLE
76
- Instructions::EMPTY_TUPLE
77
- when 71 # BINFLOAT
78
- Instructions::BinFloat.new(read_float64_be)
79
- when 75 # BININT1
80
- Instructions::BinInt1.new(read_uint8)
81
- when 84 # BINSTRING
82
- length = read_uint32_le
83
- string = @io.read(length)
84
-
85
- Instructions::BinString.new(length,string)
86
- when 85 # SHORT_BINSTRING
87
- length = read_uint8
88
- string = @io.read(length)
89
-
90
- Instructions::ShortBinString.new(length,string)
91
- when 88 # BINUNICODE
92
- length = read_uint32_le
93
- string = @io.read(length).force_encoding(Encoding::UTF_8)
94
-
95
- Instructions::BinUnicode.new(length,string)
96
- when 93 # EMPTY_LIST
97
- Instructions::EMPTY_LIST
98
- when 101 # APPENDS
99
- Instructions::APPENDS
100
- when 104 # BINGET
101
- Instructions::BinGet.new(read_uint8)
102
- when 106 # LONG_BINGET
103
- Instructions::LongBinGet.new(read_uint32_le)
104
- when 113 # BINPUT
105
- Instructions::BinPut.new(read_uint8)
106
- when 117 # SETITEMS
107
- Instructions::SETITEMS
108
- when 125 # EMPTY_DICT
109
- Instructions::EMPTY_DICT
64
+ when EMPTY_TUPLE then Instructions::EMPTY_TUPLE
65
+ when BINFLOAT then read_binfloat_instruction
66
+ when BININT1 then read_binint1_instruction
67
+ when BINSTRING then read_binstring_instruction
68
+ when SHORT_BINSTRING then read_short_binstring_instruction
69
+ when BINUNICODE then read_binunicode_instruction
70
+ when EMPTY_LIST then Instructions::EMPTY_LIST
71
+ when APPENDS then Instructions::APPENDS
72
+ when BINGET then read_binget_instruction
73
+ when LONG_BINGET then read_long_binget_instruction
74
+ when BINPUT then read_binput_instruction
75
+ when SETITEMS then Instructions::SETITEMS
76
+ when EMPTY_DICT then Instructions::EMPTY_DICT
110
77
  #
111
78
  # Protocol 2 instructions
112
79
  #
113
- when 128 # PROT
114
- Instructions::Proto.new(read_uint8)
115
- when 129 # NEWOBJ
116
- Instructions::NEWOBJ
117
- when 130 # EXT1
118
- Instructions::Ext1.new(read_uint8)
119
- when 131 # EXT2
120
- Instructions::Ext2.new(read_uint16_le)
121
- when 132 # EXT4
122
- Instructions::Ext4.new(read_uint32_le)
123
- when 133 # TUPLE1
124
- Instructions::TUPLE1
125
- when 134 # TUPLE2
126
- Instructions::TUPLE2
127
- when 135 # TUPLE3
128
- Instructions::TUPLE3
129
- when 136 # NEWTRUE
130
- Instructions::NEWTRUE
131
- when 137 # NEWFALSE
132
- Instructions::NEWFALSE
133
- when 138 # LONG1
134
- length = read_uint8
135
- long = read_int_le(length)
136
-
137
- Instructions::Long1.new(length,long)
138
- when 139 # LONG4
139
- length = read_uint32_le
140
- long = read_int_le(length)
141
-
142
- Instructions::Long4.new(length,long)
80
+ when PROTO then read_proto_instruction
81
+ when NEWOBJ then Instructions::NEWOBJ
82
+ when EXT1 then read_ext1_instruction
83
+ when EXT2 then read_ext2_instruction
84
+ when EXT4 then read_ext4_instruction
85
+ when TUPLE1 then Instructions::TUPLE1
86
+ when TUPLE2 then Instructions::TUPLE2
87
+ when TUPLE3 then Instructions::TUPLE3
88
+ when NEWTRUE then Instructions::NEWTRUE
89
+ when NEWFALSE then Instructions::NEWFALSE
90
+ when LONG1 then read_long1_instruction
91
+ when LONG4 then read_long4_instruction
143
92
  #
144
93
  # Protocol 3 instructions
145
94
  #
146
- when 66 # BINBYTES
147
- length = read_uint32_le
148
- bytes = @io.read(length)
149
-
150
- Instructions::BinBytes.new(length,bytes)
151
- when 67 # SHORT_BINBYTES
152
- length = read_uint8
153
- bytes = @io.read(length)
154
-
155
- Instructions::ShortBinBytes.new(length,bytes)
95
+ when BINBYTES then read_binbytes_instruction
96
+ when SHORT_BINBYTES then read_short_binbytes_instruction
156
97
  else
157
98
  raise(InvalidFormat,"invalid opcode (#{opcode.inspect}) for protocol 3")
158
99
  end
159
100
  end
160
101
 
102
+ #
103
+ # Reads a `BINBYTES` instruction.
104
+ #
105
+ # @return [Instructions::BinBytes]
106
+ #
107
+ # @since 0.2.0
108
+ #
109
+ def read_binbytes_instruction
110
+ length = read_uint32_le
111
+ bytes = @io.read(length)
112
+
113
+ Instructions::BinBytes.new(length,bytes)
114
+ end
115
+
116
+ #
117
+ # Reads a `SHORT_BINBYTES` instruction.
118
+ #
119
+ # @return [Instructions::ShortBinBytes]
120
+ #
121
+ # @since 0.2.0
122
+ #
123
+ def read_short_binbytes_instruction
124
+ length = read_uint8
125
+ bytes = @io.read(length)
126
+
127
+ Instructions::ShortBinBytes.new(length,bytes)
128
+ end
129
+
161
130
  end
162
131
  end
163
132
  end
@@ -26,21 +26,75 @@ module Python
26
26
  @io_stack = []
27
27
  end
28
28
 
29
- # Opcodes for Pickle protocol 4.
30
- #
31
- # @see https://peps.python.org/pep-3154/
32
- OPCODES = Protocol3::OPCODES + Set[
33
- 140, # SHORT_BINUNICODE
34
- 141, # BINUNICODE8
35
- 142, # BINBYTES8
36
- 143, # EMPTY_SET
37
- 144, # ADDITEMS
38
- 145, # FROZENSET
39
- 146, # NEWOBJ_EX
40
- 147, # STACK_GLOBAL
41
- 148, # MEMOIZE
42
- 149 # FRAME
43
- ]
29
+ # The `SHORT_BINUNICODE` opcode.
30
+ #
31
+ # @since 0.2.0
32
+ #
33
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L180
34
+ SHORT_BINUNICODE = 140
35
+
36
+ # The `BINUNICODE8` opcode.
37
+ #
38
+ # @since 0.2.0
39
+ #
40
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L181
41
+ BINUNICODE8 = 141
42
+
43
+ # The `BINBYTES` opcode.
44
+ #
45
+ # @since 0.2.0
46
+ #
47
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L182
48
+ BINBYTES8 = 142
49
+
50
+ # The `EMPTY_SET` opcode.
51
+ #
52
+ # @since 0.2.0
53
+ #
54
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L183
55
+ EMPTY_SET = 143
56
+
57
+ # The `ADDITEMS` opcode.
58
+ #
59
+ # @since 0.2.0
60
+ #
61
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L184
62
+ ADDITEMS = 144
63
+
64
+ # The `FROZENSET` opcode.
65
+ #
66
+ # @since 0.2.0
67
+ #
68
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L185
69
+ FROZENSET = 145
70
+
71
+ # The `NEWOBJ_EX` opcode.
72
+ #
73
+ # @since 0.2.0
74
+ #
75
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L186
76
+ NEWOBJ_EX = 146
77
+
78
+ # The `STACK_GLOBAL` opcode.
79
+ #
80
+ # @since 0.2.0
81
+ #
82
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L187
83
+ STACK_GLOBAL = 147
84
+
85
+ # The `MEMOIZE` opcode.
86
+ #
87
+ # @since 0.2.0
88
+ #
89
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L188
90
+ MEMOIZE = 148
91
+
92
+ # The `FRAME` opcode.
93
+ #
94
+ # @since 0.2.0
95
+ #
96
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L189
97
+ FRAME = 149
44
98
 
45
99
  #
46
100
  # Reads an instruction from the pickle stream.
@@ -56,168 +110,80 @@ module Python
56
110
  #
57
111
  # Protocol 0 instructions
58
112
  #
59
- when 40 # MARK
60
- Instructions::MARK
61
- when 46 # STOP
62
- Instructions::STOP
63
- when 48 # POP
64
- Instructions::POP
65
- when 49 # POP_MARK
66
- Instructions::POP_MARK
67
- when 50 # DUP
68
- Instructions::DUP
69
- when 70 # FLOAT
70
- Instructions::Float.new(read_float)
71
- when 73 # INT
72
- Instructions::Int.new(read_int)
73
- when 76 # LONG
74
- Instructions::Long.new(read_long)
75
- when 78 # NONE
76
- Instructions::NONE
77
- when 82 # REDUCE
78
- Instructions::REDUCE
79
- when 83 # STRING
80
- Instructions::String.new(read_string)
81
- when 86 # UNICODE
82
- Instructions::String.new(read_unicode_string)
83
- when 97 # APPEND
84
- Instructions::APPEND
85
- when 98 # BUILD
86
- Instructions::BUILD
87
- when 99 # GLOBAL
88
- Instructions::Global.new(read_nl_string,read_nl_string)
89
- when 100 # DICT
90
- Instructions::DICT
91
- when 103 # GET
92
- Instructions::Get.new(read_int)
93
- when 108 # LIST
94
- Instructions::LIST
95
- when 112 # PUT
96
- Instructions::Put.new(read_int)
97
- when 115 # SETITEM
98
- Instructions::SETITEM
99
- when 116 # TUPLE
100
- Instructions::TUPLE
113
+ when MARK then Instructions::MARK
114
+ when STOP then Instructions::STOP
115
+ when POP then Instructions::POP
116
+ when POP_MARK then Instructions::POP_MARK
117
+ when DUP then Instructions::DUP
118
+ when FLOAT then read_float_instruction
119
+ when INT then read_int_instruction
120
+ when LONG then read_long_instruction
121
+ when NONE then Instructions::NONE
122
+ when REDUCE then Instructions::REDUCE
123
+ when STRING then read_string_instruction
124
+ when UNICODE then read_unicode_instruction
125
+ when APPEND then Instructions::APPEND
126
+ when BUILD then Instructions::BUILD
127
+ when GLOBAL then read_global_instruction
128
+ when DICT then Instructions::DICT
129
+ when GET then read_get_instruction
130
+ when LIST then Instructions::LIST
131
+ when PUT then read_put_instruction
132
+ when SETITEM then Instructions::SETITEM
133
+ when TUPLE then Instructions::TUPLE
134
+ when INST then read_inst_instruction
135
+ when OBJ then Instructions::OBJ
136
+ when PERSID then read_persid_instruction
137
+ when BINPERSID then Instructions::BINPERSID
101
138
  #
102
139
  # Protocol 1 instructions
103
140
  #
104
- when 41 # EMPTY_TUPLE
105
- Instructions::EMPTY_TUPLE
106
- when 71 # BINFLOAT
107
- Instructions::BinFloat.new(read_float64_be)
108
- when 75 # BININT1
109
- Instructions::BinInt1.new(read_uint8)
110
- when 84 # BINSTRING
111
- length = read_uint32_le
112
- string = @io.read(length)
113
-
114
- Instructions::BinString.new(length,string)
115
- when 85 # SHORT_BINSTRING
116
- length = read_uint8
117
- string = @io.read(length)
118
-
119
- Instructions::ShortBinString.new(length,string)
120
- when 88 # BINUNICODE
121
- length = read_uint32_le
122
- string = @io.read(length).force_encoding(Encoding::UTF_8)
123
-
124
- Instructions::BinUnicode.new(length,string)
125
- when 93 # EMPTY_LIST
126
- Instructions::EMPTY_LIST
127
- when 101 # APPENDS
128
- Instructions::APPENDS
129
- when 104 # BINGET
130
- Instructions::BinGet.new(read_uint8)
131
- when 106 # LONG_BINGET
132
- Instructions::LongBinGet.new(read_uint32_le)
133
- when 113 # BINPUT
134
- Instructions::BinPut.new(read_uint8)
135
- when 117 # SETITEMS
136
- Instructions::SETITEMS
137
- when 125 # EMPTY_DICT
138
- Instructions::EMPTY_DICT
141
+ when EMPTY_TUPLE then Instructions::EMPTY_TUPLE
142
+ when BINFLOAT then read_binfloat_instruction
143
+ when BININT1 then read_binint1_instruction
144
+ when BINSTRING then read_binstring_instruction
145
+ when SHORT_BINSTRING then read_short_binstring_instruction
146
+ when BINUNICODE then read_binunicode_instruction
147
+ when EMPTY_LIST then Instructions::EMPTY_LIST
148
+ when APPENDS then Instructions::APPENDS
149
+ when BINGET then read_binget_instruction
150
+ when LONG_BINGET then read_long_binget_instruction
151
+ when BINPUT then read_binput_instruction
152
+ when SETITEMS then Instructions::SETITEMS
153
+ when EMPTY_DICT then Instructions::EMPTY_DICT
139
154
  #
140
155
  # Protocol 2 instructions
141
156
  #
142
- when 128 # PROT
143
- Instructions::Proto.new(read_uint8)
144
- when 129 # NEWOBJ
145
- Instructions::NEWOBJ
146
- when 130 # EXT1
147
- Instructions::Ext1.new(read_uint8)
148
- when 131 # EXT2
149
- Instructions::Ext2.new(read_uint16_le)
150
- when 132 # EXT4
151
- Instructions::Ext4.new(read_uint32_le)
152
- when 133 # TUPLE1
153
- Instructions::TUPLE1
154
- when 134 # TUPLE2
155
- Instructions::TUPLE2
156
- when 135 # TUPLE3
157
- Instructions::TUPLE3
158
- when 136 # NEWTRUE
159
- Instructions::NEWTRUE
160
- when 137 # NEWFALSE
161
- Instructions::NEWFALSE
162
- when 138 # LONG1
163
- length = read_uint8
164
- long = read_int_le(length)
165
-
166
- Instructions::Long1.new(length,long)
167
- when 139 # LONG4
168
- length = read_uint32_le
169
- long = read_int_le(length)
170
-
171
- Instructions::Long4.new(length,long)
157
+ when PROTO then read_proto_instruction
158
+ when NEWOBJ then Instructions::NEWOBJ
159
+ when EXT1 then read_ext1_instruction
160
+ when EXT2 then read_ext2_instruction
161
+ when EXT4 then read_ext4_instruction
162
+ when TUPLE1 then Instructions::TUPLE1
163
+ when TUPLE2 then Instructions::TUPLE2
164
+ when TUPLE3 then Instructions::TUPLE3
165
+ when NEWTRUE then Instructions::NEWTRUE
166
+ when NEWFALSE then Instructions::NEWFALSE
167
+ when LONG1 then read_long1_instruction
168
+ when LONG4 then read_long4_instruction
172
169
  #
173
170
  # Protocol 3 instructions
174
171
  #
175
- when 66 # BINBYTES
176
- length = read_uint32_le
177
- bytes = @io.read(length)
178
-
179
- Instructions::BinBytes.new(length,bytes)
180
- when 67 # SHORT_BINBYTES
181
- length = read_uint8
182
- bytes = @io.read(length)
183
-
184
- Instructions::ShortBinBytes.new(length,bytes)
172
+ when BINBYTES then read_binbytes_instruction
173
+ when SHORT_BINBYTES then read_short_binbytes_instruction
185
174
  #
186
175
  # Protocol 4 instructions
187
176
  #
188
- when 140 # SHORT_BINUNICODE
189
- length = read_uint8
190
- string = read_utf8_string(length)
191
-
192
- Instructions::ShortBinUnicode.new(length,string)
193
- when 141 # BINUNICODE8
194
- length = read_uint64_le
195
- string = read_utf8_string(length)
196
-
197
- Instructions::BinUnicode8.new(length,string)
198
- when 142 # BINBYTES8
199
- length = read_uint64_le
200
- bytes = @io.read(length)
201
-
202
- Instructions::BinBytes8.new(length,bytes)
203
- when 143 # EMPTY_SET
204
- Instructions::EMPTY_SET
205
- when 144 # ADDITEMS
206
- Instructions::ADDITEMS
207
- when 145 # FROZENSET
208
- Instructions::FROZENSET
209
- when 146 # NEWOBJ_EX
210
- Instructions::NEWOBJ_EX
211
- when 147 # STACK_GLOBAL
212
- Instructions::STACK_GLOBAL
213
- when 148 # MEMOIZE
214
- Instructions::MEMOIZE
215
- when 149 # FRAME
216
- length = read_uint64_le
217
-
218
- enter_frame(read_frame(length))
219
-
220
- Instructions::Frame.new(length)
177
+ when SHORT_BINUNICODE then read_short_binunicode_instruction
178
+ when BINUNICODE8 then read_binunicode8_instruction
179
+ when BINBYTES8 then read_binbytes8_instruction
180
+ when EMPTY_SET then Instructions::EMPTY_SET
181
+ when ADDITEMS then Instructions::ADDITEMS
182
+ when FROZENSET then Instructions::FROZENSET
183
+ when NEWOBJ_EX then Instructions::NEWOBJ_EX
184
+ when STACK_GLOBAL then Instructions::STACK_GLOBAL
185
+ when MEMOIZE then Instructions::MEMOIZE
186
+ when FRAME then read_frame_instruction
221
187
  else
222
188
  raise(InvalidFormat,"invalid opcode (#{opcode.inspect}) for protocol 4")
223
189
  end
@@ -280,6 +246,63 @@ module Python
280
246
  @io = @io_stack.pop
281
247
  end
282
248
 
249
+ #
250
+ # Reads a `SHORT_BINUNICODE` instruction.
251
+ #
252
+ # @return [Instructions::ShortBinUnicode]
253
+ #
254
+ # @since 0.2.0
255
+ #
256
+ def read_short_binunicode_instruction
257
+ length = read_uint8
258
+ string = read_utf8_string(length)
259
+
260
+ Instructions::ShortBinUnicode.new(length,string)
261
+ end
262
+
263
+ #
264
+ # Reads a `BINUNICODE8` instruction.
265
+ #
266
+ # @return [Instructions::BinUnicode8]
267
+ #
268
+ # @since 0.2.0
269
+ #
270
+ def read_binunicode8_instruction
271
+ length = read_uint64_le
272
+ string = read_utf8_string(length)
273
+
274
+ Instructions::BinUnicode8.new(length,string)
275
+ end
276
+
277
+ #
278
+ # Reads a `BINBYTES8` instruction.
279
+ #
280
+ # @return [Instructions::BinBytes8]
281
+ #
282
+ # @since 0.2.0
283
+ #
284
+ def read_binbytes8_instruction
285
+ length = read_uint64_le
286
+ bytes = @io.read(length)
287
+
288
+ Instructions::BinBytes8.new(length,bytes)
289
+ end
290
+
291
+ #
292
+ # Reads a `FRAME` instruction.
293
+ #
294
+ # @return [Instructions::Frame]
295
+ #
296
+ # @since 0.2.0
297
+ #
298
+ def read_frame_instruction
299
+ length = read_uint64_le
300
+
301
+ enter_frame(read_frame(length))
302
+
303
+ Instructions::Frame.new(length)
304
+ end
305
+
283
306
  end
284
307
  end
285
308
  end