He usado la biblioteca sbinary antes y es muy agradable. La documentación es un poco escasa, pero le sugiero que primero vea el viejo wiki page ya que eso le da un punto de partida. Luego, revise las especificaciones de prueba, ya que eso le da algunos ejemplos muy buenos.
El principal beneficio de sbinary es que le ofrece una forma de describir el formato de conexión de cada objeto como un objeto de Formato. A continuación, puede encapsular esos tipos de formato en un objeto Format de nivel superior y Scala hace todo el trabajo pesado de buscar ese tipo siempre que lo haya incluido en el alcance actual como un objeto implícito.
Como digo a continuación, ahora recomendaría que la gente use scodec en lugar de sbinary. Como un ejemplo de cómo utilizar scodec, voy a implementar cómo leer una representación binaria en la memoria de la siguiente estructura C:
struct ST
{
long long ll; // @ 0
int i; // @ 8
short s; // @ 12
char ch1; // @ 14
char ch2; // @ 15
} ST;
Una clase caso Scala juego sería:
case class ST(ll: Long, i: Int, s: Short, ch1: String, ch2: String)
I Me estoy haciendo las cosas un poco más fáciles al decir que estamos almacenando cadenas en lugar de caracteres y diré que son caracteres UTF-8 en la estructura. Tampoco estoy tratando con los detalles endian o el tamaño real de los tipos largo e int en esta arquitectura y simplemente suponiendo que son 64 y 32 respectivamente.
Los analizadores de Scodec generalmente usan combinadores para construir analizadores de nivel superior de los de nivel inferior. Entonces para abajo, definiremos un analizador sintáctico que combina un valor de 8 bytes, un valor de 4 bytes, un valor de 2 bytes, un valor de 1 byte y un valor de 1 byte más.El retorno de esta combinación es un códec de tupla:
val myCodec: Codec[Long ~ Int ~ Short ~ String ~ String] =
int64 ~ int32 ~ short16 ~ fixedSizeBits(8L, utf8) ~ fixedSizeBits(8L, utf8)
Entonces podemos transformar esto en la clase caso ST llamando a la función xmap
en él que tiene dos funciones, una para activar el códec de tuplas en el tipo de destino y otra función para tomar el tipo de destino y convertirla en la forma de tupla:
val stCodec: Codec[ST] = myCodec.xmap[ST]({case ll ~ i ~ s ~ ch1 ~ ch2 => ST(ll, i, s, ch1, ch2)}, st => st.ll ~ st.i ~ st.s ~ st.ch1 ~ st.ch2)
Ahora, puede utilizar el códec de este modo:
stCodec.encode(ST(1L, 2, 3.shortValue, "H", "I"))
res0: scodec.Attempt[scodec.bits.BitVector] = Successful(BitVector(128 bits, 0x00000000000000010000000200034849))
res0.flatMap(stCodec.decode)
=> res1: scodec.Attempt[scodec.DecodeResult[ST]] = Successful(DecodeResult(ST(1,2,3,H,I),BitVector(empty)))
Le animo a que mire los Scaladocs y no a la Guía ya que hay muchos más detalles en los Scaladocs. La guía es un buen comienzo desde lo básico, pero no entra mucho en la composición, pero los Scaladocs lo cubren bastante bien.
En caso de que alguien vea esto, recomendaría http://scodec.org ahora. Los mismos beneficios que sbinary pero mejor soporte y más capacidades. – Aaron
Todavía no tengo idea de cómo usar las bibliotecas 'sbinary' o' scodec' para analizar un protocolo binario definido en otra parte como una secuencia de estructuras C incluso después de pasar por las documentaciones respectivas. ¿Podría elaborar, preferiblemente con un fragmento de código? – nodakai
Acabo de agregar un ejemplo de análisis scodec para una estructura C-style. ¡Espero que ayude! – Aaron