< Summary

Information
Class: IceRpc.Internal.SequenceCoupler
Assembly: IceRpc
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc/Internal/SequenceCoupler.cs
Tag: 275_13775359185
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{
 37416    private readonly Segment _head = new();
 17
 18    internal ReadOnlySequence<byte> Concat(ReadOnlySequence<byte> first, ReadOnlySequence<byte> second)
 564819    {
 564820        if (first.IsEmpty)
 421        {
 422            return second;
 23        }
 564424        if (second.IsEmpty)
 357325        {
 357326            return first;
 27        }
 28
 207129        Segment? tail = null;
 207130        Segment next = _head;
 207131        long runningIndex = 0;
 32
 207133        Append(first);
 207134        Append(second);
 35
 207136        Debug.Assert(tail is not null);
 207137        return new ReadOnlySequence<byte>(_head, startIndex: 0, tail, endIndex: tail.Memory.Length);
 38
 39        void Append(ReadOnlySequence<byte> sequence)
 414240        {
 2081841            foreach (ReadOnlyMemory<byte> memory in sequence)
 419642            {
 419643                tail = next;
 419644                tail.Reset(memory, runningIndex);
 419645                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.
 419649                next = tail.GetNext();
 419650            }
 414251        }
 564852    }
 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()
 419659        {
 419660            if (Next is not Segment next)
 11261            {
 11262                next = new Segment();
 11263                Next = next;
 11264            }
 419665            return next;
 419666        }
 67
 68        internal void Reset(ReadOnlyMemory<byte> memory, long runningIndex)
 419669        {
 419670            Memory = memory;
 419671            RunningIndex = runningIndex;
 419672        }
 73    }
 74}