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);
        }
        internal bool ReadTypeSeq()
        {
            if (!RequestData(2))
            {
                return(false);
            }

            _tokenType = BinaryTokenType.TypeSeq;
            ValueSpan  = _buffer.Slice(_consumed, 2);
            _typeSeq   = BitConverter.ToUInt16(ValueSpan);
            if (_typeSeq == TypeMap.NullTypeSeq)
            {
                _tokenType      = BinaryTokenType.Null;
                CurrentTypeInfo = null;
            }
            else
            {
                CurrentTypeInfo = _typeMap.GetTypeInfo(_typeSeq);
            }

            if (CurrentTypeInfo == null && _tokenType != BinaryTokenType.Null)
            {
                throw new Exception();
            }
            _consumed += 2;


            return(true);
        }
        public BinaryReader(ReadOnlySpan <byte> binaryData, bool isFinalBlock, BinaryReaderState state)
        {
            _buffer = binaryData;

            _isFinalBlock = isFinalBlock;
            //_isInputSequence = false;
            _typeSeq           = state._typeSeq;
            _dicKeySeq         = state._dicKeySeq;
            CurrentTypeInfo    = state._typeInfo;
            CurrentPropertySeq = state._propertySeq;
            _typeMap           = state._typeMap;
            _version           = state._version;

            _tokenType         = state._tokenType;
            _previousTokenType = state._previousTokenType;


            _consumed       = 0;
            TokenStartIndex = 0;
            _totalConsumed  = 0;

            ValueSpan = ReadOnlySpan <byte> .Empty;


            _sequence = default;
        }
        private bool ReadCreatorArgumentsWithContinuation(ref ReadStack state,
                                                          ref BinaryReader reader,
                                                          BinarySerializerOptions options)
        {
            // Process all properties.
            while (true)
            {
                // Determine the property.
                if (state.Current.PropertyState == StackFramePropertyState.None)
                {
                    if (!reader.ReadPropertyName())
                    {
                        return(false);
                    }

                    state.Current.PropertyState = StackFramePropertyState.ReadName;
                }

                BinaryPropertyInfo binaryPropertyInfo;

                if (state.Current.PropertyState <= StackFramePropertyState.Name)
                {
                    state.Current.PropertyState = StackFramePropertyState.Name;

                    BinaryTokenType tokenType = reader.TokenType;

                    if (tokenType == BinaryTokenType.EndObject)
                    {
                        return(true);
                    }

                    // Read method would have thrown if otherwise.
                    Debug.Assert(tokenType == BinaryTokenType.PropertyName);
                    ushort           propertySeq = reader.CurrentPropertySeq;
                    BinaryMemberInfo mi          = state.GetMemberInfo(propertySeq);
                    Debug.Assert(mi != null);


                    binaryPropertyInfo = BinarySerializer.LookupProperty(
                        obj: null !,
                        mi.NameAsUtf8Bytes,
                        ref state,
                        out bool useExtensionProperty,
                        createExtensionProperty: false);

                    state.Current.UseExtensionProperty = useExtensionProperty;
                }
                else
                {
                    binaryPropertyInfo = state.Current.BinaryPropertyInfo;
                }


                if (!HandlePropertyWithContinuation(ref state, ref reader, binaryPropertyInfo !))
                {
                    return(false);
                }
            }
        }
        private void ResetHelper()
        {
            BytesPending   = default;
            BytesCommitted = default;
            _memory        = default;

            //_inObject = default;
            _tokenType    = default;
            _currentDepth = default;

            // _bitStack = default;
        }
        /// <summary>
        /// 读取指定字节数,并返回
        /// 此方法会修改Reader的读取位置及Reader的ValueSpan属性
        /// </summary>
        /// <param name="len">待读取的长度</param>
        /// <param name="output">读取结果</param>
        /// <returns>成功返回ture,如果没有足够的数据返回false</returns>
        internal bool ReadBytes(int len)
        {
            if ((_consumed + len) > _buffer.Length)
            {
                return(false);
            }

            _tokenType = BinaryTokenType.Bytes;
            ValueSpan  = _buffer.Slice(_consumed, len);
            _consumed += len;

            return(true);
        }
        /// <summary>
        /// 读取包含长度信息的字节组
        /// </summary>
        /// <returns></returns>
        public bool ReadBytes()
        {
            // 长度 16位或32位
            if (!RequestData(2))
            {
                return(false);
            }

            byte b1 = _buffer[_consumed];

            // 如果最高位是1,表示31位长度,否则表示15位长度
            int len;
            int lenBytes;

            if ((b1 & 0x80) == 0x80)
            {
                if (!RequestData(4))
                {
                    return(false);
                }

                len = ((_buffer[_consumed] & 0x7F) << 24) |
                      (_buffer[_consumed + 1] << 16) |
                      (_buffer[_consumed + 2] << 8) |
                      _buffer[_consumed + 3];

                lenBytes = 4;
            }
            else
            {
                len      = _buffer[_consumed] << 8 | _buffer[_consumed + 1];
                lenBytes = 2;
            }

            if (len == 0)
            {
                ValueSpan = ReadOnlySpan <byte> .Empty;
            }

            if (!RequestData(len + lenBytes))
            {
                return(false);
            }

            _consumed += lenBytes;
            _tokenType = BinaryTokenType.Bytes;
            ValueSpan  = _buffer.Slice(_consumed, len);
            _consumed += len;
            return(true);
        }
        //internal BitStack _bitStack;


        public BinaryReaderState(TypeMap typeMap, int version, BinaryReaderOptions options = default)
        {
            _bytePosition      = default;
            _inObject          = default;
            _isNotPrimitive    = default;
            _tokenType         = default;
            _previousTokenType = default;
            _readerOptions     = options;
            _typeMap           = typeMap;
            _typeSeq           = default;
            _version           = version;
            _typeInfo          = default;
            _propertySeq       = default;
            _dicKeySeq         = default;
        }
        internal bool ReadPropertyName()
        {
            if (!RequestData(1))
            {
                return(false);
            }

            byte b = _buffer[_consumed];

            if ((b & 0x80) == 0x80)
            {
                // 键值对方式
            }
            else
            {
                if (!RequestData(2))
                {
                    return(false);
                }

                ValueSpan = _buffer.Slice(_consumed, 2);
                ushort seq = (ushort)((ValueSpan[0] << 8) | ValueSpan[1]);
                if (seq == BinarySerializerConstants.EndObjectSeq)
                {
                    // 对象结束
                    _tokenType         = BinaryTokenType.EndObject;
                    CurrentPropertySeq = default;
                }
                else
                {
                    _tokenType         = BinaryTokenType.PropertyName;
                    CurrentPropertySeq = seq;
                }

                _consumed += 2;

                return(true);
            }

            return(false);
        }
        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);
        }
