Example #1
0
        private void DeserializeFields(BinaryReader reader, ControllerSerializationContext serializationContext, object instance)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            if (serializationContext == null)
            {
                throw new ArgumentNullException(nameof(serializationContext));
            }

            if (instance == null)
            {
                throw new ArgumentNullException(nameof(instance));
            }

            FieldInfo[] fields = serializationContext.Type.GetFields(BindingFlags.Public | BindingFlags.Instance);
            foreach (FieldInfo field in fields)
            {
                var ctx   = new ControllerSerializationContext(field, serializationContext.Controller);
                var value = DeserializeField(reader, ctx);
                // We have our value, set it.
                field.SetValue(instance, value);
            }
        }
        /// <inheritdoc />
        public object Deserialize(BinaryReader reader, ControllerSerializationContext serializationContext)
        {
            var list = (IList)Activator.CreateInstance(serializationContext.Type);

            Type[] typeArgs     = serializationContext.Type.GetGenericArguments();
            Type   elementType  = typeArgs[0];
            var    innerContext = new ControllerSerializationContext(elementType, serializationContext.Controller);

            if (serializationContext.Controller is AnimationController)
            {
                // Read n times, determined by prefixed count field.
                int count = reader.ReadUInt16();
                for (int i = 0; i < count; i++)
                {
                    list.Add(_controllerFieldSerializer.ReadField(reader, innerContext));
                }
            }
            else
            {
                // Read until end of stream.
                while (reader.BaseStream.Position < reader.BaseStream.Length)
                {
                    list.Add(_controllerFieldSerializer.ReadField(reader, innerContext));
                }
            }

            return(list);
        }
Example #3
0
        /// <inheritdoc />
        public override DateTime Deserialize(BinaryReader reader, ControllerSerializationContext serializationContext)
        {
            string sDate = reader.ReadInt32().ToString();

            if (DateTime.TryParseExact(sDate, DateFormat, null, DateTimeStyles.None, out DateTime date))
            {
                return(date);
            }

            // If a parse error occurred, this most like is because the days of month are 31, for instance for april, or 30-31 for feb, or even 29 if not a leap year. Correct this by attempting to parse by lowering the days.
            int days = int.Parse(sDate.Substring(6, 2));

            sDate = sDate.Remove(6);

            // 3 extra attempts max.
            for (var i = 0; i < 3; i++)
            {
                days--;
                if (DateTime.TryParseExact(sDate + days, DateFormat, null, DateTimeStyles.None, out date))
                {
                    return(date);
                }
            }

            throw new FormatException($"The date {sDate} is in unexpected format.");
        }
 /// <inheritdoc />
 public override void Serialize(BinaryWriter writer, ControllerSerializationContext serializationContext, string value)
 {
     if (value != null)
     {
         // Write the variable string with one zero.
         writer.Write((string)value, '\0');
     }
 }
Example #5
0
        public DateTimeValueSerializerTests()
        {
            _sut = new DateTimeValueSerializer();

            FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.Supported));

            _serializationContext = new ControllerSerializationContext(field, new Mock <Controller>().Object);
        }
        /// <inheritdoc />
        public override string Deserialize(BinaryReader reader, ControllerSerializationContext serializationContext)
        {
            if (reader.BaseStream.Position == reader.BaseStream.Length)
            {
                return(null);
            }

            return(reader.ReadNullTerminatedString());
        }
        /// <inheritdoc />
        public void Serialize(BinaryWriter writer, ControllerSerializationContext serializationContext, object value)
        {
            if (value == null)
            {
                // TODO: check if null we can actually write...
                return;
            }

            writer.WriteStruct(value);
        }
Example #8
0
 /// <summary>
 /// Writes specified <paramref name="value"/> using the <paramref name="writer"/>.
 /// </summary>
 /// <param name="writer">The writer to serialize to.</param>
 /// <param name="serializationContext">The serialization context.</param>
 /// <param name="value">The value to serialize.</param>
 protected virtual void WriteField(BinaryWriter writer, ControllerSerializationContext serializationContext, object value)
 {
     if (serializationContext.Type.IsControllerOrObject())
     {
         SerializeFields(writer, serializationContext, value);
     }
     else
     {
         WriteValue(writer, serializationContext, value);
     }
 }
Example #9
0
        private void WriteValue(BinaryWriter writer, ControllerSerializationContext ctx, object value)
        {
            IControllerValueSerializer serializer = _serializers.FirstOrDefault(s => s.IsSupported(ctx));

            if (serializer == null)
            {
                throw new NotImplementedException($"The specified type '{ctx.Type.FullName}' is not supported or implemented.");
            }

            serializer.Serialize(writer, ctx, value);
        }
        /// <inheritdoc />
        public object Deserialize(BinaryReader reader, ControllerSerializationContext serializationContext)
        {
            Type underlyingType = Nullable.GetUnderlyingType(serializationContext.Type);

            var innerContext = new ControllerSerializationContext(underlyingType, serializationContext.Controller);
            IControllerValueSerializer serializer = _serializers.FirstOrDefault(s => s.IsSupported(innerContext));

            return(serializer != null
                                ? serializer.Deserialize(reader, serializationContext)
                                : reader.ReadStruct(underlyingType));
        }
