Claude Code for xdrlib: Python XDR Data Encoding — Claude Skills 360 Blog
Blog / AI / Claude Code for xdrlib: Python XDR Data Encoding
AI

Claude Code for xdrlib: Python XDR Data Encoding

Published: November 1, 2028
Read time: 5 min read
By: Claude Skills 360

Python’s xdrlib module encodes and decodes XDR (External Data Representation, RFC 4506), the binary serialization format used by NFS, RPC (Sun RPC / ONC RPC), and distributed systems protocols. import xdrlib. Packer: p = xdrlib.Packer(). pack_int(n), pack_uint(n) — 4-byte big-endian signed/unsigned; pack_hyper(n), pack_uhyper(n) — 8-byte; pack_float(f), pack_double(f) — IEEE 754 4/8-byte; pack_bool(b) — int 0 or 1 in 4 bytes; pack_opaque(data) — fixed bytes + pad to 4-byte boundary; pack_bytes(data) — 4-byte length + data + pad; pack_string(s) — UTF-8 bytes with length prefix; pack_list(items, pack_item_fn) — each item preceded by 1 (more), ending with 0; pack_farray(items, pack_fn) — fixed array, no length marker; pack_array(items, pack_fn) — 4-byte count + items. Get result: p.get_buffer() → bytes. Unpacker: u = xdrlib.Unpacker(data). unpack_int(), unpack_uint(), unpack_hyper(), unpack_uhyper(), unpack_float(), unpack_double(), unpack_bool(), unpack_opaque(size), unpack_bytes(), unpack_string(), unpack_list(unpack_fn), unpack_farray(n, unpack_fn), unpack_array(unpack_fn). Position: u.get_position(), u.set_position(pos). Exceptions: xdrlib.Error, xdrlib.ConversionError. Note: deprecated 3.11, removed 3.13 — include compatibility guard; use struct fallback for critical code. Claude Code generates RPC message encoders, NFS XDR emitters, cross-platform binary serializers, and distributed protocol tools.

CLAUDE.md for xdrlib

## xdrlib Stack
- Stdlib: import xdrlib  (deprecated 3.11, removed 3.13 — guard with try/except)
- Pack:   p = xdrlib.Packer()
-         p.pack_int(n); p.pack_string("hello"); p.pack_bytes(b"\xff")
-         buf = p.get_buffer()
- Unpack: u = xdrlib.Unpacker(buf)
-         n = u.unpack_int();  s = u.unpack_string()
- Note:   XDR = big-endian; all values 4-byte aligned; strings are UTF-8 bytes

xdrlib XDR Encoding Pipeline

# app/xdrlibutil.py — pack/unpack primitives, structs, arrays, RPC skeleton
from __future__ import annotations

import io
import struct
from dataclasses import dataclass
from typing import Callable, Any

# Guard for Python 3.13+ where xdrlib is removed
try:
    import xdrlib as _xdrlib
    _XDRLIB_AVAILABLE = True
except ImportError:
    _XDRLIB_AVAILABLE = False


# ─────────────────────────────────────────────────────────────────────────────
# 1. Pure-Python XDR Packer / Unpacker (Python 3.13 fallback)
# ─────────────────────────────────────────────────────────────────────────────

def _pad4(n: int) -> int:
    """Round up n to the nearest multiple of 4."""
    return (n + 3) & ~3


class XdrPacker:
    """
    Pure-Python XDR packer (subset covering int, uint, hyper, float, double,
    bool, opaque, bytes, string, and arrays).
    Used as fallback when xdrlib is unavailable.

    Example:
        p = XdrPacker()
        p.pack_int(42)
        p.pack_string("hello")
        buf = p.get_buffer()
    """

    def __init__(self) -> None:
        self._buf = io.BytesIO()

    def _write(self, data: bytes) -> None:
        self._buf.write(data)

    def pack_int(self, n: int) -> None:
        self._write(struct.pack(">i", n))

    def pack_uint(self, n: int) -> None:
        self._write(struct.pack(">I", n))

    def pack_hyper(self, n: int) -> None:
        self._write(struct.pack(">q", n))

    def pack_uhyper(self, n: int) -> None:
        self._write(struct.pack(">Q", n))

    def pack_float(self, f: float) -> None:
        self._write(struct.pack(">f", f))

    def pack_double(self, f: float) -> None:
        self._write(struct.pack(">d", f))

    def pack_bool(self, b: bool) -> None:
        self.pack_int(1 if b else 0)

    def pack_opaque(self, data: bytes) -> None:
        """Fixed-length opaque: data + padding to 4-byte boundary."""
        self._write(data)
        pad = _pad4(len(data)) - len(data)
        if pad:
            self._write(b"\x00" * pad)

    def pack_bytes(self, data: bytes) -> None:
        """Variable-length bytes: 4-byte length + data + padding."""
        self.pack_uint(len(data))
        self.pack_opaque(data)

    def pack_string(self, s: str) -> None:
        self.pack_bytes(s.encode("utf-8"))

    def pack_list(self, items, pack_fn: Callable) -> None:
        """XDR linked list: each item preceded by 1 (has more), ends with 0."""
        for item in items:
            self.pack_uint(1)
            pack_fn(item)
        self.pack_uint(0)

    def pack_array(self, items, pack_fn: Callable) -> None:
        """XDR variable array: 4-byte count + items."""
        self.pack_uint(len(items))
        for item in items:
            pack_fn(item)

    def pack_farray(self, items, pack_fn: Callable) -> None:
        """XDR fixed array: no length marker."""
        for item in items:
            pack_fn(item)

    def get_buffer(self) -> bytes:
        return self._buf.getvalue()

    def reset(self) -> None:
        self._buf = io.BytesIO()


class XdrUnpacker:
    """
    Pure-Python XDR unpacker.

    Example:
        u = XdrUnpacker(buf)
        n = u.unpack_int()
        s = u.unpack_string()
    """

    def __init__(self, data: bytes) -> None:
        self._data = data
        self._pos = 0

    def _read(self, n: int) -> bytes:
        if self._pos + n > len(self._data):
            raise EOFError(f"XDR buffer underrun at position {self._pos}")
        chunk = self._data[self._pos:self._pos + n]
        self._pos += n
        return chunk

    def unpack_int(self) -> int:
        return struct.unpack(">i", self._read(4))[0]

    def unpack_uint(self) -> int:
        return struct.unpack(">I", self._read(4))[0]

    def unpack_hyper(self) -> int:
        return struct.unpack(">q", self._read(8))[0]

    def unpack_uhyper(self) -> int:
        return struct.unpack(">Q", self._read(8))[0]

    def unpack_float(self) -> float:
        return struct.unpack(">f", self._read(4))[0]

    def unpack_double(self) -> float:
        return struct.unpack(">d", self._read(8))[0]

    def unpack_bool(self) -> bool:
        return bool(self.unpack_int())

    def unpack_opaque(self, size: int) -> bytes:
        data = self._read(size)
        pad = _pad4(size) - size
        if pad:
            self._read(pad)
        return data

    def unpack_bytes(self) -> bytes:
        size = self.unpack_uint()
        return self.unpack_opaque(size)

    def unpack_string(self) -> str:
        return self.unpack_bytes().decode("utf-8")

    def unpack_list(self, unpack_fn: Callable) -> list:
        items = []
        while True:
            more = self.unpack_uint()
            if not more:
                break
            items.append(unpack_fn())
        return items

    def unpack_array(self, unpack_fn: Callable) -> list:
        count = self.unpack_uint()
        return [unpack_fn() for _ in range(count)]

    def unpack_farray(self, n: int, unpack_fn: Callable) -> list:
        return [unpack_fn() for _ in range(n)]

    def get_position(self) -> int:
        return self._pos

    def set_position(self, pos: int) -> None:
        self._pos = pos

    def done(self) -> None:
        if self._pos != len(self._data):
            raise ValueError(
                f"XDR buffer not fully consumed: "
                f"{len(self._data) - self._pos} bytes remaining"
            )


