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
@@ -33,22 +33,96 @@ module Python
33
33
  #
34
34
  class Protocol1 < Protocol0
35
35
 
36
- # Opcodes for Pickle protocol version 1.
37
- #
38
- # @see https://github.com/python/cpython/blob/main/Lib/pickletools.py
39
- OPCODES = Protocol0::OPCODES + Set[
40
- 41, # EMPTY_TUPLE
41
- 71, # BINFLOAT
42
- 75, # BININT1
43
- 84, # BINSTRING
44
- 85, # SHORT_BINSTRING
45
- 88, # BINUNICODE
46
- 93, # EMPTY_LIST
47
- 101, # APPENDS
48
- 113, # BINPUT
49
- 117, # SETITEMS
50
- 125 # EMPTY_DICT
51
- ]
36
+ # The `EMPTY_TUPLE` opcode.
37
+ #
38
+ # @since 0.2.0
39
+ #
40
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L140
41
+ EMPTY_TUPLE = 41
42
+
43
+ # The `BINFLOAT` opcode.
44
+ #
45
+ # @since 0.2.0
46
+ #
47
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L142
48
+ BINFLOAT = 71
49
+
50
+ # The `BININT1` opcode.
51
+ #
52
+ # @since 0.2.0
53
+ #
54
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L110
55
+ BININT1 = 75
56
+
57
+ # The `BINSTRING` opcode.
58
+ #
59
+ # @since 0.2.0
60
+ #
61
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L118
62
+ BINSTRING = 84
63
+
64
+ # The `SHORT_BINSTRING` opcode.
65
+ #
66
+ # @since 0.2.0
67
+ #
68
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L119
69
+ SHORT_BINSTRING = 85
70
+
71
+ # The `BINUNICODE` opcode.
72
+ #
73
+ # @since 0.2.0
74
+ #
75
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L121
76
+ BINUNICODE = 88
77
+
78
+ # The `EMPTY_LIST` opcode.
79
+ #
80
+ # @since 0.2.0
81
+ #
82
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L133
83
+ EMPTY_LIST = 93
84
+
85
+ # The `APPENDS` opcode.
86
+ #
87
+ # @since 0.2.0
88
+ #
89
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L127
90
+ APPENDS = 101
91
+
92
+ # The `BINGET` opcode.
93
+ #
94
+ # @since 0.2.0
95
+ #
96
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L138
97
+ BINGET = 104
98
+
99
+ # The `LONG_BINGET` opcode.
100
+ #
101
+ # @since 0.2.0
102
+ #
103
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L140
104
+ LONG_BINGET = 106
105
+
106
+ # The `BINPUT` opcode.
107
+ #
108
+ # @since 0.2.0
109
+ #
110
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L145
111
+ BINPUT = 113
112
+
113
+ # The `SETITEMS` opcode.
114
+ #
115
+ # @since 0.2.0
116
+ #
117
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L141
118
+ SETITEMS = 117
119
+
120
+ # The `EMPTY_DICT` opcode.
121
+ #
122
+ # @since 0.2.0
123
+ #
124
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L126
125
+ EMPTY_DICT = 125
52
126
 
53
127
  #
54
128
  # Reads an instruction from the pickle stream.
@@ -64,86 +138,47 @@ module Python
64
138
  #
65
139
  # Protocol 0 instructions
66
140
  #
