< Summary

Information
Class: ZeroC.Slice.BitSequenceReader
Assembly: ZeroC.Slice
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/ZeroC.Slice/BitSequence.cs
Tag: 275_13775359185
Line coverage
68%
Covered lines: 13
Uncovered lines: 6
Coverable lines: 19
Total lines: 106
Line coverage: 68.4%
Branch coverage
66%
Covered branches: 4
Total branches: 6
Branch coverage: 66.6%
Method coverage
100%
Covered methods: 2
Total methods: 2
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)50%2.35255.55%
Read()75%4.13480%

File(s)

/home/runner/work/icerpc-csharp/icerpc-csharp/src/ZeroC.Slice/BitSequence.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Buffers;
 4using ZeroC.Slice.Internal;
 5
 6namespace ZeroC.Slice;
 7
 8/// <summary>Provides a method for reading a bit sequence.</summary>
 9/// <remarks>This struct is typically returned by <see cref="SliceDecoder.GetBitSequenceReader(int)" />
 10/// to read the bit sequence associated with a Slice type.</remarks>
 11/// <seealso href="https://docs.icerpc.dev/slice2/encoding/encoding-only-constructs#bit-sequence"/>
 12public ref struct BitSequenceReader
 13{
 14    private byte _currentByte;
 15    private int _index; // between 0 and 7
 16    private SequenceReader<byte> _sequenceReader;
 17
 18    /// <summary>Constructs a bit sequence reader over a <see cref="ReadOnlySequence{T}" />.</summary>
 19    /// <param name="bitSequence">The read-only sequence.</param>
 20    public BitSequenceReader(ReadOnlySequence<byte> bitSequence)
 112421    {
 112422        _sequenceReader = new SequenceReader<byte>(bitSequence);
 112423        _index = 0;
 112424        if (!_sequenceReader.TryRead(out _currentByte))
 025        {
 026            throw new ArgumentException(
 027                "Cannot create a bit sequence reader over an empty byte sequence.",
 028                nameof(bitSequence));
 29        }
 112430    }
 31
 32    /// <summary>Reads the next bit.</summary>
 33    /// <returns><see langword="true" /> when the next bit is set; otherwise, <see langword="false" />.</returns>
 34    public bool Read()
 881435    {
 881436        if (_index == 8)
 93837        {
 93838            _index = 0;
 93839            if (!_sequenceReader.TryRead(out _currentByte))
 040            {
 041                throw new InvalidOperationException("Attempting to read past the end of the bit sequence.");
 42            }
 93843        }
 881444        return (_currentByte & (1 << _index++)) != 0;
 881445    }
 46}
 47
 48/// <summary>Provides a method for writing a bit sequence.</summary>
 49/// <remarks>This struct is returned by <seealso cref="SliceEncoder.GetBitSequenceWriter(int)" />
 50/// to write the bit sequence associated with a Slice type.</remarks>
 51/// <seealso href="https://docs.icerpc.dev/slice2/encoding/encoding-only-constructs#bit-sequence"/>
 52public ref struct BitSequenceWriter
 53{
 54    private int _index; // the bit index in _spanEnumerator.Current
 55
 56    private SpanEnumerator _spanEnumerator;
 57
 58    /// <summary>Writes the bit at the current position in the underlying bit sequence and moves to the next
 59    /// position.</summary>
 60    /// <param name="value"><see langword="true" /> to set the bit and <see langword="false" /> to unset it.</param>
 61    public void Write(bool value)
 62    {
 63        int byteIndex = _index >> 3; // right-shift by 3 positions, equivalent to divide by 8
 64        Span<byte> span = _spanEnumerator.Current;
 65
 66        if (byteIndex >= span.Length)
 67        {
 68            if (_spanEnumerator.MoveNext())
 69            {
 70                span = _spanEnumerator.Current;
 71                span.Clear();
 72
 73                _index = 0;
 74                byteIndex = 0;
 75            }
 76            else
 77            {
 78                throw new InvalidOperationException("Cannot write past the end of the bit sequence.");
 79            }
 80        }
 81
 82        if (value)
 83        {
 84            // set bit
 85            span[byteIndex] = (byte)(span[byteIndex] | (1 << (_index & 0x7)));
 86        }
 87        // else keep it unset
 88
 89        _index++;
 90    }
 91
 92    /// <summary>Constructs a bit sequence writer over a bit sequence represented by a <see cref="SpanEnumerator" />.
 93    /// </summary>
 94    internal BitSequenceWriter(
 95        Span<byte> firstSpan,
 96        Span<byte> secondSpan = default,
 97        IList<Memory<byte>>? additionalMemory = null)
 98    {
 99        _index = 0;
 100        _spanEnumerator = new SpanEnumerator(firstSpan, secondSpan, additionalMemory);
 101        _spanEnumerator.MoveNext();
 102
 103        // We fill the span with 0s, this way we only need to set bits, never unset them.
 104        _spanEnumerator.Current.Clear();
 105    }
 106}