Пример #11
0
        private static string GetResourceString(ExceptionResource resource, int currentDepth, byte token, BinaryTokenType tokenType)
        {
            string message = "";

            switch (resource)
            {
            case ExceptionResource.DepthTooLarge:
                message = string.Format(Strings.DepthTooLarge, currentDepth & BinarySerializerConstants.RemoveFlagsBitMask, BinarySerializerConstants.MaxWriterDepth);
                break;

            default:
                Debug.Fail($"The ExceptionResource enum value: {resource} is not part of the switch. Add the appropriate case and exception message.");
                break;
            }

            return(message);
        }
Пример #12
0
        public static InvalidOperationException GetInvalidOperationException(ExceptionResource resource, int currentDepth, byte token, BinaryTokenType tokenType)
        {
            string message = GetResourceString(resource, currentDepth, token, tokenType);
            InvalidOperationException ex = GetInvalidOperationException(message);

            ex.Source = ExceptionSourceValueToRethrowAsBinaryException;
            return(ex);
        }
Пример #13
0
 public static void ThrowInvalidOperationException(ExceptionResource resource, int currentDepth, byte token, BinaryTokenType tokenType)
 {
     throw GetInvalidOperationException(resource, currentDepth, token, tokenType);
 }
Пример #14
0
 public static InvalidOperationException GetInvalidOperationException_ExpectedString(BinaryTokenType tokenType)
 {
     return(GetInvalidOperationException("string", tokenType));
 }