67
- when 40 # MARK
68
- Instructions::MARK
69
- when 46 # STOP
70
- Instructions::STOP
71
- when 48 # POP
72
- Instructions::POP
73
- when 49 # POP_MARK
74
- Instructions::POP_MARK
75
- when 50 # DUP
76
- Instructions::DUP
77
- when 70 # FLOAT
78
- Instructions::Float.new(read_float)
79
- when 73 # INT
80
- Instructions::Int.new(read_int)
81
- when 76 # LONG
82
- Instructions::Long.new(read_long)
83
- when 78 # NONE
84
- Instructions::NONE
85
- when 82 # REDUCE
86
- Instructions::REDUCE
87
- when 83 # STRING
88
- Instructions::String.new(read_string)
89
- when 86 # UNICODE
90
- Instructions::String.new(read_unicode_string)
91
- when 97 # APPEND
92
- Instructions::APPEND
93
- when 98 # BUILD
94
- Instructions::BUILD
95
- when 99 # GLOBAL
96
- Instructions::Global.new(read_nl_string,read_nl_string)
97
- when 100 # DICT
98
- Instructions::DICT
99
- when 103 # GET
100
- Instructions::Get.new(read_int)
101
- when 108 # LIST
102
- Instructions::LIST
103
- when 112 # PUT
104
- Instructions::Put.new(read_int)
105
- when 115 # SETITEM
106
- Instructions::SETITEM
107
- when 116 # TUPLE
108
- Instructions::TUPLE
141
+ when MARK then Instructions::MARK
142
+ when STOP then Instructions::STOP
143
+ when POP then Instructions::POP
144
+ when POP_MARK then Instructions::POP_MARK
145
+ when DUP then Instructions::DUP
146
+ when FLOAT then read_float_instruction
147
+ when INT then read_int_instruction
148
+ when LONG then read_long_instruction
149
+ when NONE then Instructions::NONE
150
+ when REDUCE then Instructions::REDUCE
151
+ when STRING then read_string_instruction
152
+ when UNICODE then read_unicode_instruction
153
+ when APPEND then Instructions::APPEND
154
+ when BUILD then Instructions::BUILD
155
+ when GLOBAL then read_global_instruction
156
+ when DICT then Instructions::DICT
157
+ when GET then read_get_instruction
158
+ when LIST then Instructions::LIST
159
+ when PUT then read_put_instruction
160
+ when SETITEM then Instructions::SETITEM
161
+ when TUPLE then Instructions::TUPLE
162
+ when INST then read_inst_instruction
163
+ when OBJ then Instructions::OBJ
164
+ when PERSID then read_persid_instruction
165
+ when BINPERSID then Instructions::BINPERSID
109
166
  #
110
167
  # Protocol 1 instructions
111
168
  #
112
- when 41 # EMPTY_TUPLE
113
- Instructions::EMPTY_TUPLE
114
- when 71 # BINFLOAT
115
- Instructions::BinFloat.new(read_float64_be)
116
- when 75 # BININT1
117
- Instructions::BinInt1.new(read_uint8)
118
- when 84 # BINSTRING
119
- length = read_uint32_le
120
- string = @io.read(length)
121
-
122
- Instructions::BinString.new(length,string)
123
- when 85 # SHORT_BINSTRING
124
- length = read_uint8
125
- string = @io.read(length)
126
-
127
- Instructions::ShortBinString.new(length,string)
128
- when 88 # BINUNICODE
129
- length = read_uint32_le
130
- string = @io.read(length).force_encoding(Encoding::UTF_8)
131
-
132
- Instructions::BinUnicode.new(length,string)
133
- when 93 # EMPTY_LIST
134
- Instructions::EMPTY_LIST
135
- when 101 # APPENDS
136
- Instructions::APPENDS
137
- when 104 # BINGET
138
- Instructions::BinGet.new(read_uint8)
139
- when 106 # LONG_BINGET
140
- Instructions::LongBinGet.new(read_uint32_le)
141
- when 113 # BINPUT
142
- Instructions::BinPut.new(read_uint8)
143
- when 117 # SETITEMS
144
- Instructions::SETITEMS
145
- when 125 # EMPTY_DICT
146
- Instructions::EMPTY_DICT
169
+ when EMPTY_TUPLE then Instructions::EMPTY_TUPLE
170
+ when BINFLOAT then read_binfloat_instruction
171
+ when BININT1 then read_binint1_instruction
172
+ when BINSTRING then read_binstring_instruction
173
+ when SHORT_BINSTRING then read_short_binstring_instruction
174
+ when BINUNICODE then read_binunicode_instruction
175
+ when EMPTY_LIST then Instructions::EMPTY_LIST
176
+ when APPENDS then Instructions::APPENDS
177
+ when BINGET then read_binget_instruction
178
+ when LONG_BINGET then read_long_binget_instruction
179
+ when BINPUT then read_binput_instruction
180
+ when SETITEMS then Instructions::SETITEMS
181
+ when EMPTY_DICT then Instructions::EMPTY_DICT
147
182
  else
