예제 #1
0
 public void Deserialize(byte[] buffer, ref int offset, ref RectOffset value)
 {
     value.left   = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
     value.right  = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
     value.top    = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
     value.bottom = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
 }
예제 #2
0
        public void Deserialize(byte[] buffer, ref int offset, ref AnimationCurve value)
        {
            // Read length
            var length = SerializerBinary.ReadInt32(buffer, ref offset);

            // Deserialize individual keyframes again
            var keys = new Keyframe[length];

            for (int i = 0; i < length; i++)
            {
                _keyframeFormatter.Deserialize(buffer, ref offset, ref keys[i]);
            }

            // Create or update the given AnimationCurve
            if (value == null)
            {
                value = new AnimationCurve(keys);
            }
            else
            {
                value.keys = keys;
            }

            // Set the wrap modes
            var wrap = default(WrapMode);

            _wrapModeFormatter.Deserialize(buffer, ref offset, ref wrap);
            value.preWrapMode = wrap;

            _wrapModeFormatter.Deserialize(buffer, ref offset, ref wrap);
            value.postWrapMode = wrap;
        }
예제 #3
0
 public void Serialize(ref byte[] buffer, ref int offset, RectOffset value)
 {
     SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, value.left);
     SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, value.right);
     SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, value.top);
     SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, value.bottom);
 }
예제 #4
0
        public void Deserialize <T>(ref T value, byte[] buffer, ref int offset, int expectedReadLength = -1)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("Must provide a buffer to deserialize from!");
            }

            EnterRecursive(RecursionMode.Deserialization);

            try
            {
                var formatter = (IFormatter <T>)GetGenericFormatter(typeof(T));

                int offsetBeforeRead = offset;

                if (Config.EmbedChecksum)
                {
                    var checksum = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
                    if (checksum != ProtocolChecksum.Checksum)
                    {
                        throw new InvalidOperationException($"Checksum does not match embedded checksum (Serializer={ProtocolChecksum.Checksum}, Data={checksum})");
                    }
                }

                formatter.Deserialize(buffer, ref offset, ref value);

                if (expectedReadLength != -1)
                {
                    int bytesActuallyRead = offset - offsetBeforeRead;

                    if (bytesActuallyRead != expectedReadLength)
                    {
                        throw new UnexpectedBytesConsumedException("The deserialization has completed, but not all of the given bytes were consumed. " +
                                                                   " Maybe you tried to deserialize something directly from a larger byte-array?",
                                                                   expectedReadLength, bytesActuallyRead, offsetBeforeRead, offset);
                    }
                }

                // todo: instead of clearing and re-adding the known types, the type-cache should have a fallback cache inside it
                // todo: .. that gets used when the ID is out of range. So outside is the dynamic stuff (with an offset of where IDs will start), and inside are the
                // todo: .. known elements, and if we're given an ID that is too low, we defer to the inner cache.
                // Very important to clear out caches and stuff that is only valid for this call
                if (!Config.PersistTypeCache)
                {
                    InstanceData.TypeCache.ClearDeserializationCache();
                    foreach (var t in Config.KnownTypes)
                    {
                        InstanceData.TypeCache.AddKnownType(t);
                    }
                }
                if (!Config.PersistObjectCache)
                {
                    InstanceData.ObjectCache.ClearDeserializationCache();
                }
            }
            finally
            {
                LeaveRecursive(RecursionMode.Deserialization);
            }
        }
예제 #5
0
        /// <summary>
        /// Use this overload whenever you can. The intention is that you reuse the serialization buffer so the serializer only has to resize/reallocate a newer (larger) one if there really is not enough space; instead of allocating an array for every Serialize() call, this lets you avoid GC-pressure.
        /// You *can* pass in null for 'targetByteArray' and let the serializer allocate one for you.
        /// </summary>
        public int Serialize <T>(T obj, ref byte[] buffer, int offset = 0)
        {
            EnterRecursive(RecursionMode.Serialization);

            if (buffer == null)
            {
                buffer = new byte[0x4000];                 // 16k
            }
            try
            {
                //
                // Root object is the IExternalObject we're serializing (if any)
                // We have to keep track of it so the CacheFormatter knows what NOT to skip
                // otherwise we'd obviously only write one byte lol (the external ID) and nothing else.
                InstanceData.CurrentRoot = obj as IExternalRootObject;


                //
                // The actual serialization
                int offsetBeforeWrite = offset;
                {
                    if (Config.Advanced.EmbedChecksum)
                    {
                        SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, ProtocolChecksum.Checksum);
                    }

                    var formatter = (IFormatter <T>)GetReferenceFormatter(typeof(T));
                    formatter.Serialize(ref buffer, ref offset, obj);
                }
                int offsetAfterWrite = offset;


                //
                // After we're done, we have to clear all our caches!
                // Only very rarely can we avoid that
                // todo: implement check-pointing inside the TypeDictionary itself
                if (!Config.Advanced.PersistTypeCache)
                {
                    InstanceData.TypeCache.ResetSerializationCache();
                }

                InstanceData.ObjectCache.ClearSerializationCache();

                int dataSize = offsetAfterWrite - offsetBeforeWrite;


                return(dataSize);
            }
            finally
            {
                //
                // Clear the root object again
                //InstanceData.WrittenSchemata.Clear();
                InstanceData.EncounteredSchemaTypes.Clear();
                InstanceData.CurrentRoot = null;

                LeaveRecursive(RecursionMode.Serialization);
            }
        }
