blob: b899d3dbc6885734b9f9d4f6f2356da6ba9c14f6 [file] [log] [blame]
Jens Geyer421444f2019-03-20 22:13:25 +01001// Licensed to the Apache Software Foundation(ASF) under one
Jens Geyeraa0c8b32019-01-28 23:27:45 +01002// 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
18using System;
Mikel Blanchard4b66a9d2020-03-05 00:46:21 +010019using System.Buffers;
zembord9d958a32019-11-21 13:11:44 +030020using System.Buffers.Binary;
Jens Geyeraa0c8b32019-01-28 23:27:45 +010021using System.Collections.Generic;
Jens Geyer5a17b132019-05-26 15:53:37 +020022using System.Diagnostics;
Jens Geyeraa0c8b32019-01-28 23:27:45 +010023using System.Text;
24using System.Threading;
25using System.Threading.Tasks;
26using Thrift.Protocol.Entities;
Jens Geyer62445c12022-06-29 00:00:00 +020027using Thrift.Protocol.Utilities;
Jens Geyeraa0c8b32019-01-28 23:27:45 +010028using Thrift.Transport;
29
Jens Geyer0d128322021-02-25 09:42:52 +010030
Jens Geyeraa0c8b32019-01-28 23:27:45 +010031namespace Thrift.Protocol
32{
Jens Geyeraa0c8b32019-01-28 23:27:45 +010033
34 // ReSharper disable once InconsistentNaming
35 public class TCompactProtocol : TProtocol
36 {
37 private const byte ProtocolId = 0x82;
38 private const byte Version = 1;
39 private const byte VersionMask = 0x1f; // 0001 1111
40 private const byte TypeMask = 0xE0; // 1110 0000
41 private const byte TypeBits = 0x07; // 0000 0111
42 private const int TypeShiftAmount = 5;
Jens Geyer5a17b132019-05-26 15:53:37 +020043
44 private const byte NoTypeOverride = 0xFF;
Jens Geyeraa0c8b32019-01-28 23:27:45 +010045
46 // ReSharper disable once InconsistentNaming
Jens Geyer62445c12022-06-29 00:00:00 +020047 private static readonly byte[] TTypeToCompactType = new byte[17];
48 private static readonly TType[] CompactTypeToTType = new TType[14];
Jens Geyeraa0c8b32019-01-28 23:27:45 +010049
50 /// <summary>
51 /// Used to keep track of the last field for the current and previous structs, so we can do the delta stuff.
52 /// </summary>
53 private readonly Stack<short> _lastField = new Stack<short>(15);
54
55 /// <summary>
56 /// If we encounter a boolean field begin, save the TField here so it can have the value incorporated.
57 /// </summary>
58 private TField? _booleanField;
59
60 /// <summary>
61 /// If we Read a field header, and it's a boolean field, save the boolean value here so that ReadBool can use it.
62 /// </summary>
63 private bool? _boolValue;
64
65 private short _lastFieldId;
66
Jens Geyer5a17b132019-05-26 15:53:37 +020067 // minimize memory allocations by means of an preallocated bytes buffer
68 // The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long)
Mikel Blanchard4b66a9d2020-03-05 00:46:21 +010069 private readonly byte[] PreAllocatedBuffer = new byte[128];
Jens Geyer5a17b132019-05-26 15:53:37 +020070
71 private struct VarInt
72 {
73 public byte[] bytes;
74 public int count;
75 }
76
77 // minimize memory allocations by means of an preallocated VarInt buffer
78 private VarInt PreAllocatedVarInt = new VarInt()
79 {
80 bytes = new byte[10], // see Int64ToVarInt()
81 count = 0
82 };
83
84
85
86
Jens Geyeraa0c8b32019-01-28 23:27:45 +010087 public TCompactProtocol(TTransport trans)
88 : base(trans)
89 {
Jens Geyer62445c12022-06-29 00:00:00 +020090 TTypeToCompactType[(int)TType.Stop] = Types.Stop;
91 TTypeToCompactType[(int)TType.Bool] = Types.BooleanTrue;
92 TTypeToCompactType[(int)TType.Byte] = Types.Byte;
93 TTypeToCompactType[(int)TType.I16] = Types.I16;
94 TTypeToCompactType[(int)TType.I32] = Types.I32;
95 TTypeToCompactType[(int)TType.I64] = Types.I64;
96 TTypeToCompactType[(int)TType.Double] = Types.Double;
97 TTypeToCompactType[(int)TType.String] = Types.Binary;
98 TTypeToCompactType[(int)TType.List] = Types.List;
99 TTypeToCompactType[(int)TType.Set] = Types.Set;
100 TTypeToCompactType[(int)TType.Map] = Types.Map;
101 TTypeToCompactType[(int)TType.Struct] = Types.Struct;
102 TTypeToCompactType[(int)TType.Uuid] = Types.Uuid;
Jens Geyer5a17b132019-05-26 15:53:37 +0200103
104 CompactTypeToTType[Types.Stop] = TType.Stop;
105 CompactTypeToTType[Types.BooleanTrue] = TType.Bool;
106 CompactTypeToTType[Types.BooleanFalse] = TType.Bool;
107 CompactTypeToTType[Types.Byte] = TType.Byte;
108 CompactTypeToTType[Types.I16] = TType.I16;
109 CompactTypeToTType[Types.I32] = TType.I32;
110 CompactTypeToTType[Types.I64] = TType.I64;
111 CompactTypeToTType[Types.Double] = TType.Double;
112 CompactTypeToTType[Types.Binary] = TType.String;
113 CompactTypeToTType[Types.List] = TType.List;
114 CompactTypeToTType[Types.Set] = TType.Set;
115 CompactTypeToTType[Types.Map] = TType.Map;
116 CompactTypeToTType[Types.Struct] = TType.Struct;
Jens Geyer62445c12022-06-29 00:00:00 +0200117 CompactTypeToTType[Types.Uuid] = TType.Uuid;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100118 }
119
120 public void Reset()
121 {
122 _lastField.Clear();
123 _lastFieldId = 0;
124 }
125
126 public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken)
127 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200128 PreAllocatedBuffer[0] = ProtocolId;
129 PreAllocatedBuffer[1] = (byte)((Version & VersionMask) | (((uint)message.Type << TypeShiftAmount) & TypeMask));
130 await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100131
Jens Geyer5a17b132019-05-26 15:53:37 +0200132 Int32ToVarInt((uint) message.SeqID, ref PreAllocatedVarInt);
133 await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100134
135 await WriteStringAsync(message.Name, cancellationToken);
136 }
137
Jens Geyerdce22992020-05-16 23:02:27 +0200138 public override Task WriteMessageEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100139 {
Jens Geyerdce22992020-05-16 23:02:27 +0200140 cancellationToken.ThrowIfCancellationRequested();
141 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100142 }
143
144 /// <summary>
145 /// Write a struct begin. This doesn't actually put anything on the wire. We
146 /// use it as an opportunity to put special placeholder markers on the field
147 /// stack so we can get the field id deltas correct.
148 /// </summary>
Jens Geyerdce22992020-05-16 23:02:27 +0200149 public override Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100150 {
Jens Geyerdce22992020-05-16 23:02:27 +0200151 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100152
153 _lastField.Push(_lastFieldId);
154 _lastFieldId = 0;
Jens Geyerdce22992020-05-16 23:02:27 +0200155
156 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100157 }
158
Jens Geyerdce22992020-05-16 23:02:27 +0200159 public override Task WriteStructEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100160 {
Jens Geyerdce22992020-05-16 23:02:27 +0200161 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100162
163 _lastFieldId = _lastField.Pop();
Jens Geyerdce22992020-05-16 23:02:27 +0200164
165 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100166 }
167
Jens Geyer5a17b132019-05-26 15:53:37 +0200168 private async Task WriteFieldBeginInternalAsync(TField field, byte fieldType, CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100169 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200170 // if there's a exType override passed in, use that. Otherwise ask GetCompactType().
171 if (fieldType == NoTypeOverride)
172 fieldType = GetCompactType(field.Type);
173
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100174
175 // check if we can use delta encoding for the field id
Jens Geyer5a17b132019-05-26 15:53:37 +0200176 if (field.ID > _lastFieldId)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100177 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200178 var delta = field.ID - _lastFieldId;
179 if (delta <= 15)
180 {
181 // Write them together
182 PreAllocatedBuffer[0] = (byte)((delta << 4) | fieldType);
183 await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken);
184 _lastFieldId = field.ID;
185 return;
186 }
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100187 }
188
Jens Geyer5a17b132019-05-26 15:53:37 +0200189 // Write them separate
190 PreAllocatedBuffer[0] = fieldType;
191 await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken);
192 await WriteI16Async(field.ID, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100193 _lastFieldId = field.ID;
194 }
195
196 public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken)
197 {
198 if (field.Type == TType.Bool)
199 {
200 _booleanField = field;
201 }
202 else
203 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200204 await WriteFieldBeginInternalAsync(field, NoTypeOverride, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100205 }
206 }
207
Jens Geyerdce22992020-05-16 23:02:27 +0200208 public override Task WriteFieldEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100209 {
Jens Geyerdce22992020-05-16 23:02:27 +0200210 cancellationToken.ThrowIfCancellationRequested();
211 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100212 }
213
214 public override async Task WriteFieldStopAsync(CancellationToken cancellationToken)
215 {
Jens Geyerdce22992020-05-16 23:02:27 +0200216 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100217
Jens Geyer5a17b132019-05-26 15:53:37 +0200218 PreAllocatedBuffer[0] = Types.Stop;
219 await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100220 }
221
222 protected async Task WriteCollectionBeginAsync(TType elemType, int size, CancellationToken cancellationToken)
223 {
Jens Geyerdce22992020-05-16 23:02:27 +0200224 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100225
226 /*
227 Abstract method for writing the start of lists and sets. List and sets on
228 the wire differ only by the exType indicator.
229 */
230
231 if (size <= 14)
232 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200233 PreAllocatedBuffer[0] = (byte)((size << 4) | GetCompactType(elemType));
234 await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100235 }
236 else
237 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200238 PreAllocatedBuffer[0] = (byte)(0xf0 | GetCompactType(elemType));
239 await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100240
Jens Geyer5a17b132019-05-26 15:53:37 +0200241 Int32ToVarInt((uint) size, ref PreAllocatedVarInt);
242 await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100243 }
244 }
245
246 public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken)
247 {
248 await WriteCollectionBeginAsync(list.ElementType, list.Count, cancellationToken);
249 }
250
Jens Geyerdce22992020-05-16 23:02:27 +0200251 public override Task WriteListEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100252 {
Jens Geyerdce22992020-05-16 23:02:27 +0200253 cancellationToken.ThrowIfCancellationRequested();
254 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100255 }
256
257 public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken)
258 {
Jens Geyerdce22992020-05-16 23:02:27 +0200259 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100260
261 await WriteCollectionBeginAsync(set.ElementType, set.Count, cancellationToken);
262 }
263
Jens Geyerdce22992020-05-16 23:02:27 +0200264 public override Task WriteSetEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100265 {
Jens Geyerdce22992020-05-16 23:02:27 +0200266 cancellationToken.ThrowIfCancellationRequested();
267 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100268 }
269
270 public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken)
271 {
Jens Geyerdce22992020-05-16 23:02:27 +0200272 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100273
274 /*
275 Write a boolean value. Potentially, this could be a boolean field, in
276 which case the field header info isn't written yet. If so, decide what the
277 right exType header is for the value and then Write the field header.
278 Otherwise, Write a single byte.
279 */
280
281 if (_booleanField != null)
282 {
283 // we haven't written the field header yet
Jens Geyer5a17b132019-05-26 15:53:37 +0200284 var type = b ? Types.BooleanTrue : Types.BooleanFalse;
285 await WriteFieldBeginInternalAsync(_booleanField.Value, type, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100286 _booleanField = null;
287 }
288 else
289 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200290 // we're not part of a field, so just write the value.
291 PreAllocatedBuffer[0] = b ? Types.BooleanTrue : Types.BooleanFalse;
292 await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100293 }
294 }
295
296 public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken)
297 {
Jens Geyerdce22992020-05-16 23:02:27 +0200298 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100299
Jens Geyer5a17b132019-05-26 15:53:37 +0200300 PreAllocatedBuffer[0] = (byte)b;
301 await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100302 }
303
304 public override async Task WriteI16Async(short i16, CancellationToken cancellationToken)
305 {
Jens Geyerdce22992020-05-16 23:02:27 +0200306 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100307
Jens Geyer5a17b132019-05-26 15:53:37 +0200308 Int32ToVarInt(IntToZigzag(i16), ref PreAllocatedVarInt);
309 await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100310 }
311
Jens Geyer5a17b132019-05-26 15:53:37 +0200312 private static void Int32ToVarInt(uint n, ref VarInt varint)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100313 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200314 // Write an i32 as a varint. Results in 1 - 5 bytes on the wire.
315 varint.count = 0;
316 Debug.Assert(varint.bytes.Length >= 5);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100317
318 while (true)
319 {
320 if ((n & ~0x7F) == 0)
321 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200322 varint.bytes[varint.count++] = (byte)n;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100323 break;
324 }
325
Jens Geyer5a17b132019-05-26 15:53:37 +0200326 varint.bytes[varint.count++] = (byte)((n & 0x7F) | 0x80);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100327 n >>= 7;
328 }
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100329 }
330
331 public override async Task WriteI32Async(int i32, CancellationToken cancellationToken)
332 {
Jens Geyerdce22992020-05-16 23:02:27 +0200333 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100334
Jens Geyer5a17b132019-05-26 15:53:37 +0200335 Int32ToVarInt(IntToZigzag(i32), ref PreAllocatedVarInt);
336 await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100337 }
338
Jens Geyer5a17b132019-05-26 15:53:37 +0200339 static private void Int64ToVarInt(ulong n, ref VarInt varint)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100340 {
341 // Write an i64 as a varint. Results in 1-10 bytes on the wire.
Jens Geyer5a17b132019-05-26 15:53:37 +0200342 varint.count = 0;
343 Debug.Assert(varint.bytes.Length >= 10);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100344
345 while (true)
346 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200347 if ((n & ~(ulong)0x7FL) == 0)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100348 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200349 varint.bytes[varint.count++] = (byte)n;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100350 break;
351 }
Jens Geyer5a17b132019-05-26 15:53:37 +0200352 varint.bytes[varint.count++] = (byte)((n & 0x7F) | 0x80);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100353 n >>= 7;
354 }
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100355 }
356
357 public override async Task WriteI64Async(long i64, CancellationToken cancellationToken)
358 {
Jens Geyerdce22992020-05-16 23:02:27 +0200359 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100360
Jens Geyer5a17b132019-05-26 15:53:37 +0200361 Int64ToVarInt(LongToZigzag(i64), ref PreAllocatedVarInt);
362 await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100363 }
364
365 public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken)
366 {
Jens Geyerdce22992020-05-16 23:02:27 +0200367 cancellationToken.ThrowIfCancellationRequested();
368
zembord9d958a32019-11-21 13:11:44 +0300369 BinaryPrimitives.WriteInt64LittleEndian(PreAllocatedBuffer, BitConverter.DoubleToInt64Bits(d));
Jens Geyer5a17b132019-05-26 15:53:37 +0200370 await Trans.WriteAsync(PreAllocatedBuffer, 0, 8, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100371 }
372
373 public override async Task WriteStringAsync(string str, CancellationToken cancellationToken)
374 {
Jens Geyerdce22992020-05-16 23:02:27 +0200375 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100376
Mikel Blanchard4b66a9d2020-03-05 00:46:21 +0100377 var buf = ArrayPool<byte>.Shared.Rent(Encoding.UTF8.GetByteCount(str));
378 try
379 {
380 var numberOfBytes = Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100381
Mikel Blanchard4b66a9d2020-03-05 00:46:21 +0100382 Int32ToVarInt((uint)numberOfBytes, ref PreAllocatedVarInt);
383 await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken);
384 await Trans.WriteAsync(buf, 0, numberOfBytes, cancellationToken);
385 }
386 finally
387 {
388 ArrayPool<byte>.Shared.Return(buf);
389 }
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100390 }
391
392 public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken)
393 {
Jens Geyerdce22992020-05-16 23:02:27 +0200394 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100395
Jens Geyer5a17b132019-05-26 15:53:37 +0200396 Int32ToVarInt((uint) bytes.Length, ref PreAllocatedVarInt);
397 await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100398 await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
399 }
400
Jens Geyer62445c12022-06-29 00:00:00 +0200401 public override async Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken)
402 {
403 cancellationToken.ThrowIfCancellationRequested();
404
405 var bytes = uuid.SwapByteOrder().ToByteArray();
406 await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
407 }
408
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100409 public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken)
410 {
Jens Geyerdce22992020-05-16 23:02:27 +0200411 cancellationToken.ThrowIfCancellationRequested();
412
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100413 if (map.Count == 0)
414 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200415 PreAllocatedBuffer[0] = 0;
416 await Trans.WriteAsync( PreAllocatedBuffer, 0, 1, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100417 }
418 else
419 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200420 Int32ToVarInt((uint) map.Count, ref PreAllocatedVarInt);
421 await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken);
422
423 PreAllocatedBuffer[0] = (byte)((GetCompactType(map.KeyType) << 4) | GetCompactType(map.ValueType));
424 await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100425 }
426 }
427
Jens Geyerdce22992020-05-16 23:02:27 +0200428 public override Task WriteMapEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100429 {
Jens Geyerdce22992020-05-16 23:02:27 +0200430 cancellationToken.ThrowIfCancellationRequested();
431 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100432 }
433
Jens Geyer5a17b132019-05-26 15:53:37 +0200434 public override async ValueTask<TMessage> ReadMessageBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100435 {
Jens Geyerdce22992020-05-16 23:02:27 +0200436 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100437
438 var protocolId = (byte) await ReadByteAsync(cancellationToken);
439 if (protocolId != ProtocolId)
440 {
441 throw new TProtocolException($"Expected protocol id {ProtocolId:X} but got {protocolId:X}");
442 }
443
444 var versionAndType = (byte) await ReadByteAsync(cancellationToken);
445 var version = (byte) (versionAndType & VersionMask);
446
447 if (version != Version)
448 {
449 throw new TProtocolException($"Expected version {Version} but got {version}");
450 }
451
452 var type = (byte) ((versionAndType >> TypeShiftAmount) & TypeBits);
453 var seqid = (int) await ReadVarInt32Async(cancellationToken);
454 var messageName = await ReadStringAsync(cancellationToken);
455
456 return new TMessage(messageName, (TMessageType) type, seqid);
457 }
458
Jens Geyerdce22992020-05-16 23:02:27 +0200459 public override Task ReadMessageEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100460 {
Jens Geyerdce22992020-05-16 23:02:27 +0200461 cancellationToken.ThrowIfCancellationRequested();
462 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100463 }
464
Jens Geyerdce22992020-05-16 23:02:27 +0200465 public override ValueTask<TStruct> ReadStructBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100466 {
Jens Geyerdce22992020-05-16 23:02:27 +0200467 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100468
469 _lastField.Push(_lastFieldId);
470 _lastFieldId = 0;
471
Jens Geyerdce22992020-05-16 23:02:27 +0200472 return new ValueTask<TStruct>(AnonymousStruct);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100473 }
474
Jens Geyerdce22992020-05-16 23:02:27 +0200475 public override Task ReadStructEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100476 {
Jens Geyerdce22992020-05-16 23:02:27 +0200477 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100478
479 /*
480 Doesn't actually consume any wire data, just removes the last field for
481 this struct from the field stack.
482 */
483
484 // consume the last field we Read off the wire.
485 _lastFieldId = _lastField.Pop();
Jens Geyerdce22992020-05-16 23:02:27 +0200486
487 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100488 }
489
Jens Geyer5a17b132019-05-26 15:53:37 +0200490 public override async ValueTask<TField> ReadFieldBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100491 {
492 // Read a field header off the wire.
493 var type = (byte) await ReadByteAsync(cancellationToken);
Jens Geyer5a17b132019-05-26 15:53:37 +0200494
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100495 // if it's a stop, then we can return immediately, as the struct is over.
496 if (type == Types.Stop)
497 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200498 return StopField;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100499 }
500
Jens Geyer5a17b132019-05-26 15:53:37 +0200501
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100502 // mask off the 4 MSB of the exType header. it could contain a field id delta.
503 var modifier = (short) ((type & 0xf0) >> 4);
Jens Geyer5a17b132019-05-26 15:53:37 +0200504 var compactType = (byte)(type & 0x0f);
505
506 short fieldId;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100507 if (modifier == 0)
508 {
509 fieldId = await ReadI16Async(cancellationToken);
510 }
511 else
512 {
513 fieldId = (short) (_lastFieldId + modifier);
514 }
515
Jens Geyer5a17b132019-05-26 15:53:37 +0200516 var ttype = GetTType(compactType);
517 var field = new TField(string.Empty, ttype, fieldId);
518
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100519 // if this happens to be a boolean field, the value is encoded in the exType
Jens Geyer5a17b132019-05-26 15:53:37 +0200520 if( ttype == TType.Bool)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100521 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200522 _boolValue = (compactType == Types.BooleanTrue);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100523 }
524
525 // push the new field onto the field stack so we can keep the deltas going.
526 _lastFieldId = field.ID;
527 return field;
528 }
529
Jens Geyerdce22992020-05-16 23:02:27 +0200530 public override Task ReadFieldEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100531 {
Jens Geyerdce22992020-05-16 23:02:27 +0200532 cancellationToken.ThrowIfCancellationRequested();
533 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100534 }
535
Jens Geyer5a17b132019-05-26 15:53:37 +0200536 public override async ValueTask<TMap> ReadMapBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100537 {
Jens Geyerdce22992020-05-16 23:02:27 +0200538 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100539
540 /*
541 Read a map header off the wire. If the size is zero, skip Reading the key
542 and value exType. This means that 0-length maps will yield TMaps without the
543 "correct" types.
544 */
545
546 var size = (int) await ReadVarInt32Async(cancellationToken);
547 var keyAndValueType = size == 0 ? (byte) 0 : (byte) await ReadByteAsync(cancellationToken);
Jens Geyer50806452019-11-23 01:55:58 +0100548 var map = new TMap(GetTType((byte) (keyAndValueType >> 4)), GetTType((byte) (keyAndValueType & 0xf)), size);
549 CheckReadBytesAvailable(map);
550 return map;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100551 }
552
Jens Geyerdce22992020-05-16 23:02:27 +0200553 public override Task ReadMapEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100554 {
Jens Geyerdce22992020-05-16 23:02:27 +0200555 cancellationToken.ThrowIfCancellationRequested();
556 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100557 }
558
Jens Geyer5a17b132019-05-26 15:53:37 +0200559 public override async ValueTask<TSet> ReadSetBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100560 {
561 /*
562 Read a set header off the wire. If the set size is 0-14, the size will
563 be packed into the element exType header. If it's a longer set, the 4 MSB
564 of the element exType header will be 0xF, and a varint will follow with the
565 true size.
566 */
567
568 return new TSet(await ReadListBeginAsync(cancellationToken));
569 }
570
Jens Geyer5a17b132019-05-26 15:53:37 +0200571 public override ValueTask<bool> ReadBoolAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100572 {
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100573 /*
574 Read a boolean off the wire. If this is a boolean field, the value should
575 already have been Read during ReadFieldBegin, so we'll just consume the
576 pre-stored value. Otherwise, Read a byte.
577 */
578
579 if (_boolValue != null)
580 {
581 var result = _boolValue.Value;
582 _boolValue = null;
Jens Geyer5a17b132019-05-26 15:53:37 +0200583 return new ValueTask<bool>(result);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100584 }
585
Jens Geyer5a17b132019-05-26 15:53:37 +0200586 return InternalCall();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100587
Jens Geyer5a17b132019-05-26 15:53:37 +0200588 async ValueTask<bool> InternalCall()
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100589 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200590 var data = await ReadByteAsync(cancellationToken);
591 return (data == Types.BooleanTrue);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100592 }
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100593 }
594
Jens Geyer5a17b132019-05-26 15:53:37 +0200595
596 public override async ValueTask<sbyte> ReadByteAsync(CancellationToken cancellationToken)
597 {
598 // Read a single byte off the wire. Nothing interesting here.
599 await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 1, cancellationToken);
600 return (sbyte)PreAllocatedBuffer[0];
601 }
602
603 public override async ValueTask<short> ReadI16Async(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100604 {
Jens Geyerdce22992020-05-16 23:02:27 +0200605 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100606
607 return (short) ZigzagToInt(await ReadVarInt32Async(cancellationToken));
608 }
609
Jens Geyer5a17b132019-05-26 15:53:37 +0200610 public override async ValueTask<int> ReadI32Async(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100611 {
Jens Geyerdce22992020-05-16 23:02:27 +0200612 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100613
614 return ZigzagToInt(await ReadVarInt32Async(cancellationToken));
615 }
616
Jens Geyer5a17b132019-05-26 15:53:37 +0200617 public override async ValueTask<long> ReadI64Async(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100618 {
Jens Geyerdce22992020-05-16 23:02:27 +0200619 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100620
621 return ZigzagToLong(await ReadVarInt64Async(cancellationToken));
622 }
623
Jens Geyer5a17b132019-05-26 15:53:37 +0200624 public override async ValueTask<double> ReadDoubleAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100625 {
Jens Geyerdce22992020-05-16 23:02:27 +0200626 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100627
Jens Geyer5a17b132019-05-26 15:53:37 +0200628 await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken);
zembord9d958a32019-11-21 13:11:44 +0300629
630 return BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(PreAllocatedBuffer));
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100631 }
632
Jens Geyer5a17b132019-05-26 15:53:37 +0200633 public override async ValueTask<string> ReadStringAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100634 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200635 // read length
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100636 var length = (int) await ReadVarInt32Async(cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100637 if (length == 0)
638 {
639 return string.Empty;
640 }
641
Jens Geyer5a17b132019-05-26 15:53:37 +0200642 // read and decode data
643 if (length < PreAllocatedBuffer.Length)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100644 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200645 await Trans.ReadAllAsync(PreAllocatedBuffer, 0, length, cancellationToken);
646 return Encoding.UTF8.GetString(PreAllocatedBuffer, 0, length);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100647 }
648
Jens Geyer50806452019-11-23 01:55:58 +0100649 Transport.CheckReadBytesAvailable(length);
Mikel Blanchard4b66a9d2020-03-05 00:46:21 +0100650
651 var buf = ArrayPool<byte>.Shared.Rent(length);
652 try
653 {
654 await Trans.ReadAllAsync(buf, 0, length, cancellationToken);
655 return Encoding.UTF8.GetString(buf, 0, length);
656 }
657 finally
658 {
659 ArrayPool<byte>.Shared.Return(buf);
660 }
Jens Geyer5a17b132019-05-26 15:53:37 +0200661 }
662
663 public override async ValueTask<byte[]> ReadBinaryAsync(CancellationToken cancellationToken)
664 {
665 // read length
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100666 var length = (int) await ReadVarInt32Async(cancellationToken);
667 if (length == 0)
668 {
Mikel Blanchard4b66a9d2020-03-05 00:46:21 +0100669 return Array.Empty<byte>();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100670 }
671
Jens Geyer5a17b132019-05-26 15:53:37 +0200672 // read data
Jens Geyer50806452019-11-23 01:55:58 +0100673 Transport.CheckReadBytesAvailable(length);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100674 var buf = new byte[length];
675 await Trans.ReadAllAsync(buf, 0, length, cancellationToken);
676 return buf;
677 }
678
Jens Geyer62445c12022-06-29 00:00:00 +0200679 public override async ValueTask<Guid> ReadUuidAsync(CancellationToken cancellationToken)
680 {
681 cancellationToken.ThrowIfCancellationRequested();
682
683 Transport.CheckReadBytesAvailable(16); // = sizeof(uuid)
684 var buf = new byte[16];
685 await Trans.ReadAllAsync(buf, 0, 16, cancellationToken);
686 return new Guid(buf).SwapByteOrder();
687 }
688
Jens Geyer5a17b132019-05-26 15:53:37 +0200689 public override async ValueTask<TList> ReadListBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100690 {
Jens Geyerdce22992020-05-16 23:02:27 +0200691 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100692
693 /*
694 Read a list header off the wire. If the list size is 0-14, the size will
695 be packed into the element exType header. If it's a longer list, the 4 MSB
696 of the element exType header will be 0xF, and a varint will follow with the
697 true size.
698 */
699
700 var sizeAndType = (byte) await ReadByteAsync(cancellationToken);
701 var size = (sizeAndType >> 4) & 0x0f;
702 if (size == 15)
703 {
704 size = (int) await ReadVarInt32Async(cancellationToken);
705 }
706
707 var type = GetTType(sizeAndType);
Jens Geyer50806452019-11-23 01:55:58 +0100708 var list = new TList(type, size);
709 CheckReadBytesAvailable(list);
710 return list;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100711 }
712
Jens Geyerdce22992020-05-16 23:02:27 +0200713 public override Task ReadListEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100714 {
Jens Geyerdce22992020-05-16 23:02:27 +0200715 cancellationToken.ThrowIfCancellationRequested();
716 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100717 }
718
Jens Geyerdce22992020-05-16 23:02:27 +0200719 public override Task ReadSetEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100720 {
Jens Geyerdce22992020-05-16 23:02:27 +0200721 cancellationToken.ThrowIfCancellationRequested();
722 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100723 }
724
725 private static byte GetCompactType(TType ttype)
726 {
727 // Given a TType value, find the appropriate TCompactProtocol.Types constant.
728 return TTypeToCompactType[(int) ttype];
729 }
730
731
Jens Geyer5a17b132019-05-26 15:53:37 +0200732 private async ValueTask<uint> ReadVarInt32Async(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100733 {
Jens Geyerdce22992020-05-16 23:02:27 +0200734 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100735
736 /*
737 Read an i32 from the wire as a varint. The MSB of each byte is set
738 if there is another byte to follow. This can Read up to 5 bytes.
739 */
740
741 uint result = 0;
742 var shift = 0;
743
744 while (true)
745 {
746 var b = (byte) await ReadByteAsync(cancellationToken);
747 result |= (uint) (b & 0x7f) << shift;
748 if ((b & 0x80) != 0x80)
749 {
750 break;
751 }
752 shift += 7;
753 }
754
755 return result;
756 }
757
Jens Geyer5a17b132019-05-26 15:53:37 +0200758 private async ValueTask<ulong> ReadVarInt64Async(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100759 {
Jens Geyerdce22992020-05-16 23:02:27 +0200760 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100761
762 /*
763 Read an i64 from the wire as a proper varint. The MSB of each byte is set
764 if there is another byte to follow. This can Read up to 10 bytes.
765 */
766
767 var shift = 0;
768 ulong result = 0;
769 while (true)
770 {
771 var b = (byte) await ReadByteAsync(cancellationToken);
772 result |= (ulong) (b & 0x7f) << shift;
773 if ((b & 0x80) != 0x80)
774 {
775 break;
776 }
777 shift += 7;
778 }
779
780 return result;
781 }
782
783 private static int ZigzagToInt(uint n)
784 {
785 return (int) (n >> 1) ^ -(int) (n & 1);
786 }
787
788 private static long ZigzagToLong(ulong n)
789 {
790 return (long) (n >> 1) ^ -(long) (n & 1);
791 }
792
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100793 private static TType GetTType(byte type)
794 {
795 // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value.
Jens Geyer5a17b132019-05-26 15:53:37 +0200796 return CompactTypeToTType[type & 0x0f];
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100797 }
798
799 private static ulong LongToZigzag(long n)
800 {
801 // Convert l into a zigzag long. This allows negative numbers to be represented compactly as a varint
802 return (ulong) (n << 1) ^ (ulong) (n >> 63);
803 }
804
805 private static uint IntToZigzag(int n)
806 {
807 // Convert n into a zigzag int. This allows negative numbers to be represented compactly as a varint
808 return (uint) (n << 1) ^ (uint) (n >> 31);
809 }
810
Jens Geyer50806452019-11-23 01:55:58 +0100811 // Return the minimum number of bytes a type will consume on the wire
812 public override int GetMinSerializedSize(TType type)
813 {
814 switch (type)
815 {
Jens Geyer62445c12022-06-29 00:00:00 +0200816 case TType.Stop: return 0;
817 case TType.Void: return 0;
818 case TType.Bool: return sizeof(byte);
Jens Geyer50806452019-11-23 01:55:58 +0100819 case TType.Double: return 8; // uses fixedLongToBytes() which always writes 8 bytes
820 case TType.Byte: return sizeof(byte);
Jens Geyer62445c12022-06-29 00:00:00 +0200821 case TType.I16: return sizeof(byte); // zigzag
822 case TType.I32: return sizeof(byte); // zigzag
823 case TType.I64: return sizeof(byte); // zigzag
Jens Geyer50806452019-11-23 01:55:58 +0100824 case TType.String: return sizeof(byte); // string length
Jens Geyer62445c12022-06-29 00:00:00 +0200825 case TType.Struct: return 0; // empty struct
826 case TType.Map: return sizeof(byte); // element count
827 case TType.Set: return sizeof(byte); // element count
828 case TType.List: return sizeof(byte); // element count
829 case TType.Uuid: return 16; // uuid bytes
Jens Geyer0d128322021-02-25 09:42:52 +0100830 default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code");
Jens Geyer50806452019-11-23 01:55:58 +0100831 }
832 }
833
Jens Geyer421444f2019-03-20 22:13:25 +0100834 public class Factory : TProtocolFactory
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100835 {
Jens Geyer421444f2019-03-20 22:13:25 +0100836 public override TProtocol GetProtocol(TTransport trans)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100837 {
838 return new TCompactProtocol(trans);
839 }
840 }
841
842 /// <summary>
843 /// All of the on-wire exType codes.
844 /// </summary>
845 private static class Types
846 {
847 public const byte Stop = 0x00;
848 public const byte BooleanTrue = 0x01;
849 public const byte BooleanFalse = 0x02;
850 public const byte Byte = 0x03;
851 public const byte I16 = 0x04;
852 public const byte I32 = 0x05;
853 public const byte I64 = 0x06;
854 public const byte Double = 0x07;
855 public const byte Binary = 0x08;
856 public const byte List = 0x09;
857 public const byte Set = 0x0A;
858 public const byte Map = 0x0B;
859 public const byte Struct = 0x0C;
Jens Geyer62445c12022-06-29 00:00:00 +0200860 public const byte Uuid = 0x0D;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100861 }
862 }
Jens Geyer421444f2019-03-20 22:13:25 +0100863}