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}]"); } } }
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));;