Example #11
0
        private object ReadValue(BinaryReader reader, ControllerSerializationContext ctx)
        {
            IControllerValueSerializer serializer = _serializers.FirstOrDefault(s => s.IsSupported(ctx));
            object result = serializer?.Deserialize(reader, ctx);

            if (result == null)
            {
                throw new NotImplementedException($"The specified type '{ctx.Type.FullName}' is not supported or implemented.");
            }

            return(result);
        }
        /// <inheritdoc />
        public override void Serialize(BinaryWriter writer, ControllerSerializationContext serializationContext, string value)
        {
            int    fixedLength = serializationContext.Member.GetCustomAttribute <FixedStringAttribute>().Length;
            string s           = (string)value ?? string.Empty;

            if (s.Length > fixedLength)
            {
                throw new InvalidOperationException($"The string '{s}' for property '{serializationContext.Member.Name}' exceeds the fixed length {fixedLength}");
            }

            // Write the fixed string with zeros at the end.
            writer.Write(s, fixedLength);
        }
Example #13
0
        public void Given_value_when_serializing_should_write_value_type(Type typeWithSupportedField, object value)
        {
            FieldInfo field = typeWithSupportedField.GetField("Supported");
            var       serializationContext = new ControllerSerializationContext(field, new Mock <Controller>().Object);

            using (var ms = new MemoryStream())
                using (var writer = new BinaryWriter(ms, FileEncoding.Default))
                {
                    // Act
                    _sut.Serialize(writer, serializationContext, value);

                    // Assert
                    BitConverter.GetBytes((int)value).Should().Equal(ms.ToArray());
                }
        }
Example #14
0
        /// <inheritdoc />
        protected override void Deserialize(BinaryReader reader, ControllerSerializationContext serializationContext, object instance)
        {
            // Read the size of the controller.
            int size = reader.ReadInt32();
            // Save current position of stream. At the end, we compare the size with the number of bytes read for validation purposes.
            long startPos = reader.BaseStream.Position;

            string controllerName = serializationContext.Type.Name;

            reader.SkipMember(serializationContext.Type, controllerName);

            base.Deserialize(reader, serializationContext, instance);

            reader.BaseStream.EnsureStreamPosition(startPos + size, controllerName);
        }
        /// <inheritdoc />
        public override bool Deserialize(BinaryReader reader, ControllerSerializationContext serializationContext)
        {
            long boolLen = reader.BaseStream.Length;

            switch (boolLen)
            {
            case 1:
                return(reader.ReadByte() > 0);

            case 4:
                return(reader.ReadInt32() > 0);

            default:
                throw new FormatException($"Unable to convert {boolLen} bytes into a boolean.");
            }
        }
Example #16
0
        /// <inheritdoc />
        protected override void SerializeField(BinaryWriter writer, ControllerSerializationContext serializationContext, object value)
        {
            // If the value is null, the property has be optional, otherwise throw error.
            if (value == null && serializationContext.Type != typeof(string))
            {
                if (serializationContext.Member.HasAttribute <OptionalAttribute>())
                {
                    return;
                }

                string fieldName = serializationContext.Member.GetCustomAttribute <ParseNameAttribute>()?.Name ?? serializationContext.Name;
                throw new SilentHunterParserException($"The field '{fieldName}' is not defined as optional.");
            }

            base.SerializeField(writer, serializationContext, value);
        }
Example #17
0
        public void Given_serialized_value_type_when_deserializing_should_return_typed_value_type(object value, Type expectedType)
        {
            FieldInfo field = expectedType.GetField("Supported");
            var       serializationContext = new ControllerSerializationContext(field, new Mock <Controller>().Object);

            using (var ms = new MemoryStream(BitConverter.GetBytes((int)value)))
                using (var reader = new BinaryReader(ms, FileEncoding.Default))
                {
                    // Act
                    object actual = _sut.Deserialize(reader, serializationContext);

                    // Assert
                    actual.Should()
                    .BeOfType(field.FieldType)
                    .And.Be(value);
                }
        }
        /// <inheritdoc />
        public void Serialize(BinaryWriter writer, ControllerSerializationContext serializationContext, object value)
        {
            if (value is byte[] byteArray)
            {
                // Slightly more efficient to write directly.
                writer.Write(byteArray, 0, byteArray.Length);
                return;
            }

            // Otherwise write each primitive separately.
            var array = (Array)value;

            for (var i = 0; i < array.Length; i++)
            {
                writer.WriteStruct(array.GetValue(i));
            }
        }
