python-pickle 0.1.1 → 0.2.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +12 -0
  3. data/README.md +2 -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 +38 -32
  22. data/spec/deserializer_spec.rb +308 -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/protocol0_read_instruction_examples.rb +44 -0
  38. 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