public ulong GetEnumerableLength(ReadOnlySpan <byte> bytes) { if (bytes.Length == 1) { return(bytes[0]); } else if (bytes.Length == 2) { return(BitConverter.ToUInt16(bytes)); } else if (bytes.Length == 4) { return(BitConverter.ToUInt32(bytes)); } else if (bytes.Length == 8) { return(BitConverter.ToUInt64(bytes)); } else { ThrowHelper.ThrowBinaryException(); } return(0); }
public void WriteEnumerableIndex(long idx, BinaryWriter writer) { if (EnumerableIndexBytes == 1) { writer.WriteByteValue((byte)idx); } else if (EnumerableIndexBytes == 2) { writer.WriteUInt16Value((ushort)idx); } else if (EnumerableIndexBytes == 4) { writer.WriteUInt32Value((UInt32)idx); } else if (EnumerableIndexBytes == 8) { writer.WriteUInt64Value((ulong)idx); } else { ThrowHelper.ThrowBinaryException(); } }
internal bool TryForwardRead(BinaryTypeInfo typeInfo, ref int offset) { if (typeInfo.SerializeType == ClassType.Value) { if (_binaryTypeToBytesLen.ContainsKey(typeInfo.Type)) { int len = _binaryTypeToBytesLen[typeInfo.Type]; if (!TryRequestData(offset, len)) { return(false); } offset += len; return(true); } else if (typeInfo.Type == TypeEnum.Nullable) { int curOffset = offset; if (!TryReadTypeSeq(ref curOffset, out ushort typeSeq)) { return(false); } if (typeSeq == TypeMap.NullTypeSeq) { offset = curOffset; return(true); } if (!TryForwardRead(_typeMap.GetTypeInfo(typeSeq), ref curOffset)) { return(false); } offset = curOffset; return(true); } else { if (!TrySkipBytes(ref offset)) { return(false); } } } else if (typeInfo.SerializeType == ClassType.Object) { int curOffset = offset; // 引用、非引用 if (!TryRequestData(curOffset, 1)) { return(false); } byte _ = _buffer[curOffset++]; if (!TryRequestData(curOffset, 4)) { return(false); } curOffset += 4; // 读取属性 if (!TrySkipObjectProperties(ref curOffset)) { return(false); } offset = curOffset; } else if (typeInfo.SerializeType == ClassType.Enumerable) { int curOffset = offset; // 可枚举类型 // 引用、非引用 if (!TryRequestData(curOffset, 1)) { return(false); } byte refSign = _buffer[curOffset++]; // 引用 if (!TryRequestData(curOffset, 4)) { return(false); } curOffset += 4; // 非引用 if (refSign == 0x00) { // 索引长度 if (!TryRequestData(curOffset, 1)) { return(false); } byte lenBytes = _buffer[curOffset++]; if (!TryRequestData(curOffset, lenBytes)) { return(false); } var lenSpan = _buffer.Slice(curOffset, lenBytes); ulong len = GetEnumerableLength(lenSpan); curOffset += lenBytes; // 按顺序读取 ulong curIdx = 0; while (curIdx < len) { // 读取索引 if (!TrySkipBytes(ref curOffset, lenBytes)) { return(false); } if (!TryReadTypeSeq(ref curOffset, out ushort typeSeq)) { return(false); } if (typeSeq == TypeMap.NullTypeSeq) { continue; } BinaryTypeInfo ti = _typeMap.GetTypeInfo(typeSeq); if (!TryForwardRead(ti, ref curOffset)) { return(false); } curIdx++; } } // 读取自定义属性 if (!TrySkipObjectProperties(ref curOffset)) { return(false); } offset = curOffset; } else if (typeInfo.SerializeType == ClassType.Dictionary) { int curOffset = offset; // 引用、非引用 if (!TryRequestData(curOffset, 1)) { return(false); } byte refSign = _buffer[curOffset++]; if (!TryRequestData(curOffset, 4)) { return(false); } curOffset += 4; if (refSign == 0x00) { // Key Value while (true) { if (!TryRequestData(curOffset, 1)) { return(false); } byte keySeq = _buffer[curOffset++]; if (keySeq == BinarySerializerConstants.EndDictionaryKey) { break; } else if (keySeq != BinarySerializerConstants.DictionaryKeySeq) { ThrowHelper.ThrowBinaryReaderException(ref this, ExceptionResource.InvalidByte); } // Key if (!TryReadTypeSeq(ref curOffset, out ushort typeSeq)) { return(false); } if (typeSeq != TypeMap.NullTypeSeq) { BinaryTypeInfo ti = _typeMap.GetTypeInfo(typeSeq); if (!TryForwardRead(ti, ref curOffset)) { return(false); } } // Value if (!TryReadTypeSeq(ref curOffset, out typeSeq)) { return(false); } if (typeSeq != TypeMap.NullTypeSeq) { BinaryTypeInfo ti = _typeMap.GetTypeInfo(typeSeq); if (!TryForwardRead(ti, ref curOffset)) { return(false); } } } } // 读取属性 if (!TrySkipObjectProperties(ref curOffset)) { return(false); } offset = curOffset; } else { ThrowHelper.ThrowBinaryException(); } return(true); }