/// <summary>
 /// Initializes a new instance of the <see cref="JsonMigrationContext"/> structure. This is an internal method.
 /// </summary>
 /// <param name="serializedVersion">The serialized version read from the stream.</param>
 /// <param name="serializedObject">The view over the serialized data.</param>
 /// <param name="serializedType">The serialized type from the stream.</param>
 /// <param name="visitor">The current deserialization visitor, used for re-entry into normal deserialization.</param>
 internal JsonMigrationContext(int serializedVersion, SerializedObjectView serializedObject, Type serializedType, JsonPropertyReader visitor)
 {
     SerializedVersion = serializedVersion;
     SerializedObject  = serializedObject;
     SerializedType    = serializedType;
     m_Visitor         = visitor;
 }
        public bool TryMigrate <TValue>(UnsafeObjectView view, out TValue value, JsonPropertyReader reader, List <DeserializationEvent> events)
        {
            var migration = GetMigrationForType <TValue>(out var version);

            if (null == migration)
            {
                value = default;
                return(false);
            }

            var serializedVersion = 0;

            if (view.TryGetValue(JsonPropertyVisitor.k_SerializedVersionKey, out var serializedVersionView))
            {
                if (serializedVersionView.Type != TokenType.Primitive)
                {
                    events.Add(new DeserializationEvent(EventType.Exception, new Exception($"An error occured while deserializing Type=[{typeof(TValue)}]. Property=[{JsonPropertyVisitor.k_SerializedVersionKey}] is expected to be an int value.")));
                    value = default;
                    return(false);
                }

                serializedVersion = serializedVersionView.AsInt32();

                if (version == serializedVersion)
                {
                    value = default;
                    return(false);
                }
            }

            var context = new JsonMigrationContext(serializedVersion, view.AsSafe(), typeof(TValue), UserData, reader);

            switch (migration)
            {
            case IJsonMigration <TValue> typed:
                value = typed.Migrate(context);
                break;

            case Contravariant.IJsonMigration <TValue> typedContravariant:
                value = (TValue)typedContravariant.Migrate(context);
                break;

            default:
                throw new Exception("An internal error has occured.");
            }

            return(true);
        }