Created
November 26, 2011 12:16
-
-
Save machisuji/1395541 to your computer and use it in GitHub Desktop.
matching against a PushbackInputStream
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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._ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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