Exemple #1
0
        // Returns: Whether the sub-type was converted in here and we should return now.
        void SerializeActualType(object obj, SaveInheritanceAttribute info, Type baseType, Type actualType, ref BitTarget header)
        {
            switch (info.Mode)
            {
            case SaveInheritanceMode.Index:
                if (!TryWriteListInheritance(info, actualType, false, ref header))
                {
                    throw new UnsupportedSubTypeException(baseType, actualType);
                }

                break;

            case SaveInheritanceMode.Key:
                WriteKeyInheritance(info, baseType, actualType, ref header);

                break;

            case SaveInheritanceMode.IndexOrKey:
                if (!TryWriteListInheritance(info, actualType, true, ref header))
                {
                    header.WriteBitOff();
                    WriteKeyInheritance(info, baseType, actualType, ref header);
                }

                break;
            }

            // Serialize the actual type now.
            SerializeItemNoSetup(obj, GetRuntimeMapItem(actualType), ref header, true);
        }
Exemple #2
0
        public static void EnsureHasAllTypeCache(Type type, SaveInheritanceAttribute info)
        {
            lock (info)
            {
                // Just use one of them to see if the cache is valid or not.
                if (info.HasGeneratedFullKeyCache)
                {
                    return;
                }

                KeyedSubTypeInfo[]? keyedInfo = GetKeyedSubTypesFor(type);

                // We'll also fill in the serialize cache since we've now gone through all the types.
                info.KeySerializeCache   = new Dictionary <Type, string>(keyedInfo.Length);
                info.KeyDeserializeCache = new Dictionary <string, Type>(keyedInfo.Length);

                for (int i = 0; i < keyedInfo.Length; i++)
                {
                    KeyedSubTypeInfo currentInfo = keyedInfo[i];

                    info.KeySerializeCache.Add(currentInfo.Type, currentInfo.Key);
                    info.KeyDeserializeCache.Add(currentInfo.Key, currentInfo.Type);
                }

                info.HasGeneratedFullKeyCache = true;
            }
        }
Exemple #3
0
        public static string GetOrAddTypeKeyFromCache(Type baseType, Type type, SaveInheritanceAttribute info)
        {
            lock (info)
            {
                // Try to get it from the cache.
                if (info.KeySerializeCache != null && info.KeySerializeCache.TryGetValue(type, out string?val))
                {
                    return(val);
                }

                Debug.Assert(!info.HasGeneratedFullKeyCache);

                // If it's not in the cache, get and add it now.
                SaveInheritanceKeyAttribute?attribute = type.GetCustomAttribute <SaveInheritanceKeyAttribute>(false);
                if (attribute == null)
                {
                    throw new UnsupportedSubTypeException(baseType, type);
                }

                info.KeySerializeCache ??= new Dictionary <Type, string>(1);
                info.KeySerializeCache.Add(type, attribute.Key);

                info.KeyDeserializeCache ??= new Dictionary <string, Type>(1);
                info.KeyDeserializeCache.Add(attribute.Key, type);

                return(attribute.Key);
            }
        }
        public void EnsureHasAllTypeCache_Existing()
        {
            SaveInheritanceAttribute attribute = typeof(KeyBase).GetCustomAttribute <SaveInheritanceAttribute>();

            // Simulate it having already been done.
            attribute.HasGeneratedFullKeyCache = true;

            KeyInheritanceHandler.EnsureHasAllTypeCache(typeof(KeyBase), attribute);

            // Since nothing has actually been done these will just be null.
            Assert.IsNull(attribute.KeySerializeCache);
            Assert.IsNull(attribute.KeyDeserializeCache);
        }
Exemple #5
0
        bool TryWriteListInheritance(SaveInheritanceAttribute info, Type actualType, bool writeOnIfSuccessful, ref BitTarget header)
        {
            if (info.IndexSerializeCache !.TryGetValue(actualType, out uint pos))
            {
                if (writeOnIfSuccessful)
                {
                    header.WriteBitOn();
                }
                WriteCompressedInt(pos, ref header);
                return(true);
            }

            return(false);
        }
        public void GetOrAddTypeKeyFromCache_New()
        {
            SaveInheritanceAttribute attribute = typeof(KeyBase).GetCustomAttribute <SaveInheritanceAttribute>();

            string key = KeyInheritanceHandler.GetOrAddTypeKeyFromCache(typeof(KeyBase), typeof(KeySubFirst), attribute);

            Assert.AreEqual("First", key);

            Assert.AreEqual(1, attribute.KeySerializeCache.Count);
            Assert.AreEqual(1, attribute.KeyDeserializeCache.Count);

            Assert.AreEqual("First", attribute.KeySerializeCache[typeof(KeySubFirst)]);
            Assert.AreEqual(typeof(KeySubFirst), attribute.KeyDeserializeCache["First"]);
        }
