Exemple #1
0
        private (int, Encoding)? GetLengthAttributeValues(MemberAttributeInfo fieldAttributes, ValueStorage storage)
        {
            var fixedLengthAttribute      = fieldAttributes?.FixedLengthAttribute;
            var variableLengthAttribute   = fieldAttributes?.VariableLengthAttribute;
            var calculatedLengthAttribute = fieldAttributes?.CalculatedLengthAttribute;

            Encoding stringEncoding;
            int      length;

            if (fixedLengthAttribute != null)
            {
                stringEncoding = Tools.RetrieveEncoding(fixedLengthAttribute.StringEncoding);
                length         = fixedLengthAttribute.Length;
            }
            else if (variableLengthAttribute != null)
            {
                stringEncoding = Tools.RetrieveEncoding(variableLengthAttribute.StringEncoding);
                length         = Convert.ToInt32(storage.Get(variableLengthAttribute.FieldName)) + variableLengthAttribute.Offset;
            }
            else if (calculatedLengthAttribute != null)
            {
                stringEncoding = Tools.RetrieveEncoding(calculatedLengthAttribute.StringEncoding);
                length         = calculatedLengthAttribute.CalculationAction(storage);
            }
            else
            {
                return(null);
            }

            return(length, stringEncoding);
        }
Exemple #2
0
        private object ReadTypeInternal(BinaryReaderX br, Type readType, ValueStorage storage, FieldInfo fieldInfo = null, bool isTypeChosen = false)
        {
            var typeAttributes  = new MemberAttributeInfo(readType);
            var fieldAttributes = fieldInfo == null ? null : new MemberAttributeInfo(fieldInfo);

            var bkByteOrder = br.ByteOrder;
            var bkBitOrder  = br.BitOrder;
            var bkBlockSize = br.BlockSize;

            br.ByteOrder = fieldAttributes?.EndiannessAttribute?.ByteOrder ??
                           typeAttributes.EndiannessAttribute?.ByteOrder ??
                           br.ByteOrder;

            object returnValue;

            if (IsTypeChoice(fieldAttributes) && !isTypeChosen)
            {
                var chosenType = ChooseType(readType, fieldAttributes, storage);
                returnValue = ReadTypeInternal(br, chosenType, storage, fieldInfo, true);
            }
            else if (readType.IsPrimitive)
            {
                returnValue = ReadTypePrimitive(br, readType);
            }
            else if (readType == typeof(string))
            {
                returnValue = ReadTypeString(br, fieldAttributes, storage);
            }
            else if (readType == typeof(decimal))
            {
                returnValue = br.ReadDecimal();
            }
            else if (Tools.IsList(readType))
            {
                returnValue = ReadTypeList(br, readType, fieldAttributes, storage, fieldInfo?.Name);
            }
            else if (readType.IsClass || Tools.IsStruct(readType))
            {
                returnValue = ReadTypeClass(br, readType, storage.CreateScope(fieldInfo?.Name));
            }
            else if (readType.IsEnum)
            {
                returnValue = ReadTypeInternal(br, readType.GetEnumUnderlyingType(), storage);
            }
            else
            {
                throw new UnsupportedTypeException(readType);
            }

            br.ByteOrder = bkByteOrder;
            br.BitOrder  = bkBitOrder;
            br.BlockSize = bkBlockSize;

            return(returnValue);
        }
Exemple #3
0
        private object ReadTypeClass(BinaryReaderX br, Type readType, ValueStorage storage)
        {
            var typeAttributes = new MemberAttributeInfo(readType);

            var bitFieldInfoAttribute = typeAttributes.BitFieldInfoAttribute;
            var alignmentAttribute    = typeAttributes.AlignmentAttribute;

            if (bitFieldInfoAttribute != null)
            {
                br.ResetBitBuffer();
            }

            br.BitOrder  = (bitFieldInfoAttribute?.BitOrder != BitOrder.Default ? bitFieldInfoAttribute?.BitOrder : br.BitOrder) ?? br.BitOrder;
            br.BlockSize = bitFieldInfoAttribute?.BlockSize ?? br.BlockSize;
            if (br.BlockSize != 8 && br.BlockSize != 4 && br.BlockSize != 2 && br.BlockSize != 1)
            {
                throw new InvalidBitFieldInfoException(br.BlockSize);
            }

            var item = Activator.CreateInstance(readType);

            var fields = readType.GetFields().OrderBy(fi => fi.MetadataToken);

            foreach (var field in fields)
            {
                // If field condition is false, read no value and leave field to default
                var conditionAttribute = field.GetCustomAttribute <ConditionAttribute>();
                if (!ResolveCondition(conditionAttribute, storage))
                {
                    continue;
                }

                var bitInfo = field.GetCustomAttribute <BitFieldAttribute>();

                object fieldValue;
                if (bitInfo != null)
                {
                    fieldValue = Convert.ChangeType(br.ReadBits(bitInfo.BitLength), field.FieldType);
                }
                else
                {
                    fieldValue = ReadTypeInternal(br, field.FieldType, storage, field);
                }

                storage.Add(field.Name, fieldValue);
                field.SetValue(item, fieldValue);
            }

            if (alignmentAttribute != null)
            {
                br.SeekAlignment(alignmentAttribute.Alignment);
            }

            return(item);
        }
