Q на Python сериализация / десериализация - PullRequest
1 голос
/ 31 марта 2010

Какие у меня есть шансы создать экземпляр, сохранить и сериализовать / десериализовать в / из двоичных данных классы Python, отражающие этот паттерн (принят из RFC 2246 [TLS]):

   enum { apple, orange } VariantTag;
   struct {
       uint16 number;
       opaque string<0..10>; /* variable length */
   } V1;
   struct {
       uint32 number;
       opaque string[10];    /* fixed length */
   } V2;
   struct {
       select (VariantTag) { /* value of selector is implicit */
           case apple: V1;   /* VariantBody, tag = apple */
           case orange: V2;  /* VariantBody, tag = orange */
       } variant_body;       /* optional label on variant */
   } VariantRecord;

По сути, мне нужно было бы определить (вариант) класса VariantRecord, который варьируется в зависимости от значения VariantTag. Это не так сложно. Задача состоит в том, чтобы найти наиболее общий способ создания класса, который сериализует / десериализует в поток байтов и из него ... Pickle, буфер протокола Google, маршал - это не вариант.

Я добился небольшого успеха с явной «сериализацией def» в моем классе, но я не очень доволен этим, потому что она недостаточно универсальна.

Я надеюсь, что смогу выразить проблему.

Мое текущее решение на случай, если VariantTag = apple будет выглядеть так, но мне это не очень нравится

import binascii
import struct

class VariantRecord(object):
  def __init__(self, number, opaque):
    self.number = number
    self.opaque = opaque
  def serialize(self):
    out = struct.pack('>HB%ds' % len(self.opaque), self.number, len(self.opaque), self.opaque)
    return out


v = VariantRecord(10, 'Hello')
print binascii.hexlify(v.serialize())

>> 000a0548656c6c6f

Привет

1 Ответ

0 голосов
/ 02 апреля 2010

Два предложения:

  1. Для структуры переменной длины используйте фиксированный формат и просто нарезать результат.
  2. Использовать struct.Struct

например. Если я правильно понял ваши форматы (есть ли длина байта, которая появилась в вашем примере, но не упоминалась изначально, присутствует и в другом варианте?)

>>> import binascii
>>> import struct
>>> V1 = struct.Struct(">H10p")
>>> V2 = struct.Struct(">L10p")
>>> def serialize(variant, n, s):
    if variant:
        return V2.pack(n,s)
    else:
        return V1.pack(n,s)[:len(s)+3]


>>> print binascii.hexlify(serialize(False, 10, 'hello')) #V1
000a0568656c6c6f
>>> print binascii.hexlify(serialize(True, 10, 'hello')) #V2
0000000a0568656c6c6f00000000
>>> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...