148
183
  raise(InvalidFormat,"invalid opcode (#{opcode.inspect}) for protocol 1")
149
184
  end
@@ -178,6 +213,103 @@ module Python
178
213
  @io.read(4).unpack1('L<')
179
214
  end
180
215
 
216
+ #
217
+ # Reads a `BINFLOAT` instruction.
218
+ #
219
+ # @return [Instructions::BinFloat]
220
+ #
221
+ # @since 0.2.0
222
+ #
223
+ def read_binfloat_instruction
224
+ Instructions::BinFloat.new(read_float64_be)
225
+ end
226
+
227
+ #
228
+ # Reads a `BININT1` instruction.
229
+ #
230
+ # @return [Instructions::BinInt1]
231
+ #
232
+ # @since 0.2.0
233
+ #
234
+ def read_binint1_instruction
235
+ Instructions::BinInt1.new(read_uint8)
236
+ end
237
+
238
+ #
239
+ # Reads a `BINSTRING` instruction.
240
+ #
241
+ # @return [Instructions::BinString]
242
+ #
243
+ # @since 0.2.0
244
+ #
245
+ def read_binstring_instruction
246
+ length = read_uint32_le
247
+ string = @io.read(length)
248
+
249
+ Instructions::BinString.new(length,string)
250
+ end
251
+
252
+ #
253
+ # Reads a `SHORT_BINSTRING` instruction.
254
+ #
255
+ # @return [Instructions::ShortBinString]
256
+ #
257
+ # @since 0.2.0
258
+ #
259
+ def read_short_binstring_instruction
260
+ length = read_uint8
261
+ string = @io.read(length)
262
+
263
+ Instructions::ShortBinString.new(length,string)
264
+ end
265
+
266
+ #
267
+ # Reads a `BINUNICODE` instruction.
268
+ #
269
+ # @return [Instructions::BinUnicode]
270
+ #
271
+ # @since 0.2.0
272
+ #
273
+ def read_binunicode_instruction
274
+ length = read_uint32_le
275
+ string = @io.read(length).force_encoding(Encoding::UTF_8)
276
+
277
+ Instructions::BinUnicode.new(length,string)
278
+ end
279
+
280
+ #
281
+ # Reads a `BINGET` instruction.
282
+ #
283
+ # @return [Instructions::BinGet]
284
+ #
285
+ # @since 0.2.0
286
+ #
287
+ def read_binget_instruction
288
+ Instructions::BinGet.new(read_uint8)
289
+ end
290
+
291
+ #
292
+ # Reads a `LONG_BINGET` instruction.
293
+ #
294
+ # @return [Instructions::LongBinGet]
295
+ #
296
+ # @since 0.2.0
297
+ #
298
+ def read_long_binget_instruction
299
+ Instructions::LongBinGet.new(read_uint32_le)
300
+ end
301
+
302
+ #
303
+ # Reads a `BINPUT` instruction.
304
+ #
305
+ # @return [Instructions::BinPut]
306
+ #
307
+ # @since 0.2.0
308
+ #
309
+ def read_binput_instruction
310
+ Instructions::BinPut.new(read_uint8)
311
+ end
312
+
181
313
  end
182
314
  end
183
315
  end
@@ -16,23 +16,89 @@ module Python
16
16
  module Pickle
17
17
  class Protocol2 < Protocol1
18
18
 
