Created
March 29, 2012 18:55
-
-
Save 9len/2242038 to your computer and use it in GitHub Desktop.
A simple debug TProtocol
This file contains 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
import com.twitter.conversions.string._ | |
import java.nio.ByteBuffer | |
import org.apache.thrift.protocol._ | |
import org.apache.thrift.transport.TTransport | |
import scala.collection.mutable | |
object ThriftDebugProtocol { | |
val Tab = " " | |
val KeyValueDelim = " = " | |
val NewLine = "\n" | |
val StructOpen = "{" | |
val StructClose = "}" | |
val SetOpen = "[" | |
val SetClose = "]" | |
val ListOpen = "(" | |
val ListClose = ")" | |
class Factory( | |
tab: String = Tab, | |
keyValueDelim: String = KeyValueDelim, | |
newline: String = NewLine, | |
structOpen: String = StructOpen, | |
structClose: String = StructClose, | |
setOpen: String = SetOpen, | |
setClose: String = SetClose, | |
listOpen: String = ListOpen, | |
listClose: String = ListClose) | |
extends TProtocolFactory | |
{ | |
override def getProtocol(transport: TTransport): TProtocol = | |
new ThriftDebugProtocol( | |
transport, | |
tab, | |
keyValueDelim, | |
newline, | |
structOpen, | |
structClose, | |
setOpen, | |
setClose, | |
listOpen, | |
listClose) | |
} | |
} | |
/** | |
* A write-only protocol for generating human-readable representations of thrift structures | |
*/ | |
class ThriftDebugProtocol( | |
transport: TTransport, | |
tab: String, | |
keyValueDelim: String, | |
newline: String, | |
structOpen: String, | |
structClose: String, | |
setOpen: String, | |
setClose: String, | |
listOpen: String, | |
listClose: String) | |
extends TProtocol(transport) | |
{ | |
import ThriftDebugProtocol._ | |
protected[this] def unsupported[A]: A = { | |
throw new UnsupportedOperationException( | |
"read operations not supported, TDebugProtocol is write-only") | |
} | |
override def readBinary() = unsupported | |
override def readBool() = unsupported | |
override def readByte() = unsupported | |
override def readDouble() = unsupported | |
override def readFieldBegin() = unsupported | |
override def readFieldEnd() = unsupported | |
override def readI16() = unsupported | |
override def readI32() = unsupported | |
override def readI64() = unsupported | |
override def readListBegin() = unsupported | |
override def readListEnd() = unsupported | |
override def readMapBegin() = unsupported | |
override def readMapEnd() = unsupported | |
override def readMessageBegin() = unsupported | |
override def readMessageEnd() = unsupported | |
override def readSetBegin() = unsupported | |
override def readSetEnd() = unsupported | |
override def readString() = unsupported | |
override def readStructBegin() = unsupported | |
override def readStructEnd() = unsupported | |
/** | |
* used to determine indent amount | |
*/ | |
protected[this] var depth = 0 | |
/** | |
* used to determine if we're inside a list or set, so we can | |
* indent the values properly. | |
*/ | |
protected[this] val collectionStack = new mutable.Stack[Unit] | |
protected def indent = (tab * depth) | |
protected[this] def push(brace: String) { | |
transport.write(brace.getBytes) | |
transport.write(newline.getBytes) | |
depth += 1 | |
} | |
protected[this] def pop(brace: String) { | |
depth -= 1 | |
transport.write(indent.getBytes) | |
writeString(brace) | |
} | |
override def reset() { | |
depth = 0 | |
collectionStack.clear() | |
} | |
override def writeBinary(buf: ByteBuffer) { | |
writeString(buf.array.hexlify) | |
} | |
override def writeString(str: String) { | |
if (collectionStack.nonEmpty) { | |
transport.write(indent.getBytes) | |
} | |
transport.write(str.quoteC.getBytes) | |
transport.write(newline.getBytes) | |
} | |
override def writeDouble(dub: Double) { | |
writeString(dub.toString) | |
} | |
override def writeI64(i64: Long) { | |
writeString(i64.toString) | |
} | |
override def writeI32(i32: Int) { | |
writeI64(i32) | |
} | |
override def writeI16(i16: Short) { | |
writeI64(i16) | |
} | |
override def writeByte(b: Byte) { | |
writeI64(b) | |
} | |
override def writeBool(b: Boolean) { | |
writeString(b.toString) | |
} | |
override def writeSetBegin(s: TSet) { | |
collectionStack.push() | |
push(setOpen) | |
} | |
override def writeSetEnd() { | |
collectionStack.pop() | |
pop(setClose) | |
} | |
override def writeListBegin(l: TList) { | |
collectionStack.push() | |
push(listOpen) | |
} | |
override def writeListEnd() { | |
collectionStack.pop() | |
pop(listClose) | |
} | |
override def writeMapBegin(m: TMap) { | |
push(structOpen) | |
} | |
override def writeMapEnd() { | |
pop(structClose) | |
} | |
override def writeStructBegin(s: TStruct) { | |
push(structOpen) | |
} | |
override def writeStructEnd() { | |
pop(structClose) | |
} | |
override def writeFieldBegin(f: TField) { | |
transport.write(indent.getBytes) | |
transport.write(f.name.getBytes) | |
transport.write(keyValueDelim.getBytes) | |
} | |
override def writeFieldStop() = () | |
override def writeFieldEnd() = () | |
override def writeMessageBegin(m: TMessage) { | |
push(structOpen) | |
} | |
override def writeMessageEnd() { | |
pop(structClose) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment