< Summary

Information
Class: IceRpc.Slice.IncomingRequestExtensions
Assembly: IceRpc.Slice
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc.Slice/IncomingRequestExtensions.cs
Tag: 275_13775359185
Line coverage
72%
Covered lines: 36
Uncovered lines: 14
Coverable lines: 50
Total lines: 126
Line coverage: 72%
Branch coverage
75%
Covered branches: 12
Total branches: 16
Branch coverage: 75%
Method coverage
100%
Covered methods: 5
Total methods: 5
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
CheckNonIdempotent(...)50%2.5250%
CreateSliceExceptionResponse(...)66.66%8.44659.25%
DecodeArgsAsync(...)100%44100%
DecodeEmptyArgsAsync(...)100%22100%
GetErrorMessage(...)50%22100%

File(s)

/home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc.Slice/IncomingRequestExtensions.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using IceRpc.Slice.Internal;
 4using System.IO.Pipelines;
 5using ZeroC.Slice;
 6
 7namespace IceRpc.Slice;
 8
 9/// <summary>Provides extension methods for <see cref="IncomingRequest" /> to decode its Slice-encoded payload.
 10/// </summary>
 11public static class IncomingRequestExtensions
 12{
 13    /// <summary>The generated code calls this method to ensure that when an operation is not declared idempotent,
 14    /// the request is not marked idempotent. If the request is marked idempotent, it means the caller incorrectly
 15    /// believes this operation is idempotent.</summary>
 16    /// <param name="request">The request to check.</param>
 17    /// <exception cref="InvalidDataException">Thrown if the request contains the <see cref="RequestFieldKey.Idempotent"
 18    /// field.</exception>
 19    public static void CheckNonIdempotent(this IncomingRequest request)
 10720    {
 10721        if (request.Fields.ContainsKey(RequestFieldKey.Idempotent))
 022        {
 023            throw new InvalidDataException(
 024                $"Invocation mode mismatch for operation '{request.Operation}': received idempotent field for an operati
 25        }
 10726    }
 27
 28    /// <summary>Creates an outgoing response with status code <see cref="StatusCode.ApplicationError" /> with
 29    /// a Slice exception payload.</summary>
 30    /// <param name="request">The incoming request.</param>
 31    /// <param name="sliceException">The Slice exception to encode in the payload.</param>
 32    /// <param name="encoding">The encoding used for the request payload.</param>
 33    /// <returns>The new outgoing response.</returns>
 34    /// <exception cref="NotSupportedException">Thrown when <paramref name="sliceException" /> does not support encoding
 35    /// <paramref name="encoding" />.</exception>
 36    public static OutgoingResponse CreateSliceExceptionResponse(
 37        this IncomingRequest request,
 38        SliceException sliceException,
 39        SliceEncoding encoding)
 1640    {
 1641        SliceEncodeOptions encodeOptions =
 1642            request.Features.Get<ISliceFeature>()?.EncodeOptions ?? SliceEncodeOptions.Default;
 43
 1644        var pipe = new Pipe(encodeOptions.PipeOptions);
 45
 46        try
 1647        {
 1648            var encoder = new SliceEncoder(pipe.Writer, encoding);
 49
 50            // sliceException.Encode can throw NotSupportedException
 1651            if (encoding == SliceEncoding.Slice1)
 1652            {
 1653                sliceException.Encode(ref encoder);
 1654            }
 55            else
 056            {
 057                Span<byte> sizePlaceholder = encoder.GetPlaceholderSpan(4);
 058                int startPos = encoder.EncodedByteCount;
 059                sliceException.Encode(ref encoder);
 060                SliceEncoder.EncodeVarUInt62((ulong)(encoder.EncodedByteCount - startPos), sizePlaceholder);
 061            }
 62
 1663            pipe.Writer.Complete();
 64
 1665            return new OutgoingResponse(request, StatusCode.ApplicationError, GetErrorMessage(sliceException))
 1666            {
 1667                Payload = pipe.Reader
 1668            };
 69        }
 070        catch
 071        {
 072            pipe.Reader.Complete();
 073            pipe.Writer.Complete();
 074            throw;
 75        }
 1676    }
 77
 78    /// <summary>Decodes a request payload into a list of arguments.</summary>
 79    /// <typeparam name="T">The type of the request parameters.</typeparam>
 80    /// <param name="request">The incoming request.</param>
 81    /// <param name="encoding">The encoding of the request's payload.</param>
 82    /// <param name="decodeFunc">The decode function for the arguments from the payload.</param>
 83    /// <param name="defaultActivator">The activator to use when the activator provided by the request's <see
 84    /// cref="ISliceFeature" /> is <see langword="null" />. Used only when <paramref name="encoding" /> is <see
 85    /// cref="SliceEncoding.Slice1" />.</param>
 86    /// <param name="cancellationToken">A cancellation token that receives the cancellation requests.</param>
 87    /// <returns>The request arguments.</returns>
 88    public static ValueTask<T> DecodeArgsAsync<T>(
 89        this IncomingRequest request,
 90        SliceEncoding encoding,
 91        DecodeFunc<T> decodeFunc,
 92        IActivator? defaultActivator = null,
 93        CancellationToken cancellationToken = default)
 9194    {
 9195        ISliceFeature feature = request.Features.Get<ISliceFeature>() ?? SliceFeature.Default;
 96
 9197        return request.DecodeValueAsync(
 9198            encoding,
 9199            feature,
 91100            feature.BaseProxy,
 91101            decodeFunc,
 91102            feature.Activator ?? defaultActivator,
 91103            cancellationToken);
 91104    }
 105
 106    /// <summary>Verifies that a request payload carries no argument or only unknown tagged arguments.</summary>
 107    /// <param name="request">The incoming request.</param>
 108    /// <param name="encoding">The encoding of the request payload.</param>
 109    /// <param name="cancellationToken">A cancellation token that receives the cancellation requests.</param>
 110    /// <returns>A value task that completes when the checking is complete.</returns>
 111    public static ValueTask DecodeEmptyArgsAsync(
 112        this IncomingRequest request,
 113        SliceEncoding encoding,
 114        CancellationToken cancellationToken = default) =>
 75115        request.DecodeVoidAsync(
 75116            encoding,
 75117            request.Features.Get<ISliceFeature>() ?? SliceFeature.Default,
 75118            cancellationToken);
 119
 120    // The error message includes the inner exception type and message because we don't transmit this inner exception
 121    // with the response.
 122    private static string GetErrorMessage(SliceException exception) =>
 16123        exception.InnerException is Exception innerException ?
 16124            $"{exception.Message} This exception was caused by an exception of type '{innerException.GetType()}' with me
 16125            exception.Message;
 126}