# 14.4. `xdrlib` --- XDR データのエンコードおよびデコード

ソースコード: Lib/xdrlib.py

`xdrlib` モジュールは外部データ表現標準 (External Data Representation Standard) のサポートを実現します。この標準は 1987 年に Sun Microsystems, Inc. によって書かれ、 RFC 1014 で定義されています。このモジュールでは RFC で記述されているほとんどのデータ型をサポートしています。

`xdrlib` モジュールでは 2 つのクラスが定義されています。一つは変数を XDR 表現にパックするためのクラスで、もう一方は XDR 表現からアンパックするためのものです。2 つの例外クラスが同様にして定義されています。

class `xdrlib.``Packer`

  `Packer` はデータを XDR 表現にパックするためのクラスです。 `Packer` クラスのインスタンス生成は引数なしで行われます。

class `xdrlib.``Unpacker`(data)

  `Unpacker` は Packer と対をなしていて、文字列バッファから XDR をアンパックするためのクラスです。入力バッファ data を引数に与えてインスタンスを生成します。

参考

RFC 1014 - XDR: External Data Representation Standard

  この RFC が、かつてこのモジュールが最初に書かれた当時に XDR 標準であったデータのエンコード方法を定義していました。現在は RFC 1832 に更新されているようです。

RFC 1832 - XDR: External Data Representation Standard

  こちらが新しい方のRFCで、XDR の改訂版が定義されています。

## 14.4.1. Packer オブジェクト

`Packer` インスタンスには以下のメソッドがあります:

`Packer.``get_buffer`()

  現在のパック処理用バッファを文字列で返します。

`Packer.``reset`()

  パック処理用バッファをリセットして、空文字にします。

一般的には、適切な `pack_type()` メソッドを使えば、一般に用いられているほとんどの XDR データをパックすることができます。各々のメソッドは一つの引数をとり、パックしたい値を与えます。単純なデータ型をパックするメソッドとして、以下のメソッド: `pack_uint()` 、 `pack_int()` 、 `pack_enum()` 、 `pack_bool()` 、 `pack_uhyper()` そして `pack_hyper()` がサポートされています。

`Packer.``pack_float`(value)

  単精度 (single-precision) の浮動小数点数 value をパックします。

`Packer.``pack_double`(value)

  倍精度 (double-precision) の浮動小数点数 value をパックします。

以下のメソッドは文字列、バイト列、不透明データ (opaque data) のパック処理をサポートします:

`Packer.``pack_fstring`(n, s)

  固定長の文字列、s をパックします。n は文字列の長さですが、この値自体はデータバッファにはパック されません。4 バイトのアラインメントを保証するために、文字列は必要に応じて null バイト列でパディングされます。

`Packer.``pack_fopaque`(n, data)

  `pack_fstring()` と同じく、固定長の不透明データストリームをパックします。

`Packer.``pack_string`(s)

  可変長の文字列 s をパックします。文字列の長さが最初に符号なし整数でパックされ、続いて `pack_fstring()` を使って文字列データがパックされます。

`Packer.``pack_opaque`(data)

  `pack_string()` と同じく、可変長の不透明データ文字列をパックします。

`Packer.``pack_bytes`(bytes)

  `pack_string()` と同じく、可変長のバイトストリームをパックします。

以下のメソッドはアレイやリストのパック処理をサポートします:

`Packer.``pack_list`(list, pack_item)

  一様な項目からなる list をパックします。このメソッドはサイズ不定、すなわち、全てのリスト内容を網羅するまでサイズが分からないリストに対して有用です。リストのすべての項目に対し、最初に符号無し整数 `1` がパックされ、続いてリスト中のデータがパックされます。pack_item は個々の項目をパックするために呼び出される関数です。リストの末端に到達すると、符号無し整数 `0` がパックされます。

  例えば、整数のリストをパックするには、コードは以下のようになるはずです:

      import xdrlib
      p = xdrlib.Packer()
      p.pack_list([1, 2, 3], p.pack_int)

`Packer.``pack_farray`(n, array, pack_item)

  一様な項目からなる固定長のリスト (array) をパックします。 n はリストの長さです。この値はデータバッファにパック されません が、 `len(array)` が n と等しくない場合、例外 `ValueError` が送出されます。上と同様に、 pack_item は個々の要素をパック処理するための関数です。

