Class: Python::Pickle::Protocol0 Private

Inherits:
Protocol
  • Object
show all
Defined in:
lib/python/pickle/protocol0.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Implements reading and writing of Python Pickle protocol 0.

Direct Known Subclasses

Protocol1

Constant Summary collapse

OPCODES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Opcodes for Pickle protocol version 0.

Set[
  40,  # MARK
  46,  # STOP
  48,  # POP
  49,  # POP_MARK
  50,  # DUP
  70,  # FLOAT
  73,  # INT
  76,  # LONG
  78,  # NONE
  82,  # REDUCE
  83,  # STRING
  86,  # UNICODE
  97,  # APPEND
  98,  # BUILD
  99,  # GLOBAL
  100, # DICT
  103, # GET
  108, # LIST
  112, # PUT
  115, # SETITEM
  116  # TUPLE
]

Instance Attribute Summary

Attributes inherited from Protocol

#io

Instance Method Summary collapse

Methods inherited from Protocol

#initialize, #read

Constructor Details

This class inherits a constructor from Python::Pickle::Protocol

Instance Method Details

#read_escaped_charString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads an escaped character from the pickle stream.

Returns:

  • (String)

    The unescaped raw character.



147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/python/pickle/protocol0.rb', line 147

def read_escaped_char
  case (letter = @io.getc)
  when 'x'  then  read_hex_escaped_char
  when 't'  then "\t"
  when 'n'  then "\n"
  when 'r'  then "\r"
  when '\\' then '\\'
  when "'"  then "'"
  else
    bad_escape = letter.inspect[1..-2]

    raise(InvalidFormat,"invalid backslash escape character: \"\\#{bad_escape}\"")
  end
end

#read_floatFloat

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads a floating-point decimal from the pickle stream.

Returns:

  • (Float)

    The decoded float.

Raises:

  • (InvalidFormat)

    Encountered a non-numeric character or a premature end of the stream.



314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/python/pickle/protocol0.rb', line 314

def read_float
  new_string = String.new

  until @io.eof?
    case (char = @io.getc)
    when /[0-9\.]/
      new_string << char
    when "\n" # end-of-float
      return new_string.to_f
    else
      raise(InvalidFormat,"encountered a non-numeric character while reading a float: #{char.inspect}")
    end
  end

  raise(InvalidFormat,"unexpected end of stream while parsing a float: #{new_string.inspect}")
end

#read_hex_escaped_charString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads a hex number from the pickle stream.

Parameters:

  • digits (Integer)

    The number of digits to read.

Returns:

  • (String)

    The decoded raw character.



129
130
131
132
133
134
135
136
137
138
139
# File 'lib/python/pickle/protocol0.rb', line 129

def read_hex_escaped_char
  string = @io.read(2)

  unless string =~ /\A[0-9a-fA-F]{2}\z/
    bad_hex = string.inspect[1..-2]

    raise(InvalidFormat,"invalid hex escape character: \"\\x#{bad_hex}\"")
  end

  return string.to_i(16).chr
end

#read_instructionInstruction

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads an instruction from the pickle stream.

Returns:

Raises:



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/python/pickle/protocol0.rb', line 71

def read_instruction
  case (opcode = @io.getbyte)
  when 40 # MARK
    Instructions::MARK
  when 46 # STOP
    Instructions::STOP
  when 48 # POP
    Instructions::POP
  when 49 # POP_MARK
    Instructions::POP_MARK
  when 50 # DUP
    Instructions::DUP
  when 70 # FLOAT
    Instructions::Float.new(read_float)
  when 73 # INT
    Instructions::Int.new(read_int)
  when 76 # LONG
    Instructions::Long.new(read_long)
  when 78 # NONE
    Instructions::NONE
  when 82 # REDUCE
    Instructions::REDUCE
  when 83 # STRING
    Instructions::String.new(read_string)
  when 86 # UNICODE
    Instructions::String.new(read_unicode_string)
  when 97 # APPEND
    Instructions::APPEND
  when 98 # BUILD
    Instructions::BUILD
  when 99 # GLOBAL
    Instructions::Global.new(read_nl_string,read_nl_string)
  when 100 # DICT
    Instructions::DICT
  when 103 # GET
    Instructions::Get.new(read_int)
  when 108 # LIST
    Instructions::LIST
  when 112 # PUT
    Instructions::Put.new(read_int)
  when 115 # SETITEM
    Instructions::SETITEM
  when 116 # TUPLE
    Instructions::TUPLE
  else
    raise(InvalidFormat,"invalid opcode (#{opcode.inspect}) for protocol 0")
  end
end

#read_intInteger, ...

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads an integer from the pickle stream.

Returns:

  • (Integer, true, false)

    The decoded Integer. If the integer is 00, then false will be returned. If the integer is 01, then true will be returned.

Raises:

  • (InvalidFormat)

    Encountered a non-numeric character or a premature end of the stream.



342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/python/pickle/protocol0.rb', line 342

