deukpack 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.gyp +41 -0
- package/dist/csharp/DeukPack.Protocol.dll +0 -0
- package/dist/csharp/DeukPack.Protocol.pdb +0 -0
- package/dist/csharp/DeukPackSerializer.cs +256 -0
- package/dist/csharp/DpBinaryProtocol.cs +579 -0
- package/dist/csharp/DpJsonProtocol.cs +432 -0
- package/dist/csharp/DpProtocolCore.cs +314 -0
- package/dist/csharp/DpProtocolUtil.cs +51 -0
- package/dist/csharp/TBinaryProtocol.cs +227 -0
- package/native/cpp/include/binary_reader.h +48 -0
- package/native/cpp/include/binary_writer.h +53 -0
- package/native/cpp/include/compact_reader.h +35 -0
- package/native/cpp/include/compact_writer.h +43 -0
- package/native/cpp/include/thrift_engine.h +187 -0
- package/native/cpp/src/binary_reader.cpp +177 -0
- package/native/cpp/src/binary_writer.cpp +211 -0
- package/native/cpp/src/compact_reader.cpp +69 -0
- package/native/cpp/src/compact_writer.cpp +113 -0
- package/native/cpp/src/thrift_engine.cpp +380 -0
- package/package.json +4 -2
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
// DpBinaryProtocol.cs - Extracted from DpProtocolLibrary.cs (DpBinaryProtocol class)
|
|
2
|
+
|
|
3
|
+
using System;
|
|
4
|
+
using System.IO;
|
|
5
|
+
using System.Text;
|
|
6
|
+
using System.Buffers;
|
|
7
|
+
|
|
8
|
+
namespace DeukPack.Protocol {
|
|
9
|
+
/// <summary>
|
|
10
|
+
/// Binary protocol implementation with FastPacket-level optimization.
|
|
11
|
+
/// Unity compatible high-performance serialization.
|
|
12
|
+
/// </summary>
|
|
13
|
+
public class DpBinaryProtocol : DpProtocol, IDisposable
|
|
14
|
+
{
|
|
15
|
+
private readonly Stream _stream;
|
|
16
|
+
private readonly bool _strictRead;
|
|
17
|
+
private readonly bool _strictWrite;
|
|
18
|
+
private readonly bool _bigEndian;
|
|
19
|
+
|
|
20
|
+
// FastPacket-level optimizations
|
|
21
|
+
private static readonly ArrayPool<byte> _bufferPool = ArrayPool<byte>.Shared;
|
|
22
|
+
private byte[] _writeBuffer;
|
|
23
|
+
private int _writePosition;
|
|
24
|
+
private int _writeCapacity;
|
|
25
|
+
|
|
26
|
+
// Read buffer pooling
|
|
27
|
+
private byte[] _readBuffer;
|
|
28
|
+
private int _readPosition;
|
|
29
|
+
private int _readLength;
|
|
30
|
+
private const int READ_BUFFER_SIZE = 4096;
|
|
31
|
+
private const int MaxBinaryLength = 1024 * 1024 * 10; // 10MB
|
|
32
|
+
|
|
33
|
+
// Small buffer for primitive types (stackalloc-like optimization)
|
|
34
|
+
private const int SMALL_BUFFER_SIZE = 16;
|
|
35
|
+
private readonly byte[] _smallBuffer = new byte[SMALL_BUFFER_SIZE];
|
|
36
|
+
|
|
37
|
+
private readonly bool _directWrite;
|
|
38
|
+
|
|
39
|
+
/// <param name="bigEndian">true = Binary(Apache 호환), false = LEBinary</param>
|
|
40
|
+
public DpBinaryProtocol(Stream stream, bool bigEndian = true, bool strictRead = true, bool strictWrite = true, int initialBufferSize = 4096)
|
|
41
|
+
{
|
|
42
|
+
_stream = stream;
|
|
43
|
+
_bigEndian = bigEndian;
|
|
44
|
+
_strictRead = strictRead;
|
|
45
|
+
_strictWrite = strictWrite;
|
|
46
|
+
|
|
47
|
+
_directWrite = (stream is System.IO.MemoryStream);
|
|
48
|
+
|
|
49
|
+
if (!_directWrite && initialBufferSize > 0)
|
|
50
|
+
{
|
|
51
|
+
_writeBuffer = _bufferPool.Rent(initialBufferSize);
|
|
52
|
+
_writeCapacity = _writeBuffer.Length;
|
|
53
|
+
}
|
|
54
|
+
_writePosition = 0;
|
|
55
|
+
|
|
56
|
+
_readBuffer = _bufferPool.Rent(READ_BUFFER_SIZE);
|
|
57
|
+
_readPosition = 0;
|
|
58
|
+
_readLength = 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private void EnsureWriteBuffer(int additionalBytes)
|
|
62
|
+
{
|
|
63
|
+
if (_directWrite) return;
|
|
64
|
+
if (_writeBuffer == null || _writePosition + additionalBytes > _writeCapacity)
|
|
65
|
+
{
|
|
66
|
+
FlushWriteBuffer();
|
|
67
|
+
int newSize = Math.Max(_writePosition + additionalBytes, _writeCapacity * 2);
|
|
68
|
+
if (_writeBuffer != null)
|
|
69
|
+
{
|
|
70
|
+
_bufferPool.Return(_writeBuffer);
|
|
71
|
+
}
|
|
72
|
+
_writeBuffer = _bufferPool.Rent(newSize);
|
|
73
|
+
_writeCapacity = _writeBuffer.Length;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private void FlushWriteBuffer()
|
|
78
|
+
{
|
|
79
|
+
if (_writeBuffer != null && _writePosition > 0)
|
|
80
|
+
{
|
|
81
|
+
_stream.Write(_writeBuffer, 0, _writePosition);
|
|
82
|
+
_writePosition = 0;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public void Dispose()
|
|
87
|
+
{
|
|
88
|
+
FlushWriteBuffer();
|
|
89
|
+
if (_writeBuffer != null)
|
|
90
|
+
{
|
|
91
|
+
_bufferPool.Return(_writeBuffer);
|
|
92
|
+
_writeBuffer = null;
|
|
93
|
+
}
|
|
94
|
+
if (_readBuffer != null)
|
|
95
|
+
{
|
|
96
|
+
_bufferPool.Return(_readBuffer);
|
|
97
|
+
_readBuffer = null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public void WriteStructBegin(DpRecord structBegin)
|
|
102
|
+
{
|
|
103
|
+
// Binary protocol doesn't write struct names
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public void WriteStructEnd()
|
|
107
|
+
{
|
|
108
|
+
// Binary protocol doesn't write struct end markers
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/// <summary>
|
|
112
|
+
/// Flush all buffered writes to stream.
|
|
113
|
+
/// No-op when stream is MemoryStream (direct write mode).
|
|
114
|
+
/// </summary>
|
|
115
|
+
public void Flush()
|
|
116
|
+
{
|
|
117
|
+
if (!_directWrite) FlushWriteBuffer();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public void WriteFieldBegin(DpColumn field)
|
|
121
|
+
{
|
|
122
|
+
WriteByte((byte)field.Type);
|
|
123
|
+
WriteI16(field.ID);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public void WriteFieldEnd()
|
|
127
|
+
{
|
|
128
|
+
// Binary protocol doesn't write field end markers
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public void WriteFieldStop()
|
|
132
|
+
{
|
|
133
|
+
WriteByte((byte)DpWireType.Stop);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public void WriteBool(bool b)
|
|
137
|
+
{
|
|
138
|
+
WriteByte(b ? (byte)1 : (byte)0);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public void WriteByte(byte b)
|
|
142
|
+
{
|
|
143
|
+
if (_directWrite) { _stream.WriteByte(b); return; }
|
|
144
|
+
EnsureWriteBuffer(1);
|
|
145
|
+
_writeBuffer[_writePosition++] = b;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public void WriteI16(short i16)
|
|
149
|
+
{
|
|
150
|
+
if (_directWrite)
|
|
151
|
+
{
|
|
152
|
+
if (_bigEndian)
|
|
153
|
+
{
|
|
154
|
+
_smallBuffer[0] = (byte)((i16 >> 8) & 0xFF);
|
|
155
|
+
_smallBuffer[1] = (byte)(i16 & 0xFF);
|
|
156
|
+
}
|
|
157
|
+
else
|
|
158
|
+
{
|
|
159
|
+
_smallBuffer[0] = (byte)(i16 & 0xFF);
|
|
160
|
+
_smallBuffer[1] = (byte)((i16 >> 8) & 0xFF);
|
|
161
|
+
}
|
|
162
|
+
_stream.Write(_smallBuffer, 0, 2);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
EnsureWriteBuffer(2);
|
|
166
|
+
WriteI16Optimized(i16);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public void WriteI32(int i32)
|
|
170
|
+
{
|
|
171
|
+
if (_directWrite)
|
|
172
|
+
{
|
|
173
|
+
if (_bigEndian)
|
|
174
|
+
{
|
|
175
|
+
_smallBuffer[0] = (byte)((i32 >> 24) & 0xFF);
|
|
176
|
+
_smallBuffer[1] = (byte)((i32 >> 16) & 0xFF);
|
|
177
|
+
_smallBuffer[2] = (byte)((i32 >> 8) & 0xFF);
|
|
178
|
+
_smallBuffer[3] = (byte)(i32 & 0xFF);
|
|
179
|
+
}
|
|
180
|
+
else
|
|
181
|
+
{
|
|
182
|
+
_smallBuffer[0] = (byte)(i32 & 0xFF);
|
|
183
|
+
_smallBuffer[1] = (byte)((i32 >> 8) & 0xFF);
|
|
184
|
+
_smallBuffer[2] = (byte)((i32 >> 16) & 0xFF);
|
|
185
|
+
_smallBuffer[3] = (byte)((i32 >> 24) & 0xFF);
|
|
186
|
+
}
|
|
187
|
+
_stream.Write(_smallBuffer, 0, 4);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
EnsureWriteBuffer(4);
|
|
191
|
+
WriteI32Optimized(i32);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
public void WriteI64(long i64)
|
|
195
|
+
{
|
|
196
|
+
if (_directWrite)
|
|
197
|
+
{
|
|
198
|
+
if (_bigEndian)
|
|
199
|
+
{
|
|
200
|
+
_smallBuffer[0] = (byte)((i64 >> 56) & 0xFF);
|
|
201
|
+
_smallBuffer[1] = (byte)((i64 >> 48) & 0xFF);
|
|
202
|
+
_smallBuffer[2] = (byte)((i64 >> 40) & 0xFF);
|
|
203
|
+
_smallBuffer[3] = (byte)((i64 >> 32) & 0xFF);
|
|
204
|
+
_smallBuffer[4] = (byte)((i64 >> 24) & 0xFF);
|
|
205
|
+
_smallBuffer[5] = (byte)((i64 >> 16) & 0xFF);
|
|
206
|
+
_smallBuffer[6] = (byte)((i64 >> 8) & 0xFF);
|
|
207
|
+
_smallBuffer[7] = (byte)(i64 & 0xFF);
|
|
208
|
+
}
|
|
209
|
+
else
|
|
210
|
+
{
|
|
211
|
+
_smallBuffer[0] = (byte)(i64 & 0xFF);
|
|
212
|
+
_smallBuffer[1] = (byte)((i64 >> 8) & 0xFF);
|
|
213
|
+
_smallBuffer[2] = (byte)((i64 >> 16) & 0xFF);
|
|
214
|
+
_smallBuffer[3] = (byte)((i64 >> 24) & 0xFF);
|
|
215
|
+
_smallBuffer[4] = (byte)((i64 >> 32) & 0xFF);
|
|
216
|
+
_smallBuffer[5] = (byte)((i64 >> 40) & 0xFF);
|
|
217
|
+
_smallBuffer[6] = (byte)((i64 >> 48) & 0xFF);
|
|
218
|
+
_smallBuffer[7] = (byte)((i64 >> 56) & 0xFF);
|
|
219
|
+
}
|
|
220
|
+
_stream.Write(_smallBuffer, 0, 8);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
EnsureWriteBuffer(8);
|
|
224
|
+
WriteI64Optimized(i64);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
public void WriteDouble(double d)
|
|
228
|
+
{
|
|
229
|
+
if (_directWrite)
|
|
230
|
+
{
|
|
231
|
+
WriteI64(BitConverter.DoubleToInt64Bits(d));
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
EnsureWriteBuffer(8);
|
|
235
|
+
WriteDoubleOptimized(d);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public void WriteString(string s)
|
|
239
|
+
{
|
|
240
|
+
if (s == null)
|
|
241
|
+
{
|
|
242
|
+
WriteI32(0);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
int byteCount = Encoding.UTF8.GetByteCount(s);
|
|
247
|
+
WriteI32(byteCount);
|
|
248
|
+
|
|
249
|
+
if (byteCount > 0)
|
|
250
|
+
{
|
|
251
|
+
if (_directWrite)
|
|
252
|
+
{
|
|
253
|
+
byte[] bytes = Encoding.UTF8.GetBytes(s);
|
|
254
|
+
_stream.Write(bytes, 0, bytes.Length);
|
|
255
|
+
}
|
|
256
|
+
else
|
|
257
|
+
{
|
|
258
|
+
EnsureWriteBuffer(byteCount);
|
|
259
|
+
Encoding.UTF8.GetBytes(s, 0, s.Length, _writeBuffer, _writePosition);
|
|
260
|
+
_writePosition += byteCount;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
public void WriteBinary(byte[] b)
|
|
266
|
+
{
|
|
267
|
+
if (b == null)
|
|
268
|
+
{
|
|
269
|
+
WriteI32(0);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
WriteI32(b.Length);
|
|
274
|
+
if (b.Length > 0)
|
|
275
|
+
{
|
|
276
|
+
if (_directWrite)
|
|
277
|
+
{
|
|
278
|
+
_stream.Write(b, 0, b.Length);
|
|
279
|
+
}
|
|
280
|
+
else
|
|
281
|
+
{
|
|
282
|
+
EnsureWriteBuffer(b.Length);
|
|
283
|
+
Array.Copy(b, 0, _writeBuffer, _writePosition, b.Length);
|
|
284
|
+
_writePosition += b.Length;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
private void WriteI16Optimized(short value)
|
|
290
|
+
{
|
|
291
|
+
if (_bigEndian)
|
|
292
|
+
{
|
|
293
|
+
_writeBuffer[_writePosition] = (byte)((value >> 8) & 0xFF);
|
|
294
|
+
_writeBuffer[_writePosition + 1] = (byte)(value & 0xFF);
|
|
295
|
+
}
|
|
296
|
+
else
|
|
297
|
+
{
|
|
298
|
+
_writeBuffer[_writePosition] = (byte)(value & 0xFF);
|
|
299
|
+
_writeBuffer[_writePosition + 1] = (byte)((value >> 8) & 0xFF);
|
|
300
|
+
}
|
|
301
|
+
_writePosition += 2;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
private void WriteI32Optimized(int value)
|
|
305
|
+
{
|
|
306
|
+
if (_bigEndian)
|
|
307
|
+
{
|
|
308
|
+
_writeBuffer[_writePosition] = (byte)((value >> 24) & 0xFF);
|
|
309
|
+
_writeBuffer[_writePosition + 1] = (byte)((value >> 16) & 0xFF);
|
|
310
|
+
_writeBuffer[_writePosition + 2] = (byte)((value >> 8) & 0xFF);
|
|
311
|
+
_writeBuffer[_writePosition + 3] = (byte)(value & 0xFF);
|
|
312
|
+
}
|
|
313
|
+
else
|
|
314
|
+
{
|
|
315
|
+
_writeBuffer[_writePosition] = (byte)(value & 0xFF);
|
|
316
|
+
_writeBuffer[_writePosition + 1] = (byte)((value >> 8) & 0xFF);
|
|
317
|
+
_writeBuffer[_writePosition + 2] = (byte)((value >> 16) & 0xFF);
|
|
318
|
+
_writeBuffer[_writePosition + 3] = (byte)((value >> 24) & 0xFF);
|
|
319
|
+
}
|
|
320
|
+
_writePosition += 4;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
private void WriteI64Optimized(long value)
|
|
324
|
+
{
|
|
325
|
+
if (_bigEndian)
|
|
326
|
+
{
|
|
327
|
+
_writeBuffer[_writePosition] = (byte)((value >> 56) & 0xFF);
|
|
328
|
+
_writeBuffer[_writePosition + 1] = (byte)((value >> 48) & 0xFF);
|
|
329
|
+
_writeBuffer[_writePosition + 2] = (byte)((value >> 40) & 0xFF);
|
|
330
|
+
_writeBuffer[_writePosition + 3] = (byte)((value >> 32) & 0xFF);
|
|
331
|
+
_writeBuffer[_writePosition + 4] = (byte)((value >> 24) & 0xFF);
|
|
332
|
+
_writeBuffer[_writePosition + 5] = (byte)((value >> 16) & 0xFF);
|
|
333
|
+
_writeBuffer[_writePosition + 6] = (byte)((value >> 8) & 0xFF);
|
|
334
|
+
_writeBuffer[_writePosition + 7] = (byte)(value & 0xFF);
|
|
335
|
+
}
|
|
336
|
+
else
|
|
337
|
+
{
|
|
338
|
+
_writeBuffer[_writePosition] = (byte)(value & 0xFF);
|
|
339
|
+
_writeBuffer[_writePosition + 1] = (byte)((value >> 8) & 0xFF);
|
|
340
|
+
_writeBuffer[_writePosition + 2] = (byte)((value >> 16) & 0xFF);
|
|
341
|
+
_writeBuffer[_writePosition + 3] = (byte)((value >> 24) & 0xFF);
|
|
342
|
+
_writeBuffer[_writePosition + 4] = (byte)((value >> 32) & 0xFF);
|
|
343
|
+
_writeBuffer[_writePosition + 5] = (byte)((value >> 40) & 0xFF);
|
|
344
|
+
_writeBuffer[_writePosition + 6] = (byte)((value >> 48) & 0xFF);
|
|
345
|
+
_writeBuffer[_writePosition + 7] = (byte)((value >> 56) & 0xFF);
|
|
346
|
+
}
|
|
347
|
+
_writePosition += 8;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private void WriteDoubleOptimized(double value)
|
|
351
|
+
{
|
|
352
|
+
// Convert double to long and write as I64
|
|
353
|
+
long bits = BitConverter.DoubleToInt64Bits(value);
|
|
354
|
+
WriteI64Optimized(bits);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
public void WriteListBegin(DpList list)
|
|
358
|
+
{
|
|
359
|
+
WriteByte((byte)list.ElementType);
|
|
360
|
+
WriteI32(list.Count);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
public void WriteListEnd()
|
|
364
|
+
{
|
|
365
|
+
// Binary protocol doesn't write list end markers
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
public void WriteSetBegin(DpSet set)
|
|
369
|
+
{
|
|
370
|
+
WriteByte((byte)set.ElementType);
|
|
371
|
+
WriteI32(set.Count);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
public void WriteSetEnd()
|
|
375
|
+
{
|
|
376
|
+
// Binary protocol doesn't write set end markers
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
public void WriteMapBegin(DpDict map)
|
|
380
|
+
{
|
|
381
|
+
WriteByte((byte)map.KeyType);
|
|
382
|
+
WriteByte((byte)map.ValueType);
|
|
383
|
+
WriteI32(map.Count);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
public void WriteMapEnd()
|
|
387
|
+
{
|
|
388
|
+
// Binary protocol doesn't write map end markers
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
public DpRecord ReadStructBegin()
|
|
392
|
+
{
|
|
393
|
+
return new DpRecord();
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
public void ReadStructEnd()
|
|
397
|
+
{
|
|
398
|
+
// Binary protocol doesn't read struct end markers
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
public DpColumn ReadFieldBegin()
|
|
402
|
+
{
|
|
403
|
+
byte type = ReadByte();
|
|
404
|
+
if (type == (byte)DpWireType.Stop)
|
|
405
|
+
{
|
|
406
|
+
return new DpColumn("", DpWireType.Stop, 0);
|
|
407
|
+
}
|
|
408
|
+
short id = ReadI16();
|
|
409
|
+
return new DpColumn("", (DpWireType)type, id);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
public void ReadFieldEnd()
|
|
413
|
+
{
|
|
414
|
+
// Binary protocol doesn't read field end markers
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
public bool ReadBool()
|
|
418
|
+
{
|
|
419
|
+
return ReadByte() != 0;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
private void EnsureReadBuffer(int bytesNeeded)
|
|
423
|
+
{
|
|
424
|
+
if (_readPosition + bytesNeeded <= _readLength)
|
|
425
|
+
return;
|
|
426
|
+
|
|
427
|
+
int remaining = _readLength - _readPosition;
|
|
428
|
+
|
|
429
|
+
if (bytesNeeded > _readBuffer.Length)
|
|
430
|
+
{
|
|
431
|
+
var newBuf = _bufferPool.Rent(bytesNeeded + READ_BUFFER_SIZE);
|
|
432
|
+
if (remaining > 0)
|
|
433
|
+
Array.Copy(_readBuffer, _readPosition, newBuf, 0, remaining);
|
|
434
|
+
_bufferPool.Return(_readBuffer);
|
|
435
|
+
_readBuffer = newBuf;
|
|
436
|
+
}
|
|
437
|
+
else if (remaining > 0)
|
|
438
|
+
{
|
|
439
|
+
Array.Copy(_readBuffer, _readPosition, _readBuffer, 0, remaining);
|
|
440
|
+
}
|
|
441
|
+
_readPosition = 0;
|
|
442
|
+
_readLength = remaining;
|
|
443
|
+
|
|
444
|
+
while (_readLength < bytesNeeded)
|
|
445
|
+
{
|
|
446
|
+
int bytesRead = _stream.Read(_readBuffer, _readLength, _readBuffer.Length - _readLength);
|
|
447
|
+
if (bytesRead == 0)
|
|
448
|
+
throw new EndOfStreamException();
|
|
449
|
+
_readLength += bytesRead;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
public byte ReadByte()
|
|
454
|
+
{
|
|
455
|
+
EnsureReadBuffer(1);
|
|
456
|
+
return _readBuffer[_readPosition++];
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
public short ReadI16()
|
|
460
|
+
{
|
|
461
|
+
EnsureReadBuffer(2);
|
|
462
|
+
return ReadI16Optimized();
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
public int ReadI32()
|
|
466
|
+
{
|
|
467
|
+
EnsureReadBuffer(4);
|
|
468
|
+
return ReadI32Optimized();
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
public long ReadI64()
|
|
472
|
+
{
|
|
473
|
+
EnsureReadBuffer(8);
|
|
474
|
+
return ReadI64Optimized();
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
public double ReadDouble()
|
|
478
|
+
{
|
|
479
|
+
// Convert from long bits
|
|
480
|
+
long bits = ReadI64();
|
|
481
|
+
return BitConverter.Int64BitsToDouble(bits);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
public string ReadString()
|
|
485
|
+
{
|
|
486
|
+
int length = ReadI32();
|
|
487
|
+
if (length == 0)
|
|
488
|
+
return string.Empty;
|
|
489
|
+
if (length < 0 || length > MaxBinaryLength)
|
|
490
|
+
throw new InvalidOperationException($"Invalid string length: {length}");
|
|
491
|
+
|
|
492
|
+
EnsureReadBuffer(length);
|
|
493
|
+
string result = Encoding.UTF8.GetString(_readBuffer, _readPosition, length);
|
|
494
|
+
_readPosition += length;
|
|
495
|
+
return result;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
public byte[] ReadBinary()
|
|
499
|
+
{
|
|
500
|
+
int length = ReadI32();
|
|
501
|
+
if (length == 0)
|
|
502
|
+
return new byte[0];
|
|
503
|
+
if (length < 0 || length > MaxBinaryLength)
|
|
504
|
+
throw new InvalidOperationException($"Invalid binary length: {length}");
|
|
505
|
+
|
|
506
|
+
EnsureReadBuffer(length);
|
|
507
|
+
byte[] result = new byte[length];
|
|
508
|
+
Array.Copy(_readBuffer, _readPosition, result, 0, length);
|
|
509
|
+
_readPosition += length;
|
|
510
|
+
return result;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// 엔디언: _bigEndian에 따라 BE / LE(네트워크 바이트 순서) 고정
|
|
514
|
+
private short ReadI16Optimized()
|
|
515
|
+
{
|
|
516
|
+
short value = _bigEndian
|
|
517
|
+
? (short)((_readBuffer[_readPosition] << 8) | _readBuffer[_readPosition + 1])
|
|
518
|
+
: (short)(_readBuffer[_readPosition] | (_readBuffer[_readPosition + 1] << 8));
|
|
519
|
+
_readPosition += 2;
|
|
520
|
+
return value;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
private int ReadI32Optimized()
|
|
524
|
+
{
|
|
525
|
+
int b0 = _readBuffer[_readPosition], b1 = _readBuffer[_readPosition + 1], b2 = _readBuffer[_readPosition + 2], b3 = _readBuffer[_readPosition + 3];
|
|
526
|
+
_readPosition += 4;
|
|
527
|
+
return _bigEndian
|
|
528
|
+
? (b0 << 24) | (b1 << 16) | (b2 << 8) | b3
|
|
529
|
+
: (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
private long ReadI64Optimized()
|
|
533
|
+
{
|
|
534
|
+
long b0 = _readBuffer[_readPosition], b1 = _readBuffer[_readPosition + 1], b2 = _readBuffer[_readPosition + 2], b3 = _readBuffer[_readPosition + 3],
|
|
535
|
+
b4 = _readBuffer[_readPosition + 4], b5 = _readBuffer[_readPosition + 5], b6 = _readBuffer[_readPosition + 6], b7 = _readBuffer[_readPosition + 7];
|
|
536
|
+
_readPosition += 8;
|
|
537
|
+
return _bigEndian
|
|
538
|
+
? ((long)b0 << 56) | ((long)b1 << 48) | ((long)b2 << 40) | ((long)b3 << 32) | ((long)b4 << 24) | ((long)b5 << 16) | ((long)b6 << 8) | b7
|
|
539
|
+
: ((long)b7 << 56) | ((long)b6 << 48) | ((long)b5 << 40) | ((long)b4 << 32) | ((long)b3 << 24) | ((long)b2 << 16) | ((long)b1 << 8) | b0;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
public DpList ReadListBegin()
|
|
543
|
+
{
|
|
544
|
+
byte elementType = ReadByte();
|
|
545
|
+
int count = ReadI32();
|
|
546
|
+
return new DpList { ElementType = (DpWireType)elementType, Count = count };
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
public void ReadListEnd()
|
|
550
|
+
{
|
|
551
|
+
// Binary protocol doesn't read list end markers
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
public DpSet ReadSetBegin()
|
|
555
|
+
{
|
|
556
|
+
byte elementType = ReadByte();
|
|
557
|
+
int count = ReadI32();
|
|
558
|
+
return new DpSet { ElementType = (DpWireType)elementType, Count = count };
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
public void ReadSetEnd()
|
|
562
|
+
{
|
|
563
|
+
// Binary protocol doesn't read set end markers
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
public DpDict ReadMapBegin()
|
|
567
|
+
{
|
|
568
|
+
byte keyType = ReadByte();
|
|
569
|
+
byte valueType = ReadByte();
|
|
570
|
+
int count = ReadI32();
|
|
571
|
+
return new DpDict { KeyType = (DpWireType)keyType, ValueType = (DpWireType)valueType, Count = count };
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
public void ReadMapEnd()
|
|
575
|
+
{
|
|
576
|
+
// Binary protocol doesn't read map end markers
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|