Files
RTCSync/RTCSync.cli/Utils/BitIndex.cs
T
2026-06-25 12:19:29 +03:00

67 lines
1.9 KiB
C#

using System;
using System.Diagnostics;
namespace RTCSync.Utils;
public readonly struct BitIndex
{
private readonly ushort _byteIdx;
private readonly byte _startBitIdx0;
private readonly byte _endBitIdx0;
// порядок указывания байт в структуре
// сначала старший, потом младше
// 1<-------------------------------41
// порядок указывания бит в структуре
// сначала младший, потом старше
// 7<------0
// таким образом все биты вписываются по порядку справа налево
// BitIndex[new(3, 0..7), new(2, 0..7), new(1, 0..6)]
public BitIndex(int byteIdx1, Range bits)
{
_byteIdx = (ushort)(byteIdx1 - 1);
Debug.Assert(!bits.Start.IsFromEnd);
Debug.Assert(!bits.End.IsFromEnd);
_startBitIdx0 = (byte)bits.Start.Value;
_endBitIdx0 = (byte)bits.End.Value;
}
public int Length => _endBitIdx0 - _startBitIdx0 + 1;
public int Take(ReadOnlySpan<byte> bytes)
{
// example: Len=3, 0b00001000 - 1 = 0b00000111
var mask = (1U << (_endBitIdx0 - _startBitIdx0 + 1)) - 1U;
return (int)((bytes[_byteIdx] >> _startBitIdx0) & mask);
}
public static int Take(BitIndex[] bis, ReadOnlySpan<byte> bytes)
{
var shift = 0;
var result = 0;
foreach (var bi in bis)
{
result |= (bi.Take(bytes) << shift);
shift += bi.Length;
}
return result;
}
}
public static class BitIndexV2Extensions
{
public static int Take(this BitIndex[] bis, ReadOnlySpan<byte> bytes)
{
var shift = 0;
var result = 0;
foreach (var bi in bis)
{
result |= (bi.Take(bytes) << shift);
shift += bi.Length;
}
return result;
}
}