19
- # Opcodes for Pickle protocol version 2.
20
- #
21
- # @see https://github.com/python/cpython/blob/main/Lib/pickletools.py
22
- OPCODES = Protocol1::OPCODES + Set[
23
- 128, # PROTO
24
- 129, # NEWOBJ
25
- 130, # EXT1
26
- 131, # EXT2
27
- 132, # EXT4
28
- 133, # TUPLE1
29
- 134, # TUPLE2
30
- 135, # TUPLE3
31
- 136, # NEWTRUE
32
- 137, # NEWFALSE
33
- 138, # LONG1
34
- 139 # LONG4
35
- ]
19
+ # The `PROTO` opcode.
20
+ #
21
+ # @since 0.2.0
22
+ #
23
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L149
24
+ PROTO = 128
25
+
26
+ # The `NEWOBJ` opcode.
27
+ #
28
+ # @since 0.2.0
29
+ #
30
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L150
31
+ NEWOBJ = 129
32
+
33
+ # The `EXT1` opcode.
34
+ #
35
+ # @since 0.2.0
36
+ #
37
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L151
38
+ EXT1 = 130
39
+
40
+ # The `EXT2` opcode.
41
+ #
42
+ # @since 0.2.0
43
+ #
44
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L152
45
+ EXT2 = 131
46
+
47
+ # The `EXT4` opcode.
48
+ #
49
+ # @since 0.2.0
50
+ #
51
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L153
52
+ EXT4 = 132
53
+
54
+ # The `TUPLE1` opcode.
55
+ #
56
+ # @since 0.2.0
57
+ #
58
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L154
59
+ TUPLE1 = 133
60
+
61
+ # The `TUPLE2` opcode.
62
+ #
63
+ # @since 0.2.0
64
+ #
65
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L155
66
+ TUPLE2 = 134
67
+
68
+ # The `TUPLE3` opcode.
69
+ #
70
+ # @since 0.2.0
71
+ #
72
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L156
73
+ TUPLE3 = 135
74
+
75
+ # The `NEWTRUE` opcode.
76
+ #
77
+ # @since 0.2.0
78
+ #
79
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L157
80
+ NEWTRUE = 136
81
+
82
+ # The `NEWFALSE` opcode.
83
+ #
84
+ # @since 0.2.0
85
+ #
86
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L158
87
+ NEWFALSE = 137
88
+
89
+ # The `LONG1` opcode.
90
+ #
91
+ # @since 0.2.0
92
+ #
93
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L159
94
+ LONG1 = 138
95
+
96
+ # The `LONG4` opcode.
97
+ #
98
+ # @since 0.2.0
99
+ #
100
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L160
101
+ LONG4 = 139
36
102
 
37
103
  #
38
104
  # Reads an instruction from the pickle stream.
@@ -48,119 +114,62 @@ module Python
48
114
  #
49
115
  # Protocol 0 instructions
50
116
  #
