private static async Task <TResponse> SetBodyAsync <TResponse>(
            ApiCallDetails details, RequestData requestData, Stream responseStream, string mimeType, CancellationToken cancellationToken
            )
            where TResponse : class, ITransportResponse, new()
        {
            byte[] bytes = null;
            var    disableDirectStreaming = requestData.PostData?.DisableDirectStreaming ?? requestData.ConnectionSettings.DisableDirectStreaming;

            if (disableDirectStreaming || NeedsToEagerReadStream <TResponse>())
            {
                var inMemoryStream = requestData.MemoryStreamFactory.Create();
                await responseStream.CopyToAsync(inMemoryStream, BufferSize, cancellationToken).ConfigureAwait(false);

                bytes = SwapStreams(ref responseStream, ref inMemoryStream);
                details.ResponseBodyInBytes = bytes;
            }

            using (responseStream)
            {
                if (SetSpecialTypes <TResponse>(mimeType, bytes, requestData.MemoryStreamFactory, out var r))
                {
                    return(r);
                }

                if (details.HttpStatusCode.HasValue && requestData.SkipDeserializationForStatusCodes.Contains(details.HttpStatusCode.Value))
                {
                    return(null);
                }

                var serializer = requestData.ConnectionSettings.RequestResponseSerializer;
                if (requestData.CustomResponseBuilder != null)
                {
                    return(await requestData.CustomResponseBuilder.DeserializeResponseAsync(serializer, details, responseStream, cancellationToken).ConfigureAwait(false) as TResponse);
                }

                return(mimeType == null || !mimeType.StartsWith(requestData.Accept, StringComparison.Ordinal)
                                        ? null
                                        : await serializer
                       .DeserializeAsync <TResponse>(responseStream, cancellationToken)
                       .ConfigureAwait(false));
            }
        }
        private static ApiCallDetails Initialize(
            RequestData requestData, Exception exception, int?statusCode, IEnumerable <string> warnings, string mimeType
            )
        {
            var success            = false;
            var allowedStatusCodes = requestData.AllowedStatusCodes;

            if (statusCode.HasValue)
            {
                if (allowedStatusCodes.Contains(-1) || allowedStatusCodes.Contains(statusCode.Value))
                {
                    success = true;
                }
                else
                {
                    success = requestData.ConnectionSettings
                              .StatusCodeToResponseSuccess(requestData.Method, statusCode.Value);
                }
            }
            //mimeType can include charset information on .NET full framework
            if (!string.IsNullOrEmpty(mimeType) && !mimeType.StartsWith(requestData.Accept))
            {
                success = false;
            }

            var details = new ApiCallDetails
            {
                Success            = success,
                OriginalException  = exception,
                HttpStatusCode     = statusCode,
                RequestBodyInBytes = requestData.PostData?.WrittenBytes,
                Uri                     = requestData.Uri,
                HttpMethod              = requestData.Method,
                DeprecationWarnings     = warnings ?? Enumerable.Empty <string>(),
                ResponseMimeType        = mimeType,
                ConnectionConfiguration = requestData.ConnectionSettings
            };

            return(details);
        }