internal static RefState ReadReferenceForObject(
     BinaryConverter binaryConverter,
     ref ReadStack state,
     ref BinaryReader reader,
     out object value)
 {
     if (reader.TokenType == BinaryTokenType.StartObject)
     {
         uint refSeq = BitConverter.ToUInt32(reader.ValueSpan);
         state.ReferenceResolver.AddReference(refSeq);
         value = default;
         state.Current.RefId = refSeq;
         return(RefState.None);
     }
     else if (reader.TokenType == BinaryTokenType.ObjectRef)
     {
         uint refSeq = BitConverter.ToUInt32(reader.ValueSpan);
         state.Current.RefId = refSeq;
         var refState = state.ReferenceResolver.TryGetReference(refSeq, out value);
         if (refState == RefState.Start)
         {
             value = new ReferenceID()
             {
                 RefSeq = refSeq
             };
         }
         return(refState);
     }
     else
     {
         ThrowHelper.ThrowBinaryReaderException(ref reader, ExceptionResource.InvalidByte);
     }
     value = default;
     return(RefState.None);
 }
        internal bool ReadStartToken()
        {
            if (!RequestData(5))
            {
                return(false);
            }

            byte objType = _buffer[_consumed];

            ValueSpan  = _buffer.Slice(_consumed + 1, 4);
            _consumed += 5;

            if (objType == 0x00)
            {
                //正常
                _tokenType = BinaryTokenType.StartObject;
            }
            else if (objType == 0xFF)
            {
                _tokenType = BinaryTokenType.ObjectRef;
            }
            else
            {
                ThrowHelper.ThrowBinaryReaderException(ref this, ExceptionResource.ExpectedBinaryTokens);
            }
            return(true);
        }
        public void AheadRead()
        {
            AheadReadSingleSegment();

            if (TokenType == BinaryTokenType.None)
            {
                ThrowHelper.ThrowBinaryReaderException(ref this, ExceptionResource.ExpectedBinaryTokens);
            }
        }
        public bool Read()
        {
            bool retVal = ReadSingleSegment();

            if (!retVal)
            {
                if (_isFinalBlock && TokenType == BinaryTokenType.None)
                {
                    ThrowHelper.ThrowBinaryReaderException(ref this, ExceptionResource.ExpectedBinaryTokens);
                }
            }
            return(retVal);
        }
 internal void AheadReadDictionaryKeySeq()
 {
     ValueSpan  = _buffer.Slice(_consumed, 1);
     _dicKeySeq = ValueSpan[0];
     if (_dicKeySeq == BinarySerializerConstants.EndDictionaryKey)
     {
         _tokenType = BinaryTokenType.EndDictionaryKey;
     }
     else if (_dicKeySeq == BinarySerializerConstants.DictionaryKeySeq)
     {
         _tokenType = BinaryTokenType.DictionaryKeySeq;
     }
     else
     {
         ThrowHelper.ThrowBinaryReaderException(ref this, ExceptionResource.InvalidByte);
     }
     _consumed++;
 }
        internal void AheadReadStartToken()
        {
            byte objType = _buffer[_consumed];

            ValueSpan  = _buffer.Slice(_consumed + 1, 4);
            _consumed += 5;

            if (objType == 0x00)
            {
                //正常
                _tokenType = BinaryTokenType.StartObject;
            }
            else if (objType == 0xFF)
            {
                _tokenType = BinaryTokenType.ObjectRef;
            }
            else
            {
                ThrowHelper.ThrowBinaryReaderException(ref this, ExceptionResource.ExpectedBinaryTokens);
            }
        }
        internal bool ReadDictionaryKeySeq()
        {
            if (!RequestData(1))
            {
                return(false);
            }

            ValueSpan  = _buffer.Slice(_consumed, 1);
            _dicKeySeq = ValueSpan[0];
            if (_dicKeySeq == BinarySerializerConstants.EndDictionaryKey)
            {
                _tokenType = BinaryTokenType.EndDictionaryKey;
            }
            else if (_dicKeySeq == BinarySerializerConstants.DictionaryKeySeq)
            {
                _tokenType = BinaryTokenType.DictionaryKeySeq;
            }
            else
            {
                ThrowHelper.ThrowBinaryReaderException(ref this, ExceptionResource.InvalidByte);
            }
            _consumed++;
            return(true);
        }
        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);
        }