`Packer.``pack_array`(list, pack_item)

  一様の項目からなる可変長の list をパックします。まず、リストの長さが符号無し整数でパックされ、つづいて各要素が上の `pack_farray()` と同じやり方でパックされます。

## 14.4.2. Unpacker オブジェクト

`Unpacker` クラスは以下のメソッドを提供します:

`Unpacker.``reset`(data)

  文字列バッファを data でリセットします。

`Unpacker.``get_position`()

  データバッファ中の現在のアンパック処理位置を返します。

`Unpacker.``set_position`(position)

  データバッファ中のアンパック処理位置を position に設定します。 `get_position()` および `set_position()` は注意して使わなければなりません。

`Unpacker.``get_buffer`()

  現在のアンパック処理用データバッファを文字列で返します。

`Unpacker.``done`()

  アンパック処理を終了させます。全てのデータがまだアンパックされていなければ、例外 `Error` が送出されます。

上のメソッドに加えて、 `Packer` でパック処理できるデータ型はいずれも `Unpacker` でアンパック処理できます。アンパック処理メソッドは `unpack_type()` の形式をとり、引数をとりません。これらのメソッドはアンパックされたデータオブジェクトを返します。

`Unpacker.``unpack_float`()

  単精度の浮動小数点数をアンパックします。

`Unpacker.``unpack_double`()

  `unpack_float()` と同様に、倍精度の浮動小数点数をアンパックします。

上のメソッドに加えて、文字列、バイト列、不透明データをアンパックする以下のメソッドが提供されています:

`Unpacker.``unpack_fstring`(n)

  固定長の文字列をアンパックして返します。n は予想される文字列の長さです。4 バイトのアラインメントを保証するために null バイトによるパディングが行われているものと仮定して処理を行います。

`Unpacker.``unpack_fopaque`(n)

  `unpack_fstring()` と同様に、固定長の不透明データストリームをアンパックして返します。

`Unpacker.``unpack_string`()

  可変長の文字列をアンパックして返します。最初に文字列の長さが符号無し整数としてアンパックされ、次に `unpack_fstring()` を使って文字列データがアンパックされます。

`Unpacker.``unpack_opaque`()

  `unpack_string()` と同様に、可変長の不透明データ文字列をアンパックして返します。

`Unpacker.``unpack_bytes`()

  `unpack_string()` と同様に、可変長のバイトストリームをアンパックして返します。

以下メソッドはアレイおよびリストのアンパック処理をサポートします:

`Unpacker.``unpack_list`(unpack_item)

  一様な項目からなるリストをアンパック処理して返します。リストは、まず符号無し整数によるフラグをアンパックすることで、一度に 1 要素づつアンパック処理されます。フラグが `1` の場合、要素はアンパックされ、返り値のリストに追加されます。フラグが `0` の場合、リストの終端を示します。unpack_item は個々の項目をアンパック処理するために呼び出される関数です。

`Unpacker.``unpack_farray`(n, unpack_item)

  一様な項目からなる固定長のアレイをアンパックして（リストとして）返します。n はバッファ内に存在すると期待されるリストの要素数です。上と同様に、unpack_item は各要素をアンパックするために使われる関数です。

`Unpacker.``unpack_array`(unpack_item)

  一様な項目からなる可変長の list をアンパックして返します。まず、リストの長さが符号無し整数としてアンパックされ、続いて各要素が上の `unpack_farray()` のようにしてアンパック処理されます。

## 14.4.3. 例外

このモジュールでの例外はクラスインスタンスとしてコードされています:

exception `xdrlib.``Error`

  ベースとなる例外クラスです。 `Error` public な属性として `msg` を持ち、エラーの詳細が収められています。

exception `xdrlib.``ConversionError`

  `Error` から派生したクラスです。インスタンス変数は追加されていません。

これらの例外を補足する方法を以下の例に示します:

    import xdrlib
    p = xdrlib.Packer()
    try:
        p.pack_double(8.01)
    except xdrlib.ConversionError as instance:
        print('packing the double failed:', instance.msg)