Skip to content

Instantly share code, notes, and snippets.

@machisuji
Created November 26, 2011 12:16
Show Gist options
  • Select an option

  • Save machisuji/1395541 to your computer and use it in GitHub Desktop.

Select an option

Save machisuji/1395541 to your computer and use it in GitHub Desktop.
matching against a PushbackInputStream
object extr {
trait Message[T] {
def read(in: PushbackInputStream): Option[T]
def tag(in: PushbackInputStream) = {
val byte = in.read
in unread byte
byte
}
def peek(in: PushbackInputStream): Array[Byte] = {
val data = new Array[Byte](in.available)
in read data; in unread data
data
}
def unapply(in: PushbackInputStream): Option[T] = {
val data = peek(in)
val rest = if (data.isEmpty) new Array[Byte](0) else data.tail
println(getClass.getSimpleName.split("\\$").last + ".unapply(" +
data.headOption.getOrElse("empty") + " ... " + rest.mkString(" ") + ")")
read(in)
}
}
class Number(value: Int) {
override def toString = "Number(%s)" format value
}
object Number extends Message[Number] {
def read(in: PushbackInputStream): Option[Number] = {
if (tag(in) != 0) return None else in.read
val data = new Array[Byte](4)
in read data
Some(new Number(java.nio.ByteBuffer.wrap(data).getInt))
}
}
def receive[R](input: PushbackInputStream)(reader: PartialFunction[PushbackInputStream, R]) = {
val fallback: PartialFunction[PushbackInputStream, R] = {
case in => throw new RuntimeException("Unknown Message")
// actually respond to client with error, too
}
(reader orElse fallback) apply input
}
def createInputStream(data: Array[Byte]): PushbackInputStream =
new PushbackInputStream(new ByteArrayInputStream(data), data.size)
def text = createInputStream(1.toByte +: 6.toByte +: "Hallo!".getBytes)
def number = createInputStream(Array(0, 0, 0, 0, 42).map(_.toByte))
def fun1(input: PushbackInputStream) = receive(input) {
case Number(n) => "Number: " + n
}
def fun2(input: PushbackInputStream) = receive(input) {
case Number(n) => "Number: " + n
case _ => "nahahaaaa"
}
}
import extr._
scala> fun1(number)
Number.unapply(0 ... 0 0 0 42)
Number.unapply(empty ... )
scala.MatchError: java.io.PushbackInputStream@72e1c560 (of class java.io.PushbackInputStream)
at ...
scala> fun2(number)
Number.unapply(0 ... 0 0 0 42)
res4: java.lang.String = Number: Number(42)
scala>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment