diff options
| author | Rafael H. Schloming <rhs@apache.org> | 2009-12-26 12:42:57 +0000 |
|---|---|---|
| committer | Rafael H. Schloming <rhs@apache.org> | 2009-12-26 12:42:57 +0000 |
| commit | 248f1fe188fe2307b9dcf2c87a83b653eaa1920c (patch) | |
| tree | d5d0959a70218946ff72e107a6c106e32479a398 /python/qpid/codec010.py | |
| parent | 3c83a0e3ec7cf4dc23e83a340b25f5fc1676f937 (diff) | |
| download | qpid-python-248f1fe188fe2307b9dcf2c87a83b653eaa1920c.tar.gz | |
synchronized with trunk except for ruby dir
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/qpid.rnr@893970 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'python/qpid/codec010.py')
| -rw-r--r-- | python/qpid/codec010.py | 255 |
1 files changed, 170 insertions, 85 deletions
diff --git a/python/qpid/codec010.py b/python/qpid/codec010.py index dac023e2bd..682743df19 100644 --- a/python/qpid/codec010.py +++ b/python/qpid/codec010.py @@ -17,25 +17,69 @@ # under the License. # +import datetime from packer import Packer -from datatypes import serial, RangedSet, Struct +from datatypes import serial, timestamp, RangedSet, Struct, UUID +from ops import Compound, PRIMITIVE, COMPOUND class CodecException(Exception): pass +def direct(t): + return lambda x: t + +def map_str(s): + for c in s: + if ord(c) >= 0x80: + return "vbin16" + return "str16" + class Codec(Packer): - def __init__(self, spec): - self.spec = spec + ENCODINGS = { + unicode: direct("str16"), + str: map_str, + buffer: direct("vbin32"), + int: direct("int64"), + long: direct("int64"), + float: direct("double"), + None.__class__: direct("void"), + list: direct("list"), + tuple: direct("list"), + dict: direct("map"), + timestamp: direct("datetime"), + datetime.datetime: direct("datetime"), + UUID: direct("uuid"), + Compound: direct("struct32") + } + + def encoding(self, obj): + enc = self._encoding(obj.__class__, obj) + if enc is None: + raise CodecException("no encoding for %r" % obj) + return PRIMITIVE[enc] + + def _encoding(self, klass, obj): + if self.ENCODINGS.has_key(klass): + return self.ENCODINGS[klass](obj) + for base in klass.__bases__: + result = self._encoding(base, obj) + if result != None: + return result + + def read_primitive(self, type): + return getattr(self, "read_%s" % type.NAME)() + def write_primitive(self, type, v): + getattr(self, "write_%s" % type.NAME)(v) - def write_void(self, v): - assert v == None def read_void(self): return None + def write_void(self, v): + assert v == None - def write_bit(self, b): - if not b: raise ValueError(b) def read_bit(self): return True + def write_bit(self, b): + if not b: raise ValueError(b) def read_uint8(self): return self.unpack("!B") @@ -68,7 +112,7 @@ class Codec(Packer): def read_int16(self): return self.unpack("!h") def write_int16(self, n): - return self.unpack("!h", n) + self.pack("!h", n) def read_uint32(self): @@ -103,9 +147,11 @@ class Codec(Packer): self.pack("!q", n) def read_datetime(self): - return self.read_uint64() - def write_datetime(self, n): - self.write_uint64(n) + return timestamp(self.read_uint64()) + def write_datetime(self, t): + if isinstance(t, datetime.datetime): + t = timestamp(t) + self.write_uint64(t) def read_double(self): return self.unpack("!d") @@ -115,6 +161,8 @@ class Codec(Packer): def read_vbin8(self): return self.read(self.read_uint8()) def write_vbin8(self, b): + if isinstance(b, buffer): + b = str(b) self.write_uint8(len(b)) self.write(b) @@ -128,10 +176,17 @@ class Codec(Packer): def write_str16(self, s): self.write_vbin16(s.encode("utf8")) + def read_str16_latin(self): + return self.read_vbin16().decode("iso-8859-15") + def write_str16_latin(self, s): + self.write_vbin16(s.encode("iso-8859-15")) + def read_vbin16(self): return self.read(self.read_uint16()) def write_vbin16(self, b): + if isinstance(b, buffer): + b = str(b) self.write_uint16(len(b)) self.write(b) @@ -155,23 +210,13 @@ class Codec(Packer): def read_vbin32(self): return self.read(self.read_uint32()) def write_vbin32(self, b): + if isinstance(b, buffer): + b = str(b) self.write_uint32(len(b)) self.write(b) - def write_map(self, m): - sc = StringCodec(self.spec) - if m is not None: - sc.write_uint32(len(m)) - for k, v in m.items(): - type = self.spec.encoding(v.__class__) - if type == None: - raise CodecException("no encoding for %s" % v.__class__) - sc.write_str8(k) - sc.write_uint8(type.code) - type.encode(sc, v) - self.write_vbin32(sc.encoded) def read_map(self): - sc = StringCodec(self.spec, self.read_vbin32()) + sc = StringCodec(self.read_vbin32()) if not sc.encoded: return None count = sc.read_uint32() @@ -179,105 +224,146 @@ class Codec(Packer): while sc.encoded: k = sc.read_str8() code = sc.read_uint8() - type = self.spec.types[code] - v = type.decode(sc) + type = PRIMITIVE[code] + v = sc.read_primitive(type) result[k] = v return result + def write_map(self, m): + sc = StringCodec() + if m is not None: + sc.write_uint32(len(m)) + for k, v in m.items(): + type = self.encoding(v) + sc.write_str8(k) + sc.write_uint8(type.CODE) + sc.write_primitive(type, v) + self.write_vbin32(sc.encoded) + def read_array(self): + sc = StringCodec(self.read_vbin32()) + if not sc.encoded: + return None + type = PRIMITIVE[sc.read_uint8()] + count = sc.read_uint32() + result = [] + while count > 0: + result.append(sc.read_primitive(type)) + count -= 1 + return result def write_array(self, a): - sc = StringCodec(self.spec) + sc = StringCodec() if a is not None: if len(a) > 0: - type = self.spec.encoding(a[0].__class__) + type = self.encoding(a[0]) else: - type = self.spec.encoding(None.__class__) - sc.write_uint8(type.code) + type = self.encoding(None) + sc.write_uint8(type.CODE) sc.write_uint32(len(a)) for o in a: - type.encode(sc, o) + sc.write_primitive(type, o) self.write_vbin32(sc.encoded) - def read_array(self): - sc = StringCodec(self.spec, self.read_vbin32()) + + def read_list(self): + sc = StringCodec(self.read_vbin32()) if not sc.encoded: return None - type = self.spec.types[sc.read_uint8()] count = sc.read_uint32() result = [] while count > 0: - result.append(type.decode(sc)) + type = PRIMITIVE[sc.read_uint8()] + result.append(sc.read_primitive(type)) count -= 1 return result - def write_list(self, l): - sc = StringCodec(self.spec) + sc = StringCodec() if l is not None: sc.write_uint32(len(l)) for o in l: - type = self.spec.encoding(o.__class__) - sc.write_uint8(type.code) - type.encode(sc, o) + type = self.encoding(o) + sc.write_uint8(type.CODE) + sc.write_primitive(type, o) self.write_vbin32(sc.encoded) - def read_list(self): - sc = StringCodec(self.spec, self.read_vbin32()) - if not sc.encoded: - return None - count = sc.read_uint32() - result = [] - while count > 0: - type = self.spec.types[sc.read_uint8()] - result.append(type.decode(sc)) - count -= 1 - return result def read_struct32(self): size = self.read_uint32() code = self.read_uint16() - type = self.spec.structs[code] - fields = type.decode_fields(self) - return Struct(type, **fields) + cls = COMPOUND[code] + op = cls() + self.read_fields(op) + return op def write_struct32(self, value): - sc = StringCodec(self.spec) - sc.write_uint16(value._type.code) - value._type.encode_fields(sc, value) - self.write_vbin32(sc.encoded) - - def read_control(self): - cntrl = self.spec.controls[self.read_uint16()] - return Struct(cntrl, **cntrl.decode_fields(self)) - def write_control(self, ctrl): - type = ctrl._type - self.write_uint16(type.code) - type.encode_fields(self, ctrl) - - def read_command(self): - type = self.spec.commands[self.read_uint16()] - hdr = self.spec["session.header"].decode(self) - cmd = Struct(type, **type.decode_fields(self)) - return hdr, cmd - def write_command(self, hdr, cmd): - self.write_uint16(cmd._type.code) - hdr._type.encode(self, hdr) - cmd._type.encode_fields(self, cmd) + self.write_compound(value) + + def read_compound(self, cls): + size = self.read_size(cls.SIZE) + if cls.CODE is not None: + code = self.read_uint16() + assert code == cls.CODE + op = cls() + self.read_fields(op) + return op + def write_compound(self, op): + sc = StringCodec() + if op.CODE is not None: + sc.write_uint16(op.CODE) + sc.write_fields(op) + self.write_size(op.SIZE, len(sc.encoded)) + self.write(sc.encoded) + + def read_fields(self, op): + flags = 0 + for i in range(op.PACK): + flags |= (self.read_uint8() << 8*i) + + for i in range(len(op.FIELDS)): + f = op.FIELDS[i] + if flags & (0x1 << i): + if COMPOUND.has_key(f.type): + value = self.read_compound(COMPOUND[f.type]) + else: + value = getattr(self, "read_%s" % f.type)() + setattr(op, f.name, value) + def write_fields(self, op): + flags = 0 + for i in range(len(op.FIELDS)): + f = op.FIELDS[i] + value = getattr(op, f.name) + if f.type == "bit": + present = value + else: + present = value != None + if present: + flags |= (0x1 << i) + for i in range(op.PACK): + self.write_uint8((flags >> 8*i) & 0xFF) + for i in range(len(op.FIELDS)): + f = op.FIELDS[i] + if flags & (0x1 << i): + if COMPOUND.has_key(f.type): + enc = self.write_compound + else: + enc = getattr(self, "write_%s" % f.type) + value = getattr(op, f.name) + enc(value) def read_size(self, width): if width > 0: attr = "read_uint%d" % (width*8) return getattr(self, attr)() - def write_size(self, width, n): if width > 0: attr = "write_uint%d" % (width*8) getattr(self, attr)(n) def read_uuid(self): - return self.unpack("16s") - + return UUID(self.unpack("16s")) def write_uuid(self, s): + if isinstance(s, UUID): + s = s.bytes self.pack("16s", s) def read_bin128(self): return self.unpack("16s") - def write_bin128(self, b): self.pack("16s", b) @@ -285,14 +371,13 @@ class Codec(Packer): class StringCodec(Codec): - def __init__(self, spec, encoded = ""): - Codec.__init__(self, spec) + def __init__(self, encoded = ""): self.encoded = encoded - def write(self, s): - self.encoded += s - def read(self, n): result = self.encoded[:n] self.encoded = self.encoded[n:] return result + + def write(self, s): + self.encoded += s |
