public ComponentVisitor(GameObject gameObject, UnsafeValueView view, List <DeserializationEvent> events,
                         SerializationMetadata metadata) : base(metadata)
 {
     SetView(view);
     SetEvents(events);
     m_CustomTypeConstructor = new ComponentTypeConstructor(gameObject, GenericTypeConstructor, metadata);
 }
Beispiel #2
0
        static bool TryDeserializeAdapter <TValue>(IJsonAdapter adapter, UnsafeValueView view, ref TValue value, List <DeserializationEvent> events)
        {
            if (adapter is IJsonAdapter <TValue> typed)
            {
                try
                {
                    value = typed.Deserialize(view.AsSafe());
                }
                catch (Exception e)
                {
                    events.Add(new DeserializationEvent(EventType.Exception, e));
                }
                return(true);
            }

            if (adapter is Adapters.Contravariant.IJsonAdapter <TValue> typedContravariant)
            {
                try
                {
                    // @TODO Type checking on return value.
                    value = (TValue)typedContravariant.Deserialize(view.AsSafe());
                }
                catch (Exception e)
                {
                    events.Add(new DeserializationEvent(EventType.Exception, e));
                }
                return(true);
            }

            return(false);
        }
Beispiel #3
0
        internal void ReadValueWithAdapters <TValue>(ref TValue value, UnsafeValueView view, JsonAdapterCollection.Enumerator adapters, bool isRoot = false)
        {
            while (adapters.MoveNext())
            {
                switch (adapters.Current)
                {
                case IJsonAdapter <TValue> typed:
                    try
                    {
                        value = typed.Deserialize(new JsonDeserializationContext <TValue>(this, adapters, view, isRoot));
                    }
                    catch (Exception e)
                    {
                        m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, e));
                    }
                    return;

                case Adapters.Contravariant.IJsonAdapter <TValue> typedContravariant:
                    try
                    {
                        // NOTE: Boxing
                        value = (TValue)typedContravariant.Deserialize((IJsonDeserializationContext) new JsonDeserializationContext <TValue>(this, adapters, view, isRoot));
                    }
                    catch (Exception e)
                    {
                        m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, e));
                    }
                    return;
                }
            }

            ReadValueWithoutAdapters(ref value, view, isRoot);
        }
Beispiel #4
0
 internal JsonDeserializationContext(JsonPropertyReader visitor, JsonAdapterCollection.Enumerator adapters, UnsafeValueView view, bool isRoot)
 {
     m_Visitor  = visitor;
     m_Adapters = adapters;
     m_View     = view;
     m_IsRoot   = isRoot;
 }
Beispiel #5
0
 public SceneVisitor(Transform sceneRoot, UnsafeValueView view, List <DeserializationEvent> events,
                     JsonSerializationParameters parameters, SerializationMetadata metadata) : base(metadata)
 {
     SetView(view);
     SetEvents(events);
     m_Events     = events;
     m_SceneRoot  = sceneRoot;
     m_Parameters = parameters;
 }
 public GameObjectVisitor(UnsafeValueView view, List <DeserializationEvent> events, SerializationMetadata metadata,
                          Transform parent, GameObjectContainer prefabRoot, JsonSerializationParameters parameters) : base(metadata)
 {
     SetView(view);
     SetEvents(events);
     m_Events     = events;
     m_Parameters = parameters;
     m_Parent     = parent;
     m_PrefabRoot = prefabRoot;
 }
            MissingComponent CreateMissingComponent(UnsafeValueView view)
            {
                var missingBehaviour = m_GameObject.AddComponent <MissingComponent>();

                var value   = new JsonObject();
                var visitor = new JsonSceneReader(m_SerializationMetadata);

                visitor.SetView(view);
                PropertyContainer.Visit(ref value, visitor);
                missingBehaviour.JsonString = JsonSerialization.ToJson(value);
                return(missingBehaviour);
            }
Beispiel #8
0
        internal 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)
            {
                ReadValueWithAdapters(ref value, view, m_Adapters.GetEnumerator(), isRoot);
            }
            else
            {
                ReadValueWithoutAdapters(ref value, view, isRoot);
            }
        }
