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); } } }
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()) }); }
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));
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()); }