feat[py]: python compatible field support

This commit is contained in:
godotg
2023-09-28 10:31:46 +08:00
parent dee86d0cb4
commit 696b2ab8a1
10 changed files with 2042 additions and 3363 deletions
+5 -1
View File
@@ -15,7 +15,11 @@ def print_bytearray(array):
class ByteBufferTestCase(TestCase):
def test_complex_object(self):
# 打开文件并读取内容
with open('NormalObject.bytes', 'rb') as file:
# with open('D://github//zfoo//protocol//src//test//resources//compatible//normal-no-compatible.bytes', 'rb') as file:
# with open('D://github//zfoo//protocol//src//test//resources//compatible//normal-out-compatible.bytes', 'rb') as file:
# with open('D://github//zfoo//protocol//src//test//resources//compatible//normal-inner-compatible.bytes', 'rb') as file:
# with open('D://github//zfoo//protocol//src//test//resources//compatible//normal-out-inner-compatible.bytes', 'rb') as file:
with open('D://github//zfoo//protocol//src//test//resources//compatible//normal-out-inner-inner-compatible.bytes', 'rb') as file:
content = file.read()
# 将内容转为bytearray
@@ -14,12 +14,39 @@ class ByteBuffer():
readOffset = 0
buffer = bytearray(256)
def adjustPadding(self, predictionLength, beforeWriteIndex):
currentWriteIndex = self.writeOffset
predictionCount = self.writeIntCount(predictionLength)
length = currentWriteIndex - beforeWriteIndex - predictionCount
lengthCount = self.writeIntCount(length)
padding = lengthCount - predictionCount
if (padding == 0):
self.setWriteOffset(beforeWriteIndex)
self.writeInt(length)
self.setWriteOffset(currentWriteIndex)
else:
retainedByteBuf = self.buffer[(currentWriteIndex - length):currentWriteIndex]
self.setWriteOffset(beforeWriteIndex)
self.writeInt(length)
self.writeBytes(retainedByteBuf)
pass
def compatibleRead(self, beforeReadIndex, length):
return length != -1 and self.getReadOffset() < length + beforeReadIndex
def getWriteOffset(self):
return self.writeOffset
def setWriteOffset(self, writeOffset):
if writeOffset > len(self.buffer):
raise ValueError("index out of bounds exception:readerIndex:" + str(self.readOffset) +
", writerIndex:" + str(self.writeOffset) +
"(expected:0 <= readerIndex <= writerIndex <= capacity:" + str(len(self.buffer)))
self.writeOffset = writeOffset
pass
def getReadOffset(self):
return self.readOffset
def setReadOffset(self, readOffset):
if readOffset > self.writeOffset:
@@ -27,6 +54,7 @@ class ByteBuffer():
", writerIndex:" + str(self.writeOffset) +
"(expected:0 <= readerIndex <= writerIndex <= capacity:" + str(len(self.buffer)))
self.readOffset = readOffset
pass
def isReadable(self):
return self.writeOffset > self.readOffset
@@ -57,6 +85,7 @@ class ByteBuffer():
self.writeByte(1)
else:
self.writeByte(0)
pass
def readBool(self):
if self.readByte():
@@ -68,6 +97,7 @@ class ByteBuffer():
self.ensureCapacity(1)
struct.pack_into('>b', self.buffer, self.writeOffset, value)
self.writeOffset += 1
pass
def readByte(self):
value = struct.unpack_from('>b', self.buffer, self.readOffset)[0]
@@ -79,11 +109,13 @@ class ByteBuffer():
self.ensureCapacity(length)
self.buffer[self.writeOffset:length] = value[:]
self.writeOffset += length
pass
def writeUByte(self, value):
self.ensureCapacity(1)
struct.pack_into('>B', self.buffer, self.writeOffset, value)
self.writeOffset += 1
pass
def readUByte(self):
value = struct.unpack_from('>B', self.buffer, self.readOffset)[0]
@@ -94,6 +126,7 @@ class ByteBuffer():
self.ensureCapacity(2)
struct.pack_into('>h', self.buffer, self.writeOffset, value)
self.writeOffset += 2
pass
def readShort(self):
value = struct.unpack_from('>h', self.buffer, self.readOffset)[0]
@@ -104,6 +137,7 @@ class ByteBuffer():
self.ensureCapacity(4)
struct.pack_into('>i', self.buffer, self.writeOffset, value)
self.writeOffset += 4
pass
def readRawInt(self):
value = struct.unpack_from('>i', self.buffer, self.readOffset)[0]
@@ -144,6 +178,20 @@ class ByteBuffer():
self.writeUByte((value >> 28) & 0x7F)
pass
def writeIntCount(self, value):
if not (minInt <= value <= maxInt):
raise ValueError('value must range between minInt:-2147483648 and maxInt:2147483647')
value = (value << 1) ^ (value >> 31)
if value >> 7 == 0:
return 1
if value >> 14 == 0:
return 2
if value >> 21 == 0:
return 3
if value >> 28 == 0:
return 4
return 5
def readInt(self):
b = self.readUByte()
value = b & 0x7F
@@ -265,6 +313,7 @@ class ByteBuffer():
self.ensureCapacity(4)
struct.pack_into('>f', self.buffer, self.writeOffset, value)
self.writeOffset += 4
pass
def readFloat(self):
value = struct.unpack_from('>f', self.buffer, self.readOffset)[0]
@@ -275,21 +324,13 @@ class ByteBuffer():
self.ensureCapacity(8)
struct.pack_into('>d', self.buffer, self.writeOffset, value)
self.writeOffset += 8
pass
def readDouble(self):
value = struct.unpack_from('>d', self.buffer, self.readOffset)[0]
self.readOffset += 8
return value
def writeChar(self, value):
if len(value) == 0:
self.writeInt(0)
return
self.writeString(value[0])
def readChar(self):
return self.readString()
def writeString(self, value):
if len(value) == 0:
self.writeInt(0)
@@ -300,6 +341,7 @@ class ByteBuffer():
self.writeInt(length)
self.buffer[self.writeOffset:self.writeOffset + length] = byte_array[:]
self.writeOffset += length
pass
def readString(self):
length = self.readInt()
@@ -321,6 +363,7 @@ class ByteBuffer():
def writePacket(self, packet, protocolId):
protocolRegistration = ProtocolManager.getProtocol(protocolId)
protocolRegistration.write(self, packet)
pass
def readPacket(self, protocolId):
protocolRegistration = ProtocolManager.getProtocol(protocolId)
@@ -445,23 +488,6 @@ class ByteBuffer():
array.append(self.readDouble())
return array
def writeCharArray(self, array):
if array is None:
self.writeInt(0)
else:
self.writeInt(len(array))
for element in array:
self.writeChar(element)
pass
def readCharArray(self):
array = []
size = self.readInt()
if size > 0:
for index in range(size):
array.append(self.readChar())
return array
def writeStringArray(self, array):
if array is None:
self.writeInt(0)
@@ -855,23 +881,6 @@ class ByteBuffer():
value.add(self.readDouble())
return value
def writeCharSet(self, value):
if value is None:
self.writeInt(0)
else:
self.writeInt(len(value))
for element in value:
self.writeChar(element)
pass
def readCharValue(self):
value = set()
size = self.readInt()
if size > 0:
for index in range(size):
value.add(self.readChar())
return value
def writeStringSet(self, value):
if value is None:
self.writeInt(0)
@@ -32,10 +32,6 @@ class ComplexObject:
gg = False # bool
ggg = [] # bool[]
gggg = [] # bool[]
h = "" # char
hh = "" # char
hhh = [] # char[]
hhhh = [] # char[]
jj = "" # string
jjj = [] # string[]
kk = None # ObjectA
@@ -64,8 +60,11 @@ class ComplexObject:
@classmethod
def write(cls, buffer, packet):
if buffer.writePacketFlag(packet):
if packet is None:
buffer.writeInt(0)
return
beforeWriteIndex = buffer.getWriteOffset()
buffer.writeInt(36962)
buffer.writeByte(packet.a)
buffer.writeByte(packet.aa)
buffer.writeByteArray(packet.aaa)
@@ -94,10 +93,6 @@ class ComplexObject:
buffer.writeBool(packet.gg)
buffer.writeBooleanArray(packet.ggg)
buffer.writeBooleanArray(packet.gggg)
buffer.writeChar(packet.h)
buffer.writeChar(packet.hh)
buffer.writeCharArray(packet.hhh)
buffer.writeCharArray(packet.hhhh)
buffer.writeString(packet.jj)
buffer.writeStringArray(packet.jjj)
buffer.writePacket(packet.kk, 102)
@@ -205,12 +200,15 @@ class ComplexObject:
buffer.writeIntStringMap(element18)
buffer.writeInt(packet.myCompatible)
buffer.writePacket(packet.myObject, 102)
buffer.adjustPadding(36962, beforeWriteIndex)
pass
@classmethod
def read(cls, buffer):
if not buffer.readBool():
length = buffer.readInt()
if length == 0:
return None
beforeReadIndex = buffer.getReadOffset()
packet = ComplexObject()
result19 = buffer.readByte()
packet.a = result19
@@ -268,144 +266,134 @@ class ComplexObject:
packet.ggg = array45
array46 = buffer.readBooleanArray()
packet.gggg = array46
result47 = buffer.readChar()
packet.h = result47
result48 = buffer.readChar()
packet.hh = result48
array49 = buffer.readCharArray()
packet.hhh = array49
array50 = buffer.readCharArray()
packet.hhhh = array50
result51 = buffer.readString()
packet.jj = result51
array52 = buffer.readStringArray()
packet.jjj = array52
result53 = buffer.readPacket(102)
packet.kk = result53
array54 = buffer.readPacketArray(102)
packet.kkk = array54
list55 = buffer.readIntArray()
packet.l = list55
result56 = []
size58 = buffer.readInt()
if size58 > 0:
for index57 in range(size58):
result59 = []
size61 = buffer.readInt()
if size61 > 0:
for index60 in range(size61):
list62 = buffer.readIntArray()
result59.append(list62)
result56.append(result59)
packet.ll = result56
result63 = []
size65 = buffer.readInt()
if size65 > 0:
for index64 in range(size65):
list66 = buffer.readPacketArray(102)
result63.append(list66)
packet.lll = result63
list67 = buffer.readStringArray()
packet.llll = list67
result68 = []
size70 = buffer.readInt()
if size70 > 0:
for index69 in range(size70):
map71 = buffer.readIntStringMap()
result68.append(map71)
packet.lllll = result68
map72 = buffer.readIntStringMap()
packet.m = map72
map73 = buffer.readIntPacketMap(102)
packet.mm = map73
result74 = {}
size75 = buffer.readInt()
if size75 > 0:
for index76 in range(size75):
result77 = buffer.readPacket(102)
list78 = buffer.readIntArray()
result74[result77] = list78
packet.mmm = result74
result79 = {}
size80 = buffer.readInt()
if size80 > 0:
for index81 in range(size80):
result47 = buffer.readString()
packet.jj = result47
array48 = buffer.readStringArray()
packet.jjj = array48
result49 = buffer.readPacket(102)
packet.kk = result49
array50 = buffer.readPacketArray(102)
packet.kkk = array50
list51 = buffer.readIntArray()
packet.l = list51
result52 = []
size54 = buffer.readInt()
if size54 > 0:
for index53 in range(size54):
result55 = []
size57 = buffer.readInt()
if size57 > 0:
for index56 in range(size57):
list58 = buffer.readIntArray()
result55.append(list58)
result52.append(result55)
packet.ll = result52
result59 = []
size61 = buffer.readInt()
if size61 > 0:
for index60 in range(size61):
list62 = buffer.readPacketArray(102)
result59.append(list62)
packet.lll = result59
list63 = buffer.readStringArray()
packet.llll = list63
result64 = []
size66 = buffer.readInt()
if size66 > 0:
for index65 in range(size66):
map67 = buffer.readIntStringMap()
result64.append(map67)
packet.lllll = result64
map68 = buffer.readIntStringMap()
packet.m = map68
map69 = buffer.readIntPacketMap(102)
packet.mm = map69
result70 = {}
size71 = buffer.readInt()
if size71 > 0:
for index72 in range(size71):
result73 = buffer.readPacket(102)
list74 = buffer.readIntArray()
result70[result73] = list74
packet.mmm = result70
result75 = {}
size76 = buffer.readInt()
if size76 > 0:
for index77 in range(size76):
result78 = []
size80 = buffer.readInt()
if size80 > 0:
for index79 in range(size80):
list81 = buffer.readPacketArray(102)
result78.append(list81)
result82 = []
size84 = buffer.readInt()
if size84 > 0:
for index83 in range(size84):
list85 = buffer.readPacketArray(102)
result82.append(list85)
result86 = []
size88 = buffer.readInt()
if size88 > 0:
for index87 in range(size88):
result89 = []
size91 = buffer.readInt()
if size91 > 0:
for index90 in range(size91):
list92 = buffer.readIntArray()
result89.append(list92)
result86.append(result89)
result79[result82] = result86
packet.mmmm = result79
result93 = {}
size94 = buffer.readInt()
if size94 > 0:
for index95 in range(size94):
result85 = []
size87 = buffer.readInt()
if size87 > 0:
for index86 in range(size87):
list88 = buffer.readIntArray()
result85.append(list88)
result82.append(result85)
result75[result78] = result82
packet.mmmm = result75
result89 = {}
size90 = buffer.readInt()
if size90 > 0:
for index91 in range(size90):
result92 = []
size94 = buffer.readInt()
if size94 > 0:
for index93 in range(size94):
map95 = buffer.readIntStringMap()
result92.append(map95)
result96 = []
size98 = buffer.readInt()
if size98 > 0:
for index97 in range(size98):
map99 = buffer.readIntStringMap()
result96.append(map99)
result100 = []
size102 = buffer.readInt()
if size102 > 0:
for index101 in range(size102):
map103 = buffer.readIntStringMap()
result100.append(map103)
result93[result96] = result100
packet.mmmmm = result93
set104 = buffer.readIntSet()
packet.s = set104
result105 = []
size107 = buffer.readInt()
if size107 > 0:
for index106 in range(size107):
result108 = []
size110 = buffer.readInt()
if size110 > 0:
for index109 in range(size110):
list111 = buffer.readIntArray()
result108.append(list111)
result105.append(result108)
packet.ss = result105
result112 = []
size114 = buffer.readInt()
if size114 > 0:
for index113 in range(size114):
set115 = buffer.readPacketSet(102)
result112.append(set115)
packet.sss = result112
set116 = buffer.readStringSet()
packet.ssss = set116
result117 = []
size119 = buffer.readInt()
if size119 > 0:
for index118 in range(size119):
map120 = buffer.readIntStringMap()
result117.append(map120)
packet.sssss = result117
if not buffer.isReadable():
return packet
pass
result121 = buffer.readInt()
packet.myCompatible = result121
if not buffer.isReadable():
return packet
pass
result122 = buffer.readPacket(102)
packet.myObject = result122
result89[result92] = result96
packet.mmmmm = result89
set100 = buffer.readIntSet()
packet.s = set100
result101 = []
size103 = buffer.readInt()
if size103 > 0:
for index102 in range(size103):
result104 = []
size106 = buffer.readInt()
if size106 > 0:
for index105 in range(size106):
list107 = buffer.readIntArray()
result104.append(list107)
result101.append(result104)
packet.ss = result101
result108 = []
size110 = buffer.readInt()
if size110 > 0:
for index109 in range(size110):
set111 = buffer.readPacketSet(102)
result108.append(set111)
packet.sss = result108
set112 = buffer.readStringSet()
packet.ssss = set112
result113 = []
size115 = buffer.readInt()
if size115 > 0:
for index114 in range(size115):
map116 = buffer.readIntStringMap()
result113.append(map116)
packet.sssss = result113
if buffer.compatibleRead(beforeReadIndex, length):
result117 = buffer.readInt()
packet.myCompatible = result117
if buffer.compatibleRead(beforeReadIndex, length):
result118 = buffer.readPacket(102)
packet.myObject = result118
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
@@ -0,0 +1,28 @@
class EmptyObject:
def protocolId(self):
return 0
@classmethod
def write(cls, buffer, packet):
if packet is None:
buffer.writeInt(0)
return
buffer.writeInt(-1)
pass
@classmethod
def read(cls, buffer):
length = buffer.readInt()
if length == 0:
return None
beforeReadIndex = buffer.getReadOffset()
packet = EmptyObject()
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
@@ -19,14 +19,19 @@ class NormalObject:
mm = {} # Dictionary<int, ObjectA>
s = {} # HashSet<int>
ssss = {} # HashSet<string>
outCompatibleValue = 0 # int
outCompatibleValue2 = 0 # int
def protocolId(self):
return 101
@classmethod
def write(cls, buffer, packet):
if buffer.writePacketFlag(packet):
if packet is None:
buffer.writeInt(0)
return
beforeWriteIndex = buffer.getWriteOffset()
buffer.writeInt(857)
buffer.writeByte(packet.a)
buffer.writeByteArray(packet.aaa)
buffer.writeShort(packet.b)
@@ -45,12 +50,17 @@ class NormalObject:
buffer.writeIntPacketMap(packet.mm, 102)
buffer.writeIntSet(packet.s)
buffer.writeStringSet(packet.ssss)
buffer.writeInt(packet.outCompatibleValue)
buffer.writeInt(packet.outCompatibleValue2)
buffer.adjustPadding(857, beforeWriteIndex)
pass
@classmethod
def read(cls, buffer):
if not buffer.readBool():
length = buffer.readInt()
if length == 0:
return None
beforeReadIndex = buffer.getReadOffset()
packet = NormalObject()
result0 = buffer.readByte()
packet.a = result0
@@ -88,5 +98,13 @@ class NormalObject:
packet.s = set16
set17 = buffer.readStringSet()
packet.ssss = set17
if buffer.compatibleRead(beforeReadIndex, length):
result18 = buffer.readInt()
packet.outCompatibleValue = result18
if buffer.compatibleRead(beforeReadIndex, length):
result19 = buffer.readInt()
packet.outCompatibleValue2 = result19
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
+15 -2
View File
@@ -4,23 +4,31 @@ class ObjectA:
a = 0 # int
m = {} # Dictionary<int, string>
objectB = None # ObjectB
innerCompatibleValue = 0 # int
def protocolId(self):
return 102
@classmethod
def write(cls, buffer, packet):
if buffer.writePacketFlag(packet):
if packet is None:
buffer.writeInt(0)
return
beforeWriteIndex = buffer.getWriteOffset()
buffer.writeInt(201)
buffer.writeInt(packet.a)
buffer.writeIntStringMap(packet.m)
buffer.writePacket(packet.objectB, 103)
buffer.writeInt(packet.innerCompatibleValue)
buffer.adjustPadding(201, beforeWriteIndex)
pass
@classmethod
def read(cls, buffer):
if not buffer.readBool():
length = buffer.readInt()
if length == 0:
return None
beforeReadIndex = buffer.getReadOffset()
packet = ObjectA()
result0 = buffer.readInt()
packet.a = result0
@@ -28,5 +36,10 @@ class ObjectA:
packet.m = map1
result2 = buffer.readPacket(103)
packet.objectB = result2
if buffer.compatibleRead(beforeReadIndex, length):
result3 = buffer.readInt()
packet.innerCompatibleValue = result3
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
+15 -2
View File
@@ -2,23 +2,36 @@
class ObjectB:
flag = False # bool
innerCompatibleValue = 0 # int
def protocolId(self):
return 103
@classmethod
def write(cls, buffer, packet):
if buffer.writePacketFlag(packet):
if packet is None:
buffer.writeInt(0)
return
beforeWriteIndex = buffer.getWriteOffset()
buffer.writeInt(4)
buffer.writeBool(packet.flag)
buffer.writeInt(packet.innerCompatibleValue)
buffer.adjustPadding(4, beforeWriteIndex)
pass
@classmethod
def read(cls, buffer):
if not buffer.readBool():
length = buffer.readInt()
if length == 0:
return None
beforeReadIndex = buffer.getReadOffset()
packet = ObjectB()
result0 = buffer.readBool()
packet.flag = result0
if buffer.compatibleRead(beforeReadIndex, length):
result1 = buffer.readInt()
packet.innerCompatibleValue = result1
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
@@ -1,3 +1,4 @@
from . import EmptyObject
from . import VeryBigObject
from . import ComplexObject
from . import NormalObject
@@ -7,7 +8,8 @@ from . import SimpleObject
protocols = {}
protocols[0] = VeryBigObject.VeryBigObject
protocols[0] = EmptyObject.EmptyObject
protocols[1] = VeryBigObject.VeryBigObject
protocols[100] = ComplexObject.ComplexObject
protocols[101] = NormalObject.NormalObject
protocols[102] = ObjectA.ObjectA
@@ -9,20 +9,26 @@ class SimpleObject:
@classmethod
def write(cls, buffer, packet):
if buffer.writePacketFlag(packet):
if packet is None:
buffer.writeInt(0)
return
buffer.writeInt(-1)
buffer.writeInt(packet.c)
buffer.writeBool(packet.g)
pass
@classmethod
def read(cls, buffer):
if not buffer.readBool():
length = buffer.readInt()
if length == 0:
return None
beforeReadIndex = buffer.getReadOffset()
packet = SimpleObject()
result0 = buffer.readInt()
packet.c = result0
result1 = buffer.readBool()
packet.g = result1
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
File diff suppressed because it is too large Load Diff