Exemple #1
0
        internal void ReadValueWithoutAdapters <TValue>(ref TValue value, UnsafeValueView view, bool isRoot = false)
        {
#if UNITY_EDITOR
            if (RuntimeTypeInfoCache <TValue> .IsLazyLoadReference && view.Type == TokenType.String)
            {
                var json = view.AsStringView().ToString();

                if (json == s_EmptyGlobalObjectId) // Workaround issue where GlobalObjectId.TryParse returns false for empty GlobalObjectId
                {
                    return;
                }

                if (UnityEditor.GlobalObjectId.TryParse(json, out var id))
                {
                    var instanceID = UnityEditor.GlobalObjectId.GlobalObjectIdentifierToInstanceIDSlow(id);
                    PropertyContainer.SetValue(ref value, "m_InstanceID", instanceID);
                    return;
                }

                m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Error, $"An error occured while deserializing asset reference Value=[{json}]."));
                return;
            }
#endif

            switch (view.Type)
            {
            case TokenType.String:
            {
                var v = view.AsStringView().ToString();
                TypeConversion.TryConvert(ref v, out value);
                break;
            }

            case TokenType.Primitive:
            {
                var p = view.AsPrimitiveView();

                if (p.IsIntegral())
                {
                    if (p.IsSigned())
                    {
                        var v = p.AsInt64();
                        TypeConversion.TryConvert(ref v, out value);
                    }
                    else
                    {
                        var v = p.AsUInt64();
                        TypeConversion.TryConvert(ref v, out value);
                    }
                }
                else if (p.IsDecimal() || p.IsInfinity() || p.IsNaN())
                {
                    var v = p.AsFloat();
                    TypeConversion.TryConvert(ref v, out value);
                }
                else if (p.IsBoolean())
                {
                    var v = p.AsBoolean();
                    TypeConversion.TryConvert(ref v, out value);
                }
                else if (p.IsNull())
                {
                    value = default;
                }

                break;
            }

            default:
            {
                var metadata = view.Type == TokenType.Object ? GetSerializedContainerMetadata(view.AsObjectView()) : default;

                m_SerializedTypeProvider.View           = view;
                m_SerializedTypeProvider.SerializedType = isRoot ? m_SerializedType : null;

                if (RuntimeTypeInfoCache <TValue> .IsNullable)
                {
                    m_SerializedTypeProvider.SerializedType = Nullable.GetUnderlyingType(typeof(TValue));
                }

                if (metadata.IsSerializedReference)
                {
                    if (null == m_SerializedReferences)
                    {
                        m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, new Exception("Deserialization encountered a serialized object reference while running with DisableSerializedReferences.")));
                        return;
                    }

                    value = (TValue)m_SerializedReferences.GetDeserializedReference(metadata.SerializedId);
                    return;
                }

                try
                {
                    DefaultTypeConstruction.Construct(ref value, m_SerializedTypeProvider);
                }
                catch (ArgumentException e)
                {
                    m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, new ArgumentException(e.Message)));
                    return;
                }

                if (metadata.HasSerializedId)
                {
                    // This call is harmless to skip if we don't have serialized references.
                    m_SerializedReferences?.AddDeserializedReference(metadata.SerializedId, value);
                }

                using (new SerializedContainerMetadataScope(this, metadata))
                    using (new UnsafeViewScope(this, view))
                    {
                        if (RuntimeTypeInfoCache <TValue> .IsNullable)
                        {
                            // Unpack Nullable<T> as T
                            var underlyingType  = Nullable.GetUnderlyingType(typeof(TValue));
                            var underlyingValue = System.Convert.ChangeType(value, underlyingType);

                            if (!PropertyContainer.TryAccept(this, ref underlyingValue, out var errorCode))
                            {
                                switch (errorCode)
                                {
                                case VisitErrorCode.NullContainer:
                                    throw new ArgumentNullException(nameof(value));

                                case VisitErrorCode.InvalidContainerType:
                                    throw new InvalidContainerTypeException(value.GetType());

                                case VisitErrorCode.MissingPropertyBag:
                                    throw new MissingPropertyBagException(value.GetType());

                                default:
                                    throw new Exception($"Unexpected {nameof(VisitErrorCode)}=[{errorCode}]");
                                }
                            }

                            // Repack the T as Nullable<T>
                            value = (TValue)underlyingValue;
                        }
                        else
                        {
                            if (!PropertyContainer.TryAccept(this, ref value, out var errorCode))
                            {
                                switch (errorCode)
                                {
                                case VisitErrorCode.NullContainer:
                                    throw new ArgumentNullException(nameof(value));

                                case VisitErrorCode.InvalidContainerType:
                                    throw new InvalidContainerTypeException(value.GetType());

                                case VisitErrorCode.MissingPropertyBag:
                                    throw new MissingPropertyBagException(value.GetType());

                                default:
                                    throw new Exception($"Unexpected {nameof(VisitErrorCode)}=[{errorCode}]");
                                }
                            }
                        }
                    }

                break;
            }
            }
        }
        void ReadValue <TValue>(ref TValue value, bool isRoot = false)
        {
            var runAdapters = !(isRoot && m_DisableRootAdapters);

            if (runAdapters && m_Adapters.TryDeserialize(m_Stream, ref value))
            {
                return;
            }

            if (RuntimeTypeInfoCache <TValue> .IsEnum)
            {
                BinarySerialization.ReadPrimitiveUnsafe(m_Stream, ref value, Enum.GetUnderlyingType(typeof(TValue)));
                return;
            }

            var token = default(byte);

            if (RuntimeTypeInfoCache <TValue> .CanBeNull)
            {
                token = m_Stream->ReadNext <byte>();

                switch (token)
                {
                case k_TokenNull:
                    value = default;
                    return;

                case k_TokenSerializedReference:
                    var id = m_Stream->ReadNext <int>();
                    if (null == m_SerializedReferences)
                    {
                        throw new Exception("Deserialization encountered a serialized object reference while running with DisableSerializedReferences.");
                    }
                    value = (TValue)m_SerializedReferences.GetDeserializedReference(id);
                    return;
                }
            }

            if (RuntimeTypeInfoCache <TValue> .IsNullable)
            {
                BinarySerialization.ReadPrimitiveBoxed(m_Stream, ref value, Nullable.GetUnderlyingType(typeof(TValue)));
                return;
            }

#if !UNITY_DOTSPLAYER
            if (runAdapters && token == k_TokenUnityEngineObjectReference)
            {
                var unityEngineObject = default(UnityEngine.Object);
                m_Adapters.TryDeserialize(m_Stream, ref unityEngineObject);
                value = (TValue)(object)unityEngineObject;
                return;
            }
#endif

            if (token == k_TokenPolymorphic)
            {
                m_Stream->ReadNext(out var assemblyQualifiedTypeName);

                if (string.IsNullOrEmpty(assemblyQualifiedTypeName))
                {
                    throw new ArgumentException();
                }

                var concreteType = Type.GetType(assemblyQualifiedTypeName);

                if (null == concreteType)
                {
                    if (FormerNameAttribute.TryGetCurrentTypeName(assemblyQualifiedTypeName, out var currentAssemblyQualifiedTypeName))
                    {
                        concreteType = Type.GetType(currentAssemblyQualifiedTypeName);
                    }

                    if (null == concreteType)
                    {
                        throw new ArgumentException();
                    }
                }

                m_SerializedTypeProviderSerializedType = concreteType;
            }
            else
            {
                // If we have a user provided root type pass it to the type construction.
                m_SerializedTypeProviderSerializedType = isRoot ? m_SerializedType : null;
            }

            DefaultTypeConstruction.Construct(ref value, this);

            if (RuntimeTypeInfoCache <TValue> .IsObjectType && !RuntimeTypeInfoCache.IsContainerType(value.GetType()))
            {
                BinarySerialization.ReadPrimitiveBoxed(m_Stream, ref value, value.GetType());
                return;
            }

            if (!PropertyContainer.Visit(ref value, this, out var errorCode))
            {
                switch (errorCode)
                {
                case VisitErrorCode.NullContainer:
                    throw new ArgumentNullException(nameof(value));

                case VisitErrorCode.InvalidContainerType:
                    throw new InvalidContainerTypeException(value.GetType());

                case VisitErrorCode.MissingPropertyBag:
                    throw new MissingPropertyBagException(value.GetType());

                default:
                    throw new Exception($"Unexpected {nameof(VisitErrorCode)}=[{errorCode}]");
                }
            }
        }
        void ReadValue <TValue>(ref TValue value, UnsafeValueView view, bool isRoot = false)
        {
            var runAdapters = !(isRoot && m_DisableRootAdapters);

            // Special check so we have higher perf for primitives.
            if (runAdapters && !RuntimeTypeInfoCache <TValue> .IsPrimitiveOrString)
            {
                if (m_Adapters.TryDeserialize(view, ref value, m_SerializedTypeProvider.Events))
                {
                    return;
                }
            }

            switch (view.Type)
            {
            case TokenType.String:
            {
                TypeConversion.TryConvert(view.AsStringView().ToString(), out value);
                break;
            }

            case TokenType.Primitive:
            {
                var p = view.AsPrimitiveView();

                if (p.IsIntegral())
                {
                    if (p.IsSigned())
                    {
                        TypeConversion.TryConvert(p.AsInt64(), out value);
                    }
                    else
                    {
                        TypeConversion.TryConvert(p.AsUInt64(), out value);
                    }
                }
                else if (p.IsDecimal() || p.IsInfinity() || p.IsNaN())
                {
                    TypeConversion.TryConvert(p.AsFloat(), out value);
                }
                else if (p.IsBoolean())
                {
                    TypeConversion.TryConvert(p.AsBoolean(), out value);
                }
                else if (p.IsNull())
                {
                    value = default;
                }

                break;
            }

            default:
            {
                var metadata = view.Type == TokenType.Object ? GetSerializedContainerMetadata(view.AsObjectView()) : default;

                m_SerializedTypeProvider.View           = view;
                m_SerializedTypeProvider.SerializedType = isRoot ? m_SerializedType : null;

                if (metadata.IsSerializedReference)
                {
                    if (null == m_SerializedReferences)
                    {
                        m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, new Exception("Deserialization encountered a serialized object reference while running with DisableSerializedReferences.")));
                        return;
                    }

                    value = (TValue)m_SerializedReferences.GetDeserializedReference(metadata.SerializedId);
                    return;
                }

                try
                {
                    DefaultTypeConstruction.Construct(ref value, m_SerializedTypeProvider);
                }
                catch (ArgumentException e)
                {
                    m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, new ArgumentException(e.Message)));
                    return;
                }

                if (metadata.HasSerializedId)
                {
                    // This call is harmless to skip if we don't have serialized references.
                    m_SerializedReferences?.AddDeserializedReference(metadata.SerializedId, value);
                }

                using (new SerializedContainerMetadataScope(this, metadata))
                    using (new UnsafeViewScope(this, view))
                    {
                        if (!PropertyContainer.Visit(ref value, this, out var errorCode))
                        {
                            switch (errorCode)
                            {
                            case VisitErrorCode.NullContainer:
                                throw new ArgumentNullException(nameof(value));

                            case VisitErrorCode.InvalidContainerType:
                                throw new InvalidContainerTypeException(value.GetType());

                            case VisitErrorCode.MissingPropertyBag:
                                throw new MissingPropertyBagException(value.GetType());

                            default:
                                throw new Exception($"Unexpected {nameof(VisitErrorCode)}=[{errorCode}]");
                            }
                        }
                    }

                break;
            }
            }
        }
        internal void ReadValueWithoutAdapters <TValue>(ref TValue value, bool isRoot)
        {
            if (RuntimeTypeInfoCache <TValue> .IsEnum)
            {
                BinarySerialization.ReadPrimitiveUnsafe(m_Stream, ref value, Enum.GetUnderlyingType(typeof(TValue)));
                return;
            }

            var token = default(byte);

            if (RuntimeTypeInfoCache <TValue> .CanBeNull)
            {
                token = m_Stream->ReadNext <byte>();

                switch (token)
                {
                case k_TokenNull:
                    value = default;
                    return;

                case k_TokenSerializedReference:
                    var id = m_Stream->ReadNext <int>();
                    if (null == m_SerializedReferences)
                    {
                        throw new Exception("Deserialization encountered a serialized object reference while running with DisableSerializedReferences.");
                    }
                    value = (TValue)m_SerializedReferences.GetDeserializedReference(id);
                    return;
                }
            }

            if (RuntimeTypeInfoCache <TValue> .IsNullable)
            {
                var underlyingType = Nullable.GetUnderlyingType(typeof(TValue));

                if (RuntimeTypeInfoCache.IsContainerType(underlyingType))
                {
                    m_SerializedTypeProviderSerializedType = underlyingType;
                    DefaultTypeConstruction.Construct(ref value, this);

                    var underlyingValue = Convert.ChangeType(value, underlyingType);

                    if (!PropertyContainer.TryAccept(this, ref underlyingValue, out var errorCode))
                    {
                        switch (errorCode)
                        {
                        case VisitErrorCode.NullContainer:
                            throw new ArgumentNullException(nameof(value));

                        case VisitErrorCode.InvalidContainerType:
                            throw new InvalidContainerTypeException(value.GetType());

                        case VisitErrorCode.MissingPropertyBag:
                            throw new MissingPropertyBagException(value.GetType());

                        default:
                            throw new Exception($"Unexpected {nameof(VisitErrorCode)}=[{errorCode}]");
                        }
                    }

                    // Repack the T as Nullable<T>
                    value = (TValue)underlyingValue;
                }
                else
                {
                    BinarySerialization.ReadPrimitiveBoxed(m_Stream, ref value, Nullable.GetUnderlyingType(typeof(TValue)));
                }
                return;
            }

#if !UNITY_DOTSPLAYER
            if (!(isRoot && m_DisableRootAdapters) && token == k_TokenUnityEngineObjectReference)
            {
                value = (TValue)(m_Adapters.Internal as Adapters.Contravariant.IBinaryAdapter <UnityEngine.Object>).Deserialize(new BinaryDeserializationContext <TValue>(this, default, isRoot));;