Exemple #7
0
        // Returns: Whether the sub-type was converted in here and we should return now.
        object DeserializeActualType(SaveInheritanceAttribute info, Type baseType)
        {
            Type?actualType = info.Mode switch
            {
                SaveInheritanceMode.Index => TryReadListInheritance(info, baseType),
                SaveInheritanceMode.Key => TryReadKeyInheritance(info, baseType),
                SaveInheritanceMode.IndexOrKey => _currentHeader.ReadBit() ? TryReadListInheritance(info, baseType) : TryReadKeyInheritance(info, baseType),
                _ => throw new Exception("Invalid save inheritance mode")
            };

            if (actualType == null)
            {
                throw new InvalidSubTypeInfoException(baseType);
            }

            // Deserialize the actual type.
            return(DeserializeItemNoSetup(GetRuntimeMapItem(actualType), true));
        }

        Type?TryReadListInheritance(SaveInheritanceAttribute info, Type baseType)
        {
            uint key = ReadCompressedInt(ref _currentHeader);

            return(info.IndexDeserializeCache.GetValueOrDefault(key));
        }

        Type?TryReadKeyInheritance(SaveInheritanceAttribute info, Type baseType)
        {
            // Make sure the info is initialized for deserialization.
            KeyInheritanceHandler.EnsureHasAllTypeCache(baseType, info);

            // Read in the key from the source.
            string key = ReadString(ref _currentHeader);

            // See if there's an item with that key.
            return(info.KeyDeserializeCache !.GetValueOrDefault(key));
        }

        void EnsureReadHeader()
        {
            if (!_readHeader)
            {
                _currentHeader = new BitSource(this, 8);
                _readHeader    = true;
            }
        }
    }
        public void EnsureHasAllTypeCache_New_CrossAssembly()
        {
            SaveInheritanceAttribute attribute = typeof(KeyBase).GetCustomAttribute <SaveInheritanceAttribute>();

            KeyInheritanceHandler.EnsureHasAllTypeCache(typeof(OtherAssemblyBase), attribute);

            Assert.AreEqual(2, attribute.KeySerializeCache.Count);
            Assert.AreEqual(2, attribute.KeyDeserializeCache.Count);

            Assert.AreEqual("First", attribute.KeySerializeCache[typeof(OtherAssemblySub)]);
            Assert.AreEqual(typeof(OtherAssemblySub), attribute.KeyDeserializeCache["First"]);

            Assert.AreEqual("Second", attribute.KeySerializeCache[typeof(CrossAssemblySub)]);
            Assert.AreEqual(typeof(CrossAssemblySub), attribute.KeyDeserializeCache["Second"]);

            Assert.IsTrue(attribute.HasGeneratedFullKeyCache);
        }
        public void GetOrAddTypeKeyFromCache_Exists()
        {
            SaveInheritanceAttribute attribute = typeof(KeyBase).GetCustomAttribute <SaveInheritanceAttribute>();

            // Fill the cache up.
            var oldSerializeCache   = attribute.KeySerializeCache = new Dictionary <Type, string>();
            var oldDeserializeCache = attribute.KeyDeserializeCache = new Dictionary <string, Type>();

            oldSerializeCache.Add(typeof(KeySubFirst), "First");
            oldDeserializeCache.Add("First", typeof(KeySubFirst));

            string key = KeyInheritanceHandler.GetOrAddTypeKeyFromCache(typeof(KeyBase), typeof(KeySubFirst), attribute);

            Assert.AreEqual("First", key);

            // Ensure it didn't add to the cache.
            Assert.AreEqual(oldSerializeCache, attribute.KeySerializeCache);
            Assert.AreEqual(oldDeserializeCache, attribute.KeyDeserializeCache);

            Assert.AreEqual(1, attribute.KeySerializeCache.Count);
            Assert.AreEqual(1, attribute.KeyDeserializeCache.Count);
        }
Exemple #10
0
        void WriteKeyInheritance(SaveInheritanceAttribute info, Type baseType, Type actualType, ref BitTarget header)
        {
            string key = KeyInheritanceHandler.GetOrAddTypeKeyFromCache(baseType, actualType, info);

            WriteString(key, ref header);
        }