# ─────────────────────────────────────────────────────────────────────────────
# 2. Unified factory (xdrlib or pure-Python)
# ─────────────────────────────────────────────────────────────────────────────

def make_packer():
    """Return a Packer object (xdrlib.Packer or XdrPacker fallback)."""
    if _XDRLIB_AVAILABLE:
        return _xdrlib.Packer()
    return XdrPacker()


def make_unpacker(data: bytes):
    """Return an Unpacker object (xdrlib.Unpacker or XdrUnpacker fallback)."""
    if _XDRLIB_AVAILABLE:
        return _xdrlib.Unpacker(data)
    return XdrUnpacker(data)


# ─────────────────────────────────────────────────────────────────────────────
# 3. Struct-like XDR record encoding
# ─────────────────────────────────────────────────────────────────────────────

@dataclass
class FileHandle:
    """
    Example XDR record: an NFS-style file handle record.
    Fields: version (int), path (string), size (hyper), flags (uint).
    """
    version: int
    path:    str
    size:    int
    flags:   int

    def to_xdr(self) -> bytes:
        """Encode this record to XDR bytes."""
        p = make_packer()
        p.pack_int(self.version)
        p.pack_string(self.path)
        p.pack_hyper(self.size)
        p.pack_uint(self.flags)
        return p.get_buffer()

    @classmethod
    def from_xdr(cls, data: bytes) -> "FileHandle":
        """Decode a FileHandle from XDR bytes."""
        u = make_unpacker(data)
        version = u.unpack_int()
        path    = u.unpack_string()
        size    = u.unpack_hyper()
        flags   = u.unpack_uint()
        return cls(version=version, path=path, size=size, flags=flags)

    def __str__(self) -> str:
        return (f"FileHandle(version={self.version}, path={self.path!r}, "
                f"size={self.size}, flags=0x{self.flags:04x})")


# ─────────────────────────────────────────────────────────────────────────────
# 4. Sun RPC message skeleton
# ─────────────────────────────────────────────────────────────────────────────

