예제 #1
0
        public byte[] ConvertToBytes(object propertyValue, Type propertyType, bool?reverse = null)
        {
            switch (propertyValue)
            {
            case null:
                throw TcpException.PropertyArgumentIsNull(propertyType.ToString());

            case byte @byte:
                return(new[] { @byte });

            case byte[] byteArray:
                return(reverse.GetValueOrDefault() ? Reverse(byteArray) : byteArray);

            default:
                try
                {
                    if (_customConverters.TryConvert(propertyType, propertyValue, out var result))
                    {
                        return(reverse.GetValueOrDefault() ? Reverse(result) : result);
                    }

                    if (!_builtInConvertersToBytes.TryGetValue(propertyType, out var methodInfo))
                    {
                        throw TcpException.ConverterNotFoundType(propertyType.ToString());
                    }

                    result = (byte[])methodInfo.Invoke(null, new[] { propertyValue });
                    return(reverse ?? _options.PrimitiveValueReverse ? Reverse(result) : result);
                }
                catch (Exception exception) when(!(exception is TcpException))
                {
                    throw TcpException.ConverterUnknownError(propertyType.ToString(), exception.Message);
                }
            }
        }
예제 #2
0
        public object ConvertFromBytes(ReadOnlySequence <byte> slice, Type propertyType, bool?reverse = null)
        {
            if (propertyType == typeof(byte[]))
            {
                return(reverse.GetValueOrDefault() ? Reverse(slice.ToArray()) : slice.ToArray());
            }

            if (propertyType == typeof(byte))
            {
                return(slice.FirstSpan[0]);
            }

            var(span, returnArray) = MergeSpans(slice, propertyType.IsPrimitive ? reverse ?? _options.PrimitiveValueReverse : reverse.GetValueOrDefault());

            try
            {
                if (_customConverters.TryConvertBack(propertyType, span, out var result))
                {
                    return(result);
                }

                return(propertyType.Name switch
                {
                    nameof(Boolean) => BitConverter.ToBoolean(span),
                    nameof(Char) => BitConverter.ToChar(span),
                    nameof(Double) => BitConverter.ToDouble(span),
                    nameof(Int16) => BitConverter.ToInt16(span),
                    nameof(Int32) => BitConverter.ToInt32(span),
                    nameof(Int64) => BitConverter.ToInt64(span),
                    nameof(Single) => BitConverter.ToSingle(span),
                    nameof(UInt16) => BitConverter.ToUInt16(span),
                    nameof(UInt32) => BitConverter.ToUInt32(span),
                    nameof(UInt64) => BitConverter.ToUInt64(span),
                    _ => throw TcpException.ConverterNotFoundType(propertyType.ToString())
                });
            }
예제 #3
0
        public SerializedRequest Serialize(TData data)
        {
            int realLength;

            byte[]            serializedBody           = null;
            SerializedRequest composeSerializedRequest = null;
            var examined = 0;

            if (_reflection.BodyProperty != null)
            {
                var bodyValue = _reflection.BodyProperty.Get(data);

                if (bodyValue == null)
                {
                    throw TcpException.SerializerBodyPropertyIsNull();
                }

                serializedBody = _bitConverter.ConvertToBytes(bodyValue, _reflection.BodyProperty.PropertyType, _reflection.BodyProperty.Attribute.Reverse);
                realLength     = CalculateRealLength(_reflection.LengthProperty, ref data, _reflection.MetaLength, serializedBody.Length);
            }
            else if (_reflection.ComposeProperty != null)
            {
                var composeValue = _reflection.ComposeProperty.Get(data);

                if (composeValue == null)
                {
                    throw TcpException.SerializerComposePropertyIsNull();
                }

                if (_reflection.ComposeProperty.PropertyType.IsPrimitive)
                {
                    serializedBody = _bitConverter.ConvertToBytes(composeValue, _reflection.ComposeProperty.PropertyType, _reflection.ComposeProperty.Attribute.Reverse);
                    realLength     = CalculateRealLength(_reflection.LengthProperty, ref data, _reflection.MetaLength, serializedBody.Length);
                }
                else
                {
                    composeSerializedRequest = _reflection.ComposeProperty.Composition.Serialize(composeValue);
                    realLength = CalculateRealLength(_reflection.LengthProperty, ref data, _reflection.MetaLength, composeSerializedRequest.RealLength);
                }
            }
            else
            {
                realLength = _reflection.MetaLength;
            }

            var rentedArray = _byteArrayFactory(realLength);

            foreach (var property in _reflection.Properties)
            {
                if (!property.PropertyType.IsPrimitive && property.Attribute.TcpDataType == TcpDataType.Compose && composeSerializedRequest != null)
                {
                    Array.Copy(
                        composeSerializedRequest.RentedArray,
                        0,
                        rentedArray,
                        property.Attribute.Index,
                        composeSerializedRequest.RealLength
                        );
                }
                else
                {
                    var value = property.Attribute.TcpDataType == TcpDataType.Body || property.Attribute.TcpDataType == TcpDataType.Compose
                        ? serializedBody ?? throw TcpException.SerializerBodyPropertyIsNull()
                        : _bitConverter.ConvertToBytes(property.Get(data), property.PropertyType, property.Attribute.Reverse);

                    var valueLength = value.Length;

                    if (property.Attribute.TcpDataType != TcpDataType.Body && property.Attribute.TcpDataType != TcpDataType.Compose && valueLength > property.Attribute.Length)
                    {
                        throw TcpException.SerializerLengthOutOfRange(property.PropertyType.ToString(), valueLength.ToString(), property.Attribute.Length.ToString());
                    }

                    value.CopyTo(rentedArray, property.Attribute.Index);
                }

                if (++examined == _reflection.Properties.Count)
                {
                    break;
                }
            }

            return(new SerializedRequest(rentedArray, realLength, composeSerializedRequest));
예제 #4
0
        private static void EnsureTypeHasRequiredAttributes(Type typeData)
        {
            var properties = typeData.GetProperties();

            var key = properties.Where(item => GetTcpDataAttribute(item).TcpDataType == TcpDataType.Id).ToList();

            if (key.Count > 1)
            {
                throw TcpException.AttributeDuplicate(typeData.ToString(), nameof(TcpDataType.Id));
            }

            if (key.Count == 1 && !CanReadWrite(key.Single()))
            {
                throw TcpException.PropertyCanReadWrite(typeData.ToString(), nameof(TcpDataType.Id));
            }

            var body = properties.Where(item => GetTcpDataAttribute(item).TcpDataType == TcpDataType.Body).ToList();

            if (body.Count > 1)
            {
                throw TcpException.AttributeDuplicate(typeData.ToString(), nameof(TcpDataType.Body));
            }

            if (body.Count == 1 && !CanReadWrite(body.Single()))
            {
                throw TcpException.PropertyCanReadWrite(typeData.ToString(), nameof(TcpDataType.Body));
            }

            var compose = properties.Where(item => GetTcpDataAttribute(item).TcpDataType == TcpDataType.Compose).ToList();

            if (compose.Count > 1)
            {
                throw TcpException.AttributeDuplicate(typeData.ToString(), nameof(TcpDataType.Compose));
            }

            if (body.Count == 1 && compose.Count == 1)
            {
                throw TcpException.AttributeBodyAndComposeViolated(typeData.ToString());
            }

            var length = properties.Where(item => GetTcpDataAttribute(item).TcpDataType == TcpDataType.Length).ToList();

            if (length.Count > 1)
            {
                throw TcpException.AttributeDuplicate(typeData.ToString(), nameof(TcpDataType.Length));
            }

            if (body.Count == 1)
            {
                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (length.Count == 0)
                {
                    throw TcpException.AttributeLengthRequired(typeData.ToString(), nameof(TcpDataType.Body));
                }

                if (length.Count == 1 && !CanReadWrite(length.Single()))
                {
                    throw TcpException.PropertyCanReadWrite(typeData.ToString(), nameof(TcpDataType.Length));
                }
            }
            else if (compose.Count == 1)
            {
                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (length.Count == 0)
                {
                    throw TcpException.AttributeLengthRequired(typeData.ToString(), nameof(TcpDataType.Compose));
                }

                if (length.Count == 1 && !CanReadWrite(length.Single()))
                {
                    throw TcpException.PropertyCanReadWrite(typeData.ToString(), nameof(TcpDataType.Length));
                }
            }
            else if (length.Count == 1)
            {
                throw TcpException.AttributeRequiredWithLength(typeData.ToString());
            }

            var metaData = properties.Where(item => GetTcpDataAttribute(item).TcpDataType == TcpDataType.MetaData).ToList();

            if (key.Count == 0 && length.Count == 0 && body.Count == 0 && metaData.Count == 0)
            {
                throw TcpException.AttributesRequired(typeData.ToString());
            }

            foreach (var item in metaData.Where(item => !CanReadWrite(item)))
            {
                throw TcpException.PropertyCanReadWrite(typeData.ToString(), nameof(TcpDataType.MetaData), GetTcpDataAttribute(item).Index.ToString());
            }