2010-03-31 6 views
1

Quelles sont les chances que je dois instancier, garder et linéariser/désérialiser à/de classes Python de données binaires reflétant ce modèle (adopté à la RFC 2246 [TLS]):Q sur sérialisation Python/désérialisation

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; 

Fondamentalement Je devrais définir une classe (variante) VariantRecord, qui varie en fonction de la valeur de VariantTag. Ce n'est pas si difficile. Le défi consiste à trouver la manière la plus générique de construire une classe, qui sérialise/désérialise vers et à partir d'un flux d'octets ... Pickle, tampon de protocole Google, marshal n'est pas une option.

J'ai eu peu de succès en ayant une "sérialité sérielle" explicite dans ma classe, mais je ne suis pas très content, parce que ce n'est pas assez générique.

J'espère pouvoir exprimer le problème.

Ma solution actuelle en cas VariantTag = pomme devrait ressembler à ceci, mais je ne l'aime pas trop

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 

Cordialement

+0

Pourquoi n'êtes-vous pas heureux avec elle? –

+0

Quel est le problème avec le cornichon? Pourquoi vous souciez-vous des méthodes quelque peu ésotériques d'utiliser C++ lorsque vous utilisez Python? Qu'aimeriez-vous avoir? Il semble que vous souhaitiez une méthode dense pour stocker des données, mais il est difficile de dire ce que vous essayez réellement de généraliser. – Bear

+0

Je dois mettre en œuvre http://zinfandel.levkowetz.com/html/draft-ietf-p2psip-base-08. J'espère que tout dit. Je dois respecter le protocole de ligne, qui est binaire, mais pas conforme au pickle. Je ne suis pas content, parce que ce n'est pas assez générique :) – neil

Répondre

0

Deux suggestions:

  1. Pour la variable structure de longueur utilise un format fixe et coupe juste le résultat.
  2. utilisation struct.Struct

par exemple, Si je comprends vos formats correctement (l'octet de longueur qui est apparu dans votre exemple, mais n'a pas été mentionné à l'origine dans l'autre variante également?)

>>> 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 
>>> 
+0

Hmm. Merci pour l'indice, mais V1 n'est pas sérialisé correctement. La notation "<0..10>" a été adoptée à partir du RFC TLS. Il est nécessaire de précéder chaque tableau de longueur variable d'octets par un élément indiquant la longueur _current_ de la structure. Dans le cas V1, le résultat attendu devrait ressembler à celui de mon échantillon. – neil

+0

Je ne vois pas comment mon résultat V1 diffère du vôtre (sauf que j'ai utilisé une minuscule h dans 'bonjour'). La longueur actuelle est incluse dans le résultat: c'est ce que fait le format 'p' dans Struct. – Duncan

+0

Ah, d'accord. N'était pas au courant du "p". Merci – neil