Exemple #4
0
        private object ReadTypeString(BinaryReaderX br, MemberAttributeInfo fieldAttributes, ValueStorage storage)
        {
            var attributeValues = GetLengthAttributeValues(fieldAttributes, storage);

            if (attributeValues.HasValue)
            {
                var(length, encoding) = attributeValues.Value;
                return(br.ReadString(length, encoding));
            }

            return(null);
        }
Exemple #5
0
        private void WriteTypeClass(BinaryWriterX bw, object writeValue, Type writeType, ValueStorage storage)
        {
            var typeAttributes = new MemberAttributeInfo(writeType);

            var bitFieldInfoAttribute = typeAttributes.BitFieldInfoAttribute;
            var alignmentAttribute    = typeAttributes.AlignmentAttribute;

            if (bitFieldInfoAttribute != null)
            {
                bw.Flush();
            }

            bw.BitOrder  = (bitFieldInfoAttribute?.BitOrder != BitOrder.Default ? bitFieldInfoAttribute?.BitOrder : bw.BitOrder) ?? bw.BitOrder;
            bw.BlockSize = bitFieldInfoAttribute?.BlockSize ?? bw.BlockSize;
            if (bw.BlockSize != 8 && bw.BlockSize != 4 && bw.BlockSize != 2 && bw.BlockSize != 1)
            {
                throw new InvalidBitFieldInfoException(bw.BlockSize);
            }

            var fields = writeType.GetFields().OrderBy(fi => fi.MetadataToken);

            foreach (var field in fields)
            {
                // If field condition is false, write no value and ignore field
                var conditionAttribute = field.GetCustomAttribute <ConditionAttribute>();
                if (!ResolveCondition(conditionAttribute, storage))
                {
                    continue;
                }

                var fieldValue = field.GetValue(writeValue);
                storage.Add(field.Name, fieldValue);

                var bitInfo = field.GetCustomAttribute <BitFieldAttribute>();
                if (bitInfo != null)
                {
                    bw.WriteBits(Convert.ToInt64(fieldValue), bitInfo.BitLength);
                }
                else
                {
                    WriteTypeInternal(bw, fieldValue, storage, field);
                }
            }

            bw.Flush();

            // Apply alignment
            if (alignmentAttribute != null)
            {
                bw.WriteAlignment(alignmentAttribute.Alignment);
            }
        }
Exemple #6
0
        private object ReadTypeString(BinaryReaderX br, MemberAttributeInfo fieldAttributes, ValueStorage storage)
        {
            var attributeValues = GetLengthAttributeValues(fieldAttributes, storage);

            // If no length attributes are given, assume string with 7bit-encoded int length prefixing the string
            if (!attributeValues.HasValue)
            {
                return(br.ReadString());
            }

            var(length, encoding) = attributeValues.Value;
            return(br.ReadString(length, encoding));
        }
Exemple #7
0
        private void WriteTypeString(BinaryWriterX bw, string writeValue, MemberAttributeInfo fieldAttributes, ValueStorage storage)
        {
            var attributeValues = GetLengthAttributeValues(fieldAttributes, storage);

            // If no length attributes are given, assume string with 7bit-encoded int length prefixing the string
            if (!attributeValues.HasValue)
            {
                bw.Write(writeValue);
                return;
            }

            var(length, encoding) = attributeValues.Value;
            bw.Write(ConvertStringValue(writeValue, encoding, length));
        }
Exemple #8
0
        private void WriteTypeInternal(BinaryWriterX bw, object writeValue, ValueStorage storage, FieldInfo fieldInfo = null, bool isTypeChose = false)
        {
            var writeType       = writeValue.GetType();
            var typeAttributes  = new MemberAttributeInfo(writeType);
            var fieldAttributes = fieldInfo == null ? null : new MemberAttributeInfo(fieldInfo);

            var bkByteOrder = bw.ByteOrder;
            var bkBitOrder  = bw.BitOrder;
            var bkBlockSize = bw.BlockSize;

            bw.ByteOrder = fieldAttributes?.EndiannessAttribute?.ByteOrder ??
                           typeAttributes.EndiannessAttribute?.ByteOrder ??
                           bw.ByteOrder;

            if (writeType.IsPrimitive)
            {
                WriteTypePrimitive(bw, writeValue, writeType);
            }
            else if (writeType == typeof(string))
            {
                WriteTypeString(bw, (string)writeValue, fieldAttributes, storage);
            }
            else if (writeType == typeof(decimal))
            {
                bw.Write((decimal)writeValue);
            }
            else if (Tools.IsList(writeType))
            {
                WriteTypeList(bw, (IList)writeValue, fieldAttributes, storage);
            }
            else if (writeType.IsClass || Tools.IsStruct(writeType))
            {
                WriteTypeClass(bw, writeValue, writeType, storage.CreateScope(fieldInfo?.Name));
            }
            else if (writeType.IsEnum)
            {
                var underlyingType = (writeType as TypeInfo)?.DeclaredFields.ToList()[0];
                WriteTypeInternal(bw, underlyingType?.GetValue(writeValue), storage);
            }
            else
            {
                throw new UnsupportedTypeException(writeType);
            }

            bw.ByteOrder = bkByteOrder;
            bw.BitOrder  = bkBitOrder;
            bw.BlockSize = bkBlockSize;
        }