51
- when 40 # MARK
52
- Instructions::MARK
53
- when 46 # STOP
54
- Instructions::STOP
55
- when 48 # POP
56
- Instructions::POP
57
- when 49 # POP_MARK
58
- Instructions::POP_MARK
59
- when 50 # DUP
60
- Instructions::DUP
61
- when 70 # FLOAT
62
- Instructions::Float.new(read_float)
63
- when 73 # INT
64
- Instructions::Int.new(read_int)
65
- when 76 # LONG
66
- Instructions::Long.new(read_long)
67
- when 78 # NONE
68
- Instructions::NONE
69
- when 82 # REDUCE
70
- Instructions::REDUCE
71
- when 83 # STRING
72
- Instructions::String.new(read_string)
73
- when 86 # UNICODE
74
- Instructions::String.new(read_unicode_string)
75
- when 97 # APPEND
76
- Instructions::APPEND
77
- when 98 # BUILD
78
- Instructions::BUILD
79
- when 99 # GLOBAL
80
- Instructions::Global.new(read_nl_string,read_nl_string)
81
- when 100 # DICT
82
- Instructions::DICT
83
- when 103 # GET
84
- Instructions::Get.new(read_int)
85
- when 108 # LIST
86
- Instructions::LIST
87
- when 112 # PUT
88
- Instructions::Put.new(read_int)
89
- when 115 # SETITEM
90
- Instructions::SETITEM
91
- when 116 # TUPLE
92
- Instructions::TUPLE
117
+ when MARK then Instructions::MARK
118
+ when STOP then Instructions::STOP
119
+ when POP then Instructions::POP
120
+ when POP_MARK then Instructions::POP_MARK
121
+ when DUP then Instructions::DUP
122
+ when FLOAT then read_float_instruction
123
+ when INT then read_int_instruction
124
+ when LONG then read_long_instruction
125
+ when NONE then Instructions::NONE
126
+ when REDUCE then Instructions::REDUCE
127
+ when STRING then read_string_instruction
128
+ when UNICODE then read_unicode_instruction
129
+ when APPEND then Instructions::APPEND
130
+ when BUILD then Instructions::BUILD
131
+ when GLOBAL then read_global_instruction
132
+ when DICT then Instructions::DICT
133
+ when GET then read_get_instruction
134
+ when LIST then Instructions::LIST
135
+ when PUT then read_put_instruction
136
+ when SETITEM then Instructions::SETITEM
137
+ when TUPLE then Instructions::TUPLE
138
+ when INST then read_inst_instruction
139
+ when OBJ then Instructions::OBJ
140
+ when PERSID then read_persid_instruction
141
+ when BINPERSID then Instructions::BINPERSID
93
142
  #
94
143
  # Protocol 1 instructions
95
144
  #
96
- when 41 # EMPTY_TUPLE
97
- Instructions::EMPTY_TUPLE
98
- when 71 # BINFLOAT
99
- Instructions::BinFloat.new(read_float64_be)
100
- when 75 # BININT1
101
- Instructions::BinInt1.new(read_uint8)
102
- when 84 # BINSTRING
103
- length = read_uint32_le
104
- string = @io.read(length)
105
-
106
- Instructions::BinString.new(length,string)
107
- when 85 # SHORT_BINSTRING
108
- length = read_uint8
109
- string = @io.read(length)
110
-
111
- Instructions::ShortBinString.new(length,string)
112
- when 88 # BINUNICODE
113
- length = read_uint32_le
114
- string = @io.read(length).force_encoding(Encoding::UTF_8)
115
-
116
- Instructions::BinUnicode.new(length,string)
117
- when 93 # EMPTY_LIST
118
- Instructions::EMPTY_LIST
119
- when 101 # APPENDS
120
- Instructions::APPENDS
121
- when 104 # BINGET
122
- Instructions::BinGet.new(read_uint8)
123
- when 106 # LONG_BINGET
124
- Instructions::LongBinGet.new(read_uint32_le)
125
- when 113 # BINPUT
126
- Instructions::BinPut.new(read_uint8)
127
- when 117 # SETITEMS
128
- Instructions::SETITEMS
129
- when 125 # EMPTY_DICT
130
- Instructions::EMPTY_DICT
145
+ when EMPTY_TUPLE then Instructions::EMPTY_TUPLE
146
+ when BINFLOAT then read_binfloat_instruction
147
+ when BININT1 then read_binint1_instruction
148
+ when BINSTRING then read_binstring_instruction
149
+ when SHORT_BINSTRING then read_short_binstring_instruction
150
+ when BINUNICODE then read_binunicode_instruction
151
+ when EMPTY_LIST then Instructions::EMPTY_LIST
152
+ when APPENDS then Instructions::APPENDS
153
+ when BINGET then read_binget_instruction
154
+ when LONG_BINGET then read_long_binget_instruction
155
+ when BINPUT then read_binput_instruction
156
+ when SETITEMS then Instructions::SETITEMS
157
+ when EMPTY_DICT then Instructions::EMPTY_DICT
131
158
  #
132
159
  # Protocol 2 instructions
133
160
  #
