Ejemplo n.º 1
0
        public string Serialize(IPacket packet, Type type)
        {
            try
            {
                // load pregenerated serialization information
                PacketInformation serializationInformation = GetSerializationInformation(type);

                var builder = new StringBuilder();
                builder.Append(serializationInformation.Header);

                int lastIndex = 0;

                foreach (PacketPropertyContainer property in serializationInformation.PacketProps)
                {
                    PacketIndexAttribute packetIndex              = property.PacketIndex;
                    PropertyInfo         propertyType             = property.PropertyInfo;
                    IEnumerable <ValidationAttribute> validations = property.Validations;
                    // check if we need to add a non mapped values (pseudovalues)
                    if (packetIndex.Index > lastIndex + 1)
                    {
                        int amountOfEmptyValuesToAdd = packetIndex.Index - (lastIndex + 1);

                        for (int j = 0; j < amountOfEmptyValuesToAdd; j++)
                        {
                            builder.Append(" 0");
                        }
                    }

                    // add value for current configuration
                    builder.Append(SerializeValue(propertyType.PropertyType, propertyType.GetValue(packet), validations, packetIndex));

                    // check if the value should be serialized to end
                    if (packetIndex.SerializeToEnd)
                    {
                        // we reached the end
                        break;
                    }

                    // set new index
                    lastIndex = packetIndex.Index;
                }

                return(builder.ToString());
            }
            catch (Exception e)
            {
                Log.Error($"Wrong Packet format {type}\n", e);
                return(string.Empty);
            }
        }
Ejemplo n.º 2
0
        private object DeserializeSubpacket(string currentSubValues, Type packetBasePropertyType, PacketInformation subpacketSerializationInfo, bool isReturnPacket = false)
        {
            string[] subpacketValues = currentSubValues.Split(isReturnPacket ? '^' : '.');
            object   newSubpacket    = packetBasePropertyType.CreateInstance();

            foreach (PacketPropertyContainer tmp in subpacketSerializationInfo.PacketProps)
            {
                PacketIndexAttribute key   = tmp.PacketIndex;
                PropertyInfo         value = tmp.PropertyInfo;
                int    currentSubIndex     = isReturnPacket ? key.Index + 1 : key.Index;// return packets do include header
                string currentSubValue     = subpacketValues[currentSubIndex];

                value.SetValue(newSubpacket, DeserializeValue(value.PropertyType, currentSubValue, key, tmp.Validations, null));
            }

            return(newSubpacket);
        }
Ejemplo n.º 3
0
        private string SerializeSimpleList(IList listValues, Type propertyType, PacketIndexAttribute index)
        {
            string resultListPacket = string.Empty;
            int    listValueCount   = listValues.Count;

            if (listValueCount <= 0)
            {
                return(resultListPacket);
            }

            resultListPacket += SerializeValue(propertyType.GenericTypeArguments[0], listValues[0], propertyType.GenericTypeArguments[0].GetCustomAttributes <ValidationAttribute>());

            for (int i = 1; i < listValueCount; i++)
            {
                resultListPacket +=
                    $"{index.SpecialSeparator}{SerializeValue(propertyType.GenericTypeArguments[0], listValues[i], propertyType.GenericTypeArguments[0].GetCustomAttributes<ValidationAttribute>()).Replace(" ", "")}";
            }

            return(resultListPacket);
        }
Ejemplo n.º 4
0
        private string SerializeSubpacket(object value, PacketInformation subpacketSerializationInfo, bool isReturnPacket,
                                          bool shouldRemoveSeparator)
        {
            string serializedSubpacket = isReturnPacket ? $" #{subpacketSerializationInfo.Header}^" : " ";

            // iterate thru configure subpacket properties
            foreach (PacketPropertyContainer tmp in subpacketSerializationInfo.PacketProps)
            {
                PacketIndexAttribute key          = tmp.PacketIndex;
                PropertyInfo         propertyInfo = tmp.PropertyInfo;
                // first element
                if (key.Index != 0)
                {
                    serializedSubpacket += isReturnPacket ? "^" : key.SpecialSeparator;
                }

                serializedSubpacket += SerializeValue(propertyInfo.PropertyType, propertyInfo.GetValue(value), tmp.Validations, key).Replace(" ", "");
            }

            return(serializedSubpacket);
        }
