< Summary

Information
Class: IceRpc.Internal.SequenceCoupler
Assembly: IceRpc
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc/Internal/SequenceCoupler.cs
Tag: 592_20856082467
Line coverage
100%
Covered lines: 37
Uncovered lines: 0
Coverable lines: 37
Total lines: 74
Line coverage: 100%
Branch coverage
100%
Covered branches: 8
Total branches: 8
Branch coverage: 100%
Method coverage
100%
Covered methods: 5
Total methods: 5
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
Concat(...)100%44100%
Append()100%22100%
GetNext()100%22100%
Reset(...)100%11100%

File(s)

/home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc/Internal/SequenceCoupler.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Buffers;
 4using System.Diagnostics;
 5
 6namespace IceRpc.Internal;
 7
 8/// <summary>Represents a coupler that concatenates two <see cref="ReadOnlySequence{T} "/> of byte to form a single
 9/// sequence.</summary>
 10/// <remarks>This class does not copy the memory of the sequences it concatenates. It does however create a
 11/// ReadOnlySequenceSegment instance for each segment of the input sequences, so it's not ultra cheap. If performance is
 12/// a concern, you should reuse the same sequence coupler over and over as it reuses the ReadOnlySequenceSegment
 13/// instances it creates.</remarks>
 14internal sealed class SequenceCoupler
 15{
 19216    private readonly Segment _head = new();
 17
 18    internal ReadOnlySequence<byte> Concat(ReadOnlySequence<byte> first, ReadOnlySequence<byte> second)
 287619    {
 287620        if (first.IsEmpty)
 221        {
 222            return second;
 23        }
 287424        if (second.IsEmpty)
 182025        {
 182026            return first;
 27        }
 28
 105429        Segment? tail = null;
 105430        Segment next = _head;
 105431        long runningIndex = 0;
 32
 105433        Append(first);
 105434        Append(second);
 35
 105436        Debug.Assert(tail is not null);
 105437        return new ReadOnlySequence<byte>(_head, startIndex: 0, tail, endIndex: tail.Memory.Length);
 38
 39        void Append(ReadOnlySequence<byte> sequence)
 210840        {
 1059441            foreach (ReadOnlyMemory<byte> memory in sequence)
 213542            {
 213543                tail = next;
 213544                tail.Reset(memory, runningIndex);
 213545                runningIndex += memory.Length;
 46
 47                // We always get (and possibly create) one extra segment. It's not used if we've reached the last
 48                // segment of second.
 213549                next = tail.GetNext();
 213550            }
 210851        }
 287652    }
 53
 54    private class Segment : ReadOnlySequenceSegment<byte>
 55    {
 56        // GetNext always returns the next segment, and creates one if needed.
 57        // Note that we never clean-up these segments.
 58        internal Segment GetNext()
 213559        {
 213560            if (Next is not Segment next)
 6661            {
 6662                next = new Segment();
 6663                Next = next;
 6664            }
 213565            return next;
 213566        }
 67
 68        internal void Reset(ReadOnlyMemory<byte> memory, long runningIndex)
 213569        {
 213570            Memory = memory;
 213571            RunningIndex = runningIndex;
 213572        }
 73    }
 74}