diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/jaegertracing/thrift/lib/dart | |
parent | Initial commit. (diff) | |
download | ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/jaegertracing/thrift/lib/dart')
52 files changed, 5450 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/lib/dart/.analysis_options b/src/jaegertracing/thrift/lib/dart/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/src/jaegertracing/thrift/lib/dart/LICENSE b/src/jaegertracing/thrift/lib/dart/LICENSE new file mode 100644 index 000000000..4eacb6431 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/LICENSE @@ -0,0 +1,16 @@ +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. diff --git a/src/jaegertracing/thrift/lib/dart/Makefile.am b/src/jaegertracing/thrift/lib/dart/Makefile.am new file mode 100644 index 000000000..373a883d6 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/Makefile.am @@ -0,0 +1,39 @@ +# +# 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. +# + +all-local: + $(DARTPUB) get + +clean-local: + $(RM) -r .pub + find . -type d -name ".dart_tool" | xargs $(RM) -r + find . -type f -name ".packages" | xargs $(RM) + find . -type d -name "packages" | xargs $(RM) -r + +check-local: all + +dist-hook: + $(RM) -r $(distdir)/.pub + find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r + find $(distdir) -type f -name ".packages" | xargs $(RM) + find $(distdir) -type d -name "packages" | xargs $(RM) -r + +EXTRA_DIST = \ + .analysis_options + diff --git a/src/jaegertracing/thrift/lib/dart/README.md b/src/jaegertracing/thrift/lib/dart/README.md new file mode 100644 index 000000000..4c3029124 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/README.md @@ -0,0 +1,26 @@ +Thrift Dart Library + +License +======= + +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. + +Using Thrift with Dart +==================== + +Dart 1.24.3 or newer is required diff --git a/src/jaegertracing/thrift/lib/dart/coding_standards.md b/src/jaegertracing/thrift/lib/dart/coding_standards.md new file mode 100644 index 000000000..62f600365 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/coding_standards.md @@ -0,0 +1,6 @@ +# Dart Coding Standards + +### Please follow: + * [Thrift General Coding Standards](/doc/coding_standards.md) + * [Use dartfmt](https://www.dartlang.org/tools/dartfmt/) and follow the + [Dart Style Guide](https://www.dartlang.org/articles/style-guide/) diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/browser/t_web_socket.dart b/src/jaegertracing/thrift/lib/dart/lib/src/browser/t_web_socket.dart new file mode 100644 index 000000000..dac9ffdde --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/browser/t_web_socket.dart @@ -0,0 +1,129 @@ +/// 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. + +library thrift.src.browser; + +import 'dart:async'; +import 'package:dart2_constant/convert.dart' show base64; +import 'dart:html' show CloseEvent; +import 'dart:html' show Event; +import 'dart:html' show MessageEvent; +import 'dart:html' show WebSocket; +import 'dart:typed_data' show Uint8List; + +import 'package:thrift/thrift.dart'; + +/// A [TSocket] backed by a [WebSocket] from dart:html +class TWebSocket implements TSocket { + final Uri url; + + final StreamController<TSocketState> _onStateController; + Stream<TSocketState> get onState => _onStateController.stream; + + final StreamController<Object> _onErrorController; + Stream<Object> get onError => _onErrorController.stream; + + final StreamController<Uint8List> _onMessageController; + Stream<Uint8List> get onMessage => _onMessageController.stream; + + final List<Uint8List> _requests = []; + + TWebSocket(this.url) + : _onStateController = new StreamController.broadcast(), + _onErrorController = new StreamController.broadcast(), + _onMessageController = new StreamController.broadcast() { + if (url == null || !url.hasAuthority || !url.hasPort) { + throw new ArgumentError('Invalid url'); + } + } + + WebSocket _socket; + + bool get isOpen => _socket != null && _socket.readyState == WebSocket.OPEN; + + bool get isClosed => + _socket == null || _socket.readyState == WebSocket.CLOSED; + + Future open() { + if (!isClosed) { + throw new TTransportError( + TTransportErrorType.ALREADY_OPEN, 'Socket already connected'); + } + + _socket = new WebSocket(url.toString()); + _socket.onError.listen(_onError); + _socket.onOpen.listen(_onOpen); + _socket.onClose.listen(_onClose); + _socket.onMessage.listen(_onMessage); + + return _socket.onOpen.first; + } + + Future close() { + if (_socket != null) { + _socket.close(); + return _socket.onClose.first; + } else { + return new Future.value(); + } + } + + void send(Uint8List data) { + _requests.add(data); + _sendRequests(); + } + + void _sendRequests() { + while (isOpen && _requests.isNotEmpty) { + Uint8List data = _requests.removeAt(0); + _socket.sendString(base64.encode(data)); + } + } + + void _onOpen(Event event) { + _onStateController.add(TSocketState.OPEN); + _sendRequests(); + } + + void _onClose(CloseEvent event) { + _socket = null; + + if (_requests.isNotEmpty) { + _onErrorController + .add(new StateError('Socket was closed with pending requests')); + } + _requests.clear(); + + _onStateController.add(TSocketState.CLOSED); + } + + void _onMessage(MessageEvent message) { + try { + Uint8List data = new Uint8List.fromList(base64.decode(message.data)); + _onMessageController.add(data); + } on FormatException catch (_) { + var error = new TProtocolError(TProtocolErrorType.INVALID_DATA, + "Expected a Base 64 encoded string."); + _onErrorController.add(error); + } + } + + void _onError(Event event) { + close(); + _onErrorController.add(event.toString()); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/console/t_tcp_socket.dart b/src/jaegertracing/thrift/lib/dart/lib/src/console/t_tcp_socket.dart new file mode 100644 index 000000000..b71480334 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/console/t_tcp_socket.dart @@ -0,0 +1,81 @@ +/// 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. + +library thrift.src.console.t_tcp_socket; + +import 'dart:async'; +import 'dart:io'; +import 'dart:typed_data' show Uint8List; + +import 'package:thrift/thrift.dart'; + +/// A [TSocket] backed by a [Socket] from dart:io +class TTcpSocket implements TSocket { + final StreamController<TSocketState> _onStateController; + Stream<TSocketState> get onState => _onStateController.stream; + + final StreamController<Object> _onErrorController; + Stream<Object> get onError => _onErrorController.stream; + + final StreamController<Uint8List> _onMessageController; + Stream<Uint8List> get onMessage => _onMessageController.stream; + + TTcpSocket(Socket socket) + : _onStateController = new StreamController.broadcast(), + _onErrorController = new StreamController.broadcast(), + _onMessageController = new StreamController.broadcast() { + if (socket == null) { + throw new ArgumentError.notNull('socket'); + } + + _socket = socket; + _socket.listen(_onMessage, onError: _onError, onDone: close); + } + + Socket _socket; + + bool get isOpen => _socket != null; + + bool get isClosed => _socket == null; + + Future open() async { + _onStateController.add(TSocketState.OPEN); + } + + Future close() async { + if (_socket != null) { + await _socket.close(); + _socket = null; + } + + _onStateController.add(TSocketState.CLOSED); + } + + void send(Uint8List data) { + _socket.add(data); + } + + void _onMessage(List<int> message) { + Uint8List data = new Uint8List.fromList(message); + _onMessageController.add(data); + } + + void _onError(Object error) { + close(); + _onErrorController.add('$error'); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/console/t_web_socket.dart b/src/jaegertracing/thrift/lib/dart/lib/src/console/t_web_socket.dart new file mode 100644 index 000000000..c938a966f --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/console/t_web_socket.dart @@ -0,0 +1,88 @@ +/// 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. + +library thrift.src.console.t_web_socket; + +import 'dart:async'; +import 'package:dart2_constant/convert.dart' show base64; +import 'dart:io'; +import 'dart:typed_data' show Uint8List; + +import 'package:thrift/thrift.dart'; + +/// A [TSocket] backed by a [WebSocket] from dart:io +class TWebSocket implements TSocket { + final StreamController<TSocketState> _onStateController; + Stream<TSocketState> get onState => _onStateController.stream; + + final StreamController<Object> _onErrorController; + Stream<Object> get onError => _onErrorController.stream; + + final StreamController<Uint8List> _onMessageController; + Stream<Uint8List> get onMessage => _onMessageController.stream; + + TWebSocket(WebSocket socket) + : _onStateController = new StreamController.broadcast(), + _onErrorController = new StreamController.broadcast(), + _onMessageController = new StreamController.broadcast() { + if (socket == null) { + throw new ArgumentError.notNull('socket'); + } + + _socket = socket; + _socket.listen(_onMessage, onError: _onError, onDone: close); + } + + WebSocket _socket; + + bool get isOpen => _socket != null; + + bool get isClosed => _socket == null; + + Future open() async { + _onStateController.add(TSocketState.OPEN); + } + + Future close() async { + if (_socket != null) { + await _socket.close(); + _socket = null; + } + + _onStateController.add(TSocketState.CLOSED); + } + + void send(Uint8List data) { + _socket.add(base64.encode(data)); + } + + void _onMessage(String message) { + try { + Uint8List data = new Uint8List.fromList(base64.decode(message)); + _onMessageController.add(data); + } on FormatException catch (_) { + var error = new TProtocolError(TProtocolErrorType.INVALID_DATA, + "Expected a Base 64 encoded string."); + _onErrorController.add(error); + } + } + + void _onError(Object error) { + close(); + _onErrorController.add('$error'); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_binary_protocol.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_binary_protocol.dart new file mode 100644 index 000000000..a785d811c --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_binary_protocol.dart @@ -0,0 +1,281 @@ +/// 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. + +part of thrift; + +class TBinaryProtocolFactory implements TProtocolFactory<TBinaryProtocol> { + TBinaryProtocolFactory({this.strictRead: false, this.strictWrite: true}); + + final bool strictRead; + final bool strictWrite; + + TBinaryProtocol getProtocol(TTransport transport) { + return new TBinaryProtocol(transport, + strictRead: strictRead, strictWrite: strictWrite); + } +} + +/// Binary protocol implementation for Thrift. +/// +/// Adapted from the C# version. +class TBinaryProtocol extends TProtocol { + static const int VERSION_MASK = 0xffff0000; + static const int VERSION_1 = 0x80010000; + + static const Utf8Codec _utf8Codec = const Utf8Codec(); + + final bool strictRead; + final bool strictWrite; + + TBinaryProtocol(TTransport transport, + {this.strictRead: false, this.strictWrite: true}) + : super(transport); + + /// write + void writeMessageBegin(TMessage message) { + if (strictWrite) { + int version = VERSION_1 | message.type; + writeI32(version); + writeString(message.name); + writeI32(message.seqid); + } else { + writeString(message.name); + writeByte(message.type); + writeI32(message.seqid); + } + } + + void writeMessageEnd() {} + + void writeStructBegin(TStruct struct) {} + + void writeStructEnd() {} + + void writeFieldBegin(TField field) { + writeByte(field.type); + writeI16(field.id); + } + + void writeFieldEnd() {} + + void writeFieldStop() { + writeByte(TType.STOP); + } + + void writeMapBegin(TMap map) { + writeByte(map.keyType); + writeByte(map.valueType); + writeI32(map.length); + } + + void writeMapEnd() {} + + void writeListBegin(TList list) { + writeByte(list.elementType); + writeI32(list.length); + } + + void writeListEnd() {} + + void writeSetBegin(TSet set) { + writeByte(set.elementType); + writeI32(set.length); + } + + void writeSetEnd() {} + + void writeBool(bool b) { + if (b == null) b = false; + writeByte(b ? 1 : 0); + } + + final ByteData _byteOut = new ByteData(1); + void writeByte(int byte) { + if (byte == null) byte = 0; + _byteOut.setUint8(0, byte); + transport.write(_byteOut.buffer.asUint8List(), 0, 1); + } + + final ByteData _i16Out = new ByteData(2); + void writeI16(int i16) { + if (i16 == null) i16 = 0; + _i16Out.setInt16(0, i16); + transport.write(_i16Out.buffer.asUint8List(), 0, 2); + } + + final ByteData _i32Out = new ByteData(4); + void writeI32(int i32) { + if (i32 == null) i32 = 0; + _i32Out.setInt32(0, i32); + transport.write(_i32Out.buffer.asUint8List(), 0, 4); + } + + final Uint8List _i64Out = new Uint8List(8); + void writeI64(int i64) { + if (i64 == null) i64 = 0; + var i = new Int64(i64); + var bts = i.toBytes(); + for (var j = 0; j < 8; j++) { + _i64Out[j] = bts[8 - j - 1]; + } + transport.write(_i64Out, 0, 8); + } + + void writeString(String s) { + var bytes = s != null ? _utf8Codec.encode(s) : new Uint8List.fromList([]); + writeI32(bytes.length); + transport.write(bytes, 0, bytes.length); + } + + final ByteData _doubleOut = new ByteData(8); + void writeDouble(double d) { + if (d == null) d = 0.0; + _doubleOut.setFloat64(0, d); + transport.write(_doubleOut.buffer.asUint8List(), 0, 8); + } + + void writeBinary(Uint8List bytes) { + var length = bytes.length; + writeI32(length); + transport.write(bytes, 0, length); + } + + /// read + TMessage readMessageBegin() { + String name; + int type; + int seqid; + + int size = readI32(); + if (size < 0) { + int version = size & VERSION_MASK; + if (version != VERSION_1) { + throw new TProtocolError(TProtocolErrorType.BAD_VERSION, + "Bad version in readMessageBegin: $version"); + } + type = size & 0x000000ff; + name = readString(); + seqid = readI32(); + } else { + if (strictRead) { + throw new TProtocolError(TProtocolErrorType.BAD_VERSION, + "Missing version in readMessageBegin"); + } + name = _readString(size); + type = readByte(); + seqid = readI32(); + } + return new TMessage(name, type, seqid); + } + + void readMessageEnd() {} + + TStruct readStructBegin() { + return new TStruct(); + } + + void readStructEnd() {} + + TField readFieldBegin() { + String name = ""; + int type = readByte(); + int id = type != TType.STOP ? readI16() : 0; + + return new TField(name, type, id); + } + + void readFieldEnd() {} + + TMap readMapBegin() { + int keyType = readByte(); + int valueType = readByte(); + int length = readI32(); + + return new TMap(keyType, valueType, length); + } + + void readMapEnd() {} + + TList readListBegin() { + int elementType = readByte(); + int length = readI32(); + + return new TList(elementType, length); + } + + void readListEnd() {} + + TSet readSetBegin() { + int elementType = readByte(); + int length = readI32(); + + return new TSet(elementType, length); + } + + void readSetEnd() {} + + bool readBool() => readByte() == 1; + + final Uint8List _byteIn = new Uint8List(1); + int readByte() { + transport.readAll(_byteIn, 0, 1); + return _byteIn.buffer.asByteData().getUint8(0); + } + + final Uint8List _i16In = new Uint8List(2); + int readI16() { + transport.readAll(_i16In, 0, 2); + return _i16In.buffer.asByteData().getInt16(0); + } + + final Uint8List _i32In = new Uint8List(4); + int readI32() { + transport.readAll(_i32In, 0, 4); + return _i32In.buffer.asByteData().getInt32(0); + } + + final Uint8List _i64In = new Uint8List(8); + int readI64() { + transport.readAll(_i64In, 0, 8); + var i = new Int64.fromBytesBigEndian(_i64In); + return i.toInt(); + } + + final Uint8List _doubleIn = new Uint8List(8); + double readDouble() { + transport.readAll(_doubleIn, 0, 8); + return _doubleIn.buffer.asByteData().getFloat64(0); + } + + String readString() { + int size = readI32(); + return _readString(size); + } + + String _readString(int size) { + Uint8List stringIn = new Uint8List(size); + transport.readAll(stringIn, 0, size); + return _utf8Codec.decode(stringIn); + } + + Uint8List readBinary() { + int length = readI32(); + Uint8List binaryIn = new Uint8List(length); + transport.readAll(binaryIn, 0, length); + return binaryIn; + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_compact_protocol.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_compact_protocol.dart new file mode 100644 index 000000000..ee8094f8e --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_compact_protocol.dart @@ -0,0 +1,470 @@ +/// 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. + +part of thrift; + +class TCompactProtocolFactory implements TProtocolFactory<TCompactProtocol> { + TCompactProtocolFactory(); + + TCompactProtocol getProtocol(TTransport transport) { + return new TCompactProtocol(transport); + } +} + +/// Compact protocol implementation for Thrift. +/// +/// Use of fixnum library is required due to bugs like +/// https://github.com/dart-lang/sdk/issues/15361 +/// +/// Adapted from the Java version. +class TCompactProtocol extends TProtocol { + static const int PROTOCOL_ID = 0x82; + static const int VERSION = 1; + static const int VERSION_MASK = 0x1f; + static const int TYPE_MASK = 0xE0; + static const int TYPE_BITS = 0x07; + static const int TYPE_SHIFT_AMOUNT = 5; + static final TField TSTOP = new TField("", TType.STOP, 0); + + static const int TYPE_BOOLEAN_TRUE = 0x01; + static const int TYPE_BOOLEAN_FALSE = 0x02; + static const int TYPE_BYTE = 0x03; + static const int TYPE_I16 = 0x04; + static const int TYPE_I32 = 0x05; + static const int TYPE_I64 = 0x06; + static const int TYPE_DOUBLE = 0x07; + static const int TYPE_BINARY = 0x08; + static const int TYPE_LIST = 0x09; + static const int TYPE_SET = 0x0A; + static const int TYPE_MAP = 0x0B; + static const int TYPE_STRUCT = 0x0C; + + static final List<int> _typeMap = new List.unmodifiable(new List(16) + ..[TType.STOP] = TType.STOP + ..[TType.BOOL] = TYPE_BOOLEAN_TRUE + ..[TType.BYTE] = TYPE_BYTE + ..[TType.I16] = TYPE_I16 + ..[TType.I32] = TYPE_I32 + ..[TType.I64] = TYPE_I64 + ..[TType.DOUBLE] = TYPE_DOUBLE + ..[TType.STRING] = TYPE_BINARY + ..[TType.LIST] = TYPE_LIST + ..[TType.SET] = TYPE_SET + ..[TType.MAP] = TYPE_MAP + ..[TType.STRUCT] = TYPE_STRUCT); + + static const Utf8Codec _utf8Codec = const Utf8Codec(); + + // Pretend this is a stack + DoubleLinkedQueue<int> _lastField = new DoubleLinkedQueue<int>(); + int _lastFieldId = 0; + + TField _booleanField = null; + bool _boolValue = null; + + final Uint8List tempList = new Uint8List(10); + final ByteData tempBD = new ByteData(10); + + TCompactProtocol(TTransport transport) : super(transport); + + /// Write + void writeMessageBegin(TMessage message) { + writeByte(PROTOCOL_ID); + writeByte((VERSION & VERSION_MASK) | + ((message.type << TYPE_SHIFT_AMOUNT) & TYPE_MASK)); + _writeVarInt32(new Int32(message.seqid)); + writeString(message.name); + } + + void writeMessageEnd() {} + + void writeStructBegin(TStruct struct) { + _lastField.addLast(_lastFieldId); + _lastFieldId = 0; + } + + void writeStructEnd() { + _lastFieldId = _lastField.removeLast(); + } + + void writeFieldBegin(TField field) { + if (field.type == TType.BOOL) { + _booleanField = field; + } else { + _writeFieldBegin(field, -1); + } + } + + void _writeFieldBegin(TField field, int typeOverride) { + int typeToWrite = + typeOverride == -1 ? _getCompactType(field.type) : typeOverride; + + if (field.id > _lastFieldId && field.id - _lastFieldId <= 15) { + writeByte((field.id - _lastFieldId) << 4 | typeToWrite); + } else { + writeByte(typeToWrite); + writeI16(field.id); + } + + _lastFieldId = field.id; + } + + void writeFieldEnd() {} + + void writeFieldStop() { + writeByte(TType.STOP); + } + + void writeMapBegin(TMap map) { + if (map.length == 0) { + writeByte(0); + } else { + _writeVarInt32(new Int32(map.length)); + writeByte( + _getCompactType(map.keyType) << 4 | _getCompactType(map.valueType)); + } + } + + void writeMapEnd() {} + + void writeListBegin(TList list) { + _writeCollectionBegin(list.elementType, list.length); + } + + void writeListEnd() {} + + void writeSetBegin(TSet set) { + _writeCollectionBegin(set.elementType, set.length); + } + + void writeSetEnd() {} + + void writeBool(bool b) { + if (b == null) b = false; + if (_booleanField != null) { + _writeFieldBegin( + _booleanField, b ? TYPE_BOOLEAN_TRUE : TYPE_BOOLEAN_FALSE); + _booleanField = null; + } else { + writeByte(b ? TYPE_BOOLEAN_TRUE : TYPE_BOOLEAN_FALSE); + } + } + + void writeByte(int b) { + if (b == null) b = 0; + tempList[0] = b; + transport.write(tempList, 0, 1); + } + + void writeI16(int i16) { + if (i16 == null) i16 = 0; + _writeVarInt32(_int32ToZigZag(new Int32(i16))); + } + + void writeI32(int i32) { + if (i32 == null) i32 = 0; + _writeVarInt32(_int32ToZigZag(new Int32(i32))); + } + + void writeI64(int i64) { + if (i64 == null) i64 = 0; + _writeVarInt64(_int64ToZigZag(new Int64(i64))); + } + + void writeDouble(double d) { + if (d == null) d = 0.0; + tempBD.setFloat64(0, d, Endianness.little); + transport.write(tempBD.buffer.asUint8List(), 0, 8); + } + + void writeString(String str) { + Uint8List bytes = + str != null ? _utf8Codec.encode(str) : new Uint8List.fromList([]); + writeBinary(bytes); + } + + void writeBinary(Uint8List bytes) { + _writeVarInt32(new Int32(bytes.length)); + transport.write(bytes, 0, bytes.length); + } + + void _writeVarInt32(Int32 n) { + int idx = 0; + while (true) { + if ((n & ~0x7F) == 0) { + tempList[idx++] = (n & 0xFF).toInt(); + break; + } else { + tempList[idx++] = (((n & 0x7F) | 0x80) & 0xFF).toInt(); + n = n.shiftRightUnsigned(7); + } + } + transport.write(tempList, 0, idx); + } + + void _writeVarInt64(Int64 n) { + int idx = 0; + while (true) { + if ((n & ~0x7F) == 0) { + tempList[idx++] = (n & 0xFF).toInt(); + break; + } else { + tempList[idx++] = (((n & 0x7F) | 0x80) & 0xFF).toInt(); + n = n.shiftRightUnsigned(7); + } + } + transport.write(tempList, 0, idx); + } + + void _writeCollectionBegin(int elemType, int length) { + if (length <= 14) { + writeByte(length << 4 | _getCompactType(elemType)); + } else { + writeByte(0xF0 | _getCompactType(elemType)); + _writeVarInt32(new Int32(length)); + } + } + + Int32 _int32ToZigZag(Int32 n) { + return (n << 1) ^ (n >> 31); + } + + Int64 _int64ToZigZag(Int64 n) { + return (n << 1) ^ (n >> 63); + } + + /// Read + TMessage readMessageBegin() { + int protocolId = readByte(); + if (protocolId != PROTOCOL_ID) { + throw new TProtocolError(TProtocolErrorType.BAD_VERSION, + 'Expected protocol id $PROTOCOL_ID but got $protocolId'); + } + int versionAndType = readByte(); + int version = versionAndType & VERSION_MASK; + if (version != VERSION) { + throw new TProtocolError(TProtocolErrorType.BAD_VERSION, + 'Expected version $VERSION but got $version'); + } + int type = (versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS; + int seqId = _readVarInt32().toInt(); + String messageName = readString(); + return new TMessage(messageName, type, seqId); + } + + void readMessageEnd() {} + + TStruct readStructBegin() { + _lastField.addLast(_lastFieldId); + _lastFieldId = 0; + // TODO make this a constant? + return new TStruct(); + } + + void readStructEnd() { + _lastFieldId = _lastField.removeLast(); + } + + TField readFieldBegin() { + int type = readByte(); + if (type == TType.STOP) { + return TSTOP; + } + + int fieldId; + int modifier = (type & 0xF0) >> 4; + if (modifier == 0) { + fieldId = readI16(); + } else { + fieldId = _lastFieldId + modifier; + } + + TField field = new TField('', _getTType(type & 0x0F), fieldId); + if (_isBoolType(type)) { + _boolValue = (type & 0x0F) == TYPE_BOOLEAN_TRUE; + } + + _lastFieldId = field.id; + return field; + } + + void readFieldEnd() {} + + TMap readMapBegin() { + int length = _readVarInt32().toInt(); + _checkNegReadLength(length); + + int keyAndValueType = length == 0 ? 0 : readByte(); + int keyType = _getTType(keyAndValueType >> 4); + int valueType = _getTType(keyAndValueType & 0x0F); + return new TMap(keyType, valueType, length); + } + + void readMapEnd() {} + + TList readListBegin() { + int lengthAndType = readByte(); + int length = (lengthAndType >> 4) & 0x0F; + if (length == 15) { + length = _readVarInt32().toInt(); + } + _checkNegReadLength(length); + int type = _getTType(lengthAndType); + return new TList(type, length); + } + + void readListEnd() {} + + TSet readSetBegin() { + TList tlist = readListBegin(); + return new TSet(tlist.elementType, tlist.length); + } + + void readSetEnd() {} + + bool readBool() { + if (_boolValue != null) { + bool result = _boolValue; + _boolValue = null; + return result; + } + return readByte() == TYPE_BOOLEAN_TRUE; + } + + int readByte() { + transport.readAll(tempList, 0, 1); + return tempList.buffer.asByteData().getUint8(0); + } + + int readI16() { + return _zigzagToInt32(_readVarInt32()).toInt(); + } + + int readI32() { + return _zigzagToInt32(_readVarInt32()).toInt(); + } + + int readI64() { + return _zigzagToInt64(_readVarInt64()).toInt(); + } + + double readDouble() { + transport.readAll(tempList, 0, 8); + return tempList.buffer.asByteData().getFloat64(0, Endianness.little); + } + + String readString() { + int length = _readVarInt32().toInt(); + _checkNegReadLength(length); + + // TODO look at using temp for small strings? + Uint8List buff = new Uint8List(length); + transport.readAll(buff, 0, length); + return _utf8Codec.decode(buff); + } + + Uint8List readBinary() { + int length = _readVarInt32().toInt(); + _checkNegReadLength(length); + + Uint8List buff = new Uint8List(length); + transport.readAll(buff, 0, length); + return buff; + } + + Int32 _readVarInt32() { + Int32 result = Int32.ZERO; + int shift = 0; + while (true) { + Int32 b = new Int32(readByte()); + result |= (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) break; + shift += 7; + } + return result; + } + + Int64 _readVarInt64() { + Int64 result = Int64.ZERO; + int shift = 0; + while (true) { + Int64 b = new Int64(readByte()); + result |= (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) break; + shift += 7; + } + return result; + } + + Int32 _zigzagToInt32(Int32 n) { + return (n.shiftRightUnsigned(1)) ^ -(n & 1); + } + + Int64 _zigzagToInt64(Int64 n) { + return (n.shiftRightUnsigned(1)) ^ -(n & 1); + } + + void _checkNegReadLength(int length) { + if (length < 0) { + throw new TProtocolError( + TProtocolErrorType.NEGATIVE_SIZE, 'Negative length: $length'); + } + } + + int _getCompactType(int ttype) { + return _typeMap[ttype]; + } + + int _getTType(int type) { + switch (type & 0x0F) { + case TType.STOP: + return TType.STOP; + case TYPE_BOOLEAN_FALSE: + case TYPE_BOOLEAN_TRUE: + return TType.BOOL; + case TYPE_BYTE: + return TType.BYTE; + case TYPE_I16: + return TType.I16; + case TYPE_I32: + return TType.I32; + case TYPE_I64: + return TType.I64; + case TYPE_DOUBLE: + return TType.DOUBLE; + case TYPE_BINARY: + return TType.STRING; + case TYPE_LIST: + return TType.LIST; + case TYPE_SET: + return TType.SET; + case TYPE_MAP: + return TType.MAP; + case TYPE_STRUCT: + return TType.STRUCT; + default: + throw new TProtocolError( + TProtocolErrorType.INVALID_DATA, "Unknown type: ${type & 0x0F}"); + } + } + + bool _isBoolType(int b) { + int lowerNibble = b & 0x0F; + return lowerNibble == TYPE_BOOLEAN_TRUE || + lowerNibble == TYPE_BOOLEAN_FALSE; + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_field.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_field.dart new file mode 100644 index 000000000..444b4e57a --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_field.dart @@ -0,0 +1,26 @@ +/// 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. + +part of thrift; + +class TField { + final String name; + final int type; + final int id; + + TField(this.name, this.type, this.id); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_json_protocol.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_json_protocol.dart new file mode 100644 index 000000000..180568ddf --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_json_protocol.dart @@ -0,0 +1,784 @@ +/// 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. + +part of thrift; + +class TJsonProtocolFactory implements TProtocolFactory<TJsonProtocol> { + TJsonProtocol getProtocol(TTransport transport) { + return new TJsonProtocol(transport); + } +} + +/// JSON protocol implementation for Thrift. +/// +/// Adapted from the C# version. +class TJsonProtocol extends TProtocol { + static const int VERSION_1 = 1; + + static const Utf8Codec utf8Codec = const Utf8Codec(); + + _BaseContext _context; + _BaseContext _rootContext; + _LookaheadReader _reader; + + final List<_BaseContext> _contextStack = []; + final Uint8List _tempBuffer = new Uint8List(4); + + TJsonProtocol(TTransport transport) : super(transport) { + _rootContext = new _BaseContext(this); + _reader = new _LookaheadReader(this); + _resetContext(); + } + + void _pushContext(_BaseContext c) { + _contextStack.add(c); + _context = c; + } + + void _popContext() { + _contextStack.removeLast(); + _context = _contextStack.isEmpty ? _rootContext : _contextStack.last; + } + + void _resetContext() { + _contextStack.clear(); + _context = _rootContext; + } + + /// Read a byte that must match [char]; otherwise throw a [TProtocolError]. + void _readJsonSyntaxChar(int charByte) { + int byte = _reader.read(); + if (byte != charByte) { + throw new TProtocolError(TProtocolErrorType.INVALID_DATA, + "Expected character ${new String.fromCharCode(charByte)} but found: ${new String.fromCharCode(byte)}"); + } + } + + int _hexVal(int byte) { + if (byte >= _Constants.HEX_0_BYTES[0] && + byte <= _Constants.HEX_9_BYTES[0]) { + return byte - _Constants.HEX_0_BYTES[0]; + } else if (byte >= _Constants.HEX_A_BYTES[0] && + byte <= _Constants.HEX_F_BYTES[0]) { + byte += 10; + return byte - _Constants.HEX_A_BYTES[0]; + } else { + throw new TProtocolError( + TProtocolErrorType.INVALID_DATA, "Expected hex character"); + } + } + + int _hexChar(int byte) => byte.toRadixString(16).codeUnitAt(0); + + /// write + + /// Write the [bytes] as JSON characters, escaping as needed. + void _writeJsonString(Uint8List bytes) { + _context.write(); + transport.writeAll(_Constants.QUOTE_BYTES); + + int length = bytes.length; + for (int i = 0; i < length; i++) { + int byte = bytes[i]; + if ((byte & 0x00FF) >= 0x30) { + if (byte == _Constants.BACKSLASH_BYTES[0]) { + transport.writeAll(_Constants.BACKSLASH_BYTES); + transport.writeAll(_Constants.BACKSLASH_BYTES); + } else { + transport.write(bytes, i, 1); + } + } else { + _tempBuffer[0] = _Constants.JSON_CHAR_TABLE[byte]; + if (_tempBuffer[0] == 1) { + transport.write(bytes, i, 1); + } else if (_tempBuffer[0] > 1) { + transport.writeAll(_Constants.BACKSLASH_BYTES); + transport.write(_tempBuffer, 0, 1); + } else { + transport.writeAll(_Constants.ESCSEQ_BYTES); + _tempBuffer[0] = _hexChar(byte >> 4); + _tempBuffer[1] = _hexChar(byte); + transport.write(_tempBuffer, 0, 2); + } + } + } + + transport.writeAll(_Constants.QUOTE_BYTES); + } + + void _writeJsonInteger(int i) { + if (i == null) i = 0; + + _context.write(); + String str = i.toString(); + + if (_context.escapeNumbers) { + transport.writeAll(_Constants.QUOTE_BYTES); + } + transport.writeAll(utf8Codec.encode(str)); + if (_context.escapeNumbers) { + transport.writeAll(_Constants.QUOTE_BYTES); + } + } + + void _writeJsonDouble(double d) { + if (d == null) d = 0.0; + + _context.write(); + String str = d.toString(); + bool escapeNumbers = d.isNaN || d.isInfinite || _context.escapeNumbers; + + if (escapeNumbers) { + transport.writeAll(_Constants.QUOTE_BYTES); + } + transport.writeAll(utf8Codec.encode(str)); + if (escapeNumbers) { + transport.writeAll(_Constants.QUOTE_BYTES); + } + } + + void _writeJsonBase64(Uint8List bytes) { + _context.write(); + transport.writeAll(_Constants.QUOTE_BYTES); + + String base64text = base64.encode(bytes); + transport.writeAll(utf8Codec.encode(base64text)); + + transport.writeAll(_Constants.QUOTE_BYTES); + } + + void _writeJsonObjectStart() { + _context.write(); + transport.writeAll(_Constants.LBRACE_BYTES); + _pushContext(new _PairContext(this)); + } + + void _writeJsonObjectEnd() { + _popContext(); + transport.writeAll(_Constants.RBRACE_BYTES); + } + + void _writeJsonArrayStart() { + _context.write(); + transport.writeAll(_Constants.LBRACKET_BYTES); + _pushContext(new _ListContext(this)); + } + + void _writeJsonArrayEnd() { + _popContext(); + transport.writeAll(_Constants.RBRACKET_BYTES); + } + + void writeMessageBegin(TMessage message) { + _resetContext(); + + _writeJsonArrayStart(); + _writeJsonInteger(VERSION_1); + + _writeJsonString(utf8Codec.encode(message.name)); + _writeJsonInteger(message.type); + _writeJsonInteger(message.seqid); + } + + void writeMessageEnd() { + _writeJsonArrayEnd(); + } + + void writeStructBegin(TStruct struct) { + _writeJsonObjectStart(); + } + + void writeStructEnd() { + _writeJsonObjectEnd(); + } + + void writeFieldBegin(TField field) { + _writeJsonInteger(field.id); + _writeJsonObjectStart(); + _writeJsonString(_Constants.getTypeNameBytesForTypeId(field.type)); + } + + void writeFieldEnd() { + _writeJsonObjectEnd(); + } + + void writeFieldStop() {} + + void writeMapBegin(TMap map) { + _writeJsonArrayStart(); + _writeJsonString(_Constants.getTypeNameBytesForTypeId(map.keyType)); + _writeJsonString(_Constants.getTypeNameBytesForTypeId(map.valueType)); + _writeJsonInteger(map.length); + _writeJsonObjectStart(); + } + + void writeMapEnd() { + _writeJsonObjectEnd(); + _writeJsonArrayEnd(); + } + + void writeListBegin(TList list) { + _writeJsonArrayStart(); + _writeJsonString(_Constants.getTypeNameBytesForTypeId(list.elementType)); + _writeJsonInteger(list.length); + } + + void writeListEnd() { + _writeJsonArrayEnd(); + } + + void writeSetBegin(TSet set) { + _writeJsonArrayStart(); + _writeJsonString(_Constants.getTypeNameBytesForTypeId(set.elementType)); + _writeJsonInteger(set.length); + } + + void writeSetEnd() { + _writeJsonArrayEnd(); + } + + void writeBool(bool b) { + if (b == null) b = false; + _writeJsonInteger(b ? 1 : 0); + } + + void writeByte(int b) { + _writeJsonInteger(b); + } + + void writeI16(int i16) { + _writeJsonInteger(i16); + } + + void writeI32(int i32) { + _writeJsonInteger(i32); + } + + void writeI64(int i64) { + _writeJsonInteger(i64); + } + + void writeDouble(double d) { + _writeJsonDouble(d); + } + + void writeString(String s) { + var bytes = s != null ? utf8Codec.encode(s) : new Uint8List.fromList([]); + _writeJsonString(bytes); + } + + void writeBinary(Uint8List bytes) { + _writeJsonBase64(bytes); + } + + bool _isHighSurrogate(int b) => b >= 0xD800 && b <= 0xDBFF; + + bool _isLowSurrogate(int b) => b >= 0xDC00 && b <= 0xDFFF; + + /// read + + Uint8List _readJsonString({bool skipContext: false}) { + List<int> bytes = []; + List<int> codeunits = []; + + if (!skipContext) { + _context.read(); + } + + _readJsonSyntaxChar(_Constants.QUOTE_BYTES[0]); + while (true) { + int byte = _reader.read(); + if (byte == _Constants.QUOTE_BYTES[0]) { + break; + } + + // escaped? + if (byte != _Constants.ESCSEQ_BYTES[0]) { + bytes.add(byte); + continue; + } + + byte = _reader.read(); + + // distinguish between \uXXXX and control chars like \n + if (byte != _Constants.ESCSEQ_BYTES[1]) { + String char = new String.fromCharCode(byte); + int offset = _Constants.ESCAPE_CHARS.indexOf(char); + if (offset == -1) { + throw new TProtocolError( + TProtocolErrorType.INVALID_DATA, "Expected control char"); + } + byte = _Constants.ESCAPE_CHAR_VALS.codeUnitAt(offset); + bytes.add(byte); + continue; + } + + // it's \uXXXX + transport.readAll(_tempBuffer, 0, 4); + byte = (_hexVal(_tempBuffer[0]) << 12) + + (_hexVal(_tempBuffer[1]) << 8) + + (_hexVal(_tempBuffer[2]) << 4) + + _hexVal(_tempBuffer[3]); + if (_isHighSurrogate(byte)) { + if (codeunits.isNotEmpty) { + throw new TProtocolError( + TProtocolErrorType.INVALID_DATA, "Expected low surrogate"); + } + codeunits.add(byte); + } + else if (_isLowSurrogate(byte)) { + if (codeunits.isEmpty) { + throw new TProtocolError( + TProtocolErrorType.INVALID_DATA, "Expected high surrogate"); + } + codeunits.add(byte); + bytes.addAll(utf8Codec.encode(new String.fromCharCodes(codeunits))); + codeunits.clear(); + } + else { + bytes.addAll(utf8Codec.encode(new String.fromCharCode(byte))); + } + } + + if (codeunits.isNotEmpty) { + throw new TProtocolError( + TProtocolErrorType.INVALID_DATA, "Expected low surrogate"); + } + + return new Uint8List.fromList(bytes); + } + + String _readJsonNumericChars() { + StringBuffer buffer = new StringBuffer(); + while (true) { + if (!_Constants.isJsonNumeric(_reader.peek())) { + break; + } + buffer.write(new String.fromCharCode(_reader.read())); + } + return buffer.toString(); + } + + int _readJsonInteger() { + _context.read(); + + if (_context.escapeNumbers) { + _readJsonSyntaxChar(_Constants.QUOTE_BYTES[0]); + } + String str = _readJsonNumericChars(); + if (_context.escapeNumbers) { + _readJsonSyntaxChar(_Constants.QUOTE_BYTES[0]); + } + + try { + return int.parse(str); + } on FormatException catch (_) { + throw new TProtocolError(TProtocolErrorType.INVALID_DATA, + "Bad data encounted in numeric data"); + } + } + + double _readJsonDouble() { + _context.read(); + + if (_reader.peek() == _Constants.QUOTE_BYTES[0]) { + Uint8List bytes = _readJsonString(skipContext: true); + double d = double.parse(utf8Codec.decode(bytes), (_) { + throw new TProtocolError(TProtocolErrorType.INVALID_DATA, + "Bad data encounted in numeric data"); + }); + if (!_context.escapeNumbers && !d.isNaN && !d.isInfinite) { + throw new TProtocolError(TProtocolErrorType.INVALID_DATA, + "Numeric data unexpectedly quoted"); + } + return d; + } else { + if (_context.escapeNumbers) { + // This will throw - we should have had a quote if escapeNumbers == true + _readJsonSyntaxChar(_Constants.QUOTE_BYTES[0]); + } + return double.parse(_readJsonNumericChars(), (_) { + throw new TProtocolError(TProtocolErrorType.INVALID_DATA, + "Bad data encounted in numeric data"); + }); + } + } + + Uint8List _readJsonBase64() { + // convert UTF-8 bytes of a Base 64 encoded string to binary bytes + Uint8List base64Bytes = _readJsonString(); + String base64text = utf8Codec.decode(base64Bytes); + + return new Uint8List.fromList(base64.decode(base64text)); + } + + void _readJsonObjectStart() { + _context.read(); + _readJsonSyntaxChar(_Constants.LBRACE_BYTES[0]); + _pushContext(new _PairContext(this)); + } + + void _readJsonObjectEnd() { + _readJsonSyntaxChar(_Constants.RBRACE_BYTES[0]); + _popContext(); + } + + void _readJsonArrayStart() { + _context.read(); + _readJsonSyntaxChar(_Constants.LBRACKET_BYTES[0]); + _pushContext(new _ListContext(this)); + } + + void _readJsonArrayEnd() { + _readJsonSyntaxChar(_Constants.RBRACKET_BYTES[0]); + _popContext(); + } + + TMessage readMessageBegin() { + _resetContext(); + + _readJsonArrayStart(); + if (_readJsonInteger() != VERSION_1) { + throw new TProtocolError( + TProtocolErrorType.BAD_VERSION, "Message contained bad version."); + } + + Uint8List buffer = _readJsonString(); + String name = utf8Codec.decode(buffer); + int type = _readJsonInteger(); + int seqid = _readJsonInteger(); + + return new TMessage(name, type, seqid); + } + + void readMessageEnd() { + _readJsonArrayEnd(); + } + + TStruct readStructBegin() { + _readJsonObjectStart(); + return new TStruct(); + } + + void readStructEnd() { + _readJsonObjectEnd(); + } + + TField readFieldBegin() { + String name = ""; + int type = TType.STOP; + int id = 0; + + if (_reader.peek() != _Constants.RBRACE_BYTES[0]) { + id = _readJsonInteger(); + _readJsonObjectStart(); + type = _Constants.getTypeIdForTypeName(_readJsonString()); + } + + return new TField(name, type, id); + } + + void readFieldEnd() { + _readJsonObjectEnd(); + } + + TMap readMapBegin() { + _readJsonArrayStart(); + int keyType = _Constants.getTypeIdForTypeName(_readJsonString()); + int valueType = _Constants.getTypeIdForTypeName(_readJsonString()); + int length = _readJsonInteger(); + _readJsonObjectStart(); + + return new TMap(keyType, valueType, length); + } + + void readMapEnd() { + _readJsonObjectEnd(); + _readJsonArrayEnd(); + } + + TList readListBegin() { + _readJsonArrayStart(); + int elementType = _Constants.getTypeIdForTypeName(_readJsonString()); + int length = _readJsonInteger(); + + return new TList(elementType, length); + } + + void readListEnd() { + _readJsonArrayEnd(); + } + + TSet readSetBegin() { + _readJsonArrayStart(); + int elementType = _Constants.getTypeIdForTypeName(_readJsonString()); + int length = _readJsonInteger(); + + return new TSet(elementType, length); + } + + void readSetEnd() { + _readJsonArrayEnd(); + } + + bool readBool() { + return _readJsonInteger() == 0 ? false : true; + } + + int readByte() { + return _readJsonInteger(); + } + + int readI16() { + return _readJsonInteger(); + } + + int readI32() { + return _readJsonInteger(); + } + + int readI64() { + return _readJsonInteger(); + } + + double readDouble() { + return _readJsonDouble(); + } + + String readString() { + return utf8Codec.decode(_readJsonString()); + } + + Uint8List readBinary() { + return new Uint8List.fromList(_readJsonBase64()); + } +} + +class _Constants { + static const utf8codec = const Utf8Codec(); + + static final Uint8List HEX_0_BYTES = new Uint8List.fromList('0'.codeUnits); + static final Uint8List HEX_9_BYTES = new Uint8List.fromList('9'.codeUnits); + static final Uint8List HEX_A_BYTES = new Uint8List.fromList('a'.codeUnits); + static final Uint8List HEX_F_BYTES = new Uint8List.fromList('f'.codeUnits); + static final Uint8List COMMA_BYTES = new Uint8List.fromList(','.codeUnits); + static final Uint8List COLON_BYTES = new Uint8List.fromList(':'.codeUnits); + static final Uint8List LBRACE_BYTES = new Uint8List.fromList('{'.codeUnits); + static final Uint8List RBRACE_BYTES = new Uint8List.fromList('}'.codeUnits); + static final Uint8List LBRACKET_BYTES = new Uint8List.fromList('['.codeUnits); + static final Uint8List RBRACKET_BYTES = new Uint8List.fromList(']'.codeUnits); + static final Uint8List QUOTE_BYTES = new Uint8List.fromList('"'.codeUnits); + static final Uint8List BACKSLASH_BYTES = + new Uint8List.fromList(r'\'.codeUnits); + + static final ESCSEQ_BYTES = new Uint8List.fromList(r'\u00'.codeUnits); + + static final Uint8List JSON_CHAR_TABLE = new Uint8List.fromList([ + 0, 0, 0, 0, 0, 0, 0, 0, // 8 bytes + 'b'.codeUnitAt(0), 't'.codeUnitAt(0), 'n'.codeUnitAt(0), 0, // 4 bytes + 'f'.codeUnitAt(0), 'r'.codeUnitAt(0), 0, 0, // 4 bytes + 0, 0, 0, 0, 0, 0, 0, 0, // 8 bytes + 0, 0, 0, 0, 0, 0, 0, 0, // 8 bytes + 1, 1, '"'.codeUnitAt(0), 1, 1, 1, 1, 1, // 8 bytes + 1, 1, 1, 1, 1, 1, 1, 1 // 8 bytes + ]); + + static const String ESCAPE_CHARS = r'"\/bfnrt'; + static const String ESCAPE_CHAR_VALS = '"\\/\b\f\n\r\t'; + + static const String NAME_BOOL = 'tf'; + static const String NAME_BYTE = 'i8'; + static const String NAME_I16 = 'i16'; + static const String NAME_I32 = 'i32'; + static const String NAME_I64 = 'i64'; + static const String NAME_DOUBLE = 'dbl'; + static const String NAME_STRUCT = 'rec'; + static const String NAME_STRING = 'str'; + static const String NAME_MAP = 'map'; + static const String NAME_LIST = 'lst'; + static const String NAME_SET = 'set'; + + static final Map<int, Uint8List> _TYPE_ID_TO_NAME_BYTES = + new Map.unmodifiable({ + TType.BOOL: new Uint8List.fromList(NAME_BOOL.codeUnits), + TType.BYTE: new Uint8List.fromList(NAME_BYTE.codeUnits), + TType.I16: new Uint8List.fromList(NAME_I16.codeUnits), + TType.I32: new Uint8List.fromList(NAME_I32.codeUnits), + TType.I64: new Uint8List.fromList(NAME_I64.codeUnits), + TType.DOUBLE: new Uint8List.fromList(NAME_DOUBLE.codeUnits), + TType.STRING: new Uint8List.fromList(NAME_STRING.codeUnits), + TType.STRUCT: new Uint8List.fromList(NAME_STRUCT.codeUnits), + TType.MAP: new Uint8List.fromList(NAME_MAP.codeUnits), + TType.SET: new Uint8List.fromList(NAME_SET.codeUnits), + TType.LIST: new Uint8List.fromList(NAME_LIST.codeUnits) + }); + + static Uint8List getTypeNameBytesForTypeId(int typeId) { + if (!_TYPE_ID_TO_NAME_BYTES.containsKey(typeId)) { + throw new TProtocolError( + TProtocolErrorType.NOT_IMPLEMENTED, "Unrecognized type"); + } + + return _TYPE_ID_TO_NAME_BYTES[typeId]; + } + + static final Map<String, int> _NAME_TO_TYPE_ID = new Map.unmodifiable({ + NAME_BOOL: TType.BOOL, + NAME_BYTE: TType.BYTE, + NAME_I16: TType.I16, + NAME_I32: TType.I32, + NAME_I64: TType.I64, + NAME_DOUBLE: TType.DOUBLE, + NAME_STRING: TType.STRING, + NAME_STRUCT: TType.STRUCT, + NAME_MAP: TType.MAP, + NAME_SET: TType.SET, + NAME_LIST: TType.LIST + }); + + static int getTypeIdForTypeName(Uint8List bytes) { + String name = utf8codec.decode(bytes); + if (!_NAME_TO_TYPE_ID.containsKey(name)) { + throw new TProtocolError( + TProtocolErrorType.NOT_IMPLEMENTED, "Unrecognized type"); + } + + return _NAME_TO_TYPE_ID[name]; + } + + static final Set<int> _JSON_NUMERICS = new Set.from([ + '+'.codeUnitAt(0), + '-'.codeUnitAt(0), + '.'.codeUnitAt(0), + '0'.codeUnitAt(0), + '1'.codeUnitAt(0), + '2'.codeUnitAt(0), + '3'.codeUnitAt(0), + '4'.codeUnitAt(0), + '5'.codeUnitAt(0), + '6'.codeUnitAt(0), + '7'.codeUnitAt(0), + '8'.codeUnitAt(0), + '9'.codeUnitAt(0), + 'E'.codeUnitAt(0), + 'e'.codeUnitAt(0) + ]); + + static bool isJsonNumeric(int byte) { + return _JSON_NUMERICS.contains(byte); + } +} + +class _LookaheadReader { + final TJsonProtocol protocol; + + _LookaheadReader(this.protocol); + + bool _hasData = false; + final Uint8List _data = new Uint8List(1); + + int read() { + if (_hasData) { + _hasData = false; + } else { + protocol.transport.readAll(_data, 0, 1); + } + + return _data[0]; + } + + int peek() { + if (!_hasData) { + protocol.transport.readAll(_data, 0, 1); + } + _hasData = true; + + return _data[0]; + } +} + +class _BaseContext { + final TJsonProtocol protocol; + + _BaseContext(this.protocol); + + void write() {} + + void read() {} + + bool get escapeNumbers => false; + + String toString() => 'BaseContext'; +} + +class _ListContext extends _BaseContext { + _ListContext(TJsonProtocol protocol) : super(protocol); + + bool _first = true; + + void write() { + if (_first) { + _first = false; + } else { + protocol.transport.writeAll(_Constants.COMMA_BYTES); + } + } + + void read() { + if (_first) { + _first = false; + } else { + protocol._readJsonSyntaxChar(_Constants.COMMA_BYTES[0]); + } + } + + String toString() => 'ListContext'; +} + +class _PairContext extends _BaseContext { + _PairContext(TJsonProtocol protocol) : super(protocol); + + bool _first = true; + bool _colon = true; + + Uint8List get symbolBytes => + _colon ? _Constants.COLON_BYTES : _Constants.COMMA_BYTES; + + void write() { + if (_first) { + _first = false; + _colon = true; + } else { + protocol.transport.writeAll(symbolBytes); + _colon = !_colon; + } + } + + void read() { + if (_first) { + _first = false; + _colon = true; + } else { + protocol._readJsonSyntaxChar(symbolBytes[0]); + _colon = !_colon; + } + } + + bool get escapeNumbers => _colon; + + String toString() => 'PairContext'; +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_list.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_list.dart new file mode 100644 index 000000000..49f467329 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_list.dart @@ -0,0 +1,25 @@ +/// 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. + +part of thrift; + +class TList { + final int elementType; + final int length; + + TList(this.elementType, this.length); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_map.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_map.dart new file mode 100644 index 000000000..efdf6813a --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_map.dart @@ -0,0 +1,26 @@ +/// 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. + +part of thrift; + +class TMap { + final int keyType; + final int valueType; + final int length; + + TMap(this.keyType, this.valueType, this.length); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_message.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_message.dart new file mode 100644 index 000000000..cc7b88680 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_message.dart @@ -0,0 +1,35 @@ +/// 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. + +part of thrift; + +class TMessageType { + static const int CALL = 1; + static const int REPLY = 2; + static const int EXCEPTION = 3; + static const int ONEWAY = 4; +} + +class TMessage { + final String name; + final int type; + final int seqid; + + TMessage(this.name, this.type, this.seqid); + + String toString() => "<TMessage name: '$name' type: $type seqid: $seqid>"; +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_multiplexed_protocol.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_multiplexed_protocol.dart new file mode 100644 index 000000000..078a6d72e --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_multiplexed_protocol.dart @@ -0,0 +1,43 @@ +/// 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. + +part of thrift; + +/// Adapted from the C# version. +class TMultiplexedProtocol extends TProtocolDecorator { + static const SEPARATOR = ':'; + + final String _serviceName; + + TMultiplexedProtocol(TProtocol protocol, String serviceName) + : _serviceName = serviceName, + super(protocol) { + if (serviceName == null) { + throw new ArgumentError.notNull("serviceName"); + } + } + + void writeMessageBegin(TMessage message) { + if (message.type == TMessageType.CALL || + message.type == TMessageType.ONEWAY) { + String name = _serviceName + SEPARATOR + message.name; + message = new TMessage(name, message.type, message.seqid); + } + + super.writeMessageBegin(message); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol.dart new file mode 100644 index 000000000..f49c0321d --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol.dart @@ -0,0 +1,95 @@ +/// 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. + +part of thrift; + +abstract class TProtocol { + final TTransport transport; + + TProtocol(this.transport); + + /// Write + void writeMessageBegin(TMessage message); + void writeMessageEnd(); + + void writeStructBegin(TStruct struct); + void writeStructEnd(); + + void writeFieldBegin(TField field); + void writeFieldEnd(); + void writeFieldStop(); + + void writeMapBegin(TMap map); + void writeMapEnd(); + + void writeListBegin(TList list); + void writeListEnd(); + + void writeSetBegin(TSet set); + void writeSetEnd(); + + void writeBool(bool b); + + void writeByte(int b); + + void writeI16(int i16); + + void writeI32(int i32); + + void writeI64(int i64); + + void writeDouble(double d); + + void writeString(String str); + + void writeBinary(Uint8List bytes); + + /// Read + TMessage readMessageBegin(); + void readMessageEnd(); + + TStruct readStructBegin(); + void readStructEnd(); + + TField readFieldBegin(); + void readFieldEnd(); + + TMap readMapBegin(); + void readMapEnd(); + + TList readListBegin(); + void readListEnd(); + + TSet readSetBegin(); + void readSetEnd(); + + bool readBool(); + + int readByte(); + + int readI16(); + + int readI32(); + + int readI64(); + + double readDouble(); + + String readString(); + + Uint8List readBinary(); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_decorator.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_decorator.dart new file mode 100644 index 000000000..9cd02f645 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_decorator.dart @@ -0,0 +1,150 @@ +/// 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. + +part of thrift; + +/// Forward all operations to the wrapped protocol. Used as a base class. +/// +/// Adapted from the C# version. +class TProtocolDecorator extends TProtocol { + final TProtocol _protocol; + + TProtocolDecorator(TProtocol protocol) + : _protocol = protocol, + super(protocol.transport); + + /// Write + + void writeMessageBegin(TMessage message) { + _protocol.writeMessageBegin(message); + } + + void writeMessageEnd() { + _protocol.writeMessageEnd(); + } + + void writeStructBegin(TStruct struct) { + _protocol.writeStructBegin(struct); + } + + void writeStructEnd() { + _protocol.writeStructEnd(); + } + + void writeFieldBegin(TField field) { + _protocol.writeFieldBegin(field); + } + + void writeFieldEnd() { + _protocol.writeFieldEnd(); + } + + void writeFieldStop() { + _protocol.writeFieldStop(); + } + + void writeMapBegin(TMap map) { + _protocol.writeMapBegin(map); + } + + void writeMapEnd() { + _protocol.writeMapEnd(); + } + + void writeListBegin(TList list) { + _protocol.writeListBegin(list); + } + + void writeListEnd() { + _protocol.writeListEnd(); + } + + void writeSetBegin(TSet set) { + _protocol.writeSetBegin(set); + } + + void writeSetEnd() { + _protocol.writeSetEnd(); + } + + void writeBool(bool b) { + _protocol.writeBool(b); + } + + void writeByte(int b) { + _protocol.writeByte(b); + } + + void writeI16(int i16) { + _protocol.writeI16(i16); + } + + void writeI32(int i32) { + _protocol.writeI32(i32); + } + + void writeI64(int i64) { + _protocol.writeI64(i64); + } + + void writeDouble(double d) { + _protocol.writeDouble(d); + } + + void writeString(String str) { + _protocol.writeString(str); + } + + void writeBinary(Uint8List bytes) { + _protocol.writeBinary(bytes); + } + + /// Read + TMessage readMessageBegin() => _protocol.readMessageBegin(); + void readMessageEnd() => _protocol.readMessageEnd(); + + TStruct readStructBegin() => _protocol.readStructBegin(); + void readStructEnd() => _protocol.readStructEnd(); + + TField readFieldBegin() => _protocol.readFieldBegin(); + void readFieldEnd() => _protocol.readFieldEnd(); + + TMap readMapBegin() => _protocol.readMapBegin(); + void readMapEnd() => _protocol.readMapEnd(); + + TList readListBegin() => _protocol.readListBegin(); + void readListEnd() => _protocol.readListEnd(); + + TSet readSetBegin() => _protocol.readSetBegin(); + void readSetEnd() => _protocol.readSetEnd(); + + bool readBool() => _protocol.readBool(); + + int readByte() => _protocol.readByte(); + + int readI16() => _protocol.readI16(); + + int readI32() => _protocol.readI32(); + + int readI64() => _protocol.readI64(); + + double readDouble() => _protocol.readDouble(); + + String readString() => _protocol.readString(); + + Uint8List readBinary() => _protocol.readBinary(); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_error.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_error.dart new file mode 100644 index 000000000..456baeb79 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_error.dart @@ -0,0 +1,33 @@ +/// 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. + +part of thrift; + +class TProtocolErrorType { + static const int UNKNOWN = 0; + static const int INVALID_DATA = 1; + static const int NEGATIVE_SIZE = 2; + static const int SIZE_LIMIT = 3; + static const int BAD_VERSION = 4; + static const int NOT_IMPLEMENTED = 5; + static const int DEPTH_LIMIT = 6; +} + +class TProtocolError extends TError { + TProtocolError([int type = TProtocolErrorType.UNKNOWN, String message = ""]) + : super(type, message); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_factory.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_factory.dart new file mode 100644 index 000000000..922c6cb69 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_factory.dart @@ -0,0 +1,22 @@ +/// 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. + +part of thrift; + +abstract class TProtocolFactory<T extends TProtocol> { + T getProtocol(TTransport transport); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_util.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_util.dart new file mode 100644 index 000000000..841ea8217 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_util.dart @@ -0,0 +1,107 @@ +/// 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. + +part of thrift; + +class TProtocolUtil { + // equal to JavaScript Number.MAX_SAFE_INTEGER, 2^53 - 1 + static const int defaultRecursionLimit = 9007199254740991; + + static int maxRecursionLimit = defaultRecursionLimit; + + static skip(TProtocol prot, int type) { + _skip(prot, type, maxRecursionLimit); + } + + static _skip(TProtocol prot, int type, int recursionLimit) { + if (recursionLimit <= 0) { + throw new TProtocolError( + TProtocolErrorType.DEPTH_LIMIT, "Depth limit exceeded"); + } + + switch (type) { + case TType.BOOL: + prot.readBool(); + break; + + case TType.BYTE: + prot.readByte(); + break; + + case TType.I16: + prot.readI16(); + break; + + case TType.I32: + prot.readI32(); + break; + + case TType.I64: + prot.readI64(); + break; + + case TType.DOUBLE: + prot.readDouble(); + break; + + case TType.STRING: + prot.readBinary(); + break; + + case TType.STRUCT: + prot.readStructBegin(); + while (true) { + TField field = prot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + _skip(prot, field.type, recursionLimit - 1); + prot.readFieldEnd(); + } + prot.readStructEnd(); + break; + + case TType.MAP: + TMap map = prot.readMapBegin(); + for (int i = 0; i < map.length; i++) { + _skip(prot, map.keyType, recursionLimit - 1); + _skip(prot, map.valueType, recursionLimit - 1); + } + prot.readMapEnd(); + break; + + case TType.SET: + TSet set = prot.readSetBegin(); + for (int i = 0; i < set.length; i++) { + _skip(prot, set.elementType, recursionLimit - 1); + } + prot.readSetEnd(); + break; + + case TType.LIST: + TList list = prot.readListBegin(); + for (int i = 0; i < list.length; i++) { + _skip(prot, list.elementType, recursionLimit - 1); + } + prot.readListEnd(); + break; + + default: + throw new TProtocolError(TProtocolErrorType.INVALID_DATA, "Invalid data"); + } + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_set.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_set.dart new file mode 100644 index 000000000..b342537e3 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_set.dart @@ -0,0 +1,25 @@ +/// 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. + +part of thrift; + +class TSet { + final int elementType; + final int length; + + TSet(this.elementType, this.length); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_struct.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_struct.dart new file mode 100644 index 000000000..0303f6395 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_struct.dart @@ -0,0 +1,24 @@ +/// 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. + +part of thrift; + +class TStruct { + final String name; + + TStruct([this.name = ""]); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_type.dart b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_type.dart new file mode 100644 index 000000000..3919d969d --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_type.dart @@ -0,0 +1,34 @@ +/// 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. + +part of thrift; + +class TType { + static const int STOP = 0; + static const int VOID = 1; + static const int BOOL = 2; + static const int BYTE = 3; + static const int DOUBLE = 4; + static const int I16 = 6; + static const int I32 = 8; + static const int I64 = 10; + static const int STRING = 11; + static const int STRUCT = 12; + static const int MAP = 13; + static const int SET = 14; + static const int LIST = 15; +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/serializer/t_deserializer.dart b/src/jaegertracing/thrift/lib/dart/lib/src/serializer/t_deserializer.dart new file mode 100644 index 000000000..aefbee25b --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/serializer/t_deserializer.dart @@ -0,0 +1,50 @@ +/// 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. + +part of thrift; + +class TDeserializer { + final message = new TMessage('Deserializer', TMessageType.ONEWAY, 1); + TBufferedTransport transport; + TProtocol protocol; + + TDeserializer({TProtocolFactory protocolFactory}) { + this.transport = new TBufferedTransport(); + + if (protocolFactory == null) { + protocolFactory = new TBinaryProtocolFactory(); + } + + this.protocol = protocolFactory.getProtocol(this.transport); + } + + void read(TBase base, Uint8List data) { + transport.writeAll(data); + + transport.flush(); + + base.read(protocol); + } + + void readString(TBase base, String data) { + + transport.writeAll(base64.decode(data)); + transport.flush(); + + base.read(protocol); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/serializer/t_serializer.dart b/src/jaegertracing/thrift/lib/dart/lib/src/serializer/t_serializer.dart new file mode 100644 index 000000000..feec8226d --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/serializer/t_serializer.dart @@ -0,0 +1,48 @@ +/// 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. + +part of thrift; + +class TSerializer { + final message = new TMessage('Serializer', TMessageType.ONEWAY, 1); + TBufferedTransport transport; + TProtocol protocol; + + TSerializer({TProtocolFactory protocolFactory}) { + this.transport = new TBufferedTransport(); + + if (protocolFactory == null) { + protocolFactory = new TBinaryProtocolFactory(); + } + + this.protocol = protocolFactory.getProtocol(this.transport); + } + + Uint8List write(TBase base) { + base.write(protocol); + + return transport.consumeWriteBuffer(); + } + + String writeString(TBase base) { + base.write(protocol); + + Uint8List bytes = transport.consumeWriteBuffer(); + + return base64.encode(bytes); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/t_application_error.dart b/src/jaegertracing/thrift/lib/dart/lib/src/t_application_error.dart new file mode 100644 index 000000000..6f8abd4bd --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/t_application_error.dart @@ -0,0 +1,104 @@ +/// 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. + +part of thrift; + +class TApplicationErrorType { + static const int UNKNOWN = 0; + static const int UNKNOWN_METHOD = 1; + static const int INVALID_MESSAGE_TYPE = 2; + static const int WRONG_METHOD_NAME = 3; + static const int BAD_SEQUENCE_ID = 4; + static const int MISSING_RESULT = 5; + static const int INTERNAL_ERROR = 6; + static const int PROTOCOL_ERROR = 7; + static const int INVALID_TRANSFORM = 8; + static const int INVALID_PROTOCOL = 9; + static const int UNSUPPORTED_CLIENT_TYPE = 10; +} + +class TApplicationError extends TError { + static final TStruct _struct = new TStruct("TApplicationError"); + static const int MESSAGE = 1; + static final TField _messageField = + new TField("message", TType.STRING, MESSAGE); + static const int TYPE = 2; + static final TField _typeField = new TField("type", TType.I32, TYPE); + + TApplicationError( + [int type = TApplicationErrorType.UNKNOWN, String message = ""]) + : super(type, message); + + static TApplicationError read(TProtocol iprot) { + TField field; + + String message = null; + int type = TApplicationErrorType.UNKNOWN; + + iprot.readStructBegin(); + while (true) { + field = iprot.readFieldBegin(); + + if (field.type == TType.STOP) { + break; + } + + switch (field.id) { + case MESSAGE: + if (field.type == TType.STRING) { + message = iprot.readString(); + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + + case TYPE: + if (field.type == TType.I32) { + type = iprot.readI32(); + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + return new TApplicationError(type, message); + } + + write(TProtocol oprot) { + oprot.writeStructBegin(_struct); + + if (message != null && !message.isEmpty) { + oprot.writeFieldBegin(_messageField); + oprot.writeString(message); + oprot.writeFieldEnd(); + } + + oprot.writeFieldBegin(_typeField); + oprot.writeI32(type); + oprot.writeFieldEnd(); + + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/t_base.dart b/src/jaegertracing/thrift/lib/dart/lib/src/t_base.dart new file mode 100644 index 000000000..d5571b6dc --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/t_base.dart @@ -0,0 +1,37 @@ +/// 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. + +part of thrift; + +abstract class TBase { + /// Reads the TObject from the given input protocol. + void read(TProtocol iprot); + + /// Writes the objects out to the [oprot] protocol. + void write(TProtocol oprot); + + /// Check if a field is currently set or unset, using the [fieldId]. + bool isSet(int fieldId); + + /// Get a field's value by [fieldId]. Primitive types will be wrapped in the + /// appropriate "boxed" types. + getFieldValue(int fieldId); + + /// Set a field's value by [fieldId]. Primitive types must be "boxed" in the + /// appropriate object wrapper type. + setFieldValue(int fieldId, Object value); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/t_error.dart b/src/jaegertracing/thrift/lib/dart/lib/src/t_error.dart new file mode 100644 index 000000000..93ab73239 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/t_error.dart @@ -0,0 +1,27 @@ +/// 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. + +part of thrift; + +class TError extends Error { + final String message; + final int type; + + TError(this.type, this.message); + + String toString() => "<TError type: $type message: '$message'>"; +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/t_processor.dart b/src/jaegertracing/thrift/lib/dart/lib/src/t_processor.dart new file mode 100644 index 000000000..dcf20fbc7 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/t_processor.dart @@ -0,0 +1,24 @@ +/// 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. + +part of thrift; + +/// A processor is a generic object which operates upon an input stream and +/// writes to some output stream. +abstract class TProcessor { + bool process(TProtocol input, TProtocol output); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_buffered_transport.dart b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_buffered_transport.dart new file mode 100644 index 000000000..b73a30c0e --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_buffered_transport.dart @@ -0,0 +1,98 @@ +/// 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. + +part of thrift; + +/// Buffered implementation of [TTransport]. +class TBufferedTransport extends TTransport { + final List<int> _writeBuffer = []; + Iterator<int> _readIterator; + + Uint8List consumeWriteBuffer() { + Uint8List buffer = new Uint8List.fromList(_writeBuffer); + _writeBuffer.clear(); + return buffer; + } + + void _setReadBuffer(Uint8List readBuffer) { + _readIterator = readBuffer != null ? readBuffer.iterator : null; + } + + void _reset({bool isOpen: false}) { + _isOpen = isOpen; + _writeBuffer.clear(); + _readIterator = null; + } + + bool get hasReadData => _readIterator != null; + + bool _isOpen; + bool get isOpen => _isOpen; + + Future open() async { + _reset(isOpen: true); + } + + Future close() async { + _reset(isOpen: false); + } + + int read(Uint8List buffer, int offset, int length) { + if (buffer == null) { + throw new ArgumentError.notNull("buffer"); + } + + if (offset + length > buffer.length) { + throw new ArgumentError("The range exceeds the buffer length"); + } + + if (_readIterator == null || length <= 0) { + return 0; + } + + int i = 0; + while (i < length && _readIterator.moveNext()) { + buffer[offset + i] = _readIterator.current; + i++; + } + + // cleanup iterator when we've reached the end + if (_readIterator.current == null) { + _readIterator = null; + } + + return i; + } + + void write(Uint8List buffer, int offset, int length) { + if (buffer == null) { + throw new ArgumentError.notNull("buffer"); + } + + if (offset + length > buffer.length) { + throw new ArgumentError("The range exceeds the buffer length"); + } + + _writeBuffer.addAll(buffer.sublist(offset, offset + length)); + } + + Future flush() { + _readIterator = consumeWriteBuffer().iterator; + + return new Future.value(); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_framed_transport.dart b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_framed_transport.dart new file mode 100644 index 000000000..2ef03f7f8 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_framed_transport.dart @@ -0,0 +1,169 @@ +/// 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. + +part of thrift; + +/// Framed [TTransport]. +/// +/// Adapted from the Java Framed transport. +class TFramedTransport extends TBufferedTransport { + static const int headerByteCount = 4; + + final TTransport _transport; + + final Uint8List _headerBytes = new Uint8List(headerByteCount); + int _receivedHeaderBytes = 0; + + int _bodySize = 0; + Uint8List _body = null; + int _receivedBodyBytes = 0; + + Completer<Uint8List> _frameCompleter = null; + + TFramedTransport(TTransport transport) : _transport = transport { + if (transport == null) { + throw new ArgumentError.notNull("transport"); + } + } + + bool get isOpen => _transport.isOpen; + + Future open() { + _reset(isOpen: true); + return _transport.open(); + } + + Future close() { + _reset(isOpen: false); + return _transport.close(); + } + + int read(Uint8List buffer, int offset, int length) { + if (hasReadData) { + int got = super.read(buffer, offset, length); + if (got > 0) return got; + } + + // IMPORTANT: by the time you've got here, + // an entire frame is available for reading + + return super.read(buffer, offset, length); + } + + void _readFrame() { + if (_body == null) { + bool gotFullHeader = _readFrameHeader(); + if (!gotFullHeader) { + return; + } + } + + _readFrameBody(); + } + + bool _readFrameHeader() { + var remainingHeaderBytes = headerByteCount - _receivedHeaderBytes; + + int got = _transport.read(_headerBytes, _receivedHeaderBytes, remainingHeaderBytes); + if (got < 0) { + throw new TTransportError( + TTransportErrorType.UNKNOWN, "Socket closed during frame header read"); + } + + _receivedHeaderBytes += got; + + if (_receivedHeaderBytes == headerByteCount) { + int size = _headerBytes.buffer.asByteData().getUint32(0); + + _receivedHeaderBytes = 0; + + if (size < 0) { + throw new TTransportError( + TTransportErrorType.UNKNOWN, "Read a negative frame size: $size"); + } + + _bodySize = size; + _body = new Uint8List(_bodySize); + _receivedBodyBytes = 0; + + return true; + } else { + _registerForReadableBytes(); + return false; + } + } + + void _readFrameBody() { + var remainingBodyBytes = _bodySize - _receivedBodyBytes; + + int got = _transport.read(_body, _receivedBodyBytes, remainingBodyBytes); + if (got < 0) { + throw new TTransportError( + TTransportErrorType.UNKNOWN, "Socket closed during frame body read"); + } + + _receivedBodyBytes += got; + + if (_receivedBodyBytes == _bodySize) { + var body = _body; + + _bodySize = 0; + _body = null; + _receivedBodyBytes = 0; + + _setReadBuffer(body); + + var completer = _frameCompleter; + _frameCompleter = null; + completer.complete(new Uint8List(0)); + } else { + _registerForReadableBytes(); + } + } + + Future flush() { + if (_frameCompleter == null) { + Uint8List buffer = consumeWriteBuffer(); + int length = buffer.length; + + _headerBytes.buffer.asByteData().setUint32(0, length); + _transport.write(_headerBytes, 0, headerByteCount); + _transport.write(buffer, 0, length); + + _frameCompleter = new Completer<Uint8List>(); + _registerForReadableBytes(); + } + + return _frameCompleter.future; + } + + void _registerForReadableBytes() { + _transport.flush().then((_) { + _readFrame(); + }).catchError((e) { + var completer = _frameCompleter; + + _receivedHeaderBytes = 0; + _bodySize = 0; + _body = null; + _receivedBodyBytes = 0; + _frameCompleter = null; + + completer.completeError(e); + }); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_http_transport.dart b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_http_transport.dart new file mode 100644 index 000000000..630213fbf --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_http_transport.dart @@ -0,0 +1,99 @@ +/// 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. + +part of thrift; + +/// HTTP implementation of [TTransport]. +/// +/// For example: +/// +/// var transport = new THttpClientTransport(new BrowserClient(), +/// new THttpConfig(url, {'X-My-Custom-Header': 'my value'})); +/// var protocol = new TJsonProtocol(transport); +/// var client = new MyThriftServiceClient(protocol); +/// var result = client.myMethod(); +/// +/// Adapted from the JS XHR HTTP transport. +class THttpClientTransport extends TBufferedTransport { + final Client httpClient; + final THttpConfig config; + + THttpClientTransport(this.httpClient, this.config) { + if (httpClient == null) { + throw new ArgumentError.notNull("httpClient"); + } + } + + Future close() async { + _reset(isOpen: false); + httpClient.close(); + } + + Future flush() { + var requestBody = base64.encode(consumeWriteBuffer()); + + // Use a sync completer to ensure that the buffer can be read immediately + // after the read buffer is set, and avoid a race condition where another + // response could overwrite the read buffer. + var completer = new Completer.sync(); + + httpClient + .post(config.url, headers: config.headers, body: requestBody) + .then((response) { + Uint8List data; + try { + data = new Uint8List.fromList(base64.decode(response.body)); + } on FormatException catch (_) { + throw new TProtocolError(TProtocolErrorType.INVALID_DATA, + "Expected a Base 64 encoded string."); + } + + _setReadBuffer(data); + completer.complete(); + }); + + return completer.future; + } +} + +class THttpConfig { + final Uri url; + + Map<String, String> _headers; + Map<String, String> get headers => _headers; + + THttpConfig(this.url, Map<String, String> headers) { + if (url == null || !url.hasAuthority) { + throw new ArgumentError("Invalid url"); + } + + _initHeaders(headers); + } + + void _initHeaders(Map<String, String> initial) { + var h = {}; + + if (initial != null) { + h.addAll(initial); + } + + h['Content-Type'] = 'application/x-thrift'; + h['Accept'] = 'application/x-thrift'; + + _headers = new Map.unmodifiable(h); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_message_reader.dart b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_message_reader.dart new file mode 100644 index 000000000..8ca070834 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_message_reader.dart @@ -0,0 +1,99 @@ +/// 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. + +part of thrift; + +/// [TMessageReader] extracts a [TMessage] from bytes. This is used to allow a +/// transport to inspect the message seqid and map responses to requests. +class TMessageReader { + final TProtocolFactory protocolFactory; + + final int byteOffset; + final _TMessageReaderTransport _transport; + + /// Construct a [MessageReader]. The optional [byteOffset] specifies the + /// number of bytes to skip before reading the [TMessage]. + TMessageReader(this.protocolFactory, {int byteOffset: 0}) + : _transport = new _TMessageReaderTransport(), + this.byteOffset = byteOffset; + + TMessage readMessage(Uint8List bytes) { + _transport.reset(bytes, byteOffset); + TProtocol protocol = protocolFactory.getProtocol(_transport); + TMessage message = protocol.readMessageBegin(); + _transport.reset(null); + + return message; + } +} + +/// An internal class used to support [TMessageReader]. +class _TMessageReaderTransport extends TTransport { + _TMessageReaderTransport(); + + Iterator<int> _readIterator; + + void reset(Uint8List bytes, [int offset = 0]) { + if (bytes == null) { + _readIterator = null; + return; + } + + if (offset > bytes.length) { + throw new ArgumentError("The offset exceeds the bytes length"); + } + + _readIterator = bytes.iterator; + + for (var i = 0; i < offset; i++) { + _readIterator.moveNext(); + } + } + + get isOpen => true; + + Future open() => throw new UnsupportedError("Unsupported in MessageReader"); + + Future close() => throw new UnsupportedError("Unsupported in MessageReader"); + + int read(Uint8List buffer, int offset, int length) { + if (buffer == null) { + throw new ArgumentError.notNull("buffer"); + } + + if (offset + length > buffer.length) { + throw new ArgumentError("The range exceeds the buffer length"); + } + + if (_readIterator == null || length <= 0) { + return 0; + } + + int i = 0; + while (i < length && _readIterator.moveNext()) { + buffer[offset + i] = _readIterator.current; + i++; + } + + return i; + } + + void write(Uint8List buffer, int offset, int length) => + throw new UnsupportedError("Unsupported in MessageReader"); + + Future flush() => throw new UnsupportedError("Unsupported in MessageReader"); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_socket.dart b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_socket.dart new file mode 100644 index 000000000..b2eb6b646 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_socket.dart @@ -0,0 +1,38 @@ +/// 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. + +part of thrift; + +enum TSocketState { CLOSED, OPEN } + +abstract class TSocket { + Stream<TSocketState> get onState; + + Stream<Object> get onError; + + Stream<Uint8List> get onMessage; + + bool get isOpen; + + bool get isClosed; + + Future open(); + + Future close(); + + void send(Uint8List data); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_socket_transport.dart b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_socket_transport.dart new file mode 100644 index 000000000..c41374aff --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_socket_transport.dart @@ -0,0 +1,177 @@ +/// 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. + +part of thrift; + +/// Socket implementation of [TTransport]. +/// +/// For example: +/// +/// var transport = new TClientSocketTransport(new TWebSocket(url)); +/// var protocol = new TBinaryProtocol(transport); +/// var client = new MyThriftServiceClient(protocol); +/// var result = client.myMethod(); +/// +/// Adapted from the JS WebSocket transport. +abstract class TSocketTransport extends TBufferedTransport { + final Logger logger = new Logger('thrift.TSocketTransport'); + + final TSocket socket; + + /// A transport using the provided [socket]. + TSocketTransport(this.socket) { + if (socket == null) { + throw new ArgumentError.notNull('socket'); + } + + socket.onError.listen((e) => logger.warning(e)); + socket.onMessage.listen(handleIncomingMessage); + } + + bool get isOpen => socket.isOpen; + + Future open() { + _reset(isOpen: true); + return socket.open(); + } + + Future close() { + _reset(isOpen: false); + return socket.close(); + } + + /// Make an incoming message available to read from the transport. + void handleIncomingMessage(Uint8List messageBytes) { + _setReadBuffer(messageBytes); + } +} + +/// [TClientSocketTransport] is a basic client socket transport. It sends +/// outgoing messages and expects a response. +/// +/// NOTE: This transport expects a single threaded server, as it will process +/// responses in FIFO order. +class TClientSocketTransport extends TSocketTransport { + final List<Completer<Uint8List>> _completers = []; + + TClientSocketTransport(TSocket socket) : super(socket); + + Future flush() { + Uint8List bytes = consumeWriteBuffer(); + + // Use a sync completer to ensure that the buffer can be read immediately + // after the read buffer is set, and avoid a race condition where another + // response could overwrite the read buffer. + var completer = new Completer<Uint8List>.sync(); + _completers.add(completer); + + if (bytes.lengthInBytes > 0) { + socket.send(bytes); + } + + return completer.future; + } + + void handleIncomingMessage(Uint8List messageBytes) { + super.handleIncomingMessage(messageBytes); + + if (_completers.isNotEmpty) { + var completer = _completers.removeAt(0); + completer.complete(); + } + } +} + +/// [TAsyncClientSocketTransport] sends outgoing messages and expects an +/// asynchronous response. +/// +/// NOTE: This transport uses a [MessageReader] to read a [TMessage] when an +/// incoming message arrives to correlate a response to a request, using the +/// seqid. +class TAsyncClientSocketTransport extends TSocketTransport { + static const defaultTimeout = const Duration(seconds: 30); + + final Map<int, Completer<Uint8List>> _completers = {}; + + final TMessageReader messageReader; + + final Duration responseTimeout; + + TAsyncClientSocketTransport(TSocket socket, TMessageReader messageReader, + {Duration responseTimeout: defaultTimeout}) + : this.messageReader = messageReader, + this.responseTimeout = responseTimeout, + super(socket); + + Future flush() { + Uint8List bytes = consumeWriteBuffer(); + TMessage message = messageReader.readMessage(bytes); + int seqid = message.seqid; + + // Use a sync completer to ensure that the buffer can be read immediately + // after the read buffer is set, and avoid a race condition where another + // response could overwrite the read buffer. + var completer = new Completer<Uint8List>.sync(); + _completers[seqid] = completer; + + if (responseTimeout != null) { + new Future.delayed(responseTimeout, () { + var completer = _completers.remove(seqid); + if (completer != null) { + completer.completeError( + new TimeoutException("Response timed out.", responseTimeout)); + } + }); + } + + socket.send(bytes); + + return completer.future; + } + + void handleIncomingMessage(Uint8List messageBytes) { + super.handleIncomingMessage(messageBytes); + + TMessage message = messageReader.readMessage(messageBytes); + var completer = _completers.remove(message.seqid); + if (completer != null) { + completer.complete(); + } + } +} + +/// [TServerSocketTransport] listens for incoming messages. When it sends a +/// response, it does not expect an acknowledgement. +class TServerSocketTransport extends TSocketTransport { + final StreamController _onIncomingMessageController; + Stream get onIncomingMessage => _onIncomingMessageController.stream; + + TServerSocketTransport(TSocket socket) + : _onIncomingMessageController = new StreamController.broadcast(), + super(socket); + + Future flush() async { + Uint8List message = consumeWriteBuffer(); + socket.send(message); + } + + void handleIncomingMessage(Uint8List messageBytes) { + super.handleIncomingMessage(messageBytes); + + _onIncomingMessageController.add(null); + } +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport.dart b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport.dart new file mode 100644 index 000000000..563d5eb5a --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport.dart @@ -0,0 +1,70 @@ +/// 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. + +part of thrift; + +abstract class TTransport { + /// Queries whether the transport is open. + /// Returns [true] if the transport is open. + bool get isOpen; + + /// Opens the transport for reading/writing. + /// Throws [TTransportError] if the transport could not be opened. + Future open(); + + /// Closes the transport. + Future close(); + + /// Reads up to [length] bytes into [buffer], starting at [offset]. + /// Returns the number of bytes actually read. + /// Throws [TTransportError] if there was an error reading data + int read(Uint8List buffer, int offset, int length); + + /// Guarantees that all of [length] bytes are actually read off the transport. + /// Returns the number of bytes actually read, which must be equal to + /// [length]. + /// Throws [TTransportError] if there was an error reading data + int readAll(Uint8List buffer, int offset, int length) { + int got = 0; + int ret = 0; + while (got < length) { + ret = read(buffer, offset + got, length - got); + if (ret <= 0) { + throw new TTransportError( + TTransportErrorType.UNKNOWN, + "Cannot read. Remote side has closed. Tried to read $length " + "bytes, but only got $got bytes."); + } + got += ret; + } + return got; + } + + /// Writes up to [len] bytes from the buffer. + /// Throws [TTransportError] if there was an error writing data + void write(Uint8List buffer, int offset, int length); + + /// Writes the [bytes] to the output. + /// Throws [TTransportError] if there was an error writing data + void writeAll(Uint8List buffer) { + write(buffer, 0, buffer.length); + } + + /// Flush any pending data out of a transport buffer. + /// Throws [TTransportError] if there was an error writing out data. + Future flush(); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport_error.dart b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport_error.dart new file mode 100644 index 000000000..d3508e052 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport_error.dart @@ -0,0 +1,31 @@ +/// 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. + +part of thrift; + +class TTransportErrorType { + static const int UNKNOWN = 0; + static const int NOT_OPEN = 1; + static const int ALREADY_OPEN = 2; + static const int TIMED_OUT = 3; + static const int END_OF_FILE = 4; +} + +class TTransportError extends TError { + TTransportError([int type = TTransportErrorType.UNKNOWN, String message = ""]) + : super(type, message); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport_factory.dart b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport_factory.dart new file mode 100644 index 000000000..7a10461d2 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport_factory.dart @@ -0,0 +1,27 @@ +/// 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. + +part of thrift; + +/// Factory class used to create wrapped instance of a [TTransport]. This is +/// used primarily in servers. +/// +/// Adapted from the Java version. +class TTransportFactory { + Future<TTransport> getTransport(TTransport transport) => + new Future.value(transport); +} diff --git a/src/jaegertracing/thrift/lib/dart/lib/thrift.dart b/src/jaegertracing/thrift/lib/dart/lib/thrift.dart new file mode 100644 index 000000000..c429d773c --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/thrift.dart @@ -0,0 +1,65 @@ +/// 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. + +library thrift; + +import 'dart:async'; +import 'dart:collection'; +import 'dart:convert' show Utf8Codec; +import 'dart:typed_data' show ByteData; +import 'dart:typed_data' show Uint8List; + +import 'package:dart2_constant/convert.dart' show base64; +import 'package:dart2_constant/typed_data.dart' show Endianness; +import 'package:fixnum/fixnum.dart'; +import 'package:http/http.dart' show Client; +import 'package:logging/logging.dart'; + +part 'src/t_application_error.dart'; +part 'src/t_base.dart'; +part 'src/t_error.dart'; +part 'src/t_processor.dart'; + +part 'src/protocol/t_binary_protocol.dart'; +part 'src/protocol/t_compact_protocol.dart'; +part 'src/protocol/t_field.dart'; +part 'src/protocol/t_json_protocol.dart'; +part 'src/protocol/t_list.dart'; +part 'src/protocol/t_map.dart'; +part 'src/protocol/t_message.dart'; +part 'src/protocol/t_multiplexed_protocol.dart'; +part 'src/protocol/t_protocol.dart'; +part 'src/protocol/t_protocol_decorator.dart'; +part 'src/protocol/t_protocol_error.dart'; +part 'src/protocol/t_protocol_factory.dart'; +part 'src/protocol/t_protocol_util.dart'; +part 'src/protocol/t_set.dart'; +part 'src/protocol/t_struct.dart'; +part 'src/protocol/t_type.dart'; + +part 'src/serializer/t_deserializer.dart'; +part 'src/serializer/t_serializer.dart'; + +part 'src/transport/t_buffered_transport.dart'; +part 'src/transport/t_framed_transport.dart'; +part 'src/transport/t_http_transport.dart'; +part 'src/transport/t_message_reader.dart'; +part 'src/transport/t_socket.dart'; +part 'src/transport/t_transport.dart'; +part 'src/transport/t_transport_error.dart'; +part 'src/transport/t_transport_factory.dart'; +part 'src/transport/t_socket_transport.dart'; diff --git a/src/jaegertracing/thrift/lib/dart/lib/thrift_browser.dart b/src/jaegertracing/thrift/lib/dart/lib/thrift_browser.dart new file mode 100644 index 000000000..2ebc25758 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/thrift_browser.dart @@ -0,0 +1,22 @@ +/// 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. + +library thrift_browser; + +/// Classes that are only supported in browser applications go here + +export 'src/browser/t_web_socket.dart' show TWebSocket; diff --git a/src/jaegertracing/thrift/lib/dart/lib/thrift_console.dart b/src/jaegertracing/thrift/lib/dart/lib/thrift_console.dart new file mode 100644 index 000000000..48a83d1dc --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/lib/thrift_console.dart @@ -0,0 +1,23 @@ +/// 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. + +library thrift_console; + +/// Classes that are only supported in console applications go here + +export 'src/console/t_tcp_socket.dart' show TTcpSocket; +export 'src/console/t_web_socket.dart' show TWebSocket; diff --git a/src/jaegertracing/thrift/lib/dart/pubspec.yaml b/src/jaegertracing/thrift/lib/dart/pubspec.yaml new file mode 100644 index 000000000..f406b9932 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/pubspec.yaml @@ -0,0 +1,38 @@ +# 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. + +name: thrift +version: 0.13.0 +description: > + A Dart library for Apache Thrift +author: Apache Thrift Developers <dev@thrift.apache.org> +homepage: http://thrift.apache.org +documentation: http://thrift.apache.org + +environment: + sdk: ">=1.24.3 <3.0.0" + +dependencies: + dart2_constant: ^1.0.0 + fixnum: ^0.10.2 + http: ^0.11.3 + logging: ^0.11.0 + +dev_dependencies: + dart_dev: ^2.0.0 + mockito: ">=2.2.2 <4.0.0" + test: ">=0.12.30 <2.0.0" diff --git a/src/jaegertracing/thrift/lib/dart/test/protocol/t_protocol_test.dart b/src/jaegertracing/thrift/lib/dart/test/protocol/t_protocol_test.dart new file mode 100644 index 000000000..dc63dbb71 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/protocol/t_protocol_test.dart @@ -0,0 +1,406 @@ +// 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. + +library thrift.test.transport.t_json_protocol_test; + +import 'dart:async'; +import 'dart:typed_data' show Uint8List; + +import 'package:dart2_constant/convert.dart' show utf8; +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +void main() { + final message = new TMessage('my message', TMessageType.ONEWAY, 123); + + TProtocol protocol; + + Primitive getPrimitive(int tType) { + switch (tType) { + case TType.BOOL: + return new Primitive(protocol.readBool, protocol.writeBool, false); + + case TType.BYTE: + return new Primitive(protocol.readByte, protocol.writeByte, 0); + + case TType.I16: + return new Primitive(protocol.readI16, protocol.writeI16, 0); + + case TType.I32: + return new Primitive(protocol.readI32, protocol.writeI32, 0); + + case TType.I64: + return new Primitive(protocol.readI64, protocol.writeI64, 0); + + case TType.DOUBLE: + return new Primitive(protocol.readDouble, protocol.writeDouble, 0); + + case TType.STRING: + return new Primitive(protocol.readString, protocol.writeString, ''); + + default: + throw new UnsupportedError("Unsupported TType $tType"); + } + } + + Future primitiveTest(Primitive primitive, input) async { + primitive.write(input); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = primitive.read(); + + expect(output, input); + } + + Future primitiveNullTest(Primitive primitive) async { + primitive.write(null); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = primitive.read(); + + expect(output, primitive.defaultValue); + } + + var sharedTests = () { + test('Test message', () async { + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + var subject = protocol.readMessageBegin(); + + expect(subject.name, message.name); + expect(subject.type, message.type); + expect(subject.seqid, message.seqid); + }); + + test('Test struct', () async { + var input = new TStruct(); + + protocol.writeStructBegin(input); + protocol.writeStructEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readStructBegin(); + + // name is not serialized, see C# version for reference + expect(output, isNotNull); + }); + + test('Test field', () async { + var input = new TField('my field', TType.MAP, 123); + + protocol.writeFieldBegin(input); + protocol.writeFieldEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readFieldBegin(); + + // name is not serialized, see C# version for reference + expect(output.type, input.type); + expect(output.id, input.id); + }); + + test('Test map', () async { + var input = new TMap(TType.STRING, TType.STRUCT, 123); + + protocol.writeMapBegin(input); + protocol.writeMapEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readMapBegin(); + + expect(output.keyType, input.keyType); + expect(output.valueType, input.valueType); + expect(output.length, input.length); + }); + + test('Test list', () async { + var input = new TList(TType.STRING, 123); + + protocol.writeListBegin(input); + protocol.writeListEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readListBegin(); + + expect(output.elementType, input.elementType); + expect(output.length, input.length); + }); + + test('Test set', () async { + var input = new TSet(TType.STRING, 123); + + protocol.writeSetBegin(input); + protocol.writeSetEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readListBegin(); + + expect(output.elementType, input.elementType); + expect(output.length, input.length); + }); + + test('Test bool', () async { + await primitiveTest(getPrimitive(TType.BOOL), true); + }); + + test('Test bool null', () async { + await primitiveNullTest(getPrimitive(TType.BOOL)); + }); + + test('Test byte', () async { + await primitiveTest(getPrimitive(TType.BYTE), 64); + }); + + test('Test byte null', () async { + await primitiveNullTest(getPrimitive(TType.BYTE)); + }); + + test('Test I16', () async { + await primitiveTest(getPrimitive(TType.I16), 32767); + }); + + test('Test I16 null', () async { + await primitiveNullTest(getPrimitive(TType.I16)); + }); + + test('Test I32', () async { + await primitiveTest(getPrimitive(TType.I32), 2147483647); + }); + + test('Test I32 null', () async { + await primitiveNullTest(getPrimitive(TType.I32)); + }); + + test('Test I64', () async { + await primitiveTest(getPrimitive(TType.I64), 9223372036854775807); + }); + + test('Test I64 null', () async { + await primitiveNullTest(getPrimitive(TType.I64)); + }); + + test('Test double', () async { + await primitiveTest(getPrimitive(TType.DOUBLE), 3.1415926); + }); + + test('Test double null', () async { + await primitiveNullTest(getPrimitive(TType.DOUBLE)); + }); + + test('Test string', () async { + var input = 'There are only two hard things in computer science: ' + 'cache invalidation, naming things, and off-by-one errors.'; + await primitiveTest(getPrimitive(TType.STRING), input); + }); + + test('Test string null', () async { + await primitiveNullTest(getPrimitive(TType.STRING)); + }); + + test('Test binary', () async { + var input = new Uint8List.fromList(new List.filled(100, 123)); + + protocol.writeBinary(input); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readBinary(); + + expect(output.length, input.length); + expect(output.every((i) => i == 123), isTrue); + }); + + test('Test complex struct', () async { + // {1: {10: 20}, 2: {30: 40}} + protocol.writeStructBegin(new TStruct()); + protocol.writeFieldBegin(new TField('success', TType.MAP, 0)); + protocol.writeMapBegin(new TMap(TType.I32, TType.MAP, 2)); + + protocol.writeI32(1); // key + protocol.writeMapBegin(new TMap(TType.I32, TType.I32, 1)); + protocol.writeI32(10); // key + protocol.writeI32(20); // value + protocol.writeMapEnd(); + + protocol.writeI32(2); // key + protocol.writeMapBegin(new TMap(TType.I32, TType.I32, 1)); + protocol.writeI32(30); // key + protocol.writeI32(40); // value + protocol.writeMapEnd(); + + protocol.writeMapEnd(); + protocol.writeFieldEnd(); + protocol.writeFieldStop(); + protocol.writeStructEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + protocol.readStructBegin(); + expect(protocol.readFieldBegin().type, TType.MAP); + expect(protocol.readMapBegin().length, 2); + + expect(protocol.readI32(), 1); // key + expect(protocol.readMapBegin().length, 1); + expect(protocol.readI32(), 10); // key + expect(protocol.readI32(), 20); // value + protocol.readMapEnd(); + + expect(protocol.readI32(), 2); // key + expect(protocol.readMapBegin().length, 1); + expect(protocol.readI32(), 30); // key + expect(protocol.readI32(), 40); // value + protocol.readMapEnd(); + + protocol.readMapEnd(); + protocol.readFieldEnd(); + protocol.readStructEnd(); + protocol.readMessageEnd(); + }); + + test('Test nested maps and lists', () async { + // {1: [{10: 20}], 2: [{30: 40}]} + protocol.writeMapBegin(new TMap(TType.I32, TType.LIST, 2)); + + protocol.writeI32(1); // key + protocol.writeListBegin(new TList(TType.MAP, 1)); + protocol.writeMapBegin(new TMap(TType.I32, TType.I32, 1)); + protocol.writeI32(10); // key + protocol.writeI32(20); // value + protocol.writeMapEnd(); + protocol.writeListEnd(); + + protocol.writeI32(2); // key + protocol.writeListBegin(new TList(TType.MAP, 1)); + protocol.writeMapBegin(new TMap(TType.I32, TType.I32, 1)); + protocol.writeI32(30); // key + protocol.writeI32(40); // value + protocol.writeMapEnd(); + protocol.writeListEnd(); + + protocol.writeMapEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + expect(protocol.readMapBegin().length, 2); + + expect(protocol.readI32(), 1); // key + expect(protocol.readListBegin().length, 1); + expect(protocol.readMapBegin().length, 1); + expect(protocol.readI32(), 10); // key + expect(protocol.readI32(), 20); // value + protocol.readMapEnd(); + protocol.readListEnd(); + + expect(protocol.readI32(), 2); // key + expect(protocol.readListBegin().length, 1); + expect(protocol.readMapBegin().length, 1); + expect(protocol.readI32(), 30); // key + expect(protocol.readI32(), 40); // value + protocol.readMapEnd(); + protocol.readListEnd(); + + protocol.readMapEnd(); + protocol.readMessageEnd(); + }); + }; + + group('JSON', () { + setUp(() { + protocol = new TJsonProtocol(new TBufferedTransport()); + protocol.writeMessageBegin(message); + }); + + test('Test escaped unicode', () async { + /* + KOR_KAI + UTF-8: 0xE0 0xB8 0x81 + UTF-16: 0x0E01 + G clef: + UTF-8: 0xF0 0x9D 0x84 0x9E + UTF-16: 0xD834 0xDD1E + */ + var buffer = utf8.encode(r'"\u0001\u0e01 \ud834\udd1e"'); + var transport = new TBufferedTransport(); + transport.writeAll(buffer); + + var protocol = new TJsonProtocol(transport); + + await protocol.transport.flush(); + + var subject = protocol.readString(); + expect(subject, + utf8.decode([0x01, 0xE0, 0xB8, 0x81, 0x20, 0xF0, 0x9D, 0x84, 0x9E])); + }); + + group('shared tests', sharedTests); + }); + + group('binary', () { + setUp(() { + protocol = new TBinaryProtocol(new TBufferedTransport()); + protocol.writeMessageBegin(message); + }); + + group('shared tests', sharedTests); + }); + + group('compact', () { + setUp(() { + protocol = new TCompactProtocol(new TBufferedTransport()); + protocol.writeMessageBegin(message); + }); + + group('shared tests', sharedTests); + }); +} + +class Primitive { + final Function read; + final Function write; + final defaultValue; + + Primitive(this.read, this.write, this.defaultValue); +} diff --git a/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test.dart b/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test.dart new file mode 100644 index 000000000..2f76503c4 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test.dart @@ -0,0 +1,119 @@ +/* + * 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. + */ + +library thrift.test.serializer.serializer_test; + +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; +import 'serializer_test_data.dart'; + +void main() { + var serializer = () { + TDeserializer deserializer; + TSerializer serializer; + TestTObject testTObject; + + setUp(() { + serializer = new TSerializer(); + deserializer = new TDeserializer(); + + testTObject = new TestTObject(); + testTObject.b = true; + testTObject.s = "TEST"; + testTObject.d = 15.25; + testTObject.i = 10; + + var testList = new List<String>(); + testList.add("TEST 1"); + testList.add("TEST 2"); + + testTObject.l = testList; + }); + + assertNewObjectEqualsTObject(TestTObject newObject) { + expect(newObject.l, equals(testTObject.l)); + expect(newObject.b, equals(testTObject.b)); + expect(newObject.i, equals(testTObject.i)); + expect(newObject.d, equals(testTObject.d)); + expect(newObject.s, equals(testTObject.s)); + } + + runWriteStringTest() { + var s = serializer.writeString(testTObject); + + var newObject = new TestTObject(); + deserializer.readString(newObject, s); + + assertNewObjectEqualsTObject(newObject); + }; + + runWriteTest() { + var s = serializer.write(testTObject); + + var newObject = new TestTObject(); + deserializer.read(newObject, s); + + assertNewObjectEqualsTObject(newObject); + }; + + test('JSON Protocol String', () { + serializer.protocol = new TJsonProtocol(serializer.transport); + deserializer.protocol = new TJsonProtocol(deserializer.transport); + + runWriteStringTest(); + }); + + test('JSON Protocol', () { + serializer.protocol = new TJsonProtocol(serializer.transport); + deserializer.protocol = new TJsonProtocol(deserializer.transport); + + runWriteTest(); + }); + + test('Binary Protocol String', () { + serializer.protocol = new TBinaryProtocol(serializer.transport); + deserializer.protocol = new TBinaryProtocol(deserializer.transport); + + runWriteStringTest(); + }); + + test('Binary Protocol', () { + serializer.protocol = new TBinaryProtocol(serializer.transport); + deserializer.protocol = new TBinaryProtocol(deserializer.transport); + + runWriteTest(); + }); + + test('Compact Protocol String', () { + serializer.protocol = new TCompactProtocol(serializer.transport); + deserializer.protocol = new TCompactProtocol(deserializer.transport); + + runWriteStringTest(); + }); + + test('Compact Protocol', () { + serializer.protocol = new TCompactProtocol(serializer.transport); + deserializer.protocol = new TCompactProtocol(deserializer.transport); + + runWriteTest(); + }); + }; + + group('Serializer', serializer); +} diff --git a/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test_data.dart b/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test_data.dart new file mode 100644 index 000000000..3586f08fc --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test_data.dart @@ -0,0 +1,342 @@ +/* + * 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. + */ + +library thrift.test.serializer.serializer_test; + +import 'package:thrift/thrift.dart'; + +/// TestTObject is a simple test struct +class TestTObject implements TBase { + static final TStruct _STRUCT_DESC = new TStruct("TestTObject"); + static final TField _I_FIELD_DESC = new TField("i", TType.I32, 1); + static final TField _D_FIELD_DESC = new TField("d", TType.DOUBLE, 2); + static final TField _S_FIELD_DESC = new TField("s", TType.STRING, 3); + static final TField _L_FIELD_DESC = new TField("l", TType.LIST, 4); + static final TField _B_FIELD_DESC = new TField("b", TType.BOOL, 5); + + int _i; + static const int I = 1; + double _d; + static const int D = 2; + String _s; + static const int S = 3; + List<String> _l; + static const int L = 4; + bool _b; + static const int B = 5; + + bool __isset_i = false; + bool __isset_d = false; + bool __isset_b = false; + + TestTObject() { + } + + // i + int get i => this._i; + + set i(int i) { + this._i = i; + this.__isset_i = true; + } + + bool isSetI() => this.__isset_i; + + unsetI() { + this.__isset_i = false; + } + + // d + double get d => this._d; + + set d(double d) { + this._d = d; + this.__isset_d = true; + } + + bool isSetD() => this.__isset_d; + + unsetD() { + this.__isset_d = false; + } + + // s + String get s => this._s; + + set s(String s) { + this._s = s; + } + + bool isSetS() => this.s != null; + + unsetS() { + this.s = null; + } + + // l + List<String> get l => this._l; + + set l(List<String> l) { + this._l = l; + } + + bool isSetL() => this.l != null; + + unsetL() { + this.l = null; + } + + // b + bool get b => this._b; + + set b(bool b) { + this._b = b; + this.__isset_b = true; + } + + bool isSetB() => this.__isset_b; + + unsetB() { + this.__isset_b = false; + } + + getFieldValue(int fieldID) { + switch (fieldID) { + case I: + return this.i; + case D: + return this.d; + case S: + return this.s; + case L: + return this.l; + case B: + return this.b; + default: + throw new ArgumentError("Field $fieldID doesn't exist!"); + } + } + + setFieldValue(int fieldID, Object value) { + switch (fieldID) { + case I: + if (value == null) { + unsetI(); + } else { + this.i = value; + } + break; + + case D: + if (value == null) { + unsetD(); + } else { + this.d = value; + } + break; + + case S: + if (value == null) { + unsetS(); + } else { + this.s = value; + } + break; + + case L: + if (value == null) { + unsetL(); + } else { + this.l = value as List<String>; + } + break; + + case B: + if (value == null) { + unsetB(); + } else { + this.b = value; + } + break; + + default: + throw new ArgumentError("Field $fieldID doesn't exist!"); + } + } + + // Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise + bool isSet(int fieldID) { + switch (fieldID) { + case I: + return isSetI(); + case D: + return isSetD(); + case S: + return isSetS(); + case L: + return isSetL(); + case B: + return isSetB(); + default: + throw new ArgumentError("Field $fieldID doesn't exist!"); + } + } + + read(TProtocol iprot) { + TField field; + iprot.readStructBegin(); + while (true) { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) { + case I: + if (field.type == TType.I32) { + this.i = iprot.readI32(); + this.__isset_i = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case D: + if (field.type == TType.DOUBLE) { + this.d = iprot.readDouble(); + this.__isset_d = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case S: + if (field.type == TType.STRING) { + this.s = iprot.readString(); + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case L: + if (field.type == TType.LIST) { + { + TList _list74 = iprot.readListBegin(); + this.l = new List<String>(); + for (int _i75 = 0; _i75 < _list74.length; ++_i75) { + String _elem76; + _elem76 = iprot.readString(); + this.l.add(_elem76); + } + iprot.readListEnd(); + } + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case B: + if (field.type == TType.BOOL) { + this.b = iprot.readBool(); + this.__isset_b = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + validate(); + } + + write(TProtocol oprot) { + validate(); + + oprot.writeStructBegin(_STRUCT_DESC); + oprot.writeFieldBegin(_I_FIELD_DESC); + oprot.writeI32(this.i); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(_D_FIELD_DESC); + oprot.writeDouble(this.d); + oprot.writeFieldEnd(); + if (this.s != null) { + oprot.writeFieldBegin(_S_FIELD_DESC); + oprot.writeString(this.s); + oprot.writeFieldEnd(); + } + if (this.l != null) { + oprot.writeFieldBegin(_L_FIELD_DESC); + { + oprot.writeListBegin(new TList(TType.STRING, this.l.length)); + for (var elem77 in this.l) { + oprot.writeString(elem77); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(_B_FIELD_DESC); + oprot.writeBool(this.b); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + String toString() { + StringBuffer ret = new StringBuffer("TestTObject("); + + ret.write("i:"); + ret.write(this.i); + + ret.write(", "); + ret.write("d:"); + ret.write(this.d); + + ret.write(", "); + ret.write("s:"); + if (this.s == null) { + ret.write("null"); + } else { + ret.write(this.s); + } + + ret.write(", "); + ret.write("l:"); + if (this.l == null) { + ret.write("null"); + } else { + ret.write(this.l); + } + + ret.write(", "); + ret.write("b:"); + ret.write(this.b); + + ret.write(")"); + + return ret.toString(); + } + + validate() { + // check for required fields + // check that fields of type enum have valid values + } + +} diff --git a/src/jaegertracing/thrift/lib/dart/test/t_application_error_test.dart b/src/jaegertracing/thrift/lib/dart/test/t_application_error_test.dart new file mode 100644 index 000000000..511d8d691 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/t_application_error_test.dart @@ -0,0 +1,46 @@ +// 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. + +library thrift.test.t_application_error_test; + +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +void main() { + TProtocol protocol; + + setUp(() { + protocol = new TBinaryProtocol(new TBufferedTransport()); + }); + + test('Write and read an application error', () { + var expectedType = TApplicationErrorType.INTERNAL_ERROR; + var expectedMessage = 'test error message'; + + TApplicationError error = + new TApplicationError(expectedType, expectedMessage); + error.write(protocol); + + protocol.transport.flush(); + + TApplicationError subject = TApplicationError.read(protocol); + + expect(subject, isNotNull); + expect(subject.type, expectedType); + expect(subject.message, expectedMessage); + }); +} diff --git a/src/jaegertracing/thrift/lib/dart/test/transport/t_framed_transport_test.dart b/src/jaegertracing/thrift/lib/dart/test/transport/t_framed_transport_test.dart new file mode 100644 index 000000000..7ab490539 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/transport/t_framed_transport_test.dart @@ -0,0 +1,175 @@ +// 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. + +library thrift.test.transport.t_framed_transport_test; + +import 'dart:async'; +import 'dart:typed_data' show Uint8List; + +import 'package:dart2_constant/convert.dart' show utf8; +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +void main() { + group('TFramedTransport partial reads', () { + final flushAwaitDuration = new Duration(seconds: 10); + + FakeReadOnlySocket socket; + TSocketTransport socketTransport; + TFramedTransport transport; + var messageAvailable; + + setUp(() { + socket = new FakeReadOnlySocket(); + socketTransport = new TClientSocketTransport(socket); + transport = new TFramedTransport(socketTransport); + messageAvailable = false; + }); + + expectNoReadableBytes() { + var readBuffer = new Uint8List(128); + var readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); + expect(readBytes, 0); + expect(messageAvailable, false); + } + + test('Test transport reads messages where header and body are sent separately', () async { + // buffer into which we'll read + var readBuffer = new Uint8List(10); + var readBytes; + + // registers for readable bytes + var flushFuture = transport.flush().timeout(flushAwaitDuration); + flushFuture.then((_) { + messageAvailable = true; + }); + + // write header bytes + socket.messageController.add(new Uint8List.fromList([0x00, 0x00, 0x00, 0x06])); + + // you shouldn't be able to get any bytes from the read, + // because the header has been consumed internally + expectNoReadableBytes(); + + // write first batch of body + socket.messageController.add(new Uint8List.fromList(utf8.encode("He"))); + + // you shouldn't be able to get any bytes from the read, + // because the frame has been consumed internally + expectNoReadableBytes(); + + // write second batch of body + socket.messageController.add(new Uint8List.fromList(utf8.encode("llo!"))); + + // have to wait for the flush to complete, + // because it's only then that the frame is available for reading + await flushFuture; + expect(messageAvailable, true); + + // at this point the frame is complete, so we expect the read to complete + readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); + expect(readBytes, 6); + expect(readBuffer.sublist(0, 6), utf8.encode("Hello!")); + }); + + test('Test transport reads messages where header is sent in pieces ' + 'and body is also sent in pieces', () async { + // buffer into which we'll read + var readBuffer = new Uint8List(10); + var readBytes; + + // registers for readable bytes + var flushFuture = transport.flush().timeout(flushAwaitDuration); + flushFuture.then((_) { + messageAvailable = true; + }); + + // write first part of header bytes + socket.messageController.add(new Uint8List.fromList([0x00, 0x00])); + + // you shouldn't be able to get any bytes from the read + expectNoReadableBytes(); + + // write second part of header bytes + socket.messageController.add(new Uint8List.fromList([0x00, 0x03])); + + // you shouldn't be able to get any bytes from the read again + // because only the header was read, and there's no frame body + readBytes = expectNoReadableBytes(); + + // write first batch of body + socket.messageController.add(new Uint8List.fromList(utf8.encode("H"))); + + // you shouldn't be able to get any bytes from the read, + // because the frame has been consumed internally + expectNoReadableBytes(); + + // write second batch of body + socket.messageController.add(new Uint8List.fromList(utf8.encode("i!"))); + + // have to wait for the flush to complete, + // because it's only then that the frame is available for reading + await flushFuture; + expect(messageAvailable, true); + + // at this point the frame is complete, so we expect the read to complete + readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); + expect(readBytes, 3); + expect(readBuffer.sublist(0, 3), utf8.encode("Hi!")); + }); + }); +} + + + +class FakeReadOnlySocket extends TSocket { + + StreamController<Uint8List> messageController = new StreamController<Uint8List>(sync: true); + StreamController<Object> errorController = new StreamController<Object>(); + StreamController<TSocketState> stateController = new StreamController<TSocketState>(); + + @override + Future close() { + // noop + } + + @override + bool get isClosed => false; + + @override + bool get isOpen => true; + + @override + Stream<Object> get onError => errorController.stream; + + @override + Stream<Uint8List> get onMessage => messageController.stream; + + @override + Stream<TSocketState> get onState => stateController.stream; + + @override + Future open() { + // noop + } + + @override + void send(Uint8List data) { + // noop + } +} + diff --git a/src/jaegertracing/thrift/lib/dart/test/transport/t_http_transport_test.dart b/src/jaegertracing/thrift/lib/dart/test/transport/t_http_transport_test.dart new file mode 100644 index 000000000..03ccede9a --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/transport/t_http_transport_test.dart @@ -0,0 +1,164 @@ +// 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. + +library thrift.test.transport.t_socket_transport_test; + +import 'dart:async'; +import 'dart:convert' show Encoding; +import 'dart:convert' show Utf8Codec; +import 'dart:typed_data' show Uint8List; + +import 'package:dart2_constant/convert.dart' show base64; +import 'package:http/http.dart' show BaseRequest; +import 'package:http/http.dart' show Client; +import 'package:http/http.dart' show Response; +import 'package:http/http.dart' show StreamedResponse; +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +void main() { + const utf8Codec = const Utf8Codec(); + + group('THttpClientTransport', () { + FakeHttpClient client; + THttpClientTransport transport; + + setUp(() { + client = new FakeHttpClient(sync: false); + var config = new THttpConfig(Uri.parse('http://localhost'), {}); + transport = new THttpClientTransport(client, config); + }); + + test('Test transport sends body', () async { + var expectedText = 'my request'; + transport.writeAll(utf8Codec.encode(expectedText)); + + expect(client.postRequest, isEmpty); + + await transport.flush(); + + expect(client.postRequest, isNotEmpty); + + var requestText = utf8Codec.decode(base64.decode(client.postRequest)); + expect(requestText, expectedText); + }); + + test('Test transport receives response', () async { + var expectedText = 'my response'; + var expectedBytes = utf8Codec.encode(expectedText); + client.postResponse = base64.encode(expectedBytes); + + transport.writeAll(utf8Codec.encode('my request')); + expect(transport.hasReadData, isFalse); + + await transport.flush(); + + expect(transport.hasReadData, isTrue); + + var buffer = new Uint8List(expectedBytes.length); + transport.readAll(buffer, 0, expectedBytes.length); + + var bufferText = utf8Codec.decode(buffer); + expect(bufferText, expectedText); + }); + }); + + group('THttpClientTransport with multiple messages', () { + FakeHttpClient client; + THttpClientTransport transport; + + setUp(() { + client = new FakeHttpClient(sync: true); + var config = new THttpConfig(Uri.parse('http://localhost'), {}); + transport = new THttpClientTransport(client, config); + }); + + test('Test read correct buffer after flush', () async { + String bufferText; + var expectedText = 'response 1'; + var expectedBytes = utf8Codec.encode(expectedText); + + // prepare a response + transport.writeAll(utf8Codec.encode('request 1')); + client.postResponse = base64.encode(expectedBytes); + + Future responseReady = transport.flush().then((_) { + var buffer = new Uint8List(expectedBytes.length); + transport.readAll(buffer, 0, expectedBytes.length); + bufferText = utf8Codec.decode(buffer); + }); + + // prepare a second response + transport.writeAll(utf8Codec.encode('request 2')); + var response2Bytes = utf8Codec.encode('response 2'); + client.postResponse = base64.encode(response2Bytes); + await transport.flush(); + + await responseReady; + expect(bufferText, expectedText); + }); + }); +} + +class FakeHttpClient implements Client { + String postResponse = ''; + String postRequest = ''; + + final bool sync; + + FakeHttpClient({this.sync: false}); + + Future<Response> post(url, + {Map<String, String> headers, body, Encoding encoding}) { + postRequest = body; + var response = new Response(postResponse, 200); + + if (sync) { + return new Future.sync(() => response); + } else { + return new Future.value(response); + } + } + + Future<Response> head(url, {Map<String, String> headers}) => + throw new UnimplementedError(); + + Future<Response> get(url, {Map<String, String> headers}) => + throw new UnimplementedError(); + + Future<Response> put(url, + {Map<String, String> headers, body, Encoding encoding}) => + throw new UnimplementedError(); + + Future<Response> patch(url, + {Map<String, String> headers, body, Encoding encoding}) => + throw new UnimplementedError(); + + Future<Response> delete(url, {Map<String, String> headers}) => + throw new UnimplementedError(); + + Future<String> read(url, {Map<String, String> headers}) => + throw new UnimplementedError(); + + Future<Uint8List> readBytes(url, {Map<String, String> headers}) => + throw new UnimplementedError(); + + Future<StreamedResponse> send(BaseRequest request) => + throw new UnimplementedError(); + + void close() => throw new UnimplementedError(); +} diff --git a/src/jaegertracing/thrift/lib/dart/test/transport/t_socket_transport_test.dart b/src/jaegertracing/thrift/lib/dart/test/transport/t_socket_transport_test.dart new file mode 100644 index 000000000..90bffbe54 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/transport/t_socket_transport_test.dart @@ -0,0 +1,311 @@ +// 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. + +library thrift.test.transport.t_socket_transport_test; + +import 'dart:async'; +import 'dart:convert' show Utf8Codec; +import 'dart:typed_data' show Uint8List; + +import 'package:dart2_constant/convert.dart' show base64; +import 'package:dart2_constant/core.dart' as core; +import 'package:mockito/mockito.dart'; +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +void main() { + const utf8Codec = const Utf8Codec(); + + final requestText = 'my test request'; + final requestBytes = new Uint8List.fromList(utf8Codec.encode(requestText)); + final requestBase64 = base64.encode(requestBytes); + + final responseText = 'response 1'; + final responseBytes = new Uint8List.fromList(utf8Codec.encode(responseText)); + final responseBase64 = base64.encode(responseBytes); + + final framedResponseBase64 = base64.encode(_getFramedResponse(responseBytes)); + + group('TClientSocketTransport', () { + FakeSocket socket; + TTransport transport; + + setUp(() async { + socket = new FakeSocket(sync: false); + await socket.open(); + transport = new TClientSocketTransport(socket); + await transport.open(); + transport.writeAll(requestBytes); + }); + + test('Test client sending data over transport', () async { + expect(socket.sendPayload, isNull); + + Future responseReady = transport.flush(); + + // allow microtask events to finish + await new Future.value(); + + expect(socket.sendPayload, isNotNull); + expect(socket.sendPayload, requestBytes); + + // simulate a response + socket.receiveFakeMessage(responseBase64); + + await responseReady; + var buffer = new Uint8List(responseBytes.length); + transport.readAll(buffer, 0, responseBytes.length); + var bufferText = utf8Codec.decode(buffer); + + expect(bufferText, responseText); + }); + }, timeout: new Timeout(new Duration(seconds: 1))); + + group('TClientSocketTransport with FramedTransport', () { + FakeSocket socket; + TTransport transport; + + setUp(() async { + socket = new FakeSocket(sync: true); + await socket.open(); + + transport = new TFramedTransport(new TClientSocketTransport(socket)); + await transport.open(); + transport.writeAll(requestBytes); + }); + + test('Test client sending data over framed transport', () async { + String bufferText; + + Future responseReady = transport.flush().then((_) { + var buffer = new Uint8List(responseBytes.length); + transport.readAll(buffer, 0, responseBytes.length); + bufferText = utf8Codec.decode(buffer); + }); + + // simulate a response + socket.receiveFakeMessage(framedResponseBase64); + + await responseReady; + expect(bufferText, responseText); + }); + }, timeout: new Timeout(new Duration(seconds: 1))); + + group('TAsyncClientSocketTransport', () { + FakeSocket socket; + FakeProtocolFactory protocolFactory; + TTransport transport; + + setUp(() async { + socket = new FakeSocket(sync: true); + await socket.open(); + + protocolFactory = new FakeProtocolFactory(); + protocolFactory.message = new TMessage('foo', TMessageType.CALL, 123); + transport = new TAsyncClientSocketTransport( + socket, new TMessageReader(protocolFactory), + responseTimeout: core.Duration.zero); + await transport.open(); + transport.writeAll(requestBytes); + }); + + test('Test response correlates to correct request', () async { + String bufferText; + + Future responseReady = transport.flush().then((_) { + var buffer = new Uint8List(responseBytes.length); + transport.readAll(buffer, 0, responseBytes.length); + bufferText = utf8Codec.decode(buffer); + }); + + // simulate a response + protocolFactory.message = new TMessage('foo', TMessageType.REPLY, 123); + socket.receiveFakeMessage(responseBase64); + + // simulate a second response + var response2Text = 'response 2'; + var response2Bytes = + new Uint8List.fromList(utf8Codec.encode(response2Text)); + var response2Base64 = base64.encode(response2Bytes); + protocolFactory.message = new TMessage('foo2', TMessageType.REPLY, 124); + socket.receiveFakeMessage(response2Base64); + + await responseReady; + expect(bufferText, responseText); + }); + + test('Test response timeout', () async { + Future responseReady = transport.flush(); + expect(responseReady, throwsA(new isInstanceOf<TimeoutException>())); + }); + }, timeout: new Timeout(new Duration(seconds: 1))); + + group('TAsyncClientSocketTransport with TFramedTransport', () { + FakeSocket socket; + FakeProtocolFactory protocolFactory; + TTransport transport; + + setUp(() async { + socket = new FakeSocket(sync: true); + await socket.open(); + + protocolFactory = new FakeProtocolFactory(); + protocolFactory.message = new TMessage('foo', TMessageType.CALL, 123); + var messageReader = new TMessageReader(protocolFactory, + byteOffset: TFramedTransport.headerByteCount); + + transport = new TFramedTransport(new TAsyncClientSocketTransport( + socket, messageReader, + responseTimeout: core.Duration.zero)); + await transport.open(); + transport.writeAll(requestBytes); + }); + + test('Test async client sending data over framed transport', () async { + String bufferText; + + Future responseReady = transport.flush().then((_) { + var buffer = new Uint8List(responseBytes.length); + transport.readAll(buffer, 0, responseBytes.length); + bufferText = utf8Codec.decode(buffer); + }); + + // simulate a response + protocolFactory.message = new TMessage('foo', TMessageType.REPLY, 123); + socket.receiveFakeMessage(framedResponseBase64); + + await responseReady; + expect(bufferText, responseText); + }); + }, timeout: new Timeout(new Duration(seconds: 1))); + + group('TServerTransport', () { + test('Test server transport listens to socket', () async { + var socket = new FakeSocket(); + await socket.open(); + expect(socket.isOpen, isTrue); + + var transport = new TServerSocketTransport(socket); + expect(transport.hasReadData, isFalse); + + socket.receiveFakeMessage(requestBase64); + + // allow microtask events to finish + await new Future.value(); + + expect(transport.hasReadData, isTrue); + + var buffer = new Uint8List(requestBytes.length); + transport.readAll(buffer, 0, requestBytes.length); + + var bufferText = utf8Codec.decode(buffer); + expect(bufferText, requestText); + }); + + test('Test server sending data over transport', () async { + var socket = new FakeSocket(); + await socket.open(); + + var transport = new TServerSocketTransport(socket); + + transport.writeAll(responseBytes); + expect(socket.sendPayload, isNull); + + transport.flush(); + + // allow microtask events to finish + await new Future.value(); + + expect(socket.sendPayload, isNotNull); + expect(socket.sendPayload, responseBytes); + }); + }, timeout: new Timeout(new Duration(seconds: 1))); +} + +class FakeSocket extends TSocket { + final StreamController<TSocketState> _onStateController; + Stream<TSocketState> get onState => _onStateController.stream; + + final StreamController<Object> _onErrorController; + Stream<Object> get onError => _onErrorController.stream; + + final StreamController<Uint8List> _onMessageController; + Stream<Uint8List> get onMessage => _onMessageController.stream; + + FakeSocket({bool sync: false}) + : _onStateController = new StreamController.broadcast(sync: sync), + _onErrorController = new StreamController.broadcast(sync: sync), + _onMessageController = new StreamController.broadcast(sync: sync); + + bool _isOpen; + + bool get isOpen => _isOpen; + + bool get isClosed => !isOpen; + + Future open() async { + _isOpen = true; + _onStateController.add(TSocketState.OPEN); + } + + Future close() async { + _isOpen = false; + _onStateController.add(TSocketState.CLOSED); + } + + Uint8List _sendPayload; + Uint8List get sendPayload => _sendPayload; + + void send(Uint8List data) { + if (!isOpen) throw new StateError('The socket is not open'); + + _sendPayload = data; + } + + void receiveFakeMessage(String base64text) { + if (!isOpen) throw new StateError('The socket is not open'); + + var message = new Uint8List.fromList(base64.decode(base64text)); + _onMessageController.add(message); + } +} + +class FakeProtocolFactory implements TProtocolFactory { + FakeProtocolFactory(); + + TMessage message; + + getProtocol(TTransport transport) => new FakeProtocol(message); +} + +class FakeProtocol extends Mock implements TProtocol { + FakeProtocol(this._message); + + TMessage _message; + + readMessageBegin() => _message; +} + +Uint8List _getFramedResponse(Uint8List responseBytes) { + var byteOffset = TFramedTransport.headerByteCount; + var response = new Uint8List(byteOffset + responseBytes.length); + + response.buffer.asByteData().setInt32(0, responseBytes.length); + response.setAll(byteOffset, responseBytes); + + return response; +} diff --git a/src/jaegertracing/thrift/lib/dart/test/transport/t_transport_test.dart b/src/jaegertracing/thrift/lib/dart/test/transport/t_transport_test.dart new file mode 100644 index 000000000..0bb381ac8 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/transport/t_transport_test.dart @@ -0,0 +1,41 @@ +// 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. + +library thrift.test.transport.t_socket_transport_test; + +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +/// Common transport tests +void main() { + group('TTransportFactory', () { + test('transport is returned from base factory', () async { + TTransport result; + TTransport transport = null; + + var factory = new TTransportFactory(); + + result = await factory.getTransport(transport); + expect(result, isNull); + + transport = new TBufferedTransport(); + result = await factory.getTransport(transport); + + expect(result, transport); + }); + }); +} diff --git a/src/jaegertracing/thrift/lib/dart/tool/dev.dart b/src/jaegertracing/thrift/lib/dart/tool/dev.dart new file mode 100644 index 000000000..27f8b8fcf --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/tool/dev.dart @@ -0,0 +1,33 @@ +// 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. + +library tool.dev; + +import 'package:dart_dev/dart_dev.dart' show dev, config; + +main(List<String> args) async { + // https://github.com/Workiva/dart_dev + + var directories = ['lib/', 'test/', 'tool/']; + config.analyze.entryPoints = directories; + config.format.directories = directories; + config.copyLicense + ..licensePath = 'LICENSE_HEADER' + ..directories = directories; + + await dev(args); +} |