diff options
author | Jens Geyer <jensg@apache.org> | 2015-03-02 23:37:15 +0100 |
---|---|---|
committer | Jens Geyer <jensg@apache.org> | 2015-03-05 23:43:23 +0100 |
commit | 426ab8680126ac914c566adbcda3d6e93d57df64 (patch) | |
tree | c168201bc2b7a232688865fbdbb306ac5e3b51ea | |
parent | 6f7399b355b77b3e6dc32ffa475d42493afe2d90 (diff) | |
download | thrift-426ab8680126ac914c566adbcda3d6e93d57df64.tar.gz |
THRIFT-3022 Compact protocol for Haxe
Client: Haxe
Patch: Jens Geyer
This closes #388
-rw-r--r-- | lib/haxe/src/org/apache/thrift/helper/BitConverter.hx | 159 | ||||
-rw-r--r-- | lib/haxe/src/org/apache/thrift/helper/ZigZag.hx | 128 | ||||
-rw-r--r-- | lib/haxe/src/org/apache/thrift/protocol/TCompactProtocol.hx | 730 | ||||
-rw-r--r-- | lib/haxe/src/org/apache/thrift/protocol/TCompactProtocolFactory.hx | 40 | ||||
-rw-r--r-- | test/haxe/src/Arguments.hx | 3 | ||||
-rw-r--r-- | test/haxe/src/TestClient.hx | 150 | ||||
-rw-r--r-- | test/haxe/src/TestMacro.hx | 8 | ||||
-rw-r--r-- | test/haxe/src/TestServer.hx | 5 | ||||
-rw-r--r-- | test/haxe/src/TestServerHandler.hx | 12 |
9 files changed, 1162 insertions, 73 deletions
diff --git a/lib/haxe/src/org/apache/thrift/helper/BitConverter.hx b/lib/haxe/src/org/apache/thrift/helper/BitConverter.hx new file mode 100644 index 000000000..7f7c8f794 --- /dev/null +++ b/lib/haxe/src/org/apache/thrift/helper/BitConverter.hx @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.thrift.helper; + +import haxe.Int64; +import haxe.io.Bytes; +import haxe.io.BytesBuffer; + +class BitConverter { + + public static function DoubleToInt64Bits( db : Float) : Int64 { + var buf = new BytesBuffer(); + buf.addDouble( db); + return bytesToLong( buf.getBytes()); + } + + + public static function Int64BitsToDouble( i64 : Int64) : Float { + var buf = new BytesBuffer(); + buf.add( fixedLongToBytes( i64)); + return buf.getBytes().getDouble(0); + } + + + + /** + * Convert a long into little-endian bytes in buf starting at off and going + * until off+7. + */ + public static function fixedLongToBytes( n : Int64) : Bytes { + var buf = Bytes.alloc(8); + buf.set( 0, Int64.getLow( Int64.and( n, Int64.make(0, 0xff)))); + buf.set( 1, Int64.getLow( Int64.and( Int64.shr( n, 8), Int64.make(0, 0xff)))); + buf.set( 2, Int64.getLow( Int64.and( Int64.shr( n, 16), Int64.make(0, 0xff)))); + buf.set( 3, Int64.getLow( Int64.and( Int64.shr( n, 24), Int64.make(0, 0xff)))); + buf.set( 4, Int64.getLow( Int64.and( Int64.shr( n, 32), Int64.make(0, 0xff)))); + buf.set( 5, Int64.getLow( Int64.and( Int64.shr( n, 40), Int64.make(0, 0xff)))); + buf.set( 6, Int64.getLow( Int64.and( Int64.shr( n, 48), Int64.make(0, 0xff)))); + buf.set( 7, Int64.getLow( Int64.and( Int64.shr( n, 56), Int64.make(0, 0xff)))); + return buf; + } + + /** + * Note that it's important that the mask bytes are long literals, + * otherwise they'll default to ints, and when you shift an int left 56 bits, + * you just get a messed up int. + */ + public static function bytesToLong( bytes : Bytes) : Int64 { + var result : Int64 = Int64.make(0, 0); + result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(7))); + result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(6))); + result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(5))); + result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(4))); + result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(3))); + result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(2))); + result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(1))); + result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(0))); + return result; + } + + + #if debug + private static function TestBTL( test : Int64) : Void { + var buf : Bytes = fixedLongToBytes( test); + var erg = bytesToLong(buf); + if ( Int64.compare( erg, test) != 0) + throw 'BitConverter.bytesToLongTest($test) failed: $erg'; + } + #end + + + #if debug + private static function TestPair( a : Float, b : Int64) : Void { + var bx = DoubleToInt64Bits(a); + if ( Int64.compare( bx, b) != 0) + throw 'BitConverter.TestPair: DoubleToInt64Bits($a): expected $b, got $bx'; + var ax = Int64BitsToDouble(b); + if( ax != a) + throw 'BitConverter.TestPair: Int64BitsToDouble($b: expected $a, got $ax'; + } + #end + + + #if debug + public static function UnitTest() : Void { + + // bytesToLong() + var i : Int; + TestBTL( Int64.make(0,0)); + for ( i in 0 ... 62) { + TestBTL( Int64.shl( Int64.make(0,1), i)); + TestBTL( Int64.sub( Int64.make(0,0), Int64.shl( Int64.make(0,1), i))); + } + TestBTL( Int64.make(0x7FFFFFFF,0xFFFFFFFF)); + TestBTL( Int64.make(cast(0x80000000,Int),0x00000000)); + + // DoubleToInt64Bits; + TestPair( 1.0000000000000000E+000, Int64.make(cast(0x3FF00000,Int),cast(0x00000000,Int))); + TestPair( 1.5000000000000000E+001, Int64.make(cast(0x402E0000,Int),cast(0x00000000,Int))); + TestPair( 2.5500000000000000E+002, Int64.make(cast(0x406FE000,Int),cast(0x00000000,Int))); + TestPair( 4.2949672950000000E+009, Int64.make(cast(0x41EFFFFF,Int),cast(0xFFE00000,Int))); + TestPair( 3.9062500000000000E-003, Int64.make(cast(0x3F700000,Int),cast(0x00000000,Int))); + TestPair( 2.3283064365386963E-010, Int64.make(cast(0x3DF00000,Int),cast(0x00000000,Int))); + TestPair( 1.2345678901230000E-300, Int64.make(cast(0x01AA74FE,Int),cast(0x1C1E7E45,Int))); + TestPair( 1.2345678901234500E-150, Int64.make(cast(0x20D02A36,Int),cast(0x586DB4BB,Int))); + TestPair( 1.2345678901234565E+000, Int64.make(cast(0x3FF3C0CA,Int),cast(0x428C59FA,Int))); + TestPair( 1.2345678901234567E+000, Int64.make(cast(0x3FF3C0CA,Int),cast(0x428C59FB,Int))); + TestPair( 1.2345678901234569E+000, Int64.make(cast(0x3FF3C0CA,Int),cast(0x428C59FC,Int))); + TestPair( 1.2345678901234569E+150, Int64.make(cast(0x5F182344,Int),cast(0xCD3CDF9F,Int))); + TestPair( 1.2345678901234569E+300, Int64.make(cast(0x7E3D7EE8,Int),cast(0xBCBBD352,Int))); + TestPair( -1.7976931348623157E+308, Int64.make(cast(0xFFEFFFFF,Int),cast(0xFFFFFFFF,Int))); + TestPair( 1.7976931348623157E+308, Int64.make(cast(0x7FEFFFFF,Int),cast(0xFFFFFFFF,Int))); + TestPair( 4.9406564584124654E-324, Int64.make(cast(0x00000000,Int),cast(0x00000001,Int))); + TestPair( 0.0000000000000000E+000, Int64.make(cast(0x00000000,Int),cast(0x00000000,Int))); + TestPair( 4.94065645841247E-324, Int64.make(cast(0x00000000,Int),cast(0x00000001,Int))); + TestPair( 3.2378592100206092E-319, Int64.make(cast(0x00000000,Int),cast(0x0000FFFF,Int))); + TestPair( 1.3906711615669959E-309, Int64.make(cast(0x0000FFFF,Int),cast(0xFFFFFFFF,Int))); + TestPair( Math.NEGATIVE_INFINITY, Int64.make(cast(0xFFF00000,Int),cast(0x00000000,Int))); + TestPair( Math.POSITIVE_INFINITY, Int64.make(cast(0x7FF00000,Int),cast(0x00000000,Int))); + + // NaN is special + var i64nan = DoubleToInt64Bits( Math.NaN); + var i64cmp = Int64.make(cast(0xFFF80000, Int), cast(0x00000000, Int)); + if ( ! Math.isNaN( Int64BitsToDouble( i64cmp))) + throw 'BitConverter NaN-Test #1: expected NaN'; + + // For doubles, a quiet NaN is a bit pattern + // between 7FF8000000000000 and 7FFFFFFFFFFFFFFF + // or FFF8000000000000 and FFFFFFFFFFFFFFFF + var min1 = Int64.make( cast(0x7FF80000, Int), cast(0x00000000, Int)); + var max1 = Int64.make( cast(0x7FFFFFFF, Int), cast(0xFFFFFFFF, Int)); + var min2 = Int64.make( cast(0xFFF80000, Int), cast(0x00000000, Int)); + var max2 = Int64.make( cast(0xFFFFFFFF, Int), cast(0xFFFFFFFF, Int)); + var ok1 = (Int64.compare( min1, i64nan) <= 0) && (Int64.compare( i64nan, max1) <= 0); + var ok2 = (Int64.compare( min2, i64nan) <= 0) && (Int64.compare( i64nan, max2) <= 0); + if( ! (ok1 || ok2)) + throw 'BitConverter NaN-Test #2: failed'; + } + #end + +} +
\ No newline at end of file diff --git a/lib/haxe/src/org/apache/thrift/helper/ZigZag.hx b/lib/haxe/src/org/apache/thrift/helper/ZigZag.hx new file mode 100644 index 000000000..862060d8d --- /dev/null +++ b/lib/haxe/src/org/apache/thrift/helper/ZigZag.hx @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.thrift.helper; + +import haxe.Int64; + +class ZigZag { + + /** + * Convert n into a zigzag int. This allows negative numbers to be + * represented compactly as a varint. + */ + public static function FromInt( n : Int) : UInt { + return cast(n << 1,UInt) ^ cast(n >> 31,UInt); + } + + + /** + * Convert from zigzag int to int. + */ + public static function ToInt( n : UInt) : Int { + return (0x7FFFFFFF & cast(n >> 1,Int)) ^ (-cast(n & 1,Int)); + } + + + /** + * Convert l into a zigzag long. This allows negative numbers to be + * represented compactly as a varint. + */ + public static function FromLong( n : Int64) : Int64 { + return Int64.xor( Int64.shl(n, 1), Int64.shr(n, 63)); + } + + + /** + * Convert from zigzag long to long. + */ + public static function ToLong( n : Int64) : Int64 { + return Int64.xor( + Int64.and( + Int64.shr(n, 1), + Int64.make(0x7FFFFFFF, 0xFFFFFFFF)), + Int64.sub( + Int64.make(0, 0), + Int64.and(n, Int64.make(0,1)))); + } + + + #if debug + private static function Test32( test : Int) : Void { + var a : UInt = ZigZag.FromInt( test); + var b : Int = ZigZag.ToInt(a); + if( test != b) + throw 'ZigZag.Test32($test) failed: a = $a, b = $b'; + } + #end + + + + #if debug + private static function Test64( test : haxe.Int64) : Void { + var a : Int64 = ZigZag.FromLong( test); + var b : Int64 = ZigZag.ToLong(a); + if( Int64.compare( test, b) != 0) + throw 'ZigZag.Test64($test) failed: a = $a, b = $b'; + } + #end + + + #if debug + public static function UnitTest() : Void { + var u1 : UInt = 0xFFFFFFFE; + var u2 : UInt = 0xFFFFFFFF; + + // protobuf testcases + if( FromInt(0) != 0) throw 'pb #1 to ZigZag'; + if( FromInt(-1) != 1) throw 'pb #2 to ZigZag'; + if( FromInt(1) != 2) throw 'pb #3 to ZigZag'; + if( FromInt(-2) != 3) throw 'pb #4 to ZigZag'; + if( FromInt(2147483647) != u1) throw 'pb #5 to ZigZag'; + if( FromInt(-2147483648) != u2) throw 'pb #6 to ZigZag'; + + // protobuf testcases + if( ToInt(0) != 0) throw 'pb #1 from ZigZag'; + if( ToInt(1) != -1) throw 'pb #2 from ZigZag'; + if( ToInt(2) != 1) throw 'pb #3 from ZigZag'; + if( ToInt(3) != -2) throw 'pb #4 from ZigZag'; + if( ToInt(u1) != 2147483647) throw 'pb #5 from ZigZag, got ${ToInt(u1)}'; + if( ToInt(u2) != -2147483648) throw 'pb #6 from ZigZag, got ${ToInt(u2)}'; + + // back and forth 32 + Test32( 0); + for( i in 0 ... 30) { + Test32( 1 << i); + Test32( -(1 << i)); + } + Test32( 0x7FFFFFFF); + Test32( cast(0x80000000,Int)); + + // back and forth 64 + Test64( Int64.make(0,0)); + for( i in 0 ... 62) { + Test64( Int64.shl( Int64.make(0,1), i)); + Test64( Int64.sub( Int64.make(0,0), Int64.shl( Int64.make(0,1), i))); + } + Test64( Int64.make(0x7FFFFFFF,0xFFFFFFFF)); + Test64( Int64.make(cast(0x80000000,Int),0x00000000)); + } + #end +} +
\ No newline at end of file diff --git a/lib/haxe/src/org/apache/thrift/protocol/TCompactProtocol.hx b/lib/haxe/src/org/apache/thrift/protocol/TCompactProtocol.hx new file mode 100644 index 000000000..d08a6d0bc --- /dev/null +++ b/lib/haxe/src/org/apache/thrift/protocol/TCompactProtocol.hx @@ -0,0 +1,730 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.thrift.protocol; + +import haxe.io.Bytes; +import haxe.io.BytesInput; +import haxe.io.BytesOutput; +import haxe.io.BytesBuffer; +import haxe.ds.GenericStack; +import haxe.Int32; +import haxe.Int64; +import haxe.Utf8; + +import org.apache.thrift.TException; +import org.apache.thrift.transport.TTransport; +import org.apache.thrift.helper.ZigZag; +import org.apache.thrift.helper.BitConverter; + + +/** + * All of the on-wire type codes. + */ +class TCompactTypes { + public static inline var STOP = 0x00; + public static inline var BOOLEAN_TRUE = 0x01; + public static inline var BOOLEAN_FALSE = 0x02; + public static inline var BYTE = 0x03; + public static inline var I16 = 0x04; + public static inline var I32 = 0x05; + public static inline var I64 = 0x06; + public static inline var DOUBLE = 0x07; + public static inline var BINARY = 0x08; + public static inline var LIST = 0x09; + public static inline var SET = 0x0A; + public static inline var MAP = 0x0B; + public static inline var STRUCT = 0x0C; +} + +/** +* Binary protocol implementation for thrift. +*/ +class TCompactProtocol implements TProtocol { + + private static var ANONYMOUS_STRUCT : TStruct = new TStruct(""); + private static var TSTOP : TField = new TField("", TType.STOP, 0); + + private static inline var PROTOCOL_ID : Int = 0x82; + private static inline var VERSION : Int = 1; + private static inline var VERSION_MASK : Int = 0x1f; // 0001 1111 + private static inline var TYPE_MASK : Int = 0xE0; // 1110 0000 + private static inline var TYPE_BITS : Int = 0x07; // 0000 0111 + private static inline var TYPE_SHIFT_AMOUNT : Int = 5; + + + private static var ttypeToCompactType = [ + TType.STOP => TCompactTypes.STOP, + TType.BOOL => TCompactTypes.BOOLEAN_TRUE, + TType.BYTE => TCompactTypes.BYTE, + TType.DOUBLE => TCompactTypes.DOUBLE, + TType.I16 => TCompactTypes.I16, + TType.I32 => TCompactTypes.I32, + TType.I64 => TCompactTypes.I64, + TType.STRING => TCompactTypes.BINARY, + TType.STRUCT => TCompactTypes.STRUCT, + TType.MAP => TCompactTypes.MAP, + TType.SET => TCompactTypes.SET, + TType.LIST => TCompactTypes.LIST + ]; + + private static var tcompactTypeToType = [ + TCompactTypes.STOP => TType.STOP, + TCompactTypes.BOOLEAN_TRUE => TType.BOOL, + TCompactTypes.BOOLEAN_FALSE => TType.BOOL, + TCompactTypes.BYTE => TType.BYTE, + TCompactTypes.I16 => TType.I16, + TCompactTypes.I32 => TType.I32, + TCompactTypes.I64 => TType.I64, + TCompactTypes.DOUBLE => TType.DOUBLE, + TCompactTypes.BINARY => TType.STRING, + TCompactTypes.LIST => TType.LIST, + TCompactTypes.SET => TType.SET, + TCompactTypes.MAP => TType.MAP, + TCompactTypes.STRUCT => TType.STRUCT + ]; + + + /** + * Used to keep track of the last field for the current and previous structs, + * so we can do the delta stuff. + */ + private var lastField_ : GenericStack<Int> = new GenericStack<Int>(); + private var lastFieldId_ : Int = 0; + + /** + * If we encounter a boolean field begin, save the TField here so it can + * have the value incorporated. + */ + private var booleanField_ : Null<TField>; + + /** + * If we Read a field header, and it's a boolean field, save the boolean + * value here so that ReadBool can use it. + */ + private var boolValue_ : Null<Bool>; + + + // whether the underlying system holds Strings as UTF-8 + // http://old.haxe.org/manual/encoding + private static var utf8Strings = haxe.Utf8.validate("Ç-ß-Æ-Ю-Ш"); + + // the transport used + public var trans(default,null) : TTransport; + + + // TCompactProtocol Constructor + public function new( trans : TTransport) { + this.trans = trans; + } + + public function getTransport() : TTransport { + return trans; + } + + + public function Reset() : Void{ + while ( ! lastField_.isEmpty()) { + lastField_.pop(); + } + lastFieldId_ = 0; + } + + + /** + * Writes a byte without any possibility of all that field header nonsense. + * Used internally by other writing methods that know they need to Write a byte. + */ + private function WriteByteDirect( b : Int) : Void { + var buf = Bytes.alloc(1); + buf.set( 0, b); + trans.write( buf, 0, 1); + } + + /** + * Write an i32 as a varint. Results in 1-5 bytes on the wire. + */ + private function WriteVarint32( n : UInt) : Void { + var i32buf = new BytesBuffer(); + while (true) + { + if ((n & ~0x7F) == 0) + { + i32buf.addByte( n & 0xFF); + break; + } + else + { + i32buf.addByte( (n & 0x7F) | 0x80); + n >>= 7; + } + } + + var tmp = i32buf.getBytes(); + trans.write( tmp, 0, tmp.length); + } + + /** + * Write a message header to the wire. Compact Protocol messages contain the + * protocol version so we can migrate forwards in the future if need be. + */ + public function writeMessageBegin( message : TMessage) : Void { + Reset(); + + var versionAndType : Int = (VERSION & VERSION_MASK) | ((message.type << TYPE_SHIFT_AMOUNT) & TYPE_MASK); + WriteByteDirect( PROTOCOL_ID); + WriteByteDirect( versionAndType); + WriteVarint32( cast( message.seqid, UInt)); + writeString( message.name); + } + + /** + * Write a struct begin. This doesn't actually put anything on the wire. We + * use it as an opportunity to put special placeholder markers on the field + * stack so we can get the field id deltas correct. + */ + public function writeStructBegin(struct:TStruct) : Void { + lastField_.add( lastFieldId_); + lastFieldId_ = 0; + } + + /** + * Write a struct end. This doesn't actually put anything on the wire. We use + * this as an opportunity to pop the last field from the current struct off + * of the field stack. + */ + public function writeStructEnd() : Void { + lastFieldId_ = lastField_.pop(); + } + + /** + * Write a field header containing the field id and field type. If the + * difference between the current field id and the last one is small (< 15), + * then the field id will be encoded in the 4 MSB as a delta. Otherwise, the + * field id will follow the type header as a zigzag varint. + */ + public function writeFieldBegin(field:TField) : Void { + if (field.type == TType.BOOL) + booleanField_ = field; // we want to possibly include the value, so we'll wait. + else + WriteFieldBeginInternal(field, 0xFF); + } + + /** + * The workhorse of WriteFieldBegin. It has the option of doing a + * 'type override' of the type header. This is used specifically in the + * boolean field case. + */ + private function WriteFieldBeginInternal( field : TField, typeOverride : Int) : Void { + // if there's a type override, use that. + var typeToWrite : Int; + if ( typeOverride == 0xFF) + typeToWrite = getCompactType( field.type); + else + typeToWrite = typeOverride; + + // check if we can use delta encoding for the field id + if (field.id > lastFieldId_ && field.id - lastFieldId_ <= 15) + { + // Write them together + WriteByteDirect((field.id - lastFieldId_) << 4 | typeToWrite); + } + else + { + // Write them separate + WriteByteDirect(typeToWrite); + writeI16(field.id); + } + + lastFieldId_ = field.id; + } + + /** + * Write the STOP symbol so we know there are no more fields in this struct. + */ + public function writeFieldStop() : Void { + WriteByteDirect( cast(TCompactTypes.STOP, Int)); + } + + /** + * Write a map header. If the map is empty, omit the key and value type + * headers, as we don't need any additional information to skip it. + */ + public function writeMapBegin(map:TMap) : Void { + if (map.size == 0) + { + WriteByteDirect(0); + } + else + { + var kvtype = (getCompactType(map.keyType) << 4) | getCompactType(map.valueType); + WriteVarint32( cast( map.size, UInt)); + WriteByteDirect( kvtype); + } + } + + /** + * Write a list header. + */ + public function writeListBegin( list : TList) : Void { + WriteCollectionBegin( list.elemType, list.size); + } + + /** + * Write a set header. + */ + public function writeSetBegin( set : TSet) : Void { + WriteCollectionBegin( set.elemType, set.size); + } + + /** + * Write a boolean value. Potentially, this could be a boolean field, in + * which case the field header info isn't written yet. If so, decide what the + * right type header is for the value and then Write the field header. + * Otherwise, Write a single byte. + */ + public function writeBool(b : Bool) : Void { + var bct : Int = b ? TCompactTypes.BOOLEAN_TRUE : TCompactTypes.BOOLEAN_FALSE; + + if (booleanField_ != null) + { + // we haven't written the field header yet + WriteFieldBeginInternal( booleanField_, bct); + booleanField_ = null; + } + else + { + // we're not part of a field, so just Write the value. + WriteByteDirect( bct); + } + } + + /** + * Write a byte. Nothing to see here! + */ + public function writeByte( b : Int) : Void { + WriteByteDirect( b); + } + + /** + * Write an I16 as a zigzag varint. + */ + public function writeI16( i16 : Int) : Void { + WriteVarint32( ZigZag.FromInt( i16)); + } + + /** + * Write an i32 as a zigzag varint. + */ + public function writeI32( i32 : Int) : Void { + WriteVarint32( ZigZag.FromInt( i32)); + } + + /** + * Write an i64 as a zigzag varint. + */ + public function writeI64( i64 : haxe.Int64) : Void { + WriteVarint64( ZigZag.FromLong( i64)); + } + + /** + * Write a double to the wire as 8 bytes. + */ + public function writeDouble( dub : Float) : Void { + var data = BitConverter.fixedLongToBytes( BitConverter.DoubleToInt64Bits(dub)); + trans.write( data, 0, data.length); + } + + /** + * Write a string to the wire with a varint size preceding. + */ + public function writeString(str : String) : Void { + var buf = new BytesBuffer(); + if( utf8Strings) + buf.addString( str); // no need to encode on UTF8 targets, the string is just fine + else + buf.addString( Utf8.encode( str)); + var tmp = buf.getBytes(); + writeBinary( tmp); + } + + /** + * Write a byte array, using a varint for the size. + */ + public function writeBinary( bin : Bytes) : Void { + WriteVarint32( cast(bin.length,UInt)); + trans.write( bin, 0, bin.length); + } + + + // These methods are called by structs, but don't actually have any wire + // output or purpose. + public function writeMessageEnd() : Void { } + public function writeMapEnd() : Void { } + public function writeListEnd() : Void { } + public function writeSetEnd() : Void { } + public function writeFieldEnd() : Void { } + + // + // Internal writing methods + // + + /** + * Abstract method for writing the start of lists and sets. List and sets on + * the wire differ only by the type indicator. + */ + private function WriteCollectionBegin( elemType : Int, size : Int) : Void { + if (size <= 14) { + WriteByteDirect( size << 4 | getCompactType(elemType)); + } + else { + WriteByteDirect( 0xf0 | getCompactType(elemType)); + WriteVarint32( cast(size, UInt)); + } + } + + /** + * Write an i64 as a varint. Results in 1-10 bytes on the wire. + */ + private function WriteVarint64(n : haxe.Int64) : Void { + var varint64out = new BytesBuffer(); + while (true) + { + if( Int64.isZero( Int64.and( n, Int64.neg(Int64.make(0,0x7F))))) + { + varint64out.addByte( Int64.getLow(n)); + break; + } + else + { + varint64out.addByte( (Int64.getLow(n) & 0x7F) | 0x80); + n = Int64.shr( n, 7); + n = Int64.and( n, Int64.make(0x01FFFFFF,0xFFFFFFFF)); // clean out the shifted 7 bits + } + } + var tmp = varint64out.getBytes(); + trans.write( tmp, 0, tmp.length); + } + + + /** + * Read a message header. + */ + public function readMessageBegin():TMessage { + Reset(); + + var protocolId : Int = readByte(); + if (protocolId != PROTOCOL_ID) { + throw new TProtocolException( TProtocolException.INVALID_DATA, "Expected protocol id " + StringTools.hex(PROTOCOL_ID,2) + " but got " + StringTools.hex(protocolId)); + } + + var versionAndType : Int = readByte(); + var version : Int = (versionAndType & VERSION_MASK); + if (version != VERSION) { + throw new TProtocolException( TProtocolException.INVALID_DATA, "Expected version " + VERSION + " but got " + version); + } + + var type : Int = ((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS); + var seqid : Int = cast( ReadVarint32(), Int); + var msgNm : String = readString(); + return new TMessage( msgNm, type, seqid); + } + + /** + * Read a struct begin. There's nothing on the wire for this, but it is our + * opportunity to push a new struct begin marker onto the field stack. + */ + public function readStructBegin():TStruct { + lastField_.add(lastFieldId_); + lastFieldId_ = 0; + return ANONYMOUS_STRUCT; + } + + /** + * Doesn't actually consume any wire data, just removes the last field for + * this struct from the field stack. + */ + public function readStructEnd() : Void { + // consume the last field we Read off the wire. + lastFieldId_ = lastField_.pop(); + } + + /** + * Read a field header off the wire. + */ + public function readFieldBegin() : TField { + var type : Int = readByte(); + + // if it's a stop, then we can return immediately, as the struct is over. + if (type == cast(TCompactTypes.STOP,Int)) { + return TSTOP; + } + + var fieldId : Int; + + // mask off the 4 MSB of the type header. it could contain a field id delta. + var modifier : Int = ((type & 0xf0) >> 4); + if (modifier == 0) + fieldId = readI16(); // not a delta. look ahead for the zigzag varint field id. + else + fieldId = lastFieldId_ + modifier; // add the delta to the last Read field id. + + var field : TField = new TField( "", cast(getTType(type & 0x0f),Int), fieldId); + + // if this happens to be a boolean field, the value is encoded in the type + if (isBoolType(type)) { + // save the boolean value in a special instance variable. + boolValue_ = ((type & 0x0f) == cast(TCompactTypes.BOOLEAN_TRUE,Int)); + } + + // push the new field onto the field stack so we can keep the deltas going. + lastFieldId_ = field.id; + return field; + } + + /** + * Read a map header off the wire. If the size is zero, skip Reading the key + * and value type. This means that 0-length maps will yield TMaps without the + * "correct" types. + */ + public function readMapBegin() : TMap { + var size : Int = cast( ReadVarint32(), Int); + var keyAndValueType : Int = ((size == 0) ? 0 : readByte()); + var key : Int = cast( getTType( (keyAndValueType & 0xF0) >> 4), Int); + var val : Int = cast( getTType( keyAndValueType & 0x0F), Int); + return new TMap( key, val, size); + } + + /** + * Read a list header off the wire. If the list size is 0-14, the size will + * be packed into the element type header. If it's a longer list, the 4 MSB + * of the element type header will be 0xF, and a varint will follow with the + * true size. + */ + public function readListBegin():TList { + var size_and_type : Int = readByte(); + + var size : Int = ((size_and_type & 0xF0) >> 4) & 0x0F; + if (size == 15) { + size = cast( ReadVarint32(), Int); + } + + var type = getTType(size_and_type); + return new TList( type, size); + } + + /** + * Read a set header off the wire. If the set size is 0-14, the size will + * be packed into the element type header. If it's a longer set, the 4 MSB + * of the element type header will be 0xF, and a varint will follow with the + * true size. + */ + public function readSetBegin() : TSet { + var size_and_type : Int = readByte(); + + var size : Int = ((size_and_type & 0xF0) >> 4) & 0x0F; + if (size == 15) { + size = cast( ReadVarint32(), Int); + } + + var type = getTType(size_and_type); + return new TSet( type, size); + } + + /** + * Read a boolean off the wire. If this is a boolean field, the value should + * already have been Read during ReadFieldBegin, so we'll just consume the + * pre-stored value. Otherwise, Read a byte. + */ + public function readBool() : Bool { + if (boolValue_ != null) { + var result : Bool = boolValue_; + boolValue_ = null; + return result; + } + + return (readByte() == cast(TCompactTypes.BOOLEAN_TRUE,Int)); + } + + /** + * Read a single byte off the wire. Nothing interesting here. + */ + public function readByte() : Int { + var byteRawBuf = new BytesBuffer(); + trans.readAll( byteRawBuf, 0, 1); + return byteRawBuf.getBytes().get(0); + } + + /** + * Read an i16 from the wire as a zigzag varint. + */ + public function readI16() : Int { + return ZigZag.ToInt( ReadVarint32()); + } + + /** + * Read an i32 from the wire as a zigzag varint. + */ + public function readI32() : Int { + return ZigZag.ToInt( ReadVarint32()); + } + + /** + * Read an i64 from the wire as a zigzag varint. + */ + public function readI64() : haxe.Int64 { + return ZigZag.ToLong( ReadVarint64()); + } + + /** + * No magic here - just Read a double off the wire. + */ + public function readDouble():Float { + var longBits = new BytesBuffer(); + trans.readAll( longBits, 0, 8); + return BitConverter.Int64BitsToDouble( BitConverter.bytesToLong( longBits.getBytes())); + } + + /** + * Reads a byte[] (via ReadBinary), and then UTF-8 decodes it. + */ + public function readString() : String { + var length : Int = cast( ReadVarint32(), Int); + + if (length == 0) { + return ""; + } + + var buf = new BytesBuffer(); + trans.readAll( buf, 0, length); + + length = buf.length; + var inp = new BytesInput( buf.getBytes()); + var str = inp.readString( length); + if( utf8Strings) + return str; // no need to decode on UTF8 targets, the string is just fine + else + return Utf8.decode( str); + } + + /** + * Read a byte[] from the wire. + */ + public function readBinary() : Bytes { + var length : Int = cast( ReadVarint32(), Int); + if (length == 0) { + return Bytes.alloc(0); + } + + var buf = new BytesBuffer(); + trans.readAll( buf, 0, length); + return buf.getBytes(); + } + + + // These methods are here for the struct to call, but don't have any wire + // encoding. + public function readMessageEnd() : Void { } + public function readFieldEnd() : Void { } + public function readMapEnd() : Void { } + public function readListEnd() : Void { } + public function readSetEnd() : Void { } + + // + // Internal Reading methods + // + + /** + * Read an i32 from the wire as a varint. The MSB of each byte is set + * if there is another byte to follow. This can Read up to 5 bytes. + */ + private function ReadVarint32() : UInt { + var result : UInt = 0; + var shift : Int = 0; + while (true) { + var b : Int = readByte(); + result |= cast((b & 0x7f) << shift, UInt); + if ((b & 0x80) != 0x80) { + break; + } + shift += 7; + } + return result; + } + + /** + * Read an i64 from the wire as a proper varint. The MSB of each byte is set + * if there is another byte to follow. This can Read up to 10 bytes. + */ + private function ReadVarint64() : Int64 { + var shift : Int = 0; + var result : Int64 = Int64.make(0,0); + while (true) { + var b : Int = readByte(); + result = Int64.or( result, Int64.shl( Int64.make(0,b & 0x7f), shift)); + if ((b & 0x80) != 0x80) { + break; + } + shift += 7; + } + + return result; + } + + + // + // type testing and converting + // + + private function isBoolType( b : Int) : Bool { + var lowerNibble : Int = b & 0x0f; + switch(lowerNibble) + { + case TCompactTypes.BOOLEAN_TRUE: return true; + case TCompactTypes.BOOLEAN_FALSE: return true; + default: return false; + } + } + + + /** + * Given a TCompactProtocol.TCompactTypes constant, convert it to its corresponding + * TType value. + */ + private function getTType( type : Int) : Int { + try + { + return tcompactTypeToType[type]; + throw "fuck"; + } + catch ( e : Dynamic) + { + var tt : Int = (type & 0x0f); + throw new TProtocolException( TProtocolException.UNKNOWN, 'don\'t know what type: $tt ($e)'); + } + } + + /** + * Given a TType value, find the appropriate TCompactProtocol.TCompactTypes constant. + */ + private function getCompactType( ttype : Int) : Int + { + return cast( ttypeToCompactType[ttype], Int); + } +} diff --git a/lib/haxe/src/org/apache/thrift/protocol/TCompactProtocolFactory.hx b/lib/haxe/src/org/apache/thrift/protocol/TCompactProtocolFactory.hx new file mode 100644 index 000000000..c5673b40c --- /dev/null +++ b/lib/haxe/src/org/apache/thrift/protocol/TCompactProtocolFactory.hx @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.thrift.protocol; + +import org.apache.thrift.transport.TTransport; + + +/** +* Compact Protocol Factory +*/ +class TCompactProtocolFactory implements TProtocolFactory { + + public function new() { + } + + public function getProtocol( trans : TTransport) : TProtocol { + return new TCompactProtocol( trans); + } +} + + + +
\ No newline at end of file diff --git a/test/haxe/src/Arguments.hx b/test/haxe/src/Arguments.hx index 132f2080b..cae91dfda 100644 --- a/test/haxe/src/Arguments.hx +++ b/test/haxe/src/Arguments.hx @@ -32,6 +32,7 @@ using StringTools; enum ProtocolType { binary; json; + compact; } enum EndpointTransport { @@ -190,7 +191,7 @@ class Arguments if( arg == "binary") { protocol = binary; } else if( arg == "compact") { - throw "Compact protocol not supported yet"; + protocol = compact; } else if( arg == "json") { protocol = json; } else { diff --git a/test/haxe/src/TestClient.hx b/test/haxe/src/TestClient.hx index f77620f38..5193c4792 100644 --- a/test/haxe/src/TestClient.hx +++ b/test/haxe/src/TestClient.hx @@ -214,13 +214,15 @@ class TestClient { case json: trace("- json protocol"); protocol = new TJSONProtocol(transport); - default: - throw "Unhandled protocol"; + case compact: + trace("- compact protocol"); + protocol = new TCompactProtocol(transport); } // run the test code HaxeBasicsTest( args, rslt); + ModuleUnitTests( args, rslt); for( i in 0 ... args.numIterations) { ClientTest( transport, protocol, args, rslt); } @@ -244,107 +246,132 @@ class TestClient { map32.set( 42, 815); map64.set( Int64.make(0,42), 815); map32.set( -517, 23); - map64.set( Int64.make(-5,17), 23); + map64.set( Int64.neg(Int64.make(0,517)), 23); map32.set( 0, -123); map64.set( Int64.make(0,0), -123); rslt.Expect( map32.keys().hasNext() == map64.keys().hasNext(), "Int64Map<Int32> Test #10"); rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map<Int32> Test #11"); - rslt.Expect( map32.exists( -517) == map64.exists( Int64.make(-5,17)), "Int64Map<Int32> Test #12"); + rslt.Expect( map32.exists( -517) == map64.exists( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #12"); rslt.Expect( map32.exists( 42) == map64.exists( Int64.make(0,42)), "Int64Map<Int32> Test #13"); rslt.Expect( map32.exists( 0) == map64.exists( Int64.make(0,0)), "Int64Map<Int32> Test #14"); rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map<Int32> Test #15"); - rslt.Expect( map32.get( -517) == map64.get( Int64.make(-5,17)), "Int64Map<Int32> Test #16"); + rslt.Expect( map32.get( -517) == map64.get( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #16"); rslt.Expect( map32.get( 42) == map64.get( Int64.make(0,42)), "Int64Map<Int32> Test #Int64.make(-5,17)"); rslt.Expect( map32.get( 0) == map64.get( Int64.make(0,0)), "Int64Map<Int32> Test #18"); rslt.Expect( map32.remove( 4711) == map64.remove( Int64.make(47,11)), "Int64Map<Int32> Test #19"); - rslt.Expect( map32.remove( -517) == map64.remove( Int64.make(-5,17)), "Int64Map<Int32> Test #20"); + rslt.Expect( map32.remove( -517) == map64.remove( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #20"); rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map<Int32> Test #21"); - rslt.Expect( map32.exists( -517) == map64.exists( Int64.make(-5,17)), "Int64Map<Int32> Test #22"); + rslt.Expect( map32.exists( -517) == map64.exists( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #22"); rslt.Expect( map32.exists( 42) == map64.exists( Int64.make(0,42)), "Int64Map<Int32> Test #23"); rslt.Expect( map32.exists( 0) == map64.exists( Int64.make(0,0)), "Int64Map<Int32> Test #24"); rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map<Int32> Test #25"); - rslt.Expect( map32.get( -517) == map64.get( Int64.make(-5,17)), "Int64Map<Int32> Test #26"); + rslt.Expect( map32.get( -517) == map64.get( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #26"); rslt.Expect( map32.get( 42) == map64.get( Int64.make(0,42)), "Int64Map<Int32> Test #27"); rslt.Expect( map32.get( 0) == map64.get( Int64.make(0,0)), "Int64Map<Int32> Test #28"); map32.set( 42, 1); map64.set( Int64.make(0,42), 1); map32.set( -517, -2); - map64.set( Int64.make(-5,17), -2); + map64.set( Int64.neg(Int64.make(0,517)), -2); map32.set( 0, 3); map64.set( Int64.make(0,0), 3); var c32 = 0; + var ksum32 = 0; for (key in map32.keys()) { ++c32; + ksum32 += key; } var c64 = 0; + var ksum64 = Int64.make(0,0); for (key in map64.keys()) { ++c64; + ksum64 = Int64.add( ksum64, key); } rslt.Expect( c32 == c64, "Int64Map<Int32> Test #30"); + rslt.Expect( '$ksum64' == '$ksum32', '$ksum64 == $ksum32 Test #31'); var s32 = map32.toString(); var s64 = map64.toString(); - trace("Int64Map<Int32>.toString(): " + ' ("$s32" == "$s64")'); + rslt.Expect( s32 == s64, "Int64Map<Int32>.toString(): " + ' ("$s32" == "$s64") Test #32'); map32.remove( 42); map64.remove( Int64.make(0,42)); map32.remove( -517); - map64.remove( Int64.make(-5,17)); + map64.remove( Int64.neg(Int64.make(0,517))); map32.remove( 0); map64.remove( Int64.make(0,0)); rslt.Expect( map32.keys().hasNext() == map64.keys().hasNext(), "Int64Map<Int32> Test #90"); rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map<Int32> Test #91"); - rslt.Expect( map32.exists( -517) == map64.exists( Int64.make(-5,17)), "Int64Map<Int32> Test #92"); + rslt.Expect( map32.exists( -517) == map64.exists( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #92"); rslt.Expect( map32.exists( 42) == map64.exists( Int64.make(0,42)), "Int64Map<Int32> Test #93"); rslt.Expect( map32.exists( 0) == map64.exists( Int64.make(0,0)), "Int64Map<Int32> Test #94"); rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map<Int32> Test #95"); rslt.Expect( map32.get( -517) == map64.get( Int64.make(-5,17)), "Int64Map<Int32> Test #96"); rslt.Expect( map32.get( 42) == map64.get( Int64.make(0,42)), "Int64Map<Int32> Test #97"); - rslt.Expect( map32.get( 0) == map64.get( Int64.make(0,0)), "Int64Map<Int32> Test #98"); + rslt.Expect( map32.get( 0) == map64.get( Int64.make(0, 0)), "Int64Map<Int32> Test #98"); + } + + + // core module unit tests + public static function ModuleUnitTests( args : Arguments, rslt : TestResults) : Void { + try { + BitConverter.UnitTest(); + rslt.Expect( true, 'BitConverter.UnitTest Test #100'); + } + catch( e : Dynamic) { + rslt.Expect( false, 'BitConverter.UnitTest: $e Test #100'); + } + + try { + ZigZag.UnitTest(); + rslt.Expect( true, 'ZigZag.UnitTest Test #101'); + } + catch( e : Dynamic) { + rslt.Expect( false, 'ZigZag.UnitTest: $e Test #101'); + } + } + + + public static function BytesToHex(data : Bytes) : String { + var hex = ""; + for ( i in 0 ... data.length) { + hex += StringTools.hex( data.get(i), 2); + } + return hex; + } + + public static function PrepareTestData(randomDist : Bool) : Bytes { + var retval = Bytes.alloc(0x100); + var initLen : Int = (retval.length > 0x100 ? 0x100 : retval.length); + + // linear distribution, unless random is requested + if (!randomDist) { + for (i in 0 ... initLen) { + retval.set(i, i % 0x100); + } + return retval; + } + + // random distribution + for (i in 0 ... initLen) { + retval.set(i, 0); + } + for (i in 1 ... initLen) { + while( true) { + var nextPos = Std.random(initLen); + if (retval.get(nextPos) == 0) { + retval.set( nextPos, i % 0x100); + break; + } + } + } + return retval; } - public static function BytesToHex(data : Bytes) : String { - var hex = ""; - for ( i in 0 ... data.length) { - hex += StringTools.hex( data.get(i), 2); - } - return hex; - } - - public static function PrepareTestData(randomDist : Bool) : Bytes { - var retval = Bytes.alloc(0x100); - var initLen : Int = (retval.length > 0x100 ? 0x100 : retval.length); - - // linear distribution, unless random is requested - if (!randomDist) { - for (i in 0 ... initLen) { - retval.set(i, i % 0x100); - } - return retval; - } - - // random distribution - for (i in 0 ... initLen) { - retval.set(i, 0); - } - for (i in 1 ... initLen) { - while( true) { - var nextPos = Std.random(initLen); - if (retval.get(nextPos) == 0) { - retval.set( nextPos, i % 0x100); - break; - } - } - } - return retval; - } - - public static function ClientTest( transport : TTransport, protocol : TProtocol, args : Arguments, rslt : TestResults) : Void { @@ -402,6 +429,11 @@ class TestClient { rslt.Expect( false, 'testException("TException") - $e'); } + // reopen the transport, just in case the server closed his end + if (transport.isOpen()) + transport.close(); + transport.open(); + // else do not throw anything trace('testException("bla")'); try { @@ -413,8 +445,6 @@ class TestClient { rslt.Expect( false, 'testException("bla") - $e'); } - - rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_BASETYPES); trace('testVoid()'); @@ -459,16 +489,16 @@ class TestClient { trace('testBinary('+BytesToHex(binOut)+')'); try { var binIn = client.testBinary(binOut); - trace('testBinary() = '+BytesToHex(binIn)); - rslt.Expect( binIn.length == binOut.length, '${binIn.length} == ${binOut.length}'); - var len = ((binIn.length < binOut.length) ? binIn.length : binOut.length); + trace('testBinary() = '+BytesToHex(binIn)); + rslt.Expect( binIn.length == binOut.length, '${binIn.length} == ${binOut.length}'); + var len = ((binIn.length < binOut.length) ? binIn.length : binOut.length); for (ofs in 0 ... len) { if (binIn.get(ofs) != binOut.get(ofs)) { - rslt.Expect( false, 'testBinary('+BytesToHex(binOut)+'): content mismatch at offset $ofs'); - } - } - } - catch (e : TApplicationException) { + rslt.Expect( false, 'testBinary('+BytesToHex(binOut)+'): content mismatch at offset $ofs'); + } + } + } + catch (e : TApplicationException) { trace('testBinary('+BytesToHex(binOut)+'): '+e.errorMsg); // may not be supported by the server } diff --git a/test/haxe/src/TestMacro.hx b/test/haxe/src/TestMacro.hx index 0129d3f26..a6207606a 100644 --- a/test/haxe/src/TestMacro.hx +++ b/test/haxe/src/TestMacro.hx @@ -24,10 +24,10 @@ import haxe.macro.Expr; /**** * If you call the Thrift compiler this way (e.g. by changing the prebuild command) - * + * * thrift -r -gen haxe:buildmacro=TestMacro.handle() ../ThriftTest.thrift - * - * the TestMacro.handle() function implemented below is called for each generated class + * + * the TestMacro.handle() function implemented below is called for each generated class * and interface. Use "thrift --help" to get more info about other available options. */ class TestMacro @@ -36,5 +36,5 @@ class TestMacro trace('TestMacro called for ' + Context.getLocalType()); return Context.getBuildFields(); } - + } diff --git a/test/haxe/src/TestServer.hx b/test/haxe/src/TestServer.hx index 502d0d1b6..4490a8c9f 100644 --- a/test/haxe/src/TestServer.hx +++ b/test/haxe/src/TestServer.hx @@ -69,8 +69,9 @@ class TestServer case json: trace("- json protocol"); protfactory = new TJSONProtocolFactory(); - default: - throw "Unhandled protocol"; + case compact: + trace("- compact protocol"); + protfactory = new TCompactProtocolFactory(); } diff --git a/test/haxe/src/TestServerHandler.hx b/test/haxe/src/TestServerHandler.hx index 9e2a633bb..abcef1349 100644 --- a/test/haxe/src/TestServerHandler.hx +++ b/test/haxe/src/TestServerHandler.hx @@ -120,19 +120,19 @@ class TestServerHandler implements ThriftTest { * Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data * @param binary thing - the binary data to print * @return binary - returns the binary 'thing' - * + * * @param thing */ public function testBinary(thing : haxe.io.Bytes) : haxe.io.Bytes { - var hex = ""; - for ( i in 0 ... thing.length) { - hex += StringTools.hex( thing.get(i), 2); - } + var hex = ""; + for ( i in 0 ... thing.length) { + hex += StringTools.hex( thing.get(i), 2); + } trace('testBinary($hex)'); return thing; } - + /** * Prints 'testStruct("{%s}")' where thing has been formatted * into a string of comma separated values |