@dataclass
class RpcCallMsg:
    """
    Minimal Sun RPC call message header (RFC 5531).
    Fields: xid, msg_type(0=CALL), rpcvers(2), prog, vers, proc.
    """
    xid:     int
    prog:    int
    vers:    int
    proc:    int
    rpcvers: int = 2

    def to_xdr(self) -> bytes:
        p = make_packer()
        p.pack_uint(self.xid)
        p.pack_int(0)          # msg_type: CALL
        p.pack_uint(self.rpcvers)
        p.pack_uint(self.prog)
        p.pack_uint(self.vers)
        p.pack_uint(self.proc)
        # AUTH_NULL credentials and verifier
        p.pack_uint(0); p.pack_bytes(b"")   # cred flavor + body
        p.pack_uint(0); p.pack_bytes(b"")   # verf flavor + body
        return p.get_buffer()

    @classmethod
    def from_xdr(cls, data: bytes) -> "RpcCallMsg":
        u = make_unpacker(data)
        xid      = u.unpack_uint()
        msg_type = u.unpack_int()
        rpcvers  = u.unpack_uint()
        prog     = u.unpack_uint()
        vers     = u.unpack_uint()
        proc     = u.unpack_uint()
        return cls(xid=xid, prog=prog, vers=vers, proc=proc, rpcvers=rpcvers)

    def __str__(self) -> str:
        return (f"RpcCallMsg(xid={self.xid}, prog={self.prog}, "
                f"vers={self.vers}, proc={self.proc})")


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=== xdrlib demo ===")
    if not _XDRLIB_AVAILABLE:
        print("  xdrlib not available (Python 3.13+); using pure Python XdrPacker")

    # ── primitive round-trips ──────────────────────────────────────────────────
    print("\n--- primitive types round-trip ---")
    p = make_packer()
    p.pack_int(-42)
    p.pack_uint(65535)
    p.pack_hyper(-9_000_000_000)
    p.pack_float(3.14)
    p.pack_double(2.718281828)
    p.pack_bool(True)
    p.pack_bytes(b"\x01\x02\x03")
    p.pack_string("hello XDR")
    buf = p.get_buffer()
    print(f"  packed {len(buf)} bytes: {buf.hex()[:48)}...")

    u = make_unpacker(buf)
    print(f"  int:    {u.unpack_int()}")
    print(f"  uint:   {u.unpack_uint()}")
    print(f"  hyper:  {u.unpack_hyper()}")
    print(f"  float:  {u.unpack_float():.5f}")
    print(f"  double: {u.unpack_double():.9f}")
    print(f"  bool:   {u.unpack_bool()}")
    print(f"  bytes:  {u.unpack_bytes().hex()}")
    print(f"  string: {u.unpack_string()!r}")

    # ── array encoding ────────────────────────────────────────────────────────
    print("\n--- array encoding ---")
    p2 = make_packer()
    items = [10, 20, 30, 40]
    p2.pack_array(items, p2.pack_int)
    arr_buf = p2.get_buffer()
    u2 = make_unpacker(arr_buf)
    decoded = u2.unpack_array(u2.unpack_int)
    print(f"  original: {items}")
    print(f"  decoded:  {decoded}")

    # ── struct record ─────────────────────────────────────────────────────────
    print("\n--- FileHandle XDR record ---")
    fh = FileHandle(version=3, path="/exports/data/file.dat",
                    size=1_234_567_890, flags=0x0005)
    xdr_bytes = fh.to_xdr()
    print(f"  encoded: {len(xdr_bytes)} bytes")
    fh2 = FileHandle.from_xdr(xdr_bytes)
    print(f"  decoded: {fh2}")
    print(f"  match: version={fh.version == fh2.version} "
          f"path={fh.path == fh2.path} "
          f"size={fh.size == fh2.size}")

    # ── RPC call message ───────────────────────────────────────────────────────
    print("\n--- RpcCallMsg ---")
    # NFS3 LOOKUP: prog=100003, vers=3, proc=3
    call = RpcCallMsg(xid=0xDEADBEEF, prog=100003, vers=3, proc=3)
    rpc_buf = call.to_xdr()
    print(f"  encoded: {len(rpc_buf)} bytes  hex={rpc_buf.hex()}")
    call2 = RpcCallMsg.from_xdr(rpc_buf)
    print(f"  decoded: {call2}")

    print("\n=== done ===")

For the struct alternative — struct.pack(">iId", n, u, f) and struct.unpack_from(">iId", buf, offset) give you XDR-compatible big-endian integer and float encoding directly — use struct when your XDR usage is limited to fixed-size primitives with known offsets and you don’t need the variable-length pack_bytes() / pack_string() / pack_list() / pack_array() machinery; use xdrlib (or the XdrPacker / XdrUnpacker fallback above) when you need dynamic-length types and automatic 4-byte alignment padding that xdrlib handles transparently. For the protobuf / msgpack alternative — Protocol Buffers (google-protobuf PyPI) and MessagePack (msgpack PyPI) are modern cross-language binary serialization formats with schema support, versioning, and richer type systems — prefer these for new protocol designs; use xdrlib only when interoperating with existing XDR-based systems (NFS, ONC RPC, XDR-based data archives) where you cannot change the wire format. The Claude Skills 360 bundle includes xdrlib skill sets covering XdrPacker/XdrUnpacker pure-Python fallback classes, make_packer()/make_unpacker() unified factory, FileHandle and RpcCallMsg XDR record examples, and full primitive + array + list round-trip demonstrations. Start with the free tier to try XDR encoding patterns and xdrlib pipeline code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free