Exemple #9
0
        private void WriteTypeString(BinaryWriterX bw, string writeValue, MemberAttributeInfo fieldAttributes, ValueStorage storage)
        {
            var attributeValues = GetLengthAttributeValues(fieldAttributes, storage);

            if (!attributeValues.HasValue)
            {
                return;
            }

            var(length, encoding) = attributeValues.Value;
            if (encoding.GetByteCount(writeValue) != length)
            {
                throw new FieldLengthMismatchException(encoding.GetByteCount(writeValue), length);
            }

            bw.WriteString(writeValue, encoding, false, false);
        }
Exemple #10
0
        private object ReadTypeList(BinaryReaderX br, Type readType, MemberAttributeInfo fieldAttributes, ValueStorage storage, string listFieldName)
        {
            var attributeValues = GetLengthAttributeValues(fieldAttributes, storage);

            if (!attributeValues.HasValue)
            {
                return(null);
            }

            var(length, _) = attributeValues.Value;

            IList list;
            Type  elementType;

            if (readType.IsArray)
            {
                elementType = readType.GetElementType();
                list        = Array.CreateInstance(elementType, length);
            }
            else
            {
                elementType = readType.GetGenericArguments()[0];
                list        = (IList)Activator.CreateInstance(readType);
            }

            for (var i = 0; i < length; i++)
            {
                var elementValue = ReadTypeInternal(br, elementType, storage.CreateScope($"{listFieldName}[{i}]"));
                if (list.IsFixedSize)
                {
                    list[i] = elementValue;
                }
                else
                {
                    list.Add(elementValue);
                }
            }

            return(list);
        }
Exemple #11
0
        private void WriteTypeList(BinaryWriterX bw, IList writeValue, MemberAttributeInfo fieldAttributes, ValueStorage storage)
        {
            var attributeValues = GetLengthAttributeValues(fieldAttributes, storage);

            if (!attributeValues.HasValue)
            {
                return;
            }

            var(length, _) = attributeValues.Value;

            if (writeValue.Count != length)
            {
                throw new FieldLengthMismatchException(writeValue.Count, length);
            }

            var listCounter = 0;

            foreach (var element in writeValue)
            {
                WriteTypeInternal(bw, element, storage.CreateScope($"[{listCounter++}]"));
            }
        }
Exemple #12
0
        private Type ChooseType(Type readType, MemberAttributeInfo fieldAttributes, ValueStorage storage)
        {
            var typeChoices = fieldAttributes.TypeChoiceAttributes.ToArray();

            if (readType != typeof(object) && typeChoices.Any(x => !readType.IsAssignableFrom(x.InjectionType)))
            {
                throw new InvalidOperationException($"Not all type choices are injectable to '{readType.Name}'.");
            }

            Type chosenType = null;

            foreach (var typeChoice in typeChoices)
            {
                if (!storage.Exists(typeChoice.FieldName))
                {
                    throw new InvalidOperationException($"Field '{typeChoice.FieldName}' could not be found.");
                }

                var value = storage.Get(typeChoice.FieldName);
                switch (typeChoice.Comparer)
                {
                case TypeChoiceComparer.Equal:
                    if (Convert.ToUInt64(value) == Convert.ToUInt64(typeChoice.Value))
                    {
                        chosenType = typeChoice.InjectionType;
                    }
                    break;

                case TypeChoiceComparer.Greater:
                    if (Convert.ToUInt64(value) > Convert.ToUInt64(typeChoice.Value))
                    {
                        chosenType = typeChoice.InjectionType;
                    }
                    break;

                case TypeChoiceComparer.Smaller:
                    if (Convert.ToUInt64(value) < Convert.ToUInt64(typeChoice.Value))
                    {
                        chosenType = typeChoice.InjectionType;
                    }
                    break;

                case TypeChoiceComparer.GEqual:
                    if (Convert.ToUInt64(value) >= Convert.ToUInt64(typeChoice.Value))
                    {
                        chosenType = typeChoice.InjectionType;
                    }
                    break;

                case TypeChoiceComparer.SEqual:
                    if (Convert.ToUInt64(value) <= Convert.ToUInt64(typeChoice.Value))
                    {
                        chosenType = typeChoice.InjectionType;
                    }
                    break;

                default:
                    throw new InvalidOperationException($"Unknown comparer {typeChoice.Comparer}.");
                }

                if (chosenType != null)
                {
                    break;
                }
            }

            if (chosenType == null)
            {
                throw new InvalidOperationException($"No choice matched the criteria for injection");
            }

            return(chosenType);
        }
Exemple #13
0
 private bool IsTypeChoice(MemberAttributeInfo fieldAttributes)
 {
     return(fieldAttributes?.TypeChoiceAttributes?.Any() ?? false);
 }