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.
@@ -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
+ }