Пример #15
0
 private static InvalidOperationException GetInvalidOperationException(string message, BinaryTokenType tokenType)
 {
     return(GetInvalidOperationException(string.Format(Strings.InvalidCast, tokenType, message)));
 }
        internal bool TryRead(ref BinaryReader reader, Type typeToConvert, BinarySerializerOptions options, ref ReadStack state, out ReferenceID refId, out T value)
        {
            //if (state.Current.BinaryPropertyInfo != null && state.Current.BinaryPropertyInfo.ClassType != ClassType)
            //{
            //    // TODO
            //    throw new Exception();
            //}else if(state.Current.BinaryPropertyInfo == null && state.Current.BinaryClassInfo!=null && state.Current.BinaryClassInfo.ClassType != ClassType)
            //{
            //    throw new Exception();
            //}
            refId = default;

            if (ClassType == ClassType.Value)
            {
                // A value converter should never be within a continuation.
                //Debug.Assert(!state.IsContinuation);

                // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                if (reader.TokenType == BinaryTokenType.Null && !HandleNullOnRead)
                {
                    if (!CanBeNull)
                    {
                        ThrowHelper.ThrowBinaryException_DeserializeUnableToConvertValue(TypeToConvert);
                    }

                    value = default;
                    return(true);
                }

                if (reader.CurrentTypeInfo.Type == TypeEnum.Nullable ||
                    // 当Nullable读取需要请求更多数据时,通过此判断进入
                    //(此时Converter可能已经读取了Nullable的实际类型,reader的当前类型信息已经发生了变化)
                    (state.Current.BinaryClassInfo != null &&
                     state.Current.PropertyState > StackFramePropertyState.None &&
                     state.Current.BinaryPropertyInfo != null &&
                     state.TypeMap.GetTypeInfo(state.Current.BinaryPropertyInfo.TypeSeq).Type == TypeEnum.Nullable))
                {
                    state.Push(reader.CurrentTypeInfo);
                    bool isSuccess = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
                    state.Pop(isSuccess);
                    return(isSuccess);
                }

                int readCount = GetBytesCount(ref reader, options);
                // 读取指定数量的字节
                if (readCount > 0)
                {
                    if (!reader.ReadBytes(readCount))
                    {
                        value = default;
                        return(false);
                    }
                }
                else if (readCount == BinarySerializerConstants.BytesCount_Dynamic)
                {
                    if (!reader.ReadBytes())
                    {
                        value = default;
                        return(false);
                    }
                }
                else if (readCount == BinarySerializerConstants.BytesCount_Auto)
                {
                    // 自动
                    bool isContinue = !reader.TryReadValue(out bool isOk);
                    if (!isOk)
                    {
                        ThrowHelper.ThrowBinaryException();
                    }
                    else if (isContinue)
                    {
                        value = default;
                        return(false);
                    }
                }


                // #if !DEBUG
                // For performance, only perform validation on internal converters on debug builds.
                if (IsInternalConverter)
                {
                    value = Read(ref reader, typeToConvert, options);
                }
                else
                // #endif
                {
                    BinaryTokenType originalPropertyTokenType = reader.TokenType;
                    // int originalPropertyDepth = reader.CurrentDepth;
                    long originalPropertyBytesConsumed = reader.BytesConsumed;
                    value = Read(ref reader, typeToConvert, options);

                    //VerifyRead(
                    //    originalPropertyTokenType,
                    //    originalPropertyDepth,
                    //    originalPropertyBytesConsumed,
                    //    isValueConverter: true,
                    //    ref reader);
                }

                //if (CanBePolymorphic && options.ReferenceHandler != null && value is BinaryElement element)
                //{
                //    // Edge case where we want to lookup for a reference when parsing into typeof(object)
                //    // instead of return `value` as a BinaryElement.
                //    Debug.Assert(TypeToConvert == typeof(object));

                //    if (BinarySerializer.TryGetReferenceFromBinaryElement(ref state, element, out object? referenceValue))
                //    {
                //        value = (T?)referenceValue;
                //    }
                //}

                return(true);
            }

            bool success;
            bool wasContinuation = state.IsContinuation;

            if (!wasContinuation && reader.TokenType == BinaryTokenType.Null && state.Current.ObjectState < StackFrameObjectState.CreatedObject)
            {
                value = default;
                return(true);
            }

            // Remember if we were a continuation here since Push() may affect IsContinuation.


            // Console.WriteLine(reader.CurrentTypeInfo);
            //  if (!isPolymorphic)
            // {
            state.Push(reader.CurrentTypeInfo);
            //  }

            //if (CanBePolymorphic)
            //{
            //    Type type = state.TypeMap.GetType((state.Current.PolymorphicBinaryTypeInfo?? state.Current.BinaryTypeInfo).Seq);
            //    if (type != TypeToConvert)
            //    {
            //        // state.Current
            //        var binaryConverter = state.Current.InitializeReEntry(type, options);
            //        if (binaryConverter != this)
            //        {
            //            // We found a different converter; forward to that.
            //            if (binaryConverter.TryReadAsObject(ref reader, options, ref state, out object tmpValue))
            //            {
            //                value = (T)tmpValue;
            //                return true;
            //            }
            //            else
            //            {
            //                value = default;
            //                return false;
            //            }
            //        }
            //    }
            //    else
            //    {

            //    }
            //}

            // For performance, only perform validation on internal converters on debug builds.
            if (IsInternalConverter)
            {
                if (reader.TokenType == BinaryTokenType.Null && !HandleNullOnRead && !wasContinuation)
                {
                    if (!CanBeNull)
                    {
                        ThrowHelper.ThrowBinaryException_DeserializeUnableToConvertValue(TypeToConvert);
                    }

                    // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                    value   = default;
                    success = true;
                }
                else
                {
                    success = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
                }
            }
            else
            {
                if (!wasContinuation)
                {
                    // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                    if (reader.TokenType == BinaryTokenType.Null && !HandleNullOnRead)
                    {
                        if (!CanBeNull)
                        {
                            ThrowHelper.ThrowBinaryException_DeserializeUnableToConvertValue(TypeToConvert);
                        }

                        value = default;
                        state.Pop(true);
                        return(true);
                    }

                    Debug.Assert(state.Current.OriginalTokenType == BinaryTokenType.None);
                    state.Current.OriginalTokenType = reader.TokenType;

                    Debug.Assert(state.Current.OriginalDepth == 0);
                    // state.Current.OriginalDepth = reader.CurrentDepth;
                }

                success = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
                if (success)
                {
                    if (state.IsContinuation)
                    {
                        // The resumable converter did not forward to the next converter that previously returned false.
                        ThrowHelper.ThrowBinaryException_SerializationConverterRead(this);
                    }

                    VerifyRead(
                        state.Current.OriginalTokenType,
                        state.Current.OriginalDepth,
                        bytesConsumed: 0,
                        isValueConverter: false,
                        ref reader);

                    // No need to clear state.Current.* since a stack pop will occur.
                }
            }

            if (success && state.Current.RefState == RefState.Start)
            {
                refId = (ReferenceID)state.Current.ReturnValue;
            }
            //  if (!isPolymorphic)
            //   {
            state.Pop(success);
            //  }

            return(success);
        }
 internal void WriteStart(BinaryTokenType tokenType)
 {
     if (CurrentDepth >= BinarySerializerConstants.MaxWriterDepth)
     {
         ThrowHelper.ThrowInvalidOperationException(ExceptionResource.DepthTooLarge, _currentDepth, token: default, tokenType: default);