Ejemplo n.º 5
0
        private PacketBase Deserialize(string packetContent, PacketBase packet, PacketInformation serializeInfos, bool includeKeepAlive)
        {
            MatchCollection matches = Regex.Matches(packetContent, @"([^\040]+[\.][^\040]+[\040]?)+((?=\040)|$)|([^\040]+)((?=\040)|$)");

            if (matches.Count <= 0)
            {
                return(packet);
            }

            for (int i = 0; i < serializeInfos.PacketProps.Length; i++)
            {
                int currentIndex = i + (includeKeepAlive ? 2 : 1);
                if (currentIndex >= matches.Count)
                {
                    break;
                }

                PacketIndexAttribute index    = serializeInfos.PacketProps[i].PacketIndex;
                PropertyInfo         property = serializeInfos.PacketProps[i].PropertyInfo;
                IEnumerable <ValidationAttribute> validations = serializeInfos.PacketProps[i].Validations;

                if (index.SerializeToEnd)
                {
                    // get the value to the end and stop deserialization
                    int    tmp        = matches.Count > currentIndex ? matches[currentIndex].Index : packetContent.Length;
                    string valueToEnd = packetContent.Substring(tmp, packetContent.Length - tmp);
                    property.SetValue(packet, DeserializeValue(property.PropertyType, valueToEnd, index, validations, matches, includeKeepAlive));
                    break;
                }

                string currentValue = matches[currentIndex].Value;

                // set the value & convert currentValue
                property.SetValue(packet, DeserializeValue(property.PropertyType, currentValue, index, validations, matches, includeKeepAlive));
            }

            return(packet);
        }
Ejemplo n.º 6
0
        private static List <PropertyData> GetProperties(Type type)
        {
            var properties = new List <PropertyData>();

            foreach (PropertyInfo propertyInfo in type.GetProperties())
            {
                PacketIndexAttribute packetIndexAttribute = propertyInfo.GetCustomAttribute <PacketIndexAttribute>();
                if (packetIndexAttribute == null)
                {
                    continue;
                }

                properties.Add(new PropertyData
                {
                    PropertyType         = propertyInfo.PropertyType,
                    PacketIndexAttribute = packetIndexAttribute,
                    Setter = FastReflection.GetPropertySetter(type, propertyInfo),
                    Getter = FastReflection.GetPropertyGetter(type, propertyInfo)
                });
            }

            return(properties);
        }
Ejemplo n.º 7
0
        private Expression ListSerializer(Expression injectedPacket, Expression specificTypeExpression,
                                          PacketIndexAttribute indexAttr, Type type, string packetSplitter, Expression propertySplitter)
        {
            var subtype      = type.GenericTypeArguments.Any() ? type.GenericTypeArguments[0] : type.GetElementType();
            var param        = Expression.Parameter(subtype);
            var isPacketList = false;

            if (typeof(IPacket).IsAssignableFrom(subtype))
            {
                indexAttr.IsOptional = false;
                isPacketList         = true;
            }

            var selectExp = Expression.Call(
                typeof(Enumerable),
                "Select",
                new[] { subtype, typeof(string) },
                specificTypeExpression,
                Expression.Lambda(
                    Expression.Convert(isPacketList
                        ? PacketSerializer(injectedPacket, indexAttr, param, subtype, 0, propertySplitter, "", true)
                        : PropertySerializer(injectedPacket, indexAttr, subtype, param, 0,
                                             Expression.Constant("")), typeof(string)), param)
                );

            var listJoin = Expression.Convert(Expression.Call(
                                                  typeof(string).GetMethod("Join", new[] { typeof(string), typeof(IEnumerable <string>) }),
                                                  isPacketList || indexAttr is PacketListIndex ? Expression.Constant(packetSplitter, typeof(string)) : propertySplitter,
                                                  selectExp),
                                              typeof(object));

            return(Expression.Condition(
                       Expression.Equal(specificTypeExpression, Expression.Constant(null, typeof(object))),
                       Expression.Constant(null, typeof(object)),
                       ConcatExpression(Expression.Constant(indexAttr.SpecialSeparator != null ? " " : string.Empty), Expression.Convert(listJoin, typeof(object)))
                       ));
        }
Ejemplo n.º 8
0
        private Expression PropertySerializer(Expression injectedPacket, PacketIndexAttribute indexAttr, Type type,
                                              Expression specificTypeExpression, int maxIndex, Expression propertySplitter)
        {
            var useCustomSerializer = true;

            switch (type)
            {
            //handle boolean
            case var t when(t == typeof(bool)) || (t == typeof(bool?)):
                specificTypeExpression = BooleanSerializer(specificTypeExpression, propertySplitter);

                break;

            //handle enum
            case var t when(t.BaseType?.Equals(typeof(Enum)) ?? false) ||
                (Nullable.GetUnderlyingType(t)?.IsEnum ?? false):
                specificTypeExpression = EnumSerializer(specificTypeExpression, propertySplitter);

                break;

            //handle list
            case var t when t.GetInterface("System.Collections.ICollection") != null:
                var splitter = indexAttr is PacketListIndex ind
                        ? ind.ListSeparator ?? (typeof(IPacket).IsAssignableFrom(t.GenericTypeArguments.Any() ? t.GenericTypeArguments[0] : t.GetElementType()) ? " " : ".")
                        : indexAttr.SpecialSeparator ?? " ";

                specificTypeExpression = ListSerializer(injectedPacket, specificTypeExpression, indexAttr, t, splitter,
                                                        Expression.Constant(typeof(IPacket).IsAssignableFrom(t.GenericTypeArguments.Any() ? t.GenericTypeArguments[0] : t.GetElementType())
                            ? indexAttr.SpecialSeparator ?? "."
                            : indexAttr.SpecialSeparator ?? " "));
                break;

            //handle string
            case var t when t == typeof(string):
                specificTypeExpression = StringSerializer(specificTypeExpression, indexAttr.Index == maxIndex,
                                                          indexAttr.IsOptional, propertySplitter);
                break;

            //IPacket declared type
            case var t when typeof(IPacket).IsAssignableFrom(t) && (t != typeof(IPacket)):
                var header = specificTypeExpression.Type.GetCustomAttribute <PacketHeaderAttribute>()
                             ?.Identification;
                propertySplitter = Expression.Constant(indexAttr.SpecialSeparator ?? (header == null ? " " : "."));
                if (!string.IsNullOrEmpty(header))
                {
                    header           = $"{(indexAttr.RemoveHash ? "" : "#")}{header}{(indexAttr.RemoveHash ? " " : "")}";
                    propertySplitter = Expression.Constant(indexAttr.SpecialSeparator ?? "^");
                }

                if (header == null && indexAttr.SpecialSeparator != null)
                {
                    header = " ";
                }

                specificTypeExpression = PacketSerializer(injectedPacket, indexAttr, specificTypeExpression, t, maxIndex,
                                                          propertySplitter, indexAttr.RemoveHeader ? "" : header ?? "");
                break;

            case var t when t == typeof(IPacket):
                specificTypeExpression = Expression.Constant(InjectionKey, typeof(string));
                break;

            default:
                useCustomSerializer = false;
                break;
            }

            if ((type != typeof(string)) && (Nullable.GetUnderlyingType(type) != null))
            {
                specificTypeExpression =
                    NullableSerializer(specificTypeExpression, indexAttr.IsOptional, propertySplitter);
                useCustomSerializer = true;
            }

            if (!useCustomSerializer)
            {
                specificTypeExpression = DefaultSerializer(specificTypeExpression, propertySplitter);
            }

            return(specificTypeExpression);
        }
