]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/thrift/lib/dart/lib/src/protocol/t_compact_protocol.dart
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / jaegertracing / thrift / lib / dart / lib / src / protocol / t_compact_protocol.dart
1 /// Licensed to the Apache Software Foundation (ASF) under one
2 /// or more contributor license agreements. See the NOTICE file
3 /// distributed with this work for additional information
4 /// regarding copyright ownership. The ASF licenses this file
5 /// to you under the Apache License, Version 2.0 (the
6 /// 'License'); you may not use this file except in compliance
7 /// with the License. You may obtain a copy of the License at
8 ///
9 /// http://www.apache.org/licenses/LICENSE-2.0
10 ///
11 /// Unless required by applicable law or agreed to in writing,
12 /// software distributed under the License is distributed on an
13 /// 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 /// KIND, either express or implied. See the License for the
15 /// specific language governing permissions and limitations
16 /// under the License.
17
18 part of thrift;
19
20 class TCompactProtocolFactory implements TProtocolFactory<TCompactProtocol> {
21 TCompactProtocolFactory();
22
23 TCompactProtocol getProtocol(TTransport transport) {
24 return new TCompactProtocol(transport);
25 }
26 }
27
28 /// Compact protocol implementation for Thrift.
29 ///
30 /// Use of fixnum library is required due to bugs like
31 /// https://github.com/dart-lang/sdk/issues/15361
32 ///
33 /// Adapted from the Java version.
34 class TCompactProtocol extends TProtocol {
35 static const int PROTOCOL_ID = 0x82;
36 static const int VERSION = 1;
37 static const int VERSION_MASK = 0x1f;
38 static const int TYPE_MASK = 0xE0;
39 static const int TYPE_BITS = 0x07;
40 static const int TYPE_SHIFT_AMOUNT = 5;
41 static final TField TSTOP = new TField("", TType.STOP, 0);
42
43 static const int TYPE_BOOLEAN_TRUE = 0x01;
44 static const int TYPE_BOOLEAN_FALSE = 0x02;
45 static const int TYPE_BYTE = 0x03;
46 static const int TYPE_I16 = 0x04;
47 static const int TYPE_I32 = 0x05;
48 static const int TYPE_I64 = 0x06;
49 static const int TYPE_DOUBLE = 0x07;
50 static const int TYPE_BINARY = 0x08;
51 static const int TYPE_LIST = 0x09;
52 static const int TYPE_SET = 0x0A;
53 static const int TYPE_MAP = 0x0B;
54 static const int TYPE_STRUCT = 0x0C;
55
56 static final List<int> _typeMap = new List.unmodifiable(new List(16)
57 ..[TType.STOP] = TType.STOP
58 ..[TType.BOOL] = TYPE_BOOLEAN_TRUE
59 ..[TType.BYTE] = TYPE_BYTE
60 ..[TType.I16] = TYPE_I16
61 ..[TType.I32] = TYPE_I32
62 ..[TType.I64] = TYPE_I64
63 ..[TType.DOUBLE] = TYPE_DOUBLE
64 ..[TType.STRING] = TYPE_BINARY
65 ..[TType.LIST] = TYPE_LIST
66 ..[TType.SET] = TYPE_SET
67 ..[TType.MAP] = TYPE_MAP
68 ..[TType.STRUCT] = TYPE_STRUCT);
69
70 static const Utf8Codec _utf8Codec = const Utf8Codec();
71
72 // Pretend this is a stack
73 DoubleLinkedQueue<int> _lastField = new DoubleLinkedQueue<int>();
74 int _lastFieldId = 0;
75
76 TField _booleanField = null;
77 bool _boolValue = null;
78
79 final Uint8List tempList = new Uint8List(10);
80 final ByteData tempBD = new ByteData(10);
81
82 TCompactProtocol(TTransport transport) : super(transport);
83
84 /// Write
85 void writeMessageBegin(TMessage message) {
86 writeByte(PROTOCOL_ID);
87 writeByte((VERSION & VERSION_MASK) |
88 ((message.type << TYPE_SHIFT_AMOUNT) & TYPE_MASK));
89 _writeVarInt32(new Int32(message.seqid));
90 writeString(message.name);
91 }
92
93 void writeMessageEnd() {}
94
95 void writeStructBegin(TStruct struct) {
96 _lastField.addLast(_lastFieldId);
97 _lastFieldId = 0;
98 }
99
100 void writeStructEnd() {
101 _lastFieldId = _lastField.removeLast();
102 }
103
104 void writeFieldBegin(TField field) {
105 if (field.type == TType.BOOL) {
106 _booleanField = field;
107 } else {
108 _writeFieldBegin(field, -1);
109 }
110 }
111
112 void _writeFieldBegin(TField field, int typeOverride) {
113 int typeToWrite =
114 typeOverride == -1 ? _getCompactType(field.type) : typeOverride;
115
116 if (field.id > _lastFieldId && field.id - _lastFieldId <= 15) {
117 writeByte((field.id - _lastFieldId) << 4 | typeToWrite);
118 } else {
119 writeByte(typeToWrite);
120 writeI16(field.id);
121 }
122
123 _lastFieldId = field.id;
124 }
125
126 void writeFieldEnd() {}
127
128 void writeFieldStop() {
129 writeByte(TType.STOP);
130 }
131
132 void writeMapBegin(TMap map) {
133 if (map.length == 0) {
134 writeByte(0);
135 } else {
136 _writeVarInt32(new Int32(map.length));
137 writeByte(
138 _getCompactType(map.keyType) << 4 | _getCompactType(map.valueType));
139 }
140 }
141
142 void writeMapEnd() {}
143
144 void writeListBegin(TList list) {
145 _writeCollectionBegin(list.elementType, list.length);
146 }
147
148 void writeListEnd() {}
149
150 void writeSetBegin(TSet set) {
151 _writeCollectionBegin(set.elementType, set.length);
152 }
153
154 void writeSetEnd() {}
155
156 void writeBool(bool b) {
157 if (b == null) b = false;
158 if (_booleanField != null) {
159 _writeFieldBegin(
160 _booleanField, b ? TYPE_BOOLEAN_TRUE : TYPE_BOOLEAN_FALSE);
161 _booleanField = null;
162 } else {
163 writeByte(b ? TYPE_BOOLEAN_TRUE : TYPE_BOOLEAN_FALSE);
164 }
165 }
166
167 void writeByte(int b) {
168 if (b == null) b = 0;
169 tempList[0] = b;
170 transport.write(tempList, 0, 1);
171 }
172
173 void writeI16(int i16) {
174 if (i16 == null) i16 = 0;
175 _writeVarInt32(_int32ToZigZag(new Int32(i16)));
176 }
177
178 void writeI32(int i32) {
179 if (i32 == null) i32 = 0;
180 _writeVarInt32(_int32ToZigZag(new Int32(i32)));
181 }
182
183 void writeI64(int i64) {
184 if (i64 == null) i64 = 0;
185 _writeVarInt64(_int64ToZigZag(new Int64(i64)));
186 }
187
188 void writeDouble(double d) {
189 if (d == null) d = 0.0;
190 tempBD.setFloat64(0, d, Endianness.little);
191 transport.write(tempBD.buffer.asUint8List(), 0, 8);
192 }
193
194 void writeString(String str) {
195 Uint8List bytes =
196 str != null ? _utf8Codec.encode(str) : new Uint8List.fromList([]);
197 writeBinary(bytes);
198 }
199
200 void writeBinary(Uint8List bytes) {
201 _writeVarInt32(new Int32(bytes.length));
202 transport.write(bytes, 0, bytes.length);
203 }
204
205 void _writeVarInt32(Int32 n) {
206 int idx = 0;
207 while (true) {
208 if ((n & ~0x7F) == 0) {
209 tempList[idx++] = (n & 0xFF).toInt();
210 break;
211 } else {
212 tempList[idx++] = (((n & 0x7F) | 0x80) & 0xFF).toInt();
213 n = n.shiftRightUnsigned(7);
214 }
215 }
216 transport.write(tempList, 0, idx);
217 }
218
219 void _writeVarInt64(Int64 n) {
220 int idx = 0;
221 while (true) {
222 if ((n & ~0x7F) == 0) {
223 tempList[idx++] = (n & 0xFF).toInt();
224 break;
225 } else {
226 tempList[idx++] = (((n & 0x7F) | 0x80) & 0xFF).toInt();
227 n = n.shiftRightUnsigned(7);
228 }
229 }
230 transport.write(tempList, 0, idx);
231 }
232
233 void _writeCollectionBegin(int elemType, int length) {
234 if (length <= 14) {
235 writeByte(length << 4 | _getCompactType(elemType));
236 } else {
237 writeByte(0xF0 | _getCompactType(elemType));
238 _writeVarInt32(new Int32(length));
239 }
240 }
241
242 Int32 _int32ToZigZag(Int32 n) {
243 return (n << 1) ^ (n >> 31);
244 }
245
246 Int64 _int64ToZigZag(Int64 n) {
247 return (n << 1) ^ (n >> 63);
248 }
249
250 /// Read
251 TMessage readMessageBegin() {
252 int protocolId = readByte();
253 if (protocolId != PROTOCOL_ID) {
254 throw new TProtocolError(TProtocolErrorType.BAD_VERSION,
255 'Expected protocol id $PROTOCOL_ID but got $protocolId');
256 }
257 int versionAndType = readByte();
258 int version = versionAndType & VERSION_MASK;
259 if (version != VERSION) {
260 throw new TProtocolError(TProtocolErrorType.BAD_VERSION,
261 'Expected version $VERSION but got $version');
262 }
263 int type = (versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS;
264 int seqId = _readVarInt32().toInt();
265 String messageName = readString();
266 return new TMessage(messageName, type, seqId);
267 }
268
269 void readMessageEnd() {}
270
271 TStruct readStructBegin() {
272 _lastField.addLast(_lastFieldId);
273 _lastFieldId = 0;
274 // TODO make this a constant?
275 return new TStruct();
276 }
277
278 void readStructEnd() {
279 _lastFieldId = _lastField.removeLast();
280 }
281
282 TField readFieldBegin() {
283 int type = readByte();
284 if (type == TType.STOP) {
285 return TSTOP;
286 }
287
288 int fieldId;
289 int modifier = (type & 0xF0) >> 4;
290 if (modifier == 0) {
291 fieldId = readI16();
292 } else {
293 fieldId = _lastFieldId + modifier;
294 }
295
296 TField field = new TField('', _getTType(type & 0x0F), fieldId);
297 if (_isBoolType(type)) {
298 _boolValue = (type & 0x0F) == TYPE_BOOLEAN_TRUE;
299 }
300
301 _lastFieldId = field.id;
302 return field;
303 }
304
305 void readFieldEnd() {}
306
307 TMap readMapBegin() {
308 int length = _readVarInt32().toInt();
309 _checkNegReadLength(length);
310
311 int keyAndValueType = length == 0 ? 0 : readByte();
312 int keyType = _getTType(keyAndValueType >> 4);
313 int valueType = _getTType(keyAndValueType & 0x0F);
314 return new TMap(keyType, valueType, length);
315 }
316
317 void readMapEnd() {}
318
319 TList readListBegin() {
320 int lengthAndType = readByte();
321 int length = (lengthAndType >> 4) & 0x0F;
322 if (length == 15) {
323 length = _readVarInt32().toInt();
324 }
325 _checkNegReadLength(length);
326 int type = _getTType(lengthAndType);
327 return new TList(type, length);
328 }
329
330 void readListEnd() {}
331
332 TSet readSetBegin() {
333 TList tlist = readListBegin();
334 return new TSet(tlist.elementType, tlist.length);
335 }
336
337 void readSetEnd() {}
338
339 bool readBool() {
340 if (_boolValue != null) {
341 bool result = _boolValue;
342 _boolValue = null;
343 return result;
344 }
345 return readByte() == TYPE_BOOLEAN_TRUE;
346 }
347
348 int readByte() {
349 transport.readAll(tempList, 0, 1);
350 return tempList.buffer.asByteData().getUint8(0);
351 }
352
353 int readI16() {
354 return _zigzagToInt32(_readVarInt32()).toInt();
355 }
356
357 int readI32() {
358 return _zigzagToInt32(_readVarInt32()).toInt();
359 }
360
361 int readI64() {
362 return _zigzagToInt64(_readVarInt64()).toInt();
363 }
364
365 double readDouble() {
366 transport.readAll(tempList, 0, 8);
367 return tempList.buffer.asByteData().getFloat64(0, Endianness.little);
368 }
369
370 String readString() {
371 int length = _readVarInt32().toInt();
372 _checkNegReadLength(length);
373
374 // TODO look at using temp for small strings?
375 Uint8List buff = new Uint8List(length);
376 transport.readAll(buff, 0, length);
377 return _utf8Codec.decode(buff);
378 }
379
380 Uint8List readBinary() {
381 int length = _readVarInt32().toInt();
382 _checkNegReadLength(length);
383
384 Uint8List buff = new Uint8List(length);
385 transport.readAll(buff, 0, length);
386 return buff;
387 }
388
389 Int32 _readVarInt32() {
390 Int32 result = Int32.ZERO;
391 int shift = 0;
392 while (true) {
393 Int32 b = new Int32(readByte());
394 result |= (b & 0x7f) << shift;
395 if ((b & 0x80) != 0x80) break;
396 shift += 7;
397 }
398 return result;
399 }
400
401 Int64 _readVarInt64() {
402 Int64 result = Int64.ZERO;
403 int shift = 0;
404 while (true) {
405 Int64 b = new Int64(readByte());
406 result |= (b & 0x7f) << shift;
407 if ((b & 0x80) != 0x80) break;
408 shift += 7;
409 }
410 return result;
411 }
412
413 Int32 _zigzagToInt32(Int32 n) {
414 return (n.shiftRightUnsigned(1)) ^ -(n & 1);
415 }
416
417 Int64 _zigzagToInt64(Int64 n) {
418 return (n.shiftRightUnsigned(1)) ^ -(n & 1);
419 }
420
421 void _checkNegReadLength(int length) {
422 if (length < 0) {
423 throw new TProtocolError(
424 TProtocolErrorType.NEGATIVE_SIZE, 'Negative length: $length');
425 }
426 }
427
428 int _getCompactType(int ttype) {
429 return _typeMap[ttype];
430 }
431
432 int _getTType(int type) {
433 switch (type & 0x0F) {
434 case TType.STOP:
435 return TType.STOP;
436 case TYPE_BOOLEAN_FALSE:
437 case TYPE_BOOLEAN_TRUE:
438 return TType.BOOL;
439 case TYPE_BYTE:
440 return TType.BYTE;
441 case TYPE_I16:
442 return TType.I16;
443 case TYPE_I32:
444 return TType.I32;
445 case TYPE_I64:
446 return TType.I64;
447 case TYPE_DOUBLE:
448 return TType.DOUBLE;
449 case TYPE_BINARY:
450 return TType.STRING;
451 case TYPE_LIST:
452 return TType.LIST;
453 case TYPE_SET:
454 return TType.SET;
455 case TYPE_MAP:
456 return TType.MAP;
457 case TYPE_STRUCT:
458 return TType.STRUCT;
459 default:
460 throw new TProtocolError(
461 TProtocolErrorType.INVALID_DATA, "Unknown type: ${type & 0x0F}");
462 }
463 }
464
465 bool _isBoolType(int b) {
466 int lowerNibble = b & 0x0F;
467 return lowerNibble == TYPE_BOOLEAN_TRUE ||
468 lowerNibble == TYPE_BOOLEAN_FALSE;
469 }
470 }