blob: dd38f48705afa3d16a22c8f72c77e00c1b3bfa47 [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();
Philip Lee2d2790f2022-09-15 12:43:03 +0100462 Transport.ResetConsumedMessageSize();
Jens Geyerdce22992020-05-16 23:02:27 +0200463 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100464 }
465
Jens Geyerdce22992020-05-16 23:02:27 +0200466 public override ValueTask<TStruct> ReadStructBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100467 {
Jens Geyerdce22992020-05-16 23:02:27 +0200468 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100469
470 _lastField.Push(_lastFieldId);
471 _lastFieldId = 0;
472
Jens Geyerdce22992020-05-16 23:02:27 +0200473 return new ValueTask<TStruct>(AnonymousStruct);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100474 }
475
Jens Geyerdce22992020-05-16 23:02:27 +0200476 public override Task ReadStructEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100477 {
Jens Geyerdce22992020-05-16 23:02:27 +0200478 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100479
480 /*
481 Doesn't actually consume any wire data, just removes the last field for
482 this struct from the field stack.
483 */
484
485 // consume the last field we Read off the wire.
486 _lastFieldId = _lastField.Pop();
Jens Geyerdce22992020-05-16 23:02:27 +0200487
488 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100489 }
490
Jens Geyer5a17b132019-05-26 15:53:37 +0200491 public override async ValueTask<TField> ReadFieldBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100492 {
493 // Read a field header off the wire.
494 var type = (byte) await ReadByteAsync(cancellationToken);
Jens Geyer5a17b132019-05-26 15:53:37 +0200495
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100496 // if it's a stop, then we can return immediately, as the struct is over.
497 if (type == Types.Stop)
498 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200499 return StopField;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100500 }
501
Jens Geyer5a17b132019-05-26 15:53:37 +0200502
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100503 // mask off the 4 MSB of the exType header. it could contain a field id delta.
504 var modifier = (short) ((type & 0xf0) >> 4);
Jens Geyer5a17b132019-05-26 15:53:37 +0200505 var compactType = (byte)(type & 0x0f);
506
507 short fieldId;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100508 if (modifier == 0)
509 {
510 fieldId = await ReadI16Async(cancellationToken);
511 }
512 else
513 {
514 fieldId = (short) (_lastFieldId + modifier);
515 }
516
Jens Geyer5a17b132019-05-26 15:53:37 +0200517 var ttype = GetTType(compactType);
518 var field = new TField(string.Empty, ttype, fieldId);
519
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100520 // if this happens to be a boolean field, the value is encoded in the exType
Jens Geyer5a17b132019-05-26 15:53:37 +0200521 if( ttype == TType.Bool)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100522 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200523 _boolValue = (compactType == Types.BooleanTrue);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100524 }
525
526 // push the new field onto the field stack so we can keep the deltas going.
527 _lastFieldId = field.ID;
528 return field;
529 }
530
Jens Geyerdce22992020-05-16 23:02:27 +0200531 public override Task ReadFieldEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100532 {
Jens Geyerdce22992020-05-16 23:02:27 +0200533 cancellationToken.ThrowIfCancellationRequested();
534 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100535 }
536
Jens Geyer5a17b132019-05-26 15:53:37 +0200537 public override async ValueTask<TMap> ReadMapBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100538 {
Jens Geyerdce22992020-05-16 23:02:27 +0200539 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100540
541 /*
542 Read a map header off the wire. If the size is zero, skip Reading the key
543 and value exType. This means that 0-length maps will yield TMaps without the
544 "correct" types.
545 */
546
547 var size = (int) await ReadVarInt32Async(cancellationToken);
548 var keyAndValueType = size == 0 ? (byte) 0 : (byte) await ReadByteAsync(cancellationToken);
Jens Geyer50806452019-11-23 01:55:58 +0100549 var map = new TMap(GetTType((byte) (keyAndValueType >> 4)), GetTType((byte) (keyAndValueType & 0xf)), size);
550 CheckReadBytesAvailable(map);
551 return map;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100552 }
553
Jens Geyerdce22992020-05-16 23:02:27 +0200554 public override Task ReadMapEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100555 {
Jens Geyerdce22992020-05-16 23:02:27 +0200556 cancellationToken.ThrowIfCancellationRequested();
557 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100558 }
559
Jens Geyer5a17b132019-05-26 15:53:37 +0200560 public override async ValueTask<TSet> ReadSetBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100561 {
562 /*
563 Read a set header off the wire. If the set size is 0-14, the size will
564 be packed into the element exType header. If it's a longer set, the 4 MSB
565 of the element exType header will be 0xF, and a varint will follow with the
566 true size.
567 */
568
569 return new TSet(await ReadListBeginAsync(cancellationToken));
570 }
571
Jens Geyer5a17b132019-05-26 15:53:37 +0200572 public override ValueTask<bool> ReadBoolAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100573 {
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100574 /*
575 Read a boolean off the wire. If this is a boolean field, the value should
576 already have been Read during ReadFieldBegin, so we'll just consume the
577 pre-stored value. Otherwise, Read a byte.
578 */
579
580 if (_boolValue != null)
581 {
582 var result = _boolValue.Value;
583 _boolValue = null;
Jens Geyer5a17b132019-05-26 15:53:37 +0200584 return new ValueTask<bool>(result);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100585 }
586
Jens Geyer5a17b132019-05-26 15:53:37 +0200587 return InternalCall();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100588
Jens Geyer5a17b132019-05-26 15:53:37 +0200589 async ValueTask<bool> InternalCall()
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100590 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200591 var data = await ReadByteAsync(cancellationToken);
592 return (data == Types.BooleanTrue);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100593 }
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100594 }
595
Jens Geyer5a17b132019-05-26 15:53:37 +0200596
597 public override async ValueTask<sbyte> ReadByteAsync(CancellationToken cancellationToken)
598 {
599 // Read a single byte off the wire. Nothing interesting here.
600 await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 1, cancellationToken);
601 return (sbyte)PreAllocatedBuffer[0];
602 }
603
604 public override async ValueTask<short> ReadI16Async(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100605 {
Jens Geyerdce22992020-05-16 23:02:27 +0200606 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100607
608 return (short) ZigzagToInt(await ReadVarInt32Async(cancellationToken));
609 }
610
Jens Geyer5a17b132019-05-26 15:53:37 +0200611 public override async ValueTask<int> ReadI32Async(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100612 {
Jens Geyerdce22992020-05-16 23:02:27 +0200613 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100614
615 return ZigzagToInt(await ReadVarInt32Async(cancellationToken));
616 }
617
Jens Geyer5a17b132019-05-26 15:53:37 +0200618 public override async ValueTask<long> ReadI64Async(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100619 {
Jens Geyerdce22992020-05-16 23:02:27 +0200620 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100621
622 return ZigzagToLong(await ReadVarInt64Async(cancellationToken));
623 }
624
Jens Geyer5a17b132019-05-26 15:53:37 +0200625 public override async ValueTask<double> ReadDoubleAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100626 {
Jens Geyerdce22992020-05-16 23:02:27 +0200627 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100628
Jens Geyer5a17b132019-05-26 15:53:37 +0200629 await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken);
zembord9d958a32019-11-21 13:11:44 +0300630
631 return BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(PreAllocatedBuffer));
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100632 }
633
Jens Geyer5a17b132019-05-26 15:53:37 +0200634 public override async ValueTask<string> ReadStringAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100635 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200636 // read length
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100637 var length = (int) await ReadVarInt32Async(cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100638 if (length == 0)
639 {
640 return string.Empty;
641 }
642
Jens Geyer5a17b132019-05-26 15:53:37 +0200643 // read and decode data
644 if (length < PreAllocatedBuffer.Length)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100645 {
Jens Geyer5a17b132019-05-26 15:53:37 +0200646 await Trans.ReadAllAsync(PreAllocatedBuffer, 0, length, cancellationToken);
647 return Encoding.UTF8.GetString(PreAllocatedBuffer, 0, length);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100648 }
649
Jens Geyer50806452019-11-23 01:55:58 +0100650 Transport.CheckReadBytesAvailable(length);
Mikel Blanchard4b66a9d2020-03-05 00:46:21 +0100651
652 var buf = ArrayPool<byte>.Shared.Rent(length);
653 try
654 {
655 await Trans.ReadAllAsync(buf, 0, length, cancellationToken);
656 return Encoding.UTF8.GetString(buf, 0, length);
657 }
658 finally
659 {
660 ArrayPool<byte>.Shared.Return(buf);
661 }
Jens Geyer5a17b132019-05-26 15:53:37 +0200662 }
663
664 public override async ValueTask<byte[]> ReadBinaryAsync(CancellationToken cancellationToken)
665 {
666 // read length
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100667 var length = (int) await ReadVarInt32Async(cancellationToken);
668 if (length == 0)
669 {
Mikel Blanchard4b66a9d2020-03-05 00:46:21 +0100670 return Array.Empty<byte>();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100671 }
672
Jens Geyer5a17b132019-05-26 15:53:37 +0200673 // read data
Jens Geyer50806452019-11-23 01:55:58 +0100674 Transport.CheckReadBytesAvailable(length);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100675 var buf = new byte[length];
676 await Trans.ReadAllAsync(buf, 0, length, cancellationToken);
677 return buf;
678 }
679
Jens Geyer62445c12022-06-29 00:00:00 +0200680 public override async ValueTask<Guid> ReadUuidAsync(CancellationToken cancellationToken)
681 {
682 cancellationToken.ThrowIfCancellationRequested();
683
684 Transport.CheckReadBytesAvailable(16); // = sizeof(uuid)
685 var buf = new byte[16];
686 await Trans.ReadAllAsync(buf, 0, 16, cancellationToken);
687 return new Guid(buf).SwapByteOrder();
688 }
689
Jens Geyer5a17b132019-05-26 15:53:37 +0200690 public override async ValueTask<TList> ReadListBeginAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100691 {
Jens Geyerdce22992020-05-16 23:02:27 +0200692 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100693
694 /*
695 Read a list header off the wire. If the list size is 0-14, the size will
696 be packed into the element exType header. If it's a longer list, the 4 MSB
697 of the element exType header will be 0xF, and a varint will follow with the
698 true size.
699 */
700
701 var sizeAndType = (byte) await ReadByteAsync(cancellationToken);
702 var size = (sizeAndType >> 4) & 0x0f;
703 if (size == 15)
704 {
705 size = (int) await ReadVarInt32Async(cancellationToken);
706 }
707
708 var type = GetTType(sizeAndType);
Jens Geyer50806452019-11-23 01:55:58 +0100709 var list = new TList(type, size);
710 CheckReadBytesAvailable(list);
711 return list;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100712 }
713
Jens Geyerdce22992020-05-16 23:02:27 +0200714 public override Task ReadListEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100715 {
Jens Geyerdce22992020-05-16 23:02:27 +0200716 cancellationToken.ThrowIfCancellationRequested();
717 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100718 }
719
Jens Geyerdce22992020-05-16 23:02:27 +0200720 public override Task ReadSetEndAsync(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100721 {
Jens Geyerdce22992020-05-16 23:02:27 +0200722 cancellationToken.ThrowIfCancellationRequested();
723 return Task.CompletedTask;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100724 }
725
726 private static byte GetCompactType(TType ttype)
727 {
728 // Given a TType value, find the appropriate TCompactProtocol.Types constant.
729 return TTypeToCompactType[(int) ttype];
730 }
731
732
Jens Geyer5a17b132019-05-26 15:53:37 +0200733 private async ValueTask<uint> ReadVarInt32Async(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100734 {
Jens Geyerdce22992020-05-16 23:02:27 +0200735 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100736
737 /*
738 Read an i32 from the wire as a varint. The MSB of each byte is set
739 if there is another byte to follow. This can Read up to 5 bytes.
740 */
741
742 uint result = 0;
743 var shift = 0;
744
745 while (true)
746 {
747 var b = (byte) await ReadByteAsync(cancellationToken);
748 result |= (uint) (b & 0x7f) << shift;
749 if ((b & 0x80) != 0x80)
750 {
751 break;
752 }
753 shift += 7;
754 }
755
756 return result;
757 }
758
Jens Geyer5a17b132019-05-26 15:53:37 +0200759 private async ValueTask<ulong> ReadVarInt64Async(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100760 {
Jens Geyerdce22992020-05-16 23:02:27 +0200761 cancellationToken.ThrowIfCancellationRequested();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100762
763 /*
764 Read an i64 from the wire as a proper varint. The MSB of each byte is set
765 if there is another byte to follow. This can Read up to 10 bytes.
766 */
767
768 var shift = 0;
769 ulong result = 0;
770 while (true)
771 {
772 var b = (byte) await ReadByteAsync(cancellationToken);
773 result |= (ulong) (b & 0x7f) << shift;
774 if ((b & 0x80) != 0x80)
775 {
776 break;
777 }
778 shift += 7;
779 }
780
781 return result;
782 }
783
784 private static int ZigzagToInt(uint n)
785 {
786 return (int) (n >> 1) ^ -(int) (n & 1);
787 }
788
789 private static long ZigzagToLong(ulong n)
790 {
791 return (long) (n >> 1) ^ -(long) (n & 1);
792 }
793
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100794 private static TType GetTType(byte type)
795 {
796 // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value.
Jens Geyer5a17b132019-05-26 15:53:37 +0200797 return CompactTypeToTType[type & 0x0f];
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100798 }
799
800 private static ulong LongToZigzag(long n)
801 {
802 // Convert l into a zigzag long. This allows negative numbers to be represented compactly as a varint
803 return (ulong) (n << 1) ^ (ulong) (n >> 63);
804 }
805
806 private static uint IntToZigzag(int n)
807 {
808 // Convert n into a zigzag int. This allows negative numbers to be represented compactly as a varint
809 return (uint) (n << 1) ^ (uint) (n >> 31);
810 }
811
Jens Geyer50806452019-11-23 01:55:58 +0100812 // Return the minimum number of bytes a type will consume on the wire
813 public override int GetMinSerializedSize(TType type)
814 {
815 switch (type)
816 {
Jens Geyer62445c12022-06-29 00:00:00 +0200817 case TType.Stop: return 0;
818 case TType.Void: return 0;
819 case TType.Bool: return sizeof(byte);
Jens Geyer50806452019-11-23 01:55:58 +0100820 case TType.Double: return 8; // uses fixedLongToBytes() which always writes 8 bytes
821 case TType.Byte: return sizeof(byte);
Jens Geyer62445c12022-06-29 00:00:00 +0200822 case TType.I16: return sizeof(byte); // zigzag
823 case TType.I32: return sizeof(byte); // zigzag
824 case TType.I64: return sizeof(byte); // zigzag
Jens Geyer50806452019-11-23 01:55:58 +0100825 case TType.String: return sizeof(byte); // string length
Jens Geyer62445c12022-06-29 00:00:00 +0200826 case TType.Struct: return 0; // empty struct
827 case TType.Map: return sizeof(byte); // element count
828 case TType.Set: return sizeof(byte); // element count
829 case TType.List: return sizeof(byte); // element count
830 case TType.Uuid: return 16; // uuid bytes
Jens Geyer0d128322021-02-25 09:42:52 +0100831 default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code");
Jens Geyer50806452019-11-23 01:55:58 +0100832 }
833 }
834
Jens Geyer421444f2019-03-20 22:13:25 +0100835 public class Factory : TProtocolFactory
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100836 {
Jens Geyer421444f2019-03-20 22:13:25 +0100837 public override TProtocol GetProtocol(TTransport trans)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100838 {
839 return new TCompactProtocol(trans);
840 }
841 }
842
843 /// <summary>
844 /// All of the on-wire exType codes.
845 /// </summary>
846 private static class Types
847 {
848 public const byte Stop = 0x00;
849 public const byte BooleanTrue = 0x01;
850 public const byte BooleanFalse = 0x02;
851 public const byte Byte = 0x03;
852 public const byte I16 = 0x04;
853 public const byte I32 = 0x05;
854 public const byte I64 = 0x06;
855 public const byte Double = 0x07;
856 public const byte Binary = 0x08;
857 public const byte List = 0x09;
858 public const byte Set = 0x0A;
859 public const byte Map = 0x0B;
860 public const byte Struct = 0x0C;
Jens Geyer62445c12022-06-29 00:00:00 +0200861 public const byte Uuid = 0x0D;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100862 }
863 }
Jens Geyer421444f2019-03-20 22:13:25 +0100864}