예제 #6
0
        /// <summary>
        /// Use this overload whenever you can. The intention is that you reuse the serialization buffer so the serializer only has to resize/reallocate a newer (larger) one if there really is not enough space; instead of allocating an array for every Serialize() call, this lets you avoid GC-pressure.
        /// You *can* pass in null for 'targetByteArray' and let the serializer allocate one for you.
        /// </summary>
        public int Serialize <T>(T obj, ref byte[] targetByteArray, int offset = 0)
        {
            EnterRecursive(RecursionMode.Serialization);

            if (Config.EmbedChecksum)
            {
                SerializerBinary.WriteInt32Fixed(ref targetByteArray, ref offset, ProtocolChecksum.Checksum);
            }


            try
            {
                //
                // Root object is the IExternalObject we're serializing (if any)
                // We have to keep track of it so the CacheFormatter knows what NOT to skip
                // otherwise we'd obviously only write one byte lol (the external ID) and nothing else.
                InstanceData.CurrentRoot = obj as IExternalRootObject;


                var formatter = (IFormatter <T>)GetGenericFormatter(typeof(T));

                //
                // The actual serialization
                int offsetBeforeWrite = offset;
                formatter.Serialize(ref targetByteArray, ref offset, obj);
                int offsetAfterWrite = offset;


                //
                // After we're done, we probably have to clear all our caches!
                // Only very rarely can we avoid that
                // todo: would it be more efficient to have one static and one dynamic dictionary?
                if (!Config.PersistTypeCache)
                {
                    InstanceData.TypeCache.ClearSerializationCache();
                    foreach (var t in Config.KnownTypes)
                    {
                        InstanceData.TypeCache.RegisterObject(t);
                    }
                }

                if (!Config.PersistObjectCache)
                {
                    InstanceData.ObjectCache.ClearSerializationCache();
                }


                return(offsetAfterWrite - offsetBeforeWrite);
            }
            finally
            {
                //
                // Clear the root object again
                LeaveRecursive(RecursionMode.Serialization);
            }
        }
예제 #7
0
        public void Serialize(ref byte[] buffer, ref int offset, AnimationCurve value)
        {
            var keys = value.keys;

            // Length
            SerializerBinary.WriteInt32(ref buffer, ref offset, keys.Length);
            // Keyframes
            for (int i = 0; i < keys.Length; i++)
            {
                _keyframeFormatter.Serialize(ref buffer, ref offset, keys[i]);
            }

            _wrapModeFormatter.Serialize(ref buffer, ref offset, value.preWrapMode);
            _wrapModeFormatter.Serialize(ref buffer, ref offset, value.postWrapMode);
        }
예제 #8
0
 public void Deserialize(byte[] buffer, ref int offset, ref LayerMask value)
 {
     value.value = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
 }
예제 #9
0
 public void Serialize(ref byte[] buffer, ref int offset, LayerMask value)
 {
     SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, value.value);
 }
예제 #10
0
        /// <summary>
        /// The most advanced deserialize method.
        /// <para>Again, you can put in an existing object to populate (or a variable that's currently null, in which case Ceras creates an object for you)</para>
        /// <para>In this version you can put in the offset as well, telling Ceras where to start reading from inside the buffer.</para>
        /// <para>After the method is done, the offset will be where Ceras has stopped reading.</para>
        /// <para>If you pass in a value >0 for <paramref name="expectedReadLength"/> then Ceras will check how many bytes it has read (only rarely useful)</para>
        /// </summary>
        public void Deserialize <T>(ref T value, byte[] buffer, ref int offset, int expectedReadLength = -1)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("Must provide a buffer to deserialize from!");
            }

            EnterRecursive(RecursionMode.Deserialization);

            try
            {
                int offsetBeforeRead = offset;

                //
                // Actual deserialization
                {
                    if (Config.Advanced.EmbedChecksum)
                    {
                        var checksum = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
                        if (checksum != ProtocolChecksum.Checksum)
                        {
                            throw new InvalidOperationException($"Checksum does not match embedded checksum (Serializer={ProtocolChecksum.Checksum}, Data={checksum})");
                        }
                    }

                    var formatter = (IFormatter <T>)GetReferenceFormatter(typeof(T));
                    formatter.Deserialize(buffer, ref offset, ref value);
                }


                if (expectedReadLength != -1)
                {
                    int bytesActuallyRead = offset - offsetBeforeRead;

                    if (bytesActuallyRead != expectedReadLength)
                    {
                        throw new UnexpectedBytesConsumedException("The deserialization has completed, but not all of the given bytes were consumed. " +
                                                                   " Maybe you tried to deserialize something directly from a larger byte-array?",
                                                                   expectedReadLength, bytesActuallyRead, offsetBeforeRead, offset);
                    }
                }

                // todo: use a custom 'Bag' collection or so for deserialization caches, so we can quickly remove everything above a certain index

                // Clearing and re-adding the known types is really bad...
                // But how would we optimize it best?
                // Maybe having a sort of fallback-cache? I guess it would be faster than what we're doing now,
                // but then we'd have an additional if() check every time :/
                //
                // The deserialization cache is a list, we'd check for out of range, and then check the secondary cache?
                //
                // Or maybe the most straight-forward approach would be to simply remember at what index the KnownTypes end and the dynamic types start,
                // and then we can just RemoveRange() everything above the known index...
                if (!Config.Advanced.PersistTypeCache)
                {
                    InstanceData.TypeCache.ResetDeserializationCache();
                }

                InstanceData.ObjectCache.ClearDeserializationCache();
            }
            finally
            {
                LeaveRecursive(RecursionMode.Deserialization);
            }
        }