"""Implements (a subset of) Sun XDR -- eXternal Data Representation.

See: RFC 1014

"""

import struct

# exceptions
class Error:
    """Exception class for this module. Use:

    except xdrlib.Error, var:
        # var has the Error instance for the exception

    Public ivars:
        msg -- contains the message

    """
    def __init__(self, msg):
	self.msg = msg
    def __repr__(self):
	return repr(self.msg)
    def __str__(self):
	return str(self.msg)


class ConversionError(Error):
    pass



class Packer:
    """Pack various data representations into a buffer."""

    def __init__(self):
	self.reset()

    def reset(self):
	self.__buf = ''

    def get_buffer(self):
	return self.__buf
    # backwards compatibility
    get_buf = get_buffer

    def pack_uint(self, x):
	self.__buf = self.__buf + struct.pack('>L', x)

    pack_int = pack_uint
    pack_enum = pack_int

    def pack_bool(self, x):
	if x: self.__buf = self.__buf + '\0\0\0\1'
	else: self.__buf = self.__buf + '\0\0\0\0'

    def pack_uhyper(self, x):
	self.pack_uint(int(x>>32 & 0xffffffff))
	self.pack_uint(int(x & 0xffffffff))

    pack_hyper = pack_uhyper

    def pack_float(self, x):
	try: self.__buf = self.__buf + struct.pack('>f', x)
	except struct.error, msg:
	    raise ConversionError, msg

    def pack_double(self, x):
	try: self.__buf = self.__buf + struct.pack('>d', x)
	except struct.error, msg:
	    raise ConversionError, msg

    def pack_fstring(self, n, s):
	if n < 0:
	    raise ValueError, 'fstring size must be nonnegative'
	n = ((n+3)/4)*4
	data = s[:n]
	data = data + (n - len(data)) * '\0'
	self.__buf = self.__buf + data

    pack_fopaque = pack_fstring

    def pack_string(self, s):
	n = len(s)
	self.pack_uint(n)
	self.pack_fstring(n, s)

    pack_opaque = pack_string
    pack_bytes = pack_string

    def pack_list(self, list, pack_item):
	for item in list:
	    self.pack_uint(1)
	    pack_item(item)
	self.pack_uint(0)

    def pack_farray(self, n, list, pack_item):
	if len(list) <> n:
	    raise ValueError, 'wrong array size'
	for item in list:
	    pack_item(item)

    def pack_array(self, list, pack_item):
	n = len(list)
	self.pack_uint(n)
	self.pack_farray(n, list, pack_item)



class Unpacker:
    """Unpacks various data representations from the given buffer."""

    def __init__(self, data):
	self.reset(data)

    def reset(self, data):
	self.__buf = data
	self.__pos = 0

    def get_position(self):
	return self.__pos

    def set_position(self, position):
	self.__pos = position

    def get_buffer(self):
	return self.__buf

    def done(self):
	if self.__pos < len(self.__buf):
	    raise Error('unextracted data remains')

    def unpack_uint(self):
	i = self.__pos
	self.__pos = j = i+4
	data = self.__buf[i:j]
	if len(data) < 4:
	    raise EOFError
	x = struct.unpack('>L', data)[0]
	try:
	    return int(x)
	except OverflowError:
	    return x

    def unpack_int(self):
	i = self.__pos
	self.__pos = j = i+4
	data = self.__buf[i:j]
	if len(data) < 4:
	    raise EOFError
	return struct.unpack('>l', data)[0]

    unpack_enum = unpack_int
    unpack_bool = unpack_int

    def unpack_uhyper(self):
	hi = self.unpack_uint()
	lo = self.unpack_uint()
	return long(hi)<<32 | lo

    def unpack_hyper(self):
	x = self.unpack_uhyper()
	if x >= 0x8000000000000000L:
	    x = x - 0x10000000000000000L
	return x

    def unpack_float(self):
	i = self.__pos
	self.__pos = j = i+4
	data = self.__buf[i:j]
	if len(data) < 4:
	    raise EOFError
	return struct.unpack('>f', data)[0]

    def unpack_double(self):
	i = self.__pos
	self.__pos = j = i+8
	data = self.__buf[i:j]
	if len(data) < 8:
	    raise EOFError
	return struct.unpack('>d', data)[0]

    def unpack_fstring(self, n):
	if n < 0:
	    raise ValueError, 'fstring size must be nonnegative'
	i = self.__pos
	j = i + (n+3)/4*4
	if j > len(self.__buf):
	    raise EOFError
	self.__pos = j
	return self.__buf[i:i+n]

    unpack_fopaque = unpack_fstring

    def unpack_string(self):
	n = self.unpack_uint()
	return self.unpack_fstring(n)

    unpack_opaque = unpack_string
    unpack_bytes = unpack_string

    def unpack_list(self, unpack_item):
	list = []
	while 1:
	    x = self.unpack_uint()
	    if x == 0: break
	    if x <> 1:
		raise ConversionError, '0 or 1 expected, got ' + `x`
	    item = unpack_item()
	    list.append(item)
	return list

    def unpack_farray(self, n, unpack_item):
	list = []
	for i in range(n):
	    list.append(unpack_item())
	return list

    def unpack_array(self, unpack_item):
	n = self.unpack_uint()
	return self.unpack_farray(n, unpack_item)


# test suite
def _test():
    p = Packer()
    packtest = [
	(p.pack_uint,    (9,)),
	(p.pack_bool,    (None,)),
	(p.pack_bool,    ('hello',)),
	(p.pack_uhyper,  (45L,)),
	(p.pack_float,   (1.9,)),
	(p.pack_double,  (1.9,)),
	(p.pack_string,  ('hello world',)),
	(p.pack_list,    (range(5), p.pack_uint)),
	(p.pack_array,   (['what', 'is', 'hapnin', 'doctor'], p.pack_string)),
	]
    succeedlist = [1] * len(packtest)
    count = 0
    for method, args in packtest:
	print 'pack test', count,
	try:
	    apply(method, args)
	    print 'succeeded'
	except ConversionError, var:
	    print 'ConversionError:', var.msg
	    succeedlist[count] = 0
	count = count + 1
    data = p.get_buffer()
    # now verify
    up = Unpacker(data)
    unpacktest = [
	(up.unpack_uint,   (), lambda x: x == 9),
	(up.unpack_bool,   (), lambda x: not x),
	(up.unpack_bool,   (), lambda x: x),
	(up.unpack_uhyper, (), lambda x: x == 45L),
	(up.unpack_float,  (), lambda x: 1.89 < x < 1.91),
	(up.unpack_double, (), lambda x: 1.89 < x < 1.91),
	(up.unpack_string, (), lambda x: x == 'hello world'),
	(up.unpack_list,   (up.unpack_uint,), lambda x: x == range(5)),
	(up.unpack_array,  (up.unpack_string,),
	 lambda x: x == ['what', 'is', 'hapnin', 'doctor']),
	]
    count = 0
    for method, args, pred in unpacktest:
	print 'unpack test', count,
	try:
	    if succeedlist[count]:
		x = apply(method, args)
		print pred(x) and 'succeeded' or 'failed', ':', x
	    else:
		print 'skipping'
	except ConversionError, var:
	    print 'ConversionError:', var.msg
	count = count + 1


if __name__ == '__main__':
    _test()