Example #19
0
        /// <summary>
        /// Reads a field from the <paramref name="reader"/>.
        /// </summary>
        /// <param name="reader">The reader to deserialize from.</param>
        /// <param name="serializationContext">The serialization context.</param>
        protected virtual object ReadField(BinaryReader reader, ControllerSerializationContext serializationContext)
        {
            object retVal;

            if (serializationContext.Type.IsControllerOrObject())
            {
                // Create a new instance of this type.
                retVal = Activator.CreateInstance(serializationContext.Type);

                DeserializeFields(reader, serializationContext, retVal);
            }
            else
            {
                retVal = ReadValue(reader, serializationContext);
            }

            return(retVal);
        }
Example #20
0
        /// <inheritdoc />
        protected override object DeserializeField(BinaryReader reader, ControllerSerializationContext serializationContext)
        {
            object value = base.DeserializeField(reader, serializationContext);

            // Strings can have null are always optional.
            if (value != null || serializationContext.Type == typeof(string))
            {
                return(value);
            }

            // If null is returned, check if the field is optional and if the type supports a nullable type.
            if (serializationContext.Type.IsValueType && !serializationContext.Type.IsNullable())
            {
                throw new SilentHunterParserException(
                          $"The property '{serializationContext.Name}' is defined as optional, but the type '{serializationContext.Type}' does not support null values. Use Nullable<> if the property is a value type, or a class otherwise.");
            }

            return(null);
        }
        /// <inheritdoc />
        public override string Deserialize(BinaryReader reader, ControllerSerializationContext serializationContext)
        {
            int fixedLength = serializationContext.Member.GetCustomAttribute <FixedStringAttribute>().Length;

            if (reader.BaseStream.Length > fixedLength)
            {
                throw new SilentHunterParserException($"The stream contains more data than expected for '{serializationContext.Member.Name}', length {fixedLength}.");
            }

            if (reader.BaseStream.Length < fixedLength)
            {
                throw new SilentHunterParserException($"The stream does not contain enough data for '{serializationContext.Member.Name}', length {fixedLength}.");
            }

            string s = reader.ReadString(fixedLength);

            // Take care of possible '\0' char in middle of string.
            return(s.Split(new[] { '\0' }, 2, StringSplitOptions.None)[0]);
        }
        /// <inheritdoc />
        public void Serialize(BinaryWriter writer, ControllerSerializationContext serializationContext, object value)
        {
            var list = (IList)value;

            Type[] typeArgs     = serializationContext.Type.GetGenericArguments();
            Type   elementType  = typeArgs[0];
            var    innerContext = new ControllerSerializationContext(elementType, serializationContext.Controller);

            if (serializationContext.Controller is AnimationController)
            {
                // Output count field.
                writer.Write(unchecked ((ushort)list.Count));
            }

            foreach (object item in list)
            {
                _controllerFieldSerializer.WriteField(writer, innerContext, item);
            }
        }
Example #23
0
        /// <inheritdoc />
        protected override object ReadField(BinaryReader reader, ControllerSerializationContext serializationContext)
        {
            string name  = null;
            var    field = serializationContext.Member as FieldInfo;

            if (field != null)
            {
                if (field.HasAttribute <OptionalAttribute>() && reader.BaseStream.Position == reader.BaseStream.Length)
                {
                    // Exit because field is optional, and we are at end of stream.
                    return(null);
                }

                // The expected field or controller name to find on the stream.
                name = field.GetCustomAttribute <ParseNameAttribute>()?.Name ?? field.Name;
            }

            // Read the size of the data.
            int size = reader.ReadInt32();
            // Save current position of stream. At the end, we compare the size with the number of bytes read for validation purposes.
            long startPos = reader.BaseStream.Position;

            if (field != null && !string.IsNullOrEmpty(name) && reader.SkipMember(field, name))
            {
                // The property must be skipped, so revert stream back to the start position.
                reader.BaseStream.Position = startPos - 4;
                return(null);
            }

            long expectedPosition = startPos + size;
            long dataSize         = expectedPosition - reader.BaseStream.Position;

            using (var regionStream = new RegionStream(reader.BaseStream, dataSize))
            {
                using (var regionReader = new BinaryReader(regionStream, FileEncoding.Default, true))
                {
                    object retVal = base.ReadField(regionReader, serializationContext);
                    reader.BaseStream.EnsureStreamPosition(expectedPosition, name ?? serializationContext.Name);
                    return(retVal);
                }
            }
        }
