microsoft / CsWin32

A source generator to add a user-defined set of Win32 P/Invoke methods and supporting types to a C# project.
MIT License
2.07k stars 87 forks source link

Declare accessor properties for bitfields #1113

Closed AArnott closed 8 months ago

AArnott commented 8 months ago

Here is a sample of the output, as taken from generation of the BM_REQUEST_TYPE struct:

internal partial struct _BM
{
    internal byte _bitfield;

    /// <summary>Gets or sets bits 0-1 in the <see cref="_bitfield" /> field.</summary>
    internal byte Recipient
    {
        get => (byte)((this._bitfield & unchecked((byte)0x03)) >> 0);
        set
        {
            if ((value & unchecked((byte)~0x03)) != 0)
                throw new ArgumentOutOfRangeException(nameof(value));
            this._bitfield = (byte)((this._bitfield & unchecked((byte)~0x03)) | ((byte)value << 0));
        }
    }

    /// <summary>Gets or sets bits 2-4 in the <see cref="_bitfield" /> field.</summary>
    internal byte Reserved
    {
        get => (byte)((this._bitfield & unchecked((byte)0x1C)) >> 2);
        set
        {
            if ((value & unchecked((byte)~0x07)) != 0)
                throw new ArgumentOutOfRangeException(nameof(value));
            this._bitfield = (byte)((this._bitfield & unchecked((byte)~0x1C)) | ((byte)value << 2));
        }
    }

    /// <summary>Gets or sets bits 5-6 in the <see cref="_bitfield" /> field.</summary>
    internal byte Type
    {
        get => (byte)((this._bitfield & unchecked((byte)0x60)) >> 5);
        set
        {
            if ((value & unchecked((byte)~0x03)) != 0)
                throw new ArgumentOutOfRangeException(nameof(value));
            this._bitfield = (byte)((this._bitfield & unchecked((byte)~0x60)) | ((byte)value << 5));
        }
    }

    /// <summary>Gets or sets bit 7 in the <see cref="_bitfield" /> field.</summary>
    internal bool Dir
    {
        get => (this._bitfield & 0x80) != 0;
        set => this._bitfield = (byte)(value ? this._bitfield | 0x80 : (this._bitfield & unchecked((byte)~0x80)));
    }
}

Notice how the types of the accessor properties vary by the length of each bit field. It can be bool, byte, ushort, uint or ulong, as necessary to be at least as large as the length of the bit field.

Closes #987