Ejemplo n.º 9
0
        private Expression PacketSerializer(Expression injectedPacket, PacketIndexAttribute indexAttr, Expression specificTypeExpression, Type prop,
                                            int maxIndex, Expression propertySplitter, string discriminator, bool isFromList = false)
        {
            var properties = prop.GetProperties()
                             .Where(x => x.GetCustomAttributes(true).OfType <PacketIndexAttribute>().Any())
                             .OrderBy(x => x.GetCustomAttributes(true).OfType <PacketIndexAttribute>().First().Index).ToList();

            Expression propExp = Expression.Condition(injectedPacket, Expression.Constant($"#{discriminator}"),
                                                      Expression.Constant(discriminator, typeof(string)));

            Expression incrementExpr = Expression.Condition(
                Expression.Equal(propertySplitter, Expression.Constant(" ", typeof(string))),
                Expression.Constant(!string.IsNullOrWhiteSpace(discriminator)),
                Expression.Constant(false));
            var startserie      = true;
            var isOptionalSerie = false;

            foreach (var property in properties)
            {
                var index = property.GetCustomAttributes(true).OfType <PacketIndexAttribute>().First();
                if (startserie && index.IsOptional)
                {
                    isOptionalSerie = true;
                }
                else
                {
                    startserie      = index.IsOptional;
                    isOptionalSerie = false;
                }

                var exp = Expression.Convert(
                    PropertySerializer(injectedPacket,
                                       index,
                                       property.PropertyType,
                                       Expression.Property(specificTypeExpression, property.Name),
                                       maxIndex,
                                       Expression.Condition(injectedPacket, Expression.Constant("^", typeof(object)),
                                                            Expression.Constant(index.SpecialSeparator, typeof(object))))
                    , typeof(object));

                var splitter = Expression.Condition(injectedPacket,
                                                    Expression.Constant(string.Empty, typeof(object)),
                                                    index.SpecialSeparator != null
                        ? Expression.Constant(indexAttr.SpecialSeparator ?? string.Empty, typeof(object))
                        : (Expression)Expression.Convert(propertySplitter, typeof(object)));

                var trimfirst = Expression.Condition(
                    Expression.Equal(incrementExpr, Expression.Constant(false)),
                    exp,
                    ConcatExpression(splitter, exp));

                var trimnull = Expression.Condition(
                    Expression.Equal(exp, Expression.Constant(null, typeof(string))),
                    Expression.Constant(string.Empty, typeof(object)),
                    trimfirst);

                propExp = ConcatExpression(propExp, trimnull);

                incrementExpr = Expression.Constant(!isFromList || !isOptionalSerie);
            }

            return(Expression.Condition(
                       Expression.Equal(specificTypeExpression, Expression.Constant(null, typeof(object))),
                       Expression.Constant(indexAttr.IsOptional ? null : "-1", typeof(object)),
                       Expression.Convert(propExp, typeof(object))
                       ));
        }