def read_int
  new_string = String.new

  until @io.eof?
    case (char = @io.getc)
    when /[0-9]/
      new_string << char
    when "\n" # end-of-integer
      return case new_string
             when '00' then false
             when '01' then true
             else           new_string.to_i
             end
    else
      raise(InvalidFormat,"encountered a non-numeric character while reading an integer: #{char.inspect}")
    end
  end

  raise(InvalidFormat,"unexpected end of stream while parsing an integer: #{new_string.inspect}")
end

#read_longInteger

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads a long integer.

Returns:

  • (Integer)

    The decoded Integer.

Raises:

  • (InvalidFormat)

    Encountered a non-numeric character or a premature end of the stream.



372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/python/pickle/protocol0.rb', line 372

def read_long
  new_string = String.new

  until @io.eof?
    case (char = @io.getc)
    when /[0-9]/
      new_string << char
    when 'L'
      newline = @io.getc

      if newline == nil
        raise(InvalidFormat,"unexpected end of stream after the end of an integer")
      elsif newline != "\n"
        raise(InvalidFormat,"expected a '\\n' character following the integer, but was #{newline.inspect}")
      end

      return new_string.to_i
    else
      raise(InvalidFormat,"encountered a non-numeric character while reading a long integer: #{char.inspect}")
    end
  end

  raise(InvalidFormat,"unexpected end of stream while parsing a long integer: #{new_string.inspect}")
end

#read_nl_stringString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads a newline terminated string from the pickle string.

Returns:

  • (String)

    The read string.

Raises:



171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/python/pickle/protocol0.rb', line 171

def read_nl_string
  new_string = String.new

  until @io.eof?
    case (char = @io.getc)
    when "\n"
      return new_string
    else
      new_string << char
    end
  end

  raise(InvalidFormat,"unexpected end of stream after the end of a newline terminated string")
end

#read_stringString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads an ASCII string from the pickle stream.

Returns:

  • (String)

    The decoded raw string.



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/python/pickle/protocol0.rb', line 192

def read_string
  new_string = String.new(encoding: Encoding::ASCII_8BIT)

  unless @io.getc == "'"
    raise(InvalidFormat,"cannot find beginning single-quote of string")
  end

  until @io.eof?
    case (char = @io.getc)
    when "\\"
      new_string << read_escaped_char
    when "'" # end-of-string
      break
    else
      new_string << char
    end
  end

  newline = @io.getc

  if newline == nil
    raise(InvalidFormat,"unexpected end of stream after the end of a single-quoted string")
  elsif newline != "\n"
    raise(InvalidFormat,"expected a '\\n' character following the string, but was #{newline.inspect}")
  end

  return new_string
end

#read_unicode_escaped_charString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads a unicode escaped character from the pickle stream.

Returns:

  • (String)

    The unescaped raw unicode character.



269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/python/pickle/protocol0.rb', line 269

def read_unicode_escaped_char
  case (letter = @io.getc)
  when 'x'  then read_hex_escaped_char
  when 'u'  then read_unicode_escaped_char16
  when 'U'  then read_unicode_escaped_char32
  when "\\" then "\\"
  else
    bad_escape = letter.inspect[1..-2]

    raise(InvalidFormat,"invalid unicode escape character: \"\\#{bad_escape}\"")
  end
end

#read_unicode_escaped_char16String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads a short unicode escaped character.

Returns:

  • (String)

    The decoded UTF-8 character.

Raises:



230
231
232
233
234
235
236
237
238
239
240
# File 'lib/python/pickle/protocol0.rb', line 230

def read_unicode_escaped_char16
  string = @io.read(4)

  unless string =~ /\A[0-9a-fA-F]{4}\z/
    bad_unicode = string.inspect[1..-2]

    raise(InvalidFormat,"invalid unicode escape character: \"\\u#{bad_unicode}\"")
  end

  return string.to_i(16).chr(Encoding::UTF_8)
end

#read_unicode_escaped_char32String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads a long unicode escaped character.

Returns:

  • (String)

    The decoded UTF-8 character.

Raises:



251
252
253
254
255
256
257
258
259
260
261
# File 'lib/python/pickle/protocol0.rb', line 251

def read_unicode_escaped_char32
  string = @io.read(8)

  unless string =~ /\A[0-9a-fA-F]{8}\z/
    bad_unicode = string.inspect[1..-2]

    raise(InvalidFormat,"invalid unicode escape character: \"\\U#{bad_unicode}\"")
  end

  return string.to_i(16).chr(Encoding::UTF_8)
end

#read_unicode_stringString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads a unicode String from the pickle stream.

Returns:

  • (String)

    The decoded raw unicode String.

Raises:



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/python/pickle/protocol0.rb', line 288

def read_unicode_string
  new_string = String.new(encoding: Encoding::UTF_8)

  until @io.eof?
    case (char = @io.getc)
    when "\\" # backslash escaped character
      new_string << read_unicode_escaped_char
    when "\n" # end-of-string
      return new_string
    else
      new_string << char
    end
  end

  raise(InvalidFormat,"unexpected end of stream while parsing unicode string: #{new_string.inspect}")
end