Beispiel #9
0
        public bool TryDeserialize <TValue>(UnsafeValueView view, ref TValue value, List <DeserializationEvent> events)
        {
            if (null != UserDefined && UserDefined.Count > 0)
            {
                foreach (var adapter in UserDefined)
                {
                    if (TryDeserializeAdapter(adapter, view, ref value, events))
                    {
                        return(true);
                    }
                }
            }

            if (null != Global && Global.Count > 0)
            {
                foreach (var adapter in Global)
                {
                    if (TryDeserializeAdapter(adapter, view, ref value, events))
                    {
                        return(true);
                    }
                }
            }

            if (TryDeserializeAdapter(InternalAdapter, view, ref value, events))
            {
                return(true);
            }

#if UNITY_EDITOR
            if (TryDeserializeLazyLoadReference(view.AsSafe(), ref value, events))
            {
                return(true);
            }
#endif

            return(false);
        }
Beispiel #10
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;
            }
            }
        }
Beispiel #11
0
 internal UnsafeViewScope CreateViewScope(UnsafeValueView view)
 => new UnsafeViewScope(this, view);
Beispiel #12
0
 public void SetView(UnsafeValueView view)
 => m_View = view;
Beispiel #13
0
 public UnsafeViewScope(JsonPropertyReader visitor, UnsafeValueView view)
 {
     m_View           = visitor.m_View;
     m_Visitor        = visitor;
     m_Visitor.m_View = view;
 }
        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;
            }
            }
        }
            public object Construct(Type type, UnsafeValueView view)
            {
                if (type != typeof(Component) || m_GameObject == null)
                {
                    return(null);
                }

                try
                {
                    var componentType = m_GenericConstructor.GetSerializedType();
                    if (componentType == null)
                    {
                        return(null);
                    }

#if !NET_DOTS && !ENABLE_IL2CPP
                    SceneSerialization.RegisterPropertyBag(componentType);
#endif

                    var properties = PropertyBagStore.GetPropertyBag(componentType);
                    if (properties == null)
                    {
                        Debug.LogWarning($"Could not resolve component type {componentType} deserializing {m_GameObject.name}. Will preserve serialized contents as JSON string");
                        return(CreateMissingComponent(view));
                    }

                    if (componentType == typeof(MissingComponent))
                    {
                        try
                        {
                            var value   = new JsonObject();
                            var visitor = new JsonSceneReader(m_SerializationMetadata);
                            visitor.SetView(view);
                            PropertyContainer.Visit(ref value, visitor);
                            var jsonString = value[nameof(MissingComponent.JsonString)].ToString();

                            // For some reason, newlines are read as null characters which break parsing
                            jsonString = jsonString.Replace('\0', '\n');

                            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
                            {
                                using (var reader = new SerializedObjectReader(stream))
                                {
                                    reader.Read(out var document);
                                    var componentVisitor = new ComponentVisitor(m_GameObject, document.AsUnsafe(),
                                                                                null, m_SerializationMetadata);

                                    Component missingComponent = null;
                                    componentVisitor.ReadValue(ref missingComponent, document.AsUnsafe());
                                    return(missingComponent);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Debug.Log($"Encountered an exception trying to deserialize MissingComponent. Preserving it as-is. Exception follows:\n{e}");
                        }
                    }

                    return(componentType == typeof(Transform) ? m_GameObject.GetComponent <Transform>() : m_GameObject.AddComponent(componentType));
                }
                catch (ArgumentException)
                {
                    Debug.LogWarning($"Could not resolve component type deserializing {m_GameObject.name}. Will preserve serialized contents as JSON string");
                    return(CreateMissingComponent(view));
                }
            }
Beispiel #16
0
        protected void ReadValue <TValue>(ref TValue value, UnsafeValueView view, bool isRoot = false)
        {
            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 if (value is long)
                    {
                        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;

                try
                {
                    var customValue = m_CustomTypeConstructor?.Construct(typeof(TValue), view);
                    if (customValue != null)
                    {
                        value = (TValue)customValue;
                    }

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

                using (new SerializedContainerMetadataScope(this, metadata))
                    using (new UnsafeViewScope(this, view))
                    {
                        var type = value?.GetType();
#if !NET_DOTS && !ENABLE_IL2CPP
                        if (type != null)
                        {
                            SceneSerialization.RegisterPropertyBag(type);
                        }
#endif

                        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(type);

                            case VisitErrorCode.MissingPropertyBag:
                                throw new MissingPropertyBagException(type);

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

                break;
            }
            }
        }