Ejemplo n.º 10
0
        private string SerializeValue(Type propertyType, object value, IEnumerable <ValidationAttribute> validationAttributes, PacketIndexAttribute packetIndexAttribute = null)
        {
            if (propertyType == null && validationAttributes.All(a => a.IsValid(value)))
            {
                return(string.Empty);
            }

            if (packetIndexAttribute?.IsOptional == true && string.IsNullOrEmpty(Convert.ToString(value)))
            {
                return(string.Empty);
            }

            // check for nullable without value or string
            if (propertyType == typeof(string) && string.IsNullOrEmpty(Convert.ToString(value)))
            {
                return($"{packetIndexAttribute?.SpecialSeparator}-");
            }

            if (Nullable.GetUnderlyingType(propertyType) != null && string.IsNullOrEmpty(Convert.ToString(value)))
            {
                return($"{packetIndexAttribute?.SpecialSeparator}-1");
            }

            // enum should be casted to number
            if (propertyType.BaseType?.Equals(typeof(Enum)) == true)
            {
                return($"{packetIndexAttribute?.SpecialSeparator}{Convert.ToInt16(value)}");
            }

            if (propertyType == typeof(bool))
            {
                // bool is 0 or 1 not True or False
                return(Convert.ToBoolean(value) ? $"{packetIndexAttribute?.SpecialSeparator}1" : $"{packetIndexAttribute?.SpecialSeparator}0");
            }

            if (value is IPacket)
            {
                PacketInformation subpacketSerializationInfo = GetSerializationInformation(value.GetType());
                return(SerializeSubpacket(value, subpacketSerializationInfo, packetIndexAttribute?.IsOptional ?? false, packetIndexAttribute?.IsOptional ?? false));
            }

            if (propertyType.BaseType?.Equals(typeof(IPacket)) == true)
            {
                PacketInformation subpacketSerializationInfo = GetSerializationInformation(propertyType);
                return(SerializeSubpacket(value, subpacketSerializationInfo, packetIndexAttribute?.IsOptional ?? false, packetIndexAttribute?.IsOptional ?? false));
            }

            if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition().IsAssignableFrom(typeof(List <>)) &&
                propertyType.GenericTypeArguments[0].BaseType == typeof(IPacket))
            {
                return(packetIndexAttribute?.SpecialSeparator + SerializeSubpackets((IList)value, propertyType, packetIndexAttribute?.IsOptional ?? false));
            }

            if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition().IsAssignableFrom(typeof(List <>))) //simple list
            {
                return(packetIndexAttribute?.SpecialSeparator + SerializeSimpleList((IList)value, propertyType, packetIndexAttribute));
            }

            return($"{packetIndexAttribute?.SpecialSeparator}{value}");
        }
Ejemplo n.º 11
0
        private object?DeserializeList(Type subType, PacketIndexAttribute packetIndexAttribute, Match[] matches, ref int currentIndex, bool isMaxIndex)
        {
            int newIndex = currentIndex;
            var length   = packetIndexAttribute is PacketListIndex listIndex ? listIndex.Length : 0;

            string[]? splited = null;

            if (length < 0)
            {
                length = sbyte.Parse(matches[currentIndex + length].Value);
            }
            else
            {
                if (isMaxIndex && string.IsNullOrEmpty(packetIndexAttribute.SpecialSeparator))
                {
                    length = (sbyte)(matches.Length - currentIndex);
                }

                if (!string.IsNullOrEmpty(packetIndexAttribute.SpecialSeparator))
                {
                    splited = matches[currentIndex].Value.Split(new string[] { packetIndexAttribute.SpecialSeparator }, StringSplitOptions.None);
                    length  = (sbyte)splited.Length;
                }
            }

            if (length > 0)
            {
                var list = new List <object>();
                for (var i = 0; i < length; i++)
                {
                    if (typeof(IPacket).IsAssignableFrom(subType))
                    {
                        var dic = packetDeserializerDictionary.Values.FirstOrDefault(s => s.PacketType == subType);

                        if (dic == null)
                        {
                            continue;
                        }

                        string toConvert;

                        if (matches[currentIndex + i].ToString().Contains(packetIndexAttribute.SpecialSeparator ?? "."))
                        {
                            toConvert = matches[currentIndex + i].ToString().Replace(packetIndexAttribute.SpecialSeparator ?? ".", " ");
                        }
                        else
                        {
                            toConvert = string.Join(" ",
                                                    matches.Skip(currentIndex + i * (1 + dic.PropertyAmount)).Take(dic.PropertyAmount + 1));
                        }
                        list.Add(Convert.ChangeType(DeserializeIPacket(dic, toConvert, false, false), subType));

                        if (splited == null)
                        {
                            newIndex += 1 + dic.PropertyAmount;
                        }
                    }
                    else //simple list
                    {
                        var value = long.Parse(splited != null ? splited[i] : matches[currentIndex + i].Value);
                        list.Add(Convert.ChangeType(value, subType));
                        if (splited == null)
                        {
                            newIndex += i + 1;
                        }
                    }
                }

                if (splited != null)
                {
                    newIndex++;
                }

                currentIndex = newIndex;
                return(subType.GetAndFillListMethod()(list));
            }

            return(null);
        }
