summaryrefslogtreecommitdiffstats
path: root/src/jaegertracing/thrift/lib/dart
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/jaegertracing/thrift/lib/dart
parentInitial commit. (diff)
downloadceph-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')
-rw-r--r--src/jaegertracing/thrift/lib/dart/.analysis_options2
-rw-r--r--src/jaegertracing/thrift/lib/dart/LICENSE16
-rw-r--r--src/jaegertracing/thrift/lib/dart/Makefile.am39
-rw-r--r--src/jaegertracing/thrift/lib/dart/README.md26
-rw-r--r--src/jaegertracing/thrift/lib/dart/coding_standards.md6
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/browser/t_web_socket.dart129
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/console/t_tcp_socket.dart81
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/console/t_web_socket.dart88
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_binary_protocol.dart281
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_compact_protocol.dart470
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_field.dart26
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_json_protocol.dart784
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_list.dart25
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_map.dart26
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_message.dart35
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_multiplexed_protocol.dart43
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol.dart95
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_decorator.dart150
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_error.dart33
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_factory.dart22
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_protocol_util.dart107
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_set.dart25
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_struct.dart24
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_type.dart34
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/serializer/t_deserializer.dart50
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/serializer/t_serializer.dart48
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/t_application_error.dart104
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/t_base.dart37
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/t_error.dart27
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/t_processor.dart24
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/transport/t_buffered_transport.dart98
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/transport/t_framed_transport.dart169
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/transport/t_http_transport.dart99
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/transport/t_message_reader.dart99
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/transport/t_socket.dart38
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/transport/t_socket_transport.dart177
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport.dart70
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport_error.dart31
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/src/transport/t_transport_factory.dart27
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/thrift.dart65
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/thrift_browser.dart22
-rw-r--r--src/jaegertracing/thrift/lib/dart/lib/thrift_console.dart23
-rw-r--r--src/jaegertracing/thrift/lib/dart/pubspec.yaml38
-rw-r--r--src/jaegertracing/thrift/lib/dart/test/protocol/t_protocol_test.dart406
-rw-r--r--src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test.dart119
-rw-r--r--src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test_data.dart342
-rw-r--r--src/jaegertracing/thrift/lib/dart/test/t_application_error_test.dart46
-rw-r--r--src/jaegertracing/thrift/lib/dart/test/transport/t_framed_transport_test.dart175
-rw-r--r--src/jaegertracing/thrift/lib/dart/test/transport/t_http_transport_test.dart164
-rw-r--r--src/jaegertracing/thrift/lib/dart/test/transport/t_socket_transport_test.dart311
-rw-r--r--src/jaegertracing/thrift/lib/dart/test/transport/t_transport_test.dart41
-rw-r--r--src/jaegertracing/thrift/lib/dart/tool/dev.dart33
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);
+}