134
- when 128 # PROT
135
- Instructions::Proto.new(read_uint8)
136
- when 129 # NEWOBJ
137
- Instructions::NEWOBJ
138
- when 130 # EXT1
139
- Instructions::Ext1.new(read_uint8)
140
- when 131 # EXT2
141
- Instructions::Ext2.new(read_uint16_le)
142
- when 132 # EXT4
143
- Instructions::Ext4.new(read_uint32_le)
144
- when 133 # TUPLE1
145
- Instructions::TUPLE1
146
- when 134 # TUPLE2
147
- Instructions::TUPLE2
148
- when 135 # TUPLE3
149
- Instructions::TUPLE3
150
- when 136 # NEWTRUE
151
- Instructions::NEWTRUE
152
- when 137 # NEWFALSE
153
- Instructions::NEWFALSE
154
- when 138 # LONG1
155
- length = read_uint8
156
- long = read_int_le(length)
157
-
158
- Instructions::Long1.new(length,long)
159
- when 139 # LONG4
160
- length = read_uint32_le
161
- long = read_int_le(length)
162
-
163
- Instructions::Long4.new(length,long)
161
+ when PROTO then read_proto_instruction
162
+ when NEWOBJ then Instructions::NEWOBJ
163
+ when EXT1 then read_ext1_instruction
164
+ when EXT2 then read_ext2_instruction
165
+ when EXT4 then read_ext4_instruction
166
+ when TUPLE1 then Instructions::TUPLE1
167
+ when TUPLE2 then Instructions::TUPLE2
168
+ when TUPLE3 then Instructions::TUPLE3
169
+ when NEWTRUE then Instructions::NEWTRUE
170
+ when NEWFALSE then Instructions::NEWFALSE
171
+ when LONG1 then read_long1_instruction
172
+ when LONG4 then read_long4_instruction
164
173
  else
165
174
  raise(InvalidFormat,"invalid opcode (#{opcode.inspect}) for protocol 2")
166
175
  end
@@ -224,6 +233,78 @@ module Python
224
233
  return long
225
234
  end
226
235
 
236
+ #
237
+ # Reads a `PROTO` instruction.
238
+ #
239
+ # @return [Instructions::Proto]
240
+ #
241
+ # @since 0.2.0
242
+ #
243
+ def read_proto_instruction
244
+ Instructions::Proto.new(read_uint8)
245
+ end
246
+
247
+ #
248
+ # Reads a `EXT1` instruction.
249
+ #
250
+ # @return [Instructions::Ext1]
251
+ #
252
+ # @since 0.2.0
253
+ #
254
+ def read_ext1_instruction
255
+ Instructions::Ext1.new(read_uint8)
256
+ end
257
+
258
+ #
259
+ # Reads a `EXT2` instruction.
260
+ #
261
+ # @return [Instructions::Ext2]
262
+ #
263
+ # @since 0.2.0
264
+ #
265
+ def read_ext2_instruction
266
+ Instructions::Ext2.new(read_uint16_le)
267
+ end
268
+
269
+ #
270
+ # Reads a `EXT4` instruction.
271
+ #
272
+ # @return [Instructions::Ext4]
273
+ #
274
+ # @since 0.2.0
275
+ #
276
+ def read_ext4_instruction
277
+ Instructions::Ext4.new(read_uint32_le)
278
+ end
279
+
280
+ #
281
+ # Reads a `LONG1` instruction.
282
+ #
283
+ # @return [Instructions::Long1]
284
+ #
285
+ # @since 0.2.0
286
+ #
287
+ def read_long1_instruction
288
+ length = read_uint8
289
+ long = read_int_le(length)
290
+
291
+ Instructions::Long1.new(length,long)
292
+ end
293
+
294
+ #
295
+ # Reads a `LONG4` instruction.
296
+ #
297
+ # @return [Instructions::Long4]
298
+ #
299
+ # @since 0.2.0
300
+ #
301
+ def read_long4_instruction
302
+ length = read_uint32_le
303
+ long = read_int_le(length)
304
+
305
+ Instructions::Long4.new(length,long)
306
+ end
307
+
227
308
  end
228
309
  end
229
310
  end