Philipp Haller | 2 Aug 2006 12:28
Picon
Picon
Favicon

Re: BytePickle examples?

>> This is a definition of a suitable pickler:
>> val personPickler = wrap(p: Pair[String,int] => Person(p._1, p._2),
>>                          p: Person => Pair(p.name, p.age),
>>                          pair(string, int))
> 
> 
> Are you working with the same library version as me?  This doesn't seem 
> to actually compile.  It seems like int is missing; I had to use nat.

Ah, yes. Sorry, it used to work with an earlier version of the library 
(I didn't compile it). Actually, I am thinking about renaming `nat' to 
`base128' because it encodes integers into base128.

> The question I have is: How do I get an integer to always pickle as a 4 
> byte, network order thing?

I attached some code with a pickler that always pickles integers as 4 
bytes. I don't know which order you need, though. If you think a pickler 
for integers as 4 bytes in "network order" is generally useful, we might 
add this to our pickler library.

> As a side note, you might want to decrease the code density a bit for 
> the sake of those of us who aren't as familiar with Scala.  It took me 
> more than a little hunting through the Scala reference to unwind your 
> sample pickler into something that gave enough error verbosity to figure 
> out what was wrong.

OK, I'll try to be more verbose next time.

Cheers,
-- Philipp
import scala.io.BytePickle._

/**
 A pickler for integers as 4 bytes.

 Author: Philipp Haller <philipp.haller <at> epfl.ch>
 */
object Main {
  def byteArrayToInt(b: Array[byte]): int = {
    byteArrayToInt(b, 0)
  }

  def byteArrayToInt(b: Array[byte], offset: int): int = {
    var value = 0
    for (val i <- List.range(0, 4)) {
      val shift = (4 - 1 - i) * 8
      value = value + (b(i + offset) & 0x000000FF) << shift
    }
    value
  }

  def intToByteArray(value: int): Array[byte] = {
    val b = new Array[byte](4)
    for (val i <- List.range(0, 4)) {
      val offset = (b.length - 1 - i) * 8
      b(i) = ((value >>> offset) & 0xFF).asInstanceOf[byte]
    }
    b
  }

  def dumpBytes(bs: Array[byte]) = {
    val buf = new StringBuffer(bs.length)
    for (val i <- List.range(0, bs.length)) {
      val hex: String = Integer.toHexString(0x0100 + (bs(i) & 0x00FF)).substring(1)
      buf.append((if (hex.length() < 2) "0" else "") + hex)
    }
    buf.toString()
  }

  def int4: SPU[int] = new SPU[int] {
    def appP(n: int, s: PicklerState): PicklerState = {
      new PicklerState(Array.concat(s.stream, intToByteArray(n)), s.dict);
    }
    def appU(s: UnPicklerState): Pair[int,UnPicklerState] = {
      Pair(byteArrayToInt(s.stream.subArray(0, 4)), new UnPicklerState(s.stream.subArray(4,
s.stream.length), s.dict))
    }
  }

  def main(args: Array[String]) = {
    Console.println(dumpBytes(intToByteArray(8)))
    Console.println(dumpBytes(intToByteArray(10)))
    Console.println(dumpBytes(intToByteArray(32)))
    Console.println(dumpBytes(intToByteArray(100)))
    Console.println(dumpBytes(intToByteArray(65535)))

    val ba1 = pickle(int4, 8) 
    Console.println(dumpBytes(ba1))
    Console.println(unpickle(int4, ba1))

    val ba2 = pickle(int4, 10) 
    Console.println(dumpBytes(ba2))
    Console.println(unpickle(int4, ba2))

    val ba3 = pickle(int4, 32) 
    Console.println(dumpBytes(ba3))
    Console.println(unpickle(int4, ba3))

    val ba4 = pickle(int4, 65535) 
    Console.println(dumpBytes(ba4))
    Console.println(unpickle(int4, ba4))
  }
}

Gmane