Ejemplo n.º 12
0
        private object DeserializeValue(Type packetPropertyType, string currentValue, PacketIndexAttribute packetIndexAttribute, IEnumerable <ValidationAttribute> validationAttributes,
                                        MatchCollection packetMatches,
                                        bool includesKeepAliveIdentity = false)
        {
            foreach (ValidationAttribute i in validationAttributes)
            {
                if (!i.IsValid(currentValue))
                {
                    throw new ValidationException(i.ErrorMessage);
                }
            }

            // check for empty value and cast it to null
            if (currentValue == "-1" || currentValue == "-")
            {
                currentValue = null;
            }

            // enum should be casted to number
            if (packetPropertyType.BaseType?.Equals(typeof(Enum)) == true)
            {
                object convertedValue = null;
                try
                {
                    if (currentValue != null && packetPropertyType.IsEnumDefined(Enum.Parse(packetPropertyType, currentValue)))
                    {
                        convertedValue = Enum.Parse(packetPropertyType, currentValue);
                    }
                }
                catch (Exception)
                {
                    Log.Warn($"Could not convert value {currentValue} to type {packetPropertyType.Name}");
                }

                return(convertedValue);
            }

            if (packetPropertyType == typeof(bool)) // handle boolean values
            {
                return(currentValue != "0");
            }

            if (packetPropertyType.BaseType?.Equals(typeof(PacketBase)) == true) // subpacket
            {
                PacketInformation subpacketSerializationInfo = GetSerializationInformation(packetPropertyType);
                return(DeserializeSubpacket(currentValue, packetPropertyType, subpacketSerializationInfo, packetIndexAttribute?.IsReturnPacket ?? false));
            }

            if (packetPropertyType.IsGenericType && packetPropertyType.GetGenericTypeDefinition().IsAssignableFrom(typeof(List <>)) && // subpacket list
                packetPropertyType.GenericTypeArguments[0].BaseType == typeof(PacketBase))
            {
                return(DeserializeSubpackets(currentValue, packetPropertyType, packetIndexAttribute?.RemoveSeparator ?? false, packetMatches, packetIndexAttribute?.Index, includesKeepAliveIdentity));
            }

            if (packetPropertyType.IsGenericType && packetPropertyType.GetGenericTypeDefinition().IsAssignableFrom(typeof(List <>))) // simple list
            {
                return(DeserializeSimpleList(currentValue, packetPropertyType));
            }

            if (Nullable.GetUnderlyingType(packetPropertyType) != null && string.IsNullOrEmpty(currentValue)) // empty nullable value
            {
                return(null);
            }

            if (Nullable.GetUnderlyingType(packetPropertyType) != null) // nullable value
            {
                return(packetPropertyType.GenericTypeArguments[0]?.BaseType == typeof(Enum)
                    ? Enum.Parse(packetPropertyType.GenericTypeArguments[0], currentValue)
                    : Convert.ChangeType(currentValue, packetPropertyType.GenericTypeArguments[0]));
            }

            if (packetPropertyType == typeof(string) && string.IsNullOrEmpty(currentValue) && !packetIndexAttribute.SerializeToEnd)
            {
                throw new NullReferenceException();
            }

            if (packetPropertyType == typeof(string) && currentValue == null)
            {
                currentValue = string.Empty;
            }

            return(Convert.ChangeType(currentValue, packetPropertyType)); // cast to specified type
        }