🦁
[Feature #20669] Marshal.load 用の例外を追加する提案
[Feature #20669] Add Marshal::MarshalError class to differentiate ArgumentErrors
-
marshal
はいろんなデータをファイル(文字列)に変換し、そのデータを復元するためのライブラリ
# データを文字列に変換
data = Marshal.dump({ id: 1, name: "homu", age: 14 })
pp data
# => "\x04\b{\b:\aidi\x06:\tnameI\"\thomu\x06:\x06ET:\bagei\x13"
# そのデータを復元する
pp Marshal.load(data)
# => {:id=>1, :name=>"homu", :age=>14}
- このときに
Marshal.load
にフォーマットが不正なデータや破損したデータを渡すと次のようにTypeError
やArgumentError
が発生する
begin
# 復元できるフォーマットではない場合
Marshal.load("foobar")
rescue
pp $!
# => #<TypeError:"incompatible marshal file format (can't be read)\n\tformat version 4.8 required; 102.111 given">
end
begin
# データが途中で破損している場合
Marshal.load(Marshal.dump(Object.new).slice(0, 10))
rescue
pp $!
# => #<ArgumentError: marshal data too short>
end
begin
# 以下のように MyThing に依存するようなデータを復元する場合
# MyThing = Struct.new(:name, :age)
# Marshal.dump(MyThing.new("Alice", 20))
# => "\x04\bS:\fMyThing\a:\tnameI\"\nAlice\x06:\x06ET:\bagei\x19"
Marshal.load "\x04\bS:\fMyThing\a:\tnameI\"\nAlice\x06:\x06ET:\bagei\x19"
rescue
pp $!
# => #<ArgumentError: undefined class/module MyThing>
end
-
TypeError
やArgumentError
は通常以下のような場合に発生することを期待するがMarshal.load
の場合はそれ以外でも同エラーが発生するのでそれを区別できるようにしたい、というのがこのチケットの内容-
TypeError
: 引数の型が異なる場合 -
ArgumentError
: 引数の数が異なる場合
-
- これを回避するために
Marshal::LoadError
を追加する提案が書かれている-
Marshal
の内部でエラーが発生した場合はこの例外を返す想定
-
- この提案の問題として互換性の話が上がっています
- いままで
ArgumentError
だったものがMarshal::LoadError
に変わるのでrescue ArgumentError
している箇所が非互換になってしまう
- いままで
- これに限らず
ArgumentError
とするのかは難しそうですねえ
Discussion