2012-07-08 7 views
5

Estoy implementando un protocolo que dicta que una cadena que representa una contraseña debe ser serializada en un campo de 10 bytes de longitud fija. Estoy usando Data.Cereal para realizar esta tarea. Aquí está mi más reciente ir en él:serializar una cadena con Data.Cereal o Data.Binary

padText :: Int -> Text -> Text 
padText fieldLen = T.justifyLeft fieldLen '\NUL' 

putPassword :: Putter Password 
putPassword = put . TE.encodeUtf8 . padText 10 

poner en ByteString antepone un adicional trozo de 8 bytes en la parte frontal de lo que es la codificación de decisiones:

runPut $ putPassword "Friend" 

resultado en:

"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\nFriend\NUL\NUL\NUL\NUL" 

No quiero el trozo extra. ¿Por qué se pone así?

¿Alguien sabe cómo serializar solo los 10 bytes originales?

Respuesta

7

Supongo que por "el trozo extra" te refieres al primer bit de "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\n. Ese es un campo de longitud de 64 bits (observe que su valor es 10) que es parte de la definición de Serialize para ByteString. Como ya tiene una cadena de bytes después de llamar al TE.encodeUtf8, le sugiero que simplemente use putByteString para evitar el campo de longitud (o putLazyByteString si está importando un módulo de codificación de texto lento).

2

Como Thomas declaró put en ByteStrings, antes de la longitud codificada. Se muestra a continuación es la instancia real:

instance Serialize B.ByteString where 
    put bs = do put (B.length bs :: Int) 
       putByteString bs 
    ... 

putByteString por sí sola no. La solución es usar putByteString:

putPassword :: Putter Password 
putPassword = putByteString . TE.encodeUtf8 . padText 10 
Cuestiones relacionadas