Example #24
0
        /// <summary>
        /// Serializes specified <paramref name="controller"/> to the <paramref name="stream"/>.
        /// </summary>
        /// <param name="stream">The stream to serialize to.</param>
        /// <param name="controller">The controller instance to serialize.</param>
        public void Serialize(Stream stream, Controller controller)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (controller == null)
            {
                throw new ArgumentNullException(nameof(controller));
            }

            Type controllerType = controller.GetType();

            using (var writer = new BinaryWriter(stream, FileEncoding.Default, true))
            {
                var ctx = new ControllerSerializationContext(controllerType, controller);
                Serialize(writer, ctx, controller);
            }
        }
Example #25
0
        private void SerializeFields(BinaryWriter writer, ControllerSerializationContext serializationContext, object instance)
        {
            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            if (instance == null)
            {
                throw new ArgumentNullException(nameof(instance));
            }

            FieldInfo[] fields = serializationContext.Type.GetFields(BindingFlags.Public | BindingFlags.Instance);
            foreach (FieldInfo field in fields)
            {
                var    ctx   = new ControllerSerializationContext(field, serializationContext.Controller);
                object value = field.GetValue(instance);
                SerializeField(writer, ctx, value);
            }
        }
Example #26
0
        /// <inheritdoc />
        public object Deserialize(BinaryReader reader, ControllerSerializationContext serializationContext)
        {
            long dataSize = reader.BaseStream.Length - reader.BaseStream.Position;

            SHUnionPropertyCache propertyCache = GetCachedProperties(serializationContext.Type);

            Type[] typeArgs = serializationContext.Type.GetGenericArguments();
            // Using size of data to determine which of the SHUnion generic type arguments to use.
            Type valueType = typeArgs.FirstOrDefault(type => Marshal.SizeOf(type) == dataSize);

            if (valueType == null)
            {
                throw new SilentHunterParserException($"The available stream data does not match the size one of the two union types for property '{serializationContext.Name}'.");
            }

            object union = Activator.CreateInstance(serializationContext.Type);

            propertyCache.TypeProperty.SetValue(union, valueType, null);
            propertyCache.ValueProperty.SetValue(union, reader.ReadStruct(valueType), null);
            return(union);
        }
Example #27
0
        /// <inheritdoc />
        protected override void WriteField(BinaryWriter writer, ControllerSerializationContext serializationContext, object value)
        {
            // Write size 0. We don't know actual the size yet.
            writer.Write(0);

            long startPos = writer.BaseStream.Position;

            if (serializationContext.Member is FieldInfo fieldInfo)
            {
                string name = fieldInfo.GetCustomAttribute <ParseNameAttribute>()?.Name ?? fieldInfo.Name;
                writer.WriteNullTerminatedString(name);
            }

            base.WriteField(writer, serializationContext, value);

            // Rewind and store size.
            long currentPos = writer.BaseStream.Position;

            writer.BaseStream.Position = startPos - 4;
            writer.Write((int)(currentPos - startPos));
            writer.BaseStream.Position = currentPos;
        }
Example #28
0
        /// <summary>
        /// Deserializes specified <paramref name="controller"/> from the <paramref name="stream"/>.
        /// </summary>
        /// <param name="stream">The stream to deserialize from.</param>
        /// <param name="controller">The controller instance to populate with deserialized data.</param>
        public void Deserialize(Stream stream, Controller controller)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (controller == null)
            {
                throw new ArgumentNullException(nameof(controller));
            }

            Type controllerType = controller.GetType();

            using (var reader = new BinaryReader(stream, FileEncoding.Default, true))
            {
                var ctx = new ControllerSerializationContext(controllerType, controller);
                Deserialize(reader, ctx, controller);

                reader.BaseStream.EnsureStreamPosition(reader.BaseStream.Length, controllerType.Name);
            }
        }
Example #29
0
        /// <inheritdoc />
        protected override void Serialize(BinaryWriter writer, ControllerSerializationContext serializationContext, object instance)
        {
            // We don't know the size yet, so just write 0 for now.
            writer.Write(0);

            // Save current position of stream. At the end, we have to set the size.
            long startPos = writer.BaseStream.Position;

            string controllerName = serializationContext.Type.Name;

            writer.WriteNullTerminatedString(controllerName);

            base.Serialize(writer, serializationContext, instance);

            // After the object is written, determine and write the size.
            long currentPos = writer.BaseStream.Position;

            writer.BaseStream.Position = startPos - 4;
            writer.Write((int)(currentPos - startPos));

            // Restore position to the end of the controller.
            writer.BaseStream.Position = currentPos;
        }
Example #30
0
        /// <inheritdoc />
        public override void Serialize(BinaryWriter writer, ControllerSerializationContext serializationContext, DateTime value)
        {
            string date = value.ToString("yyyyMMdd");